summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2000-01-27 23:45:22 +0000
committerRalf Baechle <ralf@linux-mips.org>2000-01-27 23:45:22 +0000
commit5b35aa5cd29bb111d847b2a2ed18110acbfb1f44 (patch)
treec7bbaa1137528330d3c74d14056ef7016a52be72 /drivers
parent511bcd7c5924ce9e98ad1cb851988f7448dfef0f (diff)
Merge with Linux 2.3.24.
Diffstat (limited to 'drivers')
-rw-r--r--drivers/block/Config.in3
-rw-r--r--drivers/block/DAC960.c12
-rw-r--r--drivers/block/cpqarray.c23
-rw-r--r--drivers/block/ll_rw_blk.c66
-rw-r--r--drivers/block/rd.c7
-rw-r--r--drivers/char/bttv.c3
-rw-r--r--drivers/char/drm/proc.c2
-rw-r--r--drivers/char/serial.c1
-rw-r--r--drivers/i2o/i2o_block.c28
-rw-r--r--drivers/i2o/i2o_config.c24
-rw-r--r--drivers/i2o/i2o_core.c1281
-rw-r--r--drivers/i2o/i2o_lan.c102
-rw-r--r--drivers/i2o/i2o_pci.c143
-rw-r--r--drivers/i2o/i2o_proc.c138
-rw-r--r--drivers/i2o/i2o_scsi.c29
-rw-r--r--drivers/macintosh/macserial.c6
-rw-r--r--drivers/misc/acpi.c697
-rw-r--r--drivers/net/Config.in2
-rw-r--r--drivers/net/Makefile18
-rw-r--r--drivers/net/arcnet.c2827
-rw-r--r--drivers/net/irda/actisys.c179
-rw-r--r--drivers/net/irda/airport.c60
-rw-r--r--drivers/net/irda/esi.c111
-rw-r--r--drivers/net/irda/girbil.c209
-rw-r--r--drivers/net/irda/irport.c416
-rw-r--r--drivers/net/irda/irtty.c623
-rw-r--r--drivers/net/irda/litelink.c85
-rw-r--r--drivers/net/irda/pc87108.c785
-rw-r--r--drivers/net/irda/smc-ircc.c114
-rw-r--r--drivers/net/irda/tekram.c192
-rw-r--r--drivers/net/irda/toshoboe.c310
-rw-r--r--drivers/net/irda/uircc.c62
-rw-r--r--drivers/net/irda/w83977af_ir.c522
-rw-r--r--drivers/net/pcmcia/ray_cs.c612
-rw-r--r--drivers/net/pcmcia/ray_cs.h11
-rw-r--r--drivers/net/ppp_generic.c4
-rw-r--r--drivers/net/ppp_synctty.c768
-rw-r--r--drivers/net/strip.c1
-rw-r--r--drivers/pci/pcisyms.c1
-rw-r--r--drivers/pcmcia/rsrc_mgr.c20
-rw-r--r--drivers/scsi/script_asm.pl16
-rw-r--r--drivers/sound/ac97.c86
-rw-r--r--drivers/sound/ac97.h6
-rw-r--r--drivers/sound/nm256.h124
-rw-r--r--drivers/sound/nm256_audio.c721
-rw-r--r--drivers/sound/nm256_coeff.h14
-rw-r--r--drivers/usb/acm.c6
-rw-r--r--drivers/usb/cpia.c2
-rw-r--r--drivers/usb/ezusb.c3
-rw-r--r--drivers/usb/hub.c46
-rw-r--r--drivers/usb/hub.h26
-rw-r--r--drivers/usb/ohci-hcd.c93
-rw-r--r--drivers/usb/ohci-hcd.h7
-rw-r--r--drivers/usb/uhci.c5
-rw-r--r--drivers/usb/usb-serial.c5
55 files changed, 7118 insertions, 4539 deletions
diff --git a/drivers/block/Config.in b/drivers/block/Config.in
index 7f70e32ee..897aaa634 100644
--- a/drivers/block/Config.in
+++ b/drivers/block/Config.in
@@ -200,6 +200,9 @@ if [ "$CONFIG_BLK_DEV_RAM" = "y" ]; then
bool ' Initial RAM disk (initrd) support' CONFIG_BLK_DEV_INITRD
fi
tristate 'XT hard disk support' CONFIG_BLK_DEV_XD
+if [ "$CONFIG_PCI" = "y" ]; then
+ tristate 'Mylex DAC960/DAC1100 PCI RAID Controller support' CONFIG_BLK_DEV_DAC960
+fi
# PARIDE doesn't need PARPORT, but if PARPORT is configured as a module,
# PARIDE must also be a module. The bogus CONFIG_PARIDE_PARPORT option
diff --git a/drivers/block/DAC960.c b/drivers/block/DAC960.c
index 06eed2279..9f26a4b5e 100644
--- a/drivers/block/DAC960.c
+++ b/drivers/block/DAC960.c
@@ -19,8 +19,8 @@
*/
-#define DAC960_DriverVersion "2.2.4"
-#define DAC960_DriverDate "23 August 1999"
+#define DAC960_DriverVersion "2.3.4"
+#define DAC960_DriverDate "23 September 1999"
#include <linux/version.h>
@@ -256,7 +256,7 @@ static void DAC960_QueueCommand(DAC960_Command_T *Command)
static boolean DAC960_ExecuteCommand(DAC960_Command_T *Command)
{
DAC960_Controller_T *Controller = Command->Controller;
- Semaphore_T Semaphore = MUTEX_LOCKED;
+ DECLARE_MUTEX_LOCKED(Semaphore);
unsigned long ProcessorFlags;
Command->Semaphore = &Semaphore;
DAC960_AcquireControllerLock(Controller, &ProcessorFlags);
@@ -475,8 +475,8 @@ static void DAC960_DetectControllers(DAC960_ControllerType_T ControllerType)
unsigned char Device = DeviceFunction >> 3;
unsigned char Function = DeviceFunction & 0x7;
unsigned int IRQ_Channel = PCI_Device->irq;
- unsigned long BaseAddress0 = PCI_Device->base_address[0];
- unsigned long BaseAddress1 = PCI_Device->base_address[1];
+ unsigned long BaseAddress0 = PCI_Device->resource[0].start;
+ unsigned long BaseAddress1 = PCI_Device->resource[1].start;
unsigned short SubsystemVendorID, SubsystemDeviceID;
int CommandIdentifier;
pci_read_config_word(PCI_Device, PCI_SUBSYSTEM_VENDOR_ID,
@@ -825,7 +825,7 @@ static boolean DAC960_ReadDeviceConfiguration(DAC960_Controller_T *Controller)
&Controller->InquiryStandardData[Channel][TargetID];
InquiryStandardData->PeripheralDeviceType = 0x1F;
Semaphore = &Semaphores[Channel];
- *Semaphore = MUTEX_LOCKED;
+ init_MUTEX_LOCKED(Semaphore);
DCDB = &DCDBs[Channel];
DAC960_ClearCommand(Command);
Command->CommandType = DAC960_ImmediateCommand;
diff --git a/drivers/block/cpqarray.c b/drivers/block/cpqarray.c
index 579fbc13a..92b1c7d4d 100644
--- a/drivers/block/cpqarray.c
+++ b/drivers/block/cpqarray.c
@@ -34,6 +34,7 @@
#include <linux/blkpg.h>
#include <linux/timer.h>
#include <linux/proc_fs.h>
+#include <linux/init.h>
#include <linux/hdreg.h>
#include <linux/spinlock.h>
#include <asm/uaccess.h>
@@ -703,6 +704,26 @@ static ulong remap_pci_mem(ulong base, ulong size)
return (ulong) (page_remapped ? (page_remapped + page_offs) : 0UL);
}
+#ifndef MODULE
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,13)
+/*
+ * Config string is a comma seperated set of i/o addresses of EISA cards.
+ */
+static int cpqarray_setup(char *str)
+{
+ int i, ints[9];
+
+ (void)get_options(str, ARRAY_SIZE(ints), ints);
+
+ for(i=0; i<ints[0] && i<8; i++)
+ eisa[i] = ints[i+1];
+ return 1;
+}
+
+__setup("smart2=", cpqarray_setup);
+
+#else
+
/*
* Copy the contents of the ints[] array passed to us by init.
*/
@@ -712,6 +733,8 @@ void cpqarray_setup(char *str, int *ints)
for(i=0; i<ints[0] && i<8; i++)
eisa[i] = ints[i+1];
}
+#endif
+#endif
/*
* Find an EISA controller's signature. Set up an hba if we find it.
diff --git a/drivers/block/ll_rw_blk.c b/drivers/block/ll_rw_blk.c
index 9366a8856..59116c19d 100644
--- a/drivers/block/ll_rw_blk.c
+++ b/drivers/block/ll_rw_blk.c
@@ -286,15 +286,39 @@ void set_device_ro(kdev_t dev,int flag)
else ro_bits[major][minor >> 5] &= ~(1 << (minor & 31));
}
-static inline void drive_stat_acct(int cmd, unsigned long nr_sectors,
- short disk_index)
+static inline void drive_stat_acct(struct request *req,
+ unsigned long nr_sectors, int new_io)
{
- kstat.dk_drive[disk_index]++;
- if (cmd == READ) {
- kstat.dk_drive_rio[disk_index]++;
+ int major = MAJOR(req->rq_dev);
+ int minor = MINOR(req->rq_dev);
+ unsigned int disk_index;
+
+ switch (major) {
+ case DAC960_MAJOR+0:
+ disk_index = (minor & 0x00f8) >> 3;
+ break;
+ case SCSI_DISK0_MAJOR:
+ disk_index = (minor & 0x00f0) >> 4;
+ break;
+ case IDE0_MAJOR: /* same as HD_MAJOR */
+ case XT_DISK_MAJOR:
+ disk_index = (minor & 0x0040) >> 6;
+ break;
+ case IDE1_MAJOR:
+ disk_index = ((minor & 0x0040) >> 6) + 2;
+ break;
+ default:
+ return;
+ }
+ if (disk_index >= DK_NDRIVE)
+ return;
+
+ kstat.dk_drive[disk_index] += new_io;
+ if (req->cmd == READ) {
+ kstat.dk_drive_rio[disk_index] += new_io;
kstat.dk_drive_rblk[disk_index] += nr_sectors;
- } else if (cmd == WRITE) {
- kstat.dk_drive_wio[disk_index]++;
+ } else if (req->cmd == WRITE) {
+ kstat.dk_drive_wio[disk_index] += new_io;
kstat.dk_drive_wblk[disk_index] += nr_sectors;
} else
printk(KERN_ERR "drive_stat_acct: cmd not R/W?\n");
@@ -313,35 +337,11 @@ static inline void drive_stat_acct(int cmd, unsigned long nr_sectors,
void add_request(struct blk_dev_struct * dev, struct request * req)
{
int major = MAJOR(req->rq_dev);
- int minor = MINOR(req->rq_dev);
struct request * tmp, **current_request;
- short disk_index;
unsigned long flags;
int queue_new_request = 0;
- switch (major) {
- case DAC960_MAJOR+0:
- disk_index = (minor & 0x00f8) >> 3;
- if (disk_index < 4)
- drive_stat_acct(req->cmd, req->nr_sectors, disk_index);
- break;
- case SCSI_DISK0_MAJOR:
- disk_index = (minor & 0x00f0) >> 4;
- if (disk_index < 4)
- drive_stat_acct(req->cmd, req->nr_sectors, disk_index);
- break;
- case IDE0_MAJOR: /* same as HD_MAJOR */
- case XT_DISK_MAJOR:
- disk_index = (minor & 0x0040) >> 6;
- drive_stat_acct(req->cmd, req->nr_sectors, disk_index);
- break;
- case IDE1_MAJOR:
- disk_index = ((minor & 0x0040) >> 6) + 2;
- drive_stat_acct(req->cmd, req->nr_sectors, disk_index);
- default:
- break;
- }
-
+ drive_stat_acct(req, req->nr_sectors, 1);
req->next = NULL;
/*
@@ -575,6 +575,7 @@ void make_request(int major,int rw, struct buffer_head * bh)
req->bhtail->b_reqnext = bh;
req->bhtail = bh;
req->nr_sectors += count;
+ drive_stat_acct(req, count, 0);
/* Can we now merge this req with the next? */
attempt_merge(req, max_sectors);
/* or to the beginning? */
@@ -585,6 +586,7 @@ void make_request(int major,int rw, struct buffer_head * bh)
req->current_nr_sectors = count;
req->sector = sector;
req->nr_sectors += count;
+ drive_stat_acct(req, count, 0);
} else
continue;
diff --git a/drivers/block/rd.c b/drivers/block/rd.c
index 7c2b23dab..9fec26361 100644
--- a/drivers/block/rd.c
+++ b/drivers/block/rd.c
@@ -276,12 +276,9 @@ static ssize_t initrd_read(struct file *file, char *buf,
static int initrd_release(struct inode *inode,struct file *file)
{
- unsigned long i;
-
- if (--initrd_users) return 0;
- for (i = initrd_start; i < initrd_end; i += PAGE_SIZE)
- free_page(i);
initrd_start = 0;
+ /* No need to actually release the pages, because that is
+ done later by free_all_bootmem. */
return 0;
}
diff --git a/drivers/char/bttv.c b/drivers/char/bttv.c
index ac21c68f0..17e87e7f8 100644
--- a/drivers/char/bttv.c
+++ b/drivers/char/bttv.c
@@ -121,8 +121,9 @@ static inline unsigned long uvirt_to_kva(pgd_t *pgd, unsigned long adr)
if (!pmd_none(*pmd)) {
ptep = pte_offset(pmd, adr);
pte = *ptep;
+ /* Note; page_address will panic for us if the page is high */
if(pte_present(pte))
- ret = (pte_page(pte)|(adr&(PAGE_SIZE-1)));
+ ret = page_address(pte_page(pte))|(adr&(PAGE_SIZE-1));
}
}
MDEBUG(printk("uv2kva(%lx-->%lx)", adr, ret));
diff --git a/drivers/char/drm/proc.c b/drivers/char/drm/proc.c
index 7db90aea8..666b6e5ac 100644
--- a/drivers/char/drm/proc.c
+++ b/drivers/char/drm/proc.c
@@ -393,7 +393,7 @@ static int _drm_vma_info(char *buf, char **start, off_t offset, int len,
pgprot & _PAGE_PCD ? 'u' : 'c',
pgprot & _PAGE_ACCESSED ? 'a' : '-',
pgprot & _PAGE_DIRTY ? 'd' : '-',
- pgprot & _PAGE_4M ? 'm' : 'k',
+ pgprot & _PAGE_PSE ? 'm' : 'k',
pgprot & _PAGE_GLOBAL ? 'g' : 'l' );
#endif
DRM_PROC_PRINT("\n");
diff --git a/drivers/char/serial.c b/drivers/char/serial.c
index 38bbf438b..45193f9ce 100644
--- a/drivers/char/serial.c
+++ b/drivers/char/serial.c
@@ -158,6 +158,7 @@
#ifdef LOCAL_HEADERS
#include "serial_local.h"
#else
+#include <linux/serialP.h>
#include <linux/serial.h>
#include <linux/serial_reg.h>
#include <asm/serial.h>
diff --git a/drivers/i2o/i2o_block.c b/drivers/i2o/i2o_block.c
index 5042f4e97..c06b61d2d 100644
--- a/drivers/i2o/i2o_block.c
+++ b/drivers/i2o/i2o_block.c
@@ -703,7 +703,7 @@ static int i2ob_release(struct inode *inode, struct file *file)
msg[2] = i2ob_context|0x80000000;
msg[3] = (u32)query_done;
msg[4] = 60<<16;
- i2o_post_wait(dev->controller, dev->tid, msg, 20, query_done,2);
+ i2o_post_wait(dev->controller, msg, 20, 2);
/*
* Unlock the media
*/
@@ -712,7 +712,7 @@ static int i2ob_release(struct inode *inode, struct file *file)
msg[2] = i2ob_context|0x80000000;
msg[3] = (u32)query_done;
msg[4] = -1;
- i2o_post_wait(dev->controller, dev->tid, msg, 20, query_done,2);
+ i2o_post_wait(dev->controller, msg, 20, 2);
/*
* Now unclaim the device.
@@ -766,7 +766,7 @@ static int i2ob_open(struct inode *inode, struct file *file)
msg[3] = (u32)query_done;
msg[4] = -1;
msg[5] = 0;
- i2o_post_wait(dev->controller, dev->tid, msg, 24, query_done,2);
+ i2o_post_wait(dev->controller, msg, 24, 2);
/*
* Lock the media
*/
@@ -775,7 +775,7 @@ static int i2ob_open(struct inode *inode, struct file *file)
msg[2] = i2ob_context|0x80000000;
msg[3] = (u32)query_done;
msg[4] = -1;
- i2o_post_wait(dev->controller, dev->tid, msg, 20, query_done,2);
+ i2o_post_wait(dev->controller, msg, 20, 2);
}
MOD_INC_USE_COUNT;
return 0;
@@ -788,8 +788,8 @@ static int i2ob_open(struct inode *inode, struct file *file)
static int i2ob_query_device(struct i2ob_device *dev, int table,
int field, void *buf, int buflen)
{
- return i2o_query_scalar(dev->controller, dev->tid, i2ob_context,
- table, field, buf, buflen, &dev->done_flag);
+ return i2o_query_scalar(dev->controller, dev->tid,
+ table, field, buf, buflen);
}
@@ -891,7 +891,10 @@ static void i2ob_probe(void)
for(d=c->devices;d!=NULL;d=d->next)
{
- if(d->class!=I2O_CLASS_RANDOM_BLOCK_STORAGE)
+ if(d->lct_data->class_id!=I2O_CLASS_RANDOM_BLOCK_STORAGE)
+ continue;
+
+ if(d->lct_data->user_tid != 0xFFF)
continue;
if(unit<MAX_I2OB<<4)
@@ -903,7 +906,7 @@ static void i2ob_probe(void)
struct i2ob_device *dev=&i2ob_dev[unit];
dev->i2odev = d;
dev->controller = c;
- dev->tid = d->id;
+ dev->tid = d->lct_data->tid;
/*
* Insure the device can be claimed
@@ -930,9 +933,10 @@ static void i2ob_probe(void)
else
{
if(!warned++)
- printk("i2o_block: too many controllers, registering only %d.\n", unit>>4);
+ printk("i2o_block: too many device, registering only %d.\n", unit>>4);
}
}
+ i2o_unlock_controller(c);
}
i2ob_devices = unit;
}
@@ -981,7 +985,7 @@ static int i2ob_reboot_event(struct notifier_block *n, unsigned long code, void
msg[2] = i2ob_context|0x80000000;
msg[3] = (u32)query_done;
msg[4] = 60<<16;
- i2o_post_wait(dev->controller, dev->tid, msg, 20, query_done,2);
+ i2o_post_wait(dev->controller, msg, 20, 2);
/*
* Unlock the media
*/
@@ -990,7 +994,7 @@ static int i2ob_reboot_event(struct notifier_block *n, unsigned long code, void
msg[2] = i2ob_context|0x80000000;
msg[3] = (u32)query_done;
msg[4] = -1;
- i2o_post_wait(dev->controller, dev->tid, msg, 20, query_done,2);
+ i2o_post_wait(dev->controller, msg, 20, 2);
}
}
return NOTIFY_DONE;
@@ -1058,7 +1062,7 @@ int i2o_block_init(void)
{
int i;
- printk(KERN_INFO "I2O block device OSM v0.07. (C) 1999 Red Hat Software.\n");
+ printk(KERN_INFO "I2O Block Storage OSM v0.07. (C) 1999 Red Hat Software.\n");
/*
* Register the block device interfaces
diff --git a/drivers/i2o/i2o_config.c b/drivers/i2o/i2o_config.c
index 518093ea0..c8682f077 100644
--- a/drivers/i2o/i2o_config.c
+++ b/drivers/i2o/i2o_config.c
@@ -317,14 +317,14 @@ static int ioctl_parms(unsigned long arg, unsigned int type)
return -ENOMEM;
}
- len = i2o_issue_params(i2o_cmd, c, kcmd.tid, cfg_handler.context,
- ops, kcmd.oplen, res, 65536, &i2o_cfg_token);
+ len = i2o_issue_params(i2o_cmd, c, kcmd.tid,
+ ops, kcmd.oplen, res, 65536);
i2o_unlock_controller(c);
kfree(ops);
- if (len < 0) {
+ if (len) {
kfree(res);
- return len; /* -DetailedStatus */
+ return len; /* -DetailedStatus || -ETIMEDOUT */
}
put_user(len, kcmd.reslen);
@@ -413,8 +413,8 @@ int ioctl_html(unsigned long arg)
msg[8] = virt_to_phys(query);
}
- token = i2o_post_wait(c, cmd->tid, msg, 9*4, &i2o_cfg_token, 10);
- if(token != I2O_POST_WAIT_OK)
+ token = i2o_post_wait(c, msg, 9*4, 10);
+ if(token)
{
i2o_unlock_controller(c);
kfree(res);
@@ -531,8 +531,8 @@ int ioctl_swdl(unsigned long arg)
// Yes...that's one minute, but the spec states that
// transfers take a long time, and I've seen just how
// long they can take.
- token = i2o_post_wait(c, ADAPTER_TID, msg, sizeof(msg), &i2o_cfg_token,60);
- if (token != I2O_POST_WAIT_OK ) // Something very wrong
+ token = i2o_post_wait(c, msg, sizeof(msg), 60);
+ if (token) // Something very wrong
{
i2o_unlock_controller(c);
printk("Timeout downloading software");
@@ -547,8 +547,8 @@ int ioctl_swdl(unsigned long arg)
msg[4] |= (u32)maxfrag;
msg[7] = (0xD0000000 | diff);
__copy_from_user(buffer, kxfer.buf, 8192);
- token = i2o_post_wait(c, ADAPTER_TID, msg, sizeof(msg), &i2o_cfg_token,60);
- if( token != I2O_POST_WAIT_OK ) // Something very wrong
+ token = i2o_post_wait(c, msg, sizeof(msg), 60);
+ if(token) // Something very wrong
{
i2o_unlock_controller(c);
printk("Timeout downloading software");
@@ -588,10 +588,10 @@ int ioctl_validate(unsigned long arg)
msg[2] = (u32)i2o_cfg_context;
msg[3] = 0;
- token = i2o_post_wait(c, ADAPTER_TID, msg, sizeof(msg),&i2o_cfg_token, 10);
+ token = i2o_post_wait(c, msg, sizeof(msg), 10);
i2o_unlock_controller(c);
- if (token != I2O_POST_WAIT_OK)
+ if (token)
{
printk("Can't validate configuration, ErrorStatus = %d\n",
token);
diff --git a/drivers/i2o/i2o_core.c b/drivers/i2o/i2o_core.c
index fe8a86483..c2ade9ded 100644
--- a/drivers/i2o/i2o_core.c
+++ b/drivers/i2o/i2o_core.c
@@ -1,22 +1,24 @@
-/*
- * Core I2O structure managment
- *
- * (C) Copyright 1999 Red Hat Software
+/*
+ * Core I2O structure managment
+ *
+ * (C) Copyright 1999 Red Hat Software
*
- * Written by Alan Cox, Building Number Three Ltd
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
- *
- * A lot of the I2O message side code from this is taken from the
- * Red Creek RCPCI45 adapter driver by Red Creek Communications
+ * Written by Alan Cox, Building Number Three Ltd
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ * A lot of the I2O message side code from this is taken from the
+ * Red Creek RCPCI45 adapter driver by Red Creek Communications
*
- * Fixes by Philipp Rumpf
- * Juha Sievänen <Juha.Sievanen@cs.Helsinki.FI>
- * Auvo Häkkinen <Auvo.Hakkinen@cs.Helsinki.FI>
- * Deepak Saxena <deepak@plexity.net>
+ * Fixes by:
+ * Philipp Rumpf
+ * Juha Sievänen <Juha.Sievanen@cs.Helsinki.FI>
+ * Auvo Häkkinen <Auvo.Hakkinen@cs.Helsinki.FI>
+ * Deepak Saxena <deepak@plexity.net>
+ *
*/
#include <linux/config.h>
@@ -31,11 +33,16 @@
#include <linux/malloc.h>
#include <linux/spinlock.h>
+#include <linux/bitops.h>
+#include <linux/wait.h>
+#include <linux/timer.h>
+
#include <asm/io.h>
#include "i2o_lan.h"
#define DRIVERDEBUG
+// #define DEBUG_IRQ
/*
* Size of the I2O module table
@@ -48,12 +55,36 @@ static int core_context = 0;
static int reply_flag = 0;
extern int i2o_online_controller(struct i2o_controller *c);
+static int i2o_init_outbound_q(struct i2o_controller *c);
static void i2o_core_reply(struct i2o_handler *, struct i2o_controller *,
struct i2o_message *);
static int i2o_add_management_user(struct i2o_device *, struct i2o_handler *);
static int i2o_remove_management_user(struct i2o_device *, struct i2o_handler *);
+static int i2o_quiesce_system(void);
+static int i2o_enable_system(void);
static void i2o_dump_message(u32 *);
+static int i2o_lct_get(struct i2o_controller *);
+static int i2o_hrt_get(struct i2o_controller *);
+
+static void i2o_sys_init(void);
+static void i2o_sys_shutdown(void);
+
+static int i2o_build_sys_table(void);
+static int i2o_systab_send(struct i2o_controller *c);
+
+/*
+ * I2O System Table. Contains information about
+ * all the IOPs in the system. Used to inform IOPs
+ * about each other's existence.
+ *
+ * sys_tbl_ver is the CurrentChangeIndicator that is
+ * used by IOPs to track changes.
+ */
+static struct i2o_sys_tbl *sys_tbl = NULL;
+static int sys_tbl_ind = 0;
+static int sys_tbl_len = 0;
+
#ifdef MODULE
/*
* Function table to send to bus specific layers
@@ -76,6 +107,21 @@ extern void i2o_pci_core_detach(void);
#endif /* MODULE */
+/*
+ * Structures and definitions for synchronous message posting.
+ * See i2o_post_wait() for description.
+ */
+struct i2o_post_wait_data
+{
+ int status;
+ u32 id;
+ wait_queue_head_t *wq;
+ struct i2o_post_wait_data *next;
+};
+static struct i2o_post_wait_data *post_wait_queue = NULL;
+static u32 post_wait_id = 0; // Unique ID for each post_wait
+static spinlock_t post_wait_lock = SPIN_LOCK_UNLOCKED;
+static void i2o_post_wait_complete(u32, int);
/* Message handler */
static struct i2o_handler i2o_core_handler =
@@ -85,6 +131,7 @@ static struct i2o_handler i2o_core_handler =
0
};
+
/*
* I2O configuration spinlock. This isnt a big deal for contention
* so we have one only
@@ -92,11 +139,17 @@ static struct i2o_handler i2o_core_handler =
static spinlock_t i2o_configuration_lock = SPIN_LOCK_UNLOCKED;
+/*
+ * I2O Core reply handler
+ *
+ * Only messages this should see are i2o_post_wait() replies
+ */
void i2o_core_reply(struct i2o_handler *h, struct i2o_controller *c,
struct i2o_message *m)
{
u32 *msg=(u32 *)m;
- u32 *flag = (u32 *)msg[3];
+ u32 status;
+ u32 context = msg[3];
#if 0
i2o_report_status(KERN_INFO, "i2o_core", msg);
@@ -117,13 +170,18 @@ void i2o_core_reply(struct i2o_handler *h, struct i2o_controller *c,
return;
}
- if (msg[4] >> 24)
+ if(msg[2]&0x80000000) // Post wait message
{
- i2o_report_status(KERN_WARNING, "i2o_core", msg);
- *flag = -(msg[4] & 0xFFFF);
+ if (msg[4] >> 24)
+ {
+ i2o_report_status(KERN_WARNING, "i2o_core: post_wait reply", msg);
+ status = -(msg[4] & 0xFFFF);
+ }
+ else
+ status = I2O_POST_WAIT_OK;
+
+ i2o_post_wait_complete(context, status);
}
- else
- *flag = I2O_POST_WAIT_OK;
}
/*
@@ -245,6 +303,12 @@ int i2o_install_controller(struct i2o_controller *c)
c->next=i2o_controller_chain;
i2o_controller_chain=c;
c->unit = i;
+ c->page_frame = NULL;
+ c->hrt = NULL;
+ c->lct = NULL;
+ c->status_block = NULL;
+ printk(KERN_INFO "lct @ %p hrt @ %p status @ %p",
+ c->lct, c->hrt, c->status_block);
sprintf(c->name, "i2o/iop%d", i);
i2o_num_controllers++;
spin_unlock(&i2o_configuration_lock);
@@ -261,10 +325,14 @@ int i2o_delete_controller(struct i2o_controller *c)
struct i2o_controller **p;
int users;
+#ifdef DRIVERDEBUG
+ printk(KERN_INFO "Deleting controller iop%d\n", c->unit);
+#endif
+
spin_lock(&i2o_configuration_lock);
if((users=atomic_read(&c->users)))
{
- printk("I2O: %d users for controller iop%d\n", users, c->unit);
+ printk(KERN_INFO "I2O: %d users for controller iop%d\n", users, c->unit);
spin_unlock(&i2o_configuration_lock);
return -EBUSY;
}
@@ -280,21 +348,6 @@ int i2o_delete_controller(struct i2o_controller *c)
p=&i2o_controller_chain;
- /* Send first SysQuiesce to other IOPs */
- while(*p)
- {
- if(*p!=c)
- {
- printk("Quiescing controller %p != %p\n", c, *p);
- if(i2o_quiesce_controller(*p)<0)
- printk(KERN_INFO "Unable to quiesce iop%d\n",
- (*p)->unit);
- }
- p=&((*p)->next);
- }
-
- p=&i2o_controller_chain;
-
while(*p)
{
if(*p==c)
@@ -308,15 +361,26 @@ int i2o_delete_controller(struct i2o_controller *c)
*p=c->next;
spin_unlock(&i2o_configuration_lock);
+
+ printk(KERN_INFO "hrt %p lct %p page_frame %p status_block %p\n",
+ c->hrt, c->lct, c->page_frame, c->status_block);
if(c->page_frame)
kfree(c->page_frame);
if(c->hrt)
kfree(c->hrt);
if(c->lct)
kfree(c->lct);
- i2o_controllers[c->unit]=NULL;
+ if(c->status_block)
+ kfree(c->status_block);
+
kfree(c);
+
+ i2o_controllers[c->unit]=NULL;
+
i2o_num_controllers--;
+#ifdef DRIVERDEBUG
+ printk(KERN_INFO "iop deleted\n");
+#endif
return 0;
}
p=&((*p)->next);
@@ -360,7 +424,7 @@ int i2o_claim_device(struct i2o_device *d, struct i2o_handler *h, u32 type)
return -EBUSY;
}
- if(i2o_issue_claim(d->controller,d->id, h->context, 1, &reply_flag, type) < 0)
+ if(i2o_issue_claim(d->controller,d->lct_data->tid, h->context, 1, &reply_flag, type))
{
return -EBUSY;
}
@@ -395,8 +459,8 @@ int i2o_release_device(struct i2o_device *d, struct i2o_handler *h, u32 type)
err = -ENOENT;
else
{
- if(i2o_issue_claim(d->controller, d->id, h->context, 0,
- &reply_flag, type) < 0)
+ if(i2o_issue_claim(d->controller, d->lct_data->tid, h->context, 0,
+ &reply_flag, type))
{
err = -ENXIO;
}
@@ -418,8 +482,8 @@ int i2o_release_device(struct i2o_device *d, struct i2o_handler *h, u32 type)
{
atomic_dec(&d->controller->users);
- if(i2o_issue_claim(d->controller,d->id, h->context, 0,
- &reply_flag, type) < 0)
+ if(i2o_issue_claim(d->controller,d->lct_data->tid, h->context, 0,
+ &reply_flag, type))
err = -ENXIO;
}
@@ -468,7 +532,11 @@ void i2o_run_queue(struct i2o_controller *c)
{
struct i2o_message *m;
u32 mv;
-
+
+#ifdef DEBUG_IRQ
+ printk(KERN_INFO "iop%d interrupt\n", c->unit);
+#endif
+
while((mv=I2O_REPLY_READ32(c))!=0xFFFFFFFF)
{
struct i2o_handler *i;
@@ -478,7 +546,11 @@ void i2o_run_queue(struct i2o_controller *c)
*/
if(((m->function_addr>>24)&0xFF)==0x15)
printk("UTFR!\n");
-// printk("dispatching.\n");
+
+#ifdef DEBUG_IRQ
+ i2o_dump_message((u32*)m);
+#endif
+
i=i2o_handlers[m->initiator_context&(MAX_I2O_MODULES-1)];
if(i)
i->reply(i,c,m);
@@ -572,8 +644,10 @@ u32 i2o_wait_message(struct i2o_controller *c, char *why)
{
if((jiffies-time)>=5*HZ)
{
+#ifdef DRIVERDEBUG
printk(KERN_ERR "%s: Timeout waiting for message frame to send %s.\n",
c->name, why);
+#endif
return 0xFFFFFFFF;
}
schedule();
@@ -596,8 +670,10 @@ u32 i2o_wait_reply(struct i2o_controller *c, char *why, int timeout)
{
if(jiffies-time >= timeout*HZ )
{
+#ifdef DRIVERDEBUG
printk(KERN_ERR "%s: timeout waiting for %s reply.\n",
c->name, why);
+#endif
return 0xFFFFFFFF;
}
schedule();
@@ -686,8 +762,10 @@ static int i2o_query_scalar_polled(struct i2o_controller *c, int tid, void *buf,
/* Do we have an error block ? */
if(p[1]&0xFF000000)
{
+#ifdef DRIVERDEBUG
printk(KERN_ERR "%s: error in field read.\n",
c->name);
+#endif
kfree(rbuf);
return -EBADR;
}
@@ -711,25 +789,27 @@ static int i2o_query_scalar_polled(struct i2o_controller *c, int tid, void *buf,
void i2o_report_controller_unit(struct i2o_controller *c, int unit)
{
char buf[64];
+ return;
- if(i2o_query_scalar_polled(c, unit, buf, 16, 0xF100, 3)>=0)
+ if(i2o_query_scalar(c, unit, 0xF100, 3, buf, 16))
{
buf[16]=0;
printk(KERN_INFO " Vendor: %s\n", buf);
}
- if(i2o_query_scalar_polled(c, unit, buf, 16, 0xF100, 4)>=0)
+ if(i2o_query_scalar(c, unit, 0xF100, 4, buf, 16))
{
+
buf[16]=0;
printk(KERN_INFO " Device: %s\n", buf);
}
#if 0
- if(i2o_query_scalar_polled(c, unit, buf, 16, 0xF100, 5)>=0)
+ if(i2o_query_scalar(c, unit, 0xF100, 5, buf, 16))
{
buf[16]=0;
printk(KERN_INFO "Description: %s\n", buf);
}
#endif
- if(i2o_query_scalar_polled(c, unit, buf, 8, 0xF100, 6)>=0)
+ if(i2o_query_scalar(c, unit, 0xF100, 6, buf, 8))
{
buf[8]=0;
printk(KERN_INFO " Rev: %s\n", buf);
@@ -749,6 +829,7 @@ void i2o_report_controller_unit(struct i2o_controller *c, int unit)
static int i2o_parse_hrt(struct i2o_controller *c)
{
+#ifdef DRIVERDEBUG
u32 *rows=c->hrt;
u8 *p=(u8 *)c->hrt;
u8 *d;
@@ -766,8 +847,8 @@ static int i2o_parse_hrt(struct i2o_controller *c)
count=p[0]|(p[1]<<8);
length = p[2];
- printk(KERN_INFO "HRT has %d entries of %d bytes each.\n",
- count, length<<2);
+ printk(KERN_INFO "iop%d: HRT has %d entries of %d bytes each.\n",
+ c->unit, count, length<<2);
rows+=2;
@@ -829,6 +910,7 @@ static int i2o_parse_hrt(struct i2o_controller *c)
printk("\n");
rows+=length;
}
+#endif
return 0;
}
@@ -845,12 +927,12 @@ static int i2o_parse_lct(struct i2o_controller *c)
u32 *p;
struct i2o_device *d;
char str[22];
- u32 *lct=(u32 *)c->lct;
+ pi2o_lct lct = c->lct;
- max=lct[0]&0xFFFF;
+ max = lct->table_size;
- max-=3;
- max/=9;
+ max -= 3;
+ max /= 9;
if(max==0)
{
@@ -866,28 +948,25 @@ static int i2o_parse_lct(struct i2o_controller *c)
max=128;
}
- if(lct[1]&(1<<0))
- printk(KERN_WARNING "Configuration dialog desired.\n");
+ if(lct->iop_flags&(1<<0))
+ printk(KERN_WARNING "I2O: Configuration dialog desired by iop%d.\n", c->unit);
- p=lct+3;
-
for(i=0;i<max;i++)
{
d = (struct i2o_device *)kmalloc(sizeof(struct i2o_device), GFP_KERNEL);
if(d==NULL)
{
- printk("i2o_core: Out of memory for LCT data.\n");
+ printk("i2o_core: Out of memory for I2O device data.\n");
return -ENOMEM;
}
d->controller = c;
d->next = NULL;
-
- d->id = tid = (p[0]>>16)&0xFFF;
- d->class = p[3]&0xFFF;
- d->subclass = p[4]&0xFFF;
- d->parent = (p[5]>>12)&0xFFF;
+
+ d->lct_data = &lct->lct_entry[i];
+
d->flags = 0;
+ tid = d->lct_data->tid;
printk(KERN_INFO "TID %d.\n", tid);
@@ -897,19 +976,19 @@ static int i2o_parse_lct(struct i2o_controller *c)
printk(KERN_INFO " Class: ");
- sprintf(str, "%-21s", i2o_get_class_name(d->class));
+ sprintf(str, "%-21s", i2o_get_class_name(d->lct_data->class_id));
printk("%s", str);
printk(" Subclass: 0x%03X Flags: ",
- d->subclass);
+ d->lct_data->sub_class);
- if(p[2]&(1<<0))
+ if(d->lct_data->device_flags&(1<<0))
printk("C"); // ConfigDialog requested
- if(p[2]&(1<<1))
+ if(d->lct_data->device_flags&(1<<1))
printk("M"); // Multi-user capable
- if(!(p[2]&(1<<4)))
+ if(!(d->lct_data->device_flags&(1<<4)))
printk("P"); // Peer service enabled!
- if(!(p[2]&(1<<5)))
+ if(!(d->lct_data->device_flags&(1<<5)))
printk("m"); // Mgmt service enabled!
printk("\n");
p+=9;
@@ -917,30 +996,120 @@ static int i2o_parse_lct(struct i2o_controller *c)
return 0;
}
+
/* Quiesce IOP */
int i2o_quiesce_controller(struct i2o_controller *c)
{
u32 msg[4];
+ if(c->status_block->iop_state != ADAPTER_STATE_OPERATIONAL)
+ return -EINVAL;
+
msg[0]=FOUR_WORD_MSG_SIZE|SGL_OFFSET_0;
msg[1]=I2O_CMD_SYS_QUIESCE<<24|HOST_TID<<12|ADAPTER_TID;
- msg[2]=core_context;
+ msg[2]=(u32)core_context;
msg[3]=(u32)&reply_flag;
/* Long timeout needed for quiesce if lots of devices */
- return i2o_post_wait(c, ADAPTER_TID, msg, sizeof(msg), &reply_flag, 120);
+#ifdef DRIVERDEBUG
+ printk(KERN_INFO "Posting quiesce message to iop%d\n", c->unit);
+#endif
+ if(i2o_post_wait(c, msg, sizeof(msg), 120))
+ return -1;
+ else
+ return 0;
+}
+
+/* Enable IOP */
+int i2o_enable_controller(struct i2o_controller *c)
+{
+ u32 msg[4];
+
+ msg[0]=FOUR_WORD_MSG_SIZE|SGL_OFFSET_0;
+ msg[1]=I2O_CMD_SYS_ENABLE<<24|HOST_TID<<12|ADAPTER_TID;
+ msg[2]=core_context;
+ msg[3]=(u32)&reply_flag;
+
+ /* How long of a timeout do we need? */
+ return i2o_post_wait(c, msg, sizeof(msg), 240);
+}
+
+/*
+ * Quiesce _all_ IOPs in OP state.
+ * Used during init/shutdown time.
+ */
+int i2o_quiesce_system(void)
+{
+ struct i2o_controller *iop;
+ int ret = 0;
+
+ for(iop=i2o_controller_chain; iop != NULL; iop=iop->next)
+ {
+ /*
+ * Quiesce only needed on operational IOPs
+ */
+ i2o_status_get(iop);
+
+ if(iop->status_block->iop_state == ADAPTER_STATE_OPERATIONAL)
+ {
+#ifdef DRIVERDEBUG
+ printk(KERN_INFO "Attempting to quiesce iop%d\n", iop->unit);
+#endif
+ if(i2o_quiesce_controller(iop))
+ {
+ printk(KERN_INFO "Unable to quiesce iop%d\n", iop->unit);
+ ret = -ENXIO;
+ }
+#ifdef DRIVERDEBUG
+ else
+ printk(KERN_INFO "%s quiesced\n", iop->name);
+#endif
+
+ i2o_status_get(iop); // Update IOP state information
+ }
+ }
+
+ return ret;
}
+/*
+ * (re)Enable _all_ IOPs in READY state.
+ */
+int i2o_enable_system(void)
+{
+ struct i2o_controller *iop;
+ int ret = 0;
+
+ for(iop=i2o_controller_chain; iop != NULL; iop=iop->next)
+ {
+ /*
+ * Enable only valid for IOPs in READY state
+ */
+ i2o_status_get(iop);
+
+ if(iop->status_block->iop_state == ADAPTER_STATE_READY)
+ {
+ if(i2o_enable_controller(iop)<0)
+ printk(KERN_INFO "Unable to (re)enable iop%d\n",
+ iop->unit);
+
+ i2o_status_get(iop); // Update IOP state information
+ }
+ }
+
+ return ret;
+}
+
+/* Reset an IOP, but keep message queues alive */
int i2o_clear_controller(struct i2o_controller *c)
{
u32 msg[4];
+ int ret;
- /* First stop external operations for this IOP */
- if(i2o_quiesce_controller(c)<0)
- printk(KERN_INFO "Unable to quiesce iop%d\n", c->unit);
- else
- printk(KERN_INFO "Iop%d quiesced\n", c->unit);
+#ifdef DRIVERDEBUG
+ printk(KERN_INFO "Clearing iop%d\n", c->unit);
+#endif
/* Then clear the IOP */
msg[0]=FOUR_WORD_MSG_SIZE|SGL_OFFSET_0;
@@ -948,7 +1117,14 @@ int i2o_clear_controller(struct i2o_controller *c)
msg[2]=core_context;
msg[3]=(u32)&reply_flag;
- return i2o_post_wait(c, ADAPTER_TID, msg, sizeof(msg), &reply_flag, 10);
+ if((ret=i2o_post_wait(c, msg, sizeof(msg), 30)))
+ printk(KERN_INFO "ExecIopClear failed: %#10x\n", ret);
+#ifdef DRIVERDEBUG
+ else
+ printk(KERN_INFO "ExecIopClear success!\n");
+#endif
+
+ return ret;
}
@@ -959,27 +1135,15 @@ static int i2o_reset_controller(struct i2o_controller *c)
u8 *work8;
u32 *msg;
long time;
- struct i2o_controller *iop;
- /* First stop external operations */
- for(iop=i2o_controller_chain; iop != NULL; iop=iop->next)
- {
- /* Quiesce is rejected on hold state */
- if(iop->status != ADAPTER_STATE_HOLD)
- {
- if(i2o_quiesce_controller(iop)<0)
- printk(KERN_INFO "Unable to quiesce iop%d\n",
- iop->unit);
- else
- printk(KERN_DEBUG "%s quiesced\n", iop->name);
- }
- }
+#ifdef DRIVERDEBUG
+ printk(KERN_INFO "Reseting iop%d\n", c->unit);
+#endif
- /* Then reset the IOP */
+ /* Get a message */
m=i2o_wait_message(c, "AdapterReset");
- if(m==0xFFFFFFFF)
+ if(m==0xFFFFFFFF)
return -ETIMEDOUT;
-
msg=(u32 *)(c->mem_offset+m);
work8=(void *)kmalloc(4, GFP_KERNEL);
@@ -999,12 +1163,16 @@ static int i2o_reset_controller(struct i2o_controller *c)
msg[6]=virt_to_phys(work8);
msg[7]=0; /* 64bit host FIXME */
+ /* Then reset the IOP */
i2o_post_message(c,m);
/* Wait for a reply */
time=jiffies;
- while(work8[0]==0x01)
+#ifdef DRIVERDEBUG
+ printk(KERN_INFO "Reset posted, waiting...\n");
+#endif
+ while(work8[0]==0)
{
if((jiffies-time)>=5*HZ)
{
@@ -1016,8 +1184,41 @@ static int i2o_reset_controller(struct i2o_controller *c)
barrier();
}
- if (work8[0]==0x02)
- printk(KERN_WARNING "IOP Reset rejected\n");
+ if (work8[0]==0x02)
+ {
+ printk(KERN_WARNING "IOP Reset rejected\n");
+ }
+ else
+ {
+ /*
+ * Once the reset is sent, the IOP goes into the INIT state
+ * which is inditerminate. We need to wait until the IOP
+ * has rebooted before we can let the system talk to
+ * it. We read the inbound Free_List until a message is
+ * available. If we can't read one in the given ammount of
+ * time, we assume the IOP could not reboot properly.
+ */
+#ifdef DRIVERDEBUG
+ printk(KERN_INFO "Reset succeeded...waiting for reboot\n");
+#endif
+ time = jiffies;
+ m = I2O_POST_READ32(c);
+ while(m == 0XFFFFFFFF)
+ {
+ if((jiffies-time) >= 30*HZ)
+ {
+ printk(KERN_ERR "i2o/iop%d: Timeout waiting for IOP reset.\n",
+ c->unit);
+ return -ETIMEDOUT;
+ }
+ schedule();
+ barrier();
+ m = I2O_POST_READ32(c);
+ }
+#ifdef DRIVERDEBUG
+ printk(KERN_INFO "Reboot completed\n");
+#endif
+ }
return 0;
}
@@ -1030,13 +1231,24 @@ int i2o_status_get(struct i2o_controller *c)
u32 *msg;
u8 *status_block;
- status_block=(void *)kmalloc(88, GFP_KERNEL);
- if(status_block==NULL)
+#ifdef DRIVERDEBUG
+ printk(KERN_INFO "Getting status block for iop%d\n", c->unit);
+#endif
+ if(c->status_block)
+ kfree(c->status_block);
+
+ c->status_block =
+ (pi2o_status_block)kmalloc(sizeof(i2o_status_block),GFP_KERNEL);
+ if(c->status_block == NULL)
{
- printk(KERN_ERR "StatusGet failed - no free memory.\n");
+#ifdef DRIVERDEBUG
+ printk(KERN_ERR "No memory in status get!\n");
+#endif
return -ENOMEM;
}
+ status_block = (u8*)c->status_block;
+
m=i2o_wait_message(c, "StatusGet");
if(m==0xFFFFFFFF)
return -ETIMEDOUT;
@@ -1049,7 +1261,7 @@ int i2o_status_get(struct i2o_controller *c)
msg[3]=0;
msg[4]=0;
msg[5]=0;
- msg[6]=virt_to_phys(status_block);
+ msg[6]=virt_to_phys(c->status_block);
msg[7]=0; /* 64bit host FIXME */
msg[8]=88;
@@ -1062,7 +1274,9 @@ int i2o_status_get(struct i2o_controller *c)
{
if((jiffies-time)>=5*HZ)
{
+#ifdef DRIVERDEBUG
printk(KERN_ERR "IOP get status timeout.\n");
+#endif
return -ETIMEDOUT;
}
schedule();
@@ -1070,8 +1284,6 @@ int i2o_status_get(struct i2o_controller *c)
}
/* Ok the reply has arrived. Fill in the important stuff */
- c->status = status_block[10];
- c->i2oversion = (status_block[9]>>4)&0xFF;
c->inbound_size = (status_block[12]|(status_block[13]<<8))*4;
return 0;
@@ -1080,8 +1292,10 @@ int i2o_status_get(struct i2o_controller *c)
int i2o_hrt_get(struct i2o_controller *c)
{
- u32 m;
- u32 *msg;
+ u32 msg[6];
+
+ if(c->hrt)
+ kfree(c->hrt);
c->hrt=kmalloc(2048, GFP_KERNEL);
if(c->hrt==NULL)
@@ -1090,12 +1304,6 @@ int i2o_hrt_get(struct i2o_controller *c)
return -ENOMEM;
}
- m=i2o_wait_message(c, "HRTGet");
- if(m==0xFFFFFFFF)
- return -ETIMEDOUT;
-
- msg=(u32 *)(c->mem_offset+m);
-
msg[0]= SIX_WORD_MSG_SIZE| SGL_OFFSET_4;
msg[1]= I2O_CMD_HRT_GET<<24 | HOST_TID<<12 | ADAPTER_TID;
msg[2]= core_context;
@@ -1103,26 +1311,200 @@ int i2o_hrt_get(struct i2o_controller *c)
msg[4]= (0xD0000000 | 2048); /* Simple transaction , 2K */
msg[5]= virt_to_phys(c->hrt); /* Dump it here */
- i2o_post_message(c,m);
+ return i2o_post_wait(c, msg, sizeof(msg), 20);
+}
- barrier();
+static int i2o_systab_send(struct i2o_controller* iop)
+{
+ u32 msg[10];
+ u32 privmem[2];
+ u32 privio[2];
+ int ret;
- /* Now wait for a reply */
- m=i2o_wait_reply(c, "HRTGet", 5);
+ privmem[0]=iop->priv_mem; /* Private memory space base address */
+ privmem[1]=iop->priv_mem_size;
+ privio[0]=iop->priv_io; /* Private I/O address */
+ privio[1]=iop->priv_io_size;
- if(m==0xFFFFFFFF)
- return -ETIMEDOUT;
+ msg[0] = NINE_WORD_MSG_SIZE|SGL_OFFSET_6;
+ msg[1] = I2O_CMD_SYS_TAB_SET<<24 | HOST_TID<<12 | ADAPTER_TID;
+ msg[2] = 0; /* Context not needed */
+ msg[3] = 0;
+ msg[4] = (0<<16)|((iop->unit+2)<<12); /* Host 0 IOP ID (unit + 2) */
+ msg[5] = 0; /* Segment 0 */
+
+ /*
+ * Scatter Gather List
+ */
+ msg[6] = 0x54000000|sys_tbl_len;
+ msg[7] = virt_to_phys(sys_tbl);
+ msg[8] = 0xD4000000|48; /* One table for now */
+ msg[9] = virt_to_phys(privmem);
+/* msg[10] = virt_to_phys(privio); */
- msg=(u32 *)bus_to_virt(m);
+ ret=i2o_post_wait(iop, msg, sizeof(msg), 120);
+ if(ret)
+ return ret;
- if(msg[4]>>24)
- i2o_report_status(KERN_WARNING, "i2o_core", msg);
+ return 0;
+}
- I2O_REPLY_WRITE32(c,m);
+/*
+ * Initialize I2O subsystem.
+ */
+static void __init i2o_sys_init()
+{
+ struct i2o_controller *iop;
+ int ret;
+ u32 m;
- return 0;
+ printk(KERN_INFO "Activating I2O controllers\n");
+ printk(KERN_INFO "This may take a few minutes if there are many devices\n");
+
+ /* Get the status for each IOP */
+ for(iop = i2o_controller_chain; iop; iop = iop->next)
+ {
+#ifdef DRIVERDEBUG
+ printk(KERN_INFO "Getting initial status for iop%d\n", iop->unit);
+#endif
+ i2o_status_get(iop);
+
+ if(iop->status_block->iop_state == ADAPTER_STATE_FAULTED)
+ {
+ printk(KERN_CRIT "i2o: iop%d has hardware fault\n",
+ iop->unit);
+ i2o_delete_controller(iop);
+ }
+
+ if(iop->status_block->iop_state == ADAPTER_STATE_HOLD ||
+ iop->status_block->iop_state == ADAPTER_STATE_READY ||
+ iop->status_block->iop_state == ADAPTER_STATE_OPERATIONAL ||
+ iop->status_block->iop_state == ADAPTER_STATE_FAILED)
+ {
+ int msg[256];
+
+#ifdef DRIVERDEBUG
+ printk(KERN_INFO "iop%d already running...trying to reboot",
+ iop->unit);
+#endif
+ i2o_init_outbound_q(iop);
+ I2O_REPLY_WRITE32(iop,virt_to_phys(msg));
+ i2o_quiesce_controller(iop);
+ i2o_reset_controller(iop);
+ i2o_status_get(iop);
+ }
+ }
+
+ /*
+ * Now init the outbound queue for each one.
+ */
+ for(iop = i2o_controller_chain; iop; iop = iop->next)
+ {
+ int i;
+
+ if((ret=i2o_init_outbound_q(iop)))
+ {
+ printk(KERN_ERR
+ "IOP%d initialization failed: Could not initialize outbound q\n",
+ iop->unit);
+ i2o_delete_controller(iop);
+ }
+ iop->page_frame = kmalloc(MSG_POOL_SIZE, GFP_KERNEL);
+
+ if(iop->page_frame==NULL)
+ {
+ printk(KERN_ERR "IOP init failed: no memory for message page.\n");
+ i2o_delete_controller(iop);
+ continue;
+ }
+
+ m=virt_to_phys(iop->page_frame);
+
+ for(i=0; i< NMBR_MSG_FRAMES; i++)
+ {
+ I2O_REPLY_WRITE32(iop,m);
+ mb();
+ m+=MSG_FRAME_SIZE;
+ mb();
+ }
+ }
+
+ /*
+ * OK..parse the HRT
+ */
+ for(iop = i2o_controller_chain; iop; iop = iop->next)
+ {
+ if(i2o_hrt_get(iop))
+ {
+ i2o_delete_controller(iop);
+ break;
+ }
+ if(i2o_parse_hrt(iop))
+ i2o_delete_controller(iop);
+ }
+
+ /*
+ * Build and send the system table
+ */
+ i2o_build_sys_table();
+ for(iop = i2o_controller_chain; iop; iop = iop->next)
+#ifdef DRIVERDEBUG
+ {
+ printk(KERN_INFO "Sending system table to iop%d\n", iop->unit);
+#endif
+ i2o_systab_send(iop);
+#ifdef DRIVERDEBUG
+ }
+#endif
+
+ /*
+ * Enable
+ */
+ for(iop = i2o_controller_chain; iop; iop = iop->next)
+ {
+#ifdef DRIVERDEBUG
+ printk(KERN_INFO "Enableing iop%d\n", iop->unit);
+#endif
+ if(i2o_enable_controller(iop))
+ {
+ printk(KERN_ERR "Could not enable iop%d\n", iop->unit);
+ i2o_delete_controller(iop);
+ }
+ }
+
+ /*
+ * OK..one last thing and we're ready to go!
+ */
+ for(iop = i2o_controller_chain; iop; iop = iop->next)
+ {
+#ifdef DRIVERDEBUG
+ printk(KERN_INFO "Getting LCT for iop%d\n", iop->unit);
+#endif
+ if(i2o_lct_get(iop))
+ {
+ printk(KERN_ERR "Could not get LCT from iop%d\n", iop->unit);
+ i2o_delete_controller(iop);
+ }
+ else
+ i2o_parse_lct(iop);
+ }
}
+/*
+ * Shutdown I2O system
+ *
+ * 1. Quiesce all controllers
+ * 2. Delete all controllers
+ *
+ */
+static void i2o_sys_shutdown(void)
+{
+ struct i2o_controller *iop = NULL;
+
+ i2o_quiesce_system();
+ for(iop = i2o_controller_chain; iop; iop = iop->next)
+ i2o_delete_controller(iop);
+}
/*
* Bring an I2O controller into HOLD state. See the 1.5
@@ -1141,13 +1523,11 @@ int i2o_hrt_get(struct i2o_controller *c)
*
* Send GetHRT, Parse it
*/
-
int i2o_activate_controller(struct i2o_controller *c)
{
- long time;
+ return 0;
+#ifdef I2O_HOTPLUG_SUPPORT
u32 m;
- u8 *workspace;
- u32 *msg;
int i;
int ret;
@@ -1157,7 +1537,8 @@ int i2o_activate_controller(struct i2o_controller *c)
if((ret=i2o_status_get(c)))
return ret;
- if(c->status == ADAPTER_STATE_FAULTED) /* not likely to be seen */
+ /* not likely to be seen */
+ if(c->status_block->iop_state == ADAPTER_STATE_FAULTED)
{
printk(KERN_CRIT "i2o: iop%d has hardware fault\n",
c->unit);
@@ -1165,14 +1546,22 @@ int i2o_activate_controller(struct i2o_controller *c)
}
/*
- * If the board is running, reset it - we have no idea
- * what kind of a mess the previous owner left it in.
+ * If the board is running, reset it - we have no idea
+ * what kind of a mess the previous owner left it in.
+ * We need to feed the IOP a single outbound message
+ * so that it can reply back to the ExecSysQuiesce.
*/
- if(c->status == ADAPTER_STATE_HOLD ||
- c->status == ADAPTER_STATE_READY ||
- c->status == ADAPTER_STATE_OPERATIONAL ||
- c->status == ADAPTER_STATE_FAILED)
+ if(c->status_block->iop_state == ADAPTER_STATE_HOLD ||
+ c->status_block->iop_state == ADAPTER_STATE_READY ||
+ c->status_block->iop_state == ADAPTER_STATE_OPERATIONAL ||
+ c->status_block->iop_state == ADAPTER_STATE_FAILED)
{
+ int msg[256];
+ printk(KERN_INFO "i2o/iop%d already running, reseting\n", c->unit);
+
+ if(i2o_init_outbound_q(c));
+ I2O_REPLY_WRITE32(c,virt_to_phys(msg));
+
if((ret=i2o_reset_controller(c)))
return ret;
@@ -1180,15 +1569,62 @@ int i2o_activate_controller(struct i2o_controller *c)
return ret;
}
- workspace = (void *)kmalloc(88, GFP_KERNEL);
- if(workspace==NULL)
+ if((ret=i2o_init_outbound_q(c)))
+ {
+ printk(KERN_ERR
+ "IOP%d initialization failed: Could not initialize outbound queue\n",
+ c->unit);
+ return ret;
+ }
+
+ /* TODO: v2.0: Set Executive class group 000Bh - OS Operating Info */
+
+ c->page_frame = kmalloc(MSG_POOL_SIZE, GFP_KERNEL);
+ if(c->page_frame==NULL)
{
- printk(KERN_ERR "IOP initialisation failed - no free memory.\n");
+ printk(KERN_ERR "IOP init failed: no memory for message page.\n");
return -ENOMEM;
}
+
+ m=virt_to_phys(c->page_frame);
+
+ for(i=0; i< NMBR_MSG_FRAMES; i++)
+ {
+ I2O_REPLY_WRITE32(c,m);
+ mb();
+ m+=MSG_FRAME_SIZE;
+ mb();
+ }
+
+ /*
+ * The outbound queue is initialised and loaded,
+ *
+ * Now we need the Hardware Resource Table. We must ask for
+ * this next we can't issue random messages yet.
+ */
+ ret=i2o_hrt_get(c); if(ret) return ret;
+
+ ret=i2o_parse_hrt(c);
+ if(ret)
+ return ret;
+
+ return i2o_online_controller(c);
+#endif
+}
+
+/*
+ * Clear and (re)initialize IOP's outbound queue
+ */
+int i2o_init_outbound_q(struct i2o_controller *c)
+{
+ u8 workspace[88];
+ u32 m;
+ u32 *msg;
+ u32 time;
memset(workspace, 0, 88);
+ printk(KERN_INFO "i2o/iop%d: Initializing Outbound Queue\n", c->unit);
m=i2o_wait_message(c, "OutboundInit");
if(m==0xFFFFFFFF)
{
@@ -1211,7 +1647,6 @@ int i2o_activate_controller(struct i2o_controller *c)
/*
* Post it
*/
-
i2o_post_message(c,m);
barrier();
@@ -1222,7 +1657,8 @@ int i2o_activate_controller(struct i2o_controller *c)
{
if((jiffies-time)>=5*HZ)
{
- printk(KERN_ERR "IOP outbound initialise failed.\n");
+ printk(KERN_ERR "i2o/iop%d: IOP outbound initialise failed.\n",
+ c->unit);
kfree(workspace);
return -ETIMEDOUT;
}
@@ -1230,64 +1666,28 @@ int i2o_activate_controller(struct i2o_controller *c)
barrier();
}
- kfree(workspace);
-
- /* TODO: v2.0: Set Executive class group 000Bh - OS Operating Info */
-
- c->page_frame = kmalloc(MSG_POOL_SIZE, GFP_KERNEL);
- if(c->page_frame==NULL)
- {
- printk(KERN_ERR "IOP init failed: no memory for message page.\n");
- return -ENOMEM;
- }
-
- m=virt_to_phys(c->page_frame);
-
- for(i=0; i< NMBR_MSG_FRAMES; i++)
- {
- I2O_REPLY_WRITE32(c,m);
- mb();
- m+=MSG_FRAME_SIZE;
- }
-
- /*
- * The outbound queue is initialised and loaded,
- *
- * Now we need the Hardware Resource Table. We must ask for
- * this next we can't issue random messages yet.
- */
- ret=i2o_hrt_get(c);
- if(ret)
- return ret;
-
- ret=i2o_parse_hrt(c);
- if(ret)
- return ret;
-
- return i2o_online_controller(c);
-// i2o_report_controller_unit(c, ADAPTER_TID);
+ return 0;
}
-
+/*
+ * Get the IOP's Logical Configuration Table
+ */
int i2o_lct_get(struct i2o_controller *c)
{
- u32 m;
- u32 *msg;
+ u32 msg[8];
- m=i2o_wait_message(c, "LCTNotify");
-
- if(m==0xFFFFFFFF)
- return -ETIMEDOUT;
+#ifdef DRIVERDEBUG
+ printk(KERN_INFO "Getting lct for iop%d\n", c->unit);
+#endif
- msg=(u32 *)(c->mem_offset+m);
+ if(c->lct)
+ kfree(c->lct);
c->lct = kmalloc(8192, GFP_KERNEL);
if(c->lct==NULL)
{
- msg[0]=FOUR_WORD_MSG_SIZE|SGL_OFFSET_0;
- msg[1]= HOST_TID<<12|ADAPTER_TID; /* NOP */
- i2o_post_message(c,m);
- printk(KERN_ERR "No free memory for i2o controller buffer.\n");
+ printk(KERN_ERR "i2o/iop%d: No free memory for i2o controller buffer.\n",
+ c->unit);
return -ENOMEM;
}
@@ -1302,25 +1702,8 @@ int i2o_lct_get(struct i2o_controller *c)
msg[6] = 0xD0000000|8192;
msg[7] = virt_to_bus(c->lct);
- i2o_post_message(c,m);
-
- barrier();
-
- /* Now wait for a reply */
- m=i2o_wait_reply(c, "LCTNotify", 5);
-
- if(m==0xFFFFFFFF)
- return -ETIMEDOUT;
-
- msg=(u32 *)bus_to_virt(m);
-
- /* TODO: Check TableSize for big LCTs and send new ExecLctNotify
- * with bigger workspace */
-
- if(msg[4]>>24)
- i2o_report_status(KERN_ERR, "i2o_core", msg);
-
- return 0;
+
+ return(i2o_post_wait(c, msg, sizeof(msg), 120));
}
@@ -1330,13 +1713,14 @@ int i2o_lct_get(struct i2o_controller *c)
int i2o_online_controller(struct i2o_controller *c)
{
- u32 m;
- u32 *msg;
- u32 systab[32];
+ return 0;
+#ifdef I2O_HOTPLUG_SUPPORT
+ u32 msg[10];
u32 privmem[2];
u32 privio[2];
+ u32 systab[32];
int ret;
-
+
systab[0]=1;
systab[1]=0;
systab[2]=0;
@@ -1350,103 +1734,45 @@ int i2o_online_controller(struct i2o_controller *c)
systab[10]=virt_to_phys(c->post_port);
systab[11]=0;
+ i2o_build_sys_table();
+
privmem[0]=c->priv_mem; /* Private memory space base address */
privmem[1]=c->priv_mem_size;
privio[0]=c->priv_io; /* Private I/O address */
privio[1]=c->priv_io_size;
-
- m=i2o_wait_message(c, "SysTabSet");
- if(m==0xFFFFFFFF)
- return -ETIMEDOUT;
-
- /* Now we build the systab */
- msg=(u32 *)(c->mem_offset+m);
-
+
msg[0] = NINE_WORD_MSG_SIZE|SGL_OFFSET_6;
msg[1] = I2O_CMD_SYS_TAB_SET<<24 | HOST_TID<<12 | ADAPTER_TID;
msg[2] = 0; /* Context not needed */
msg[3] = 0;
- msg[4] = (1<<16)|(2<<12); /* Host 1 I2O 2 */
- msg[5] = 1; /* Segment 1 */
+ msg[4] = (0<<16)|(2<<12); /* Host 1 I2O 2 */
+ msg[5] = 0; /* Segment 1 */
/*
* Scatter Gather List
*/
-
- msg[6] = 0x54000000|48; /* One table for now */
- msg[7] = virt_to_phys(systab);
+ msg[6] = 0x54000000|sys_tbl_len; /* One table for now */
+ msg[7] = virt_to_phys(sys_tbl);
msg[8] = 0xD4000000|48; /* One table for now */
msg[9] = virt_to_phys(privmem);
-/* msg[10] = virt_to_phys(privio); */
-
- i2o_post_message(c,m);
+/* msg[10] = virt_to_phys(privio); */
- barrier();
-
- /*
- * Now wait for a reply
- */
-
-
- m=i2o_wait_reply(c, "SysTabSet", 5);
-
- if(m==0xFFFFFFFF)
- return -ETIMEDOUT;
-
- msg=(u32 *)bus_to_virt(m);
-
- if(msg[4]>>24)
- {
- i2o_report_status(KERN_ERR, "i2o_core", msg);
- }
- I2O_REPLY_WRITE32(c,m);
+ return(i2o_post_wait(c, msg, sizeof(msg), 120));
/*
* Finally we go online
*/
-
- m=i2o_wait_message(c, "SysEnable");
-
- if(m==0xFFFFFFFF)
- return -ETIMEDOUT;
-
- msg=(u32 *)(c->mem_offset+m);
-
- msg[0] = FOUR_WORD_MSG_SIZE|SGL_OFFSET_0;
- msg[1] = I2O_CMD_SYS_ENABLE<<24 | HOST_TID<<12 | ADAPTER_TID;
- msg[2] = 0; /* Context not needed */
- msg[3] = 0;
-
- i2o_post_message(c,m);
-
- barrier();
-
- /*
- * Now wait for a reply
- */
-
-
- m=i2o_wait_reply(c, "SysEnable", 240);
-
- if(m==0xFFFFFFFF)
- return -ETIMEDOUT;
-
- msg=(u32 *)bus_to_virt(m);
-
- if(msg[4]>>24)
- {
- i2o_report_status(KERN_ERR, "i2o_core", msg);
- }
- I2O_REPLY_WRITE32(c,m);
+ ret = i2o_enable_controller(c);
+ if(ret)
+ return ret;
/*
* Grab the LCT, see what is attached
*/
-
ret=i2o_lct_get(c);
if(ret)
{
- /* Maybe we should do also sthg else */
+ /* Maybe we should do also do something else */
return ret;
}
@@ -1454,11 +1780,73 @@ int i2o_online_controller(struct i2o_controller *c)
if(ret)
return ret;
- I2O_REPLY_WRITE32(c,m);
-
return 0;
+#endif
}
+static int i2o_build_sys_table(void)
+{
+ struct i2o_controller *iop = NULL;
+ int count = 0;
+#ifdef DRIVERDEBUG
+ u32 *table;
+#endif
+
+ sys_tbl_len = sizeof(struct i2o_sys_tbl) + // Header + IOPs
+ (i2o_num_controllers) *
+ sizeof(struct i2o_sys_tbl_entry);
+
+#ifdef DRIVERDEBUG
+ printk(KERN_INFO "Building system table len = %d\n", sys_tbl_len);
+#endif
+ if(sys_tbl)
+ kfree(sys_tbl);
+
+ sys_tbl = kmalloc(sys_tbl_len, GFP_KERNEL);
+ if(!sys_tbl)
+ return -ENOMEM;
+ memset((void*)sys_tbl, 0, sys_tbl_len);
+
+ sys_tbl->num_entries = i2o_num_controllers;
+ sys_tbl->version = I2OVERSION; /* TODO: Version 2.0 */
+ sys_tbl->change_ind = sys_tbl_ind++;
+
+ for(iop = i2o_controller_chain; iop; iop = iop->next)
+ {
+ // Get updated IOP state so we have the latest information
+ i2o_status_get(iop);
+
+ sys_tbl->iops[count].org_id = iop->status_block->org_id;
+ sys_tbl->iops[count].iop_id = iop->unit + 2;
+ sys_tbl->iops[count].seg_num = 0;
+ sys_tbl->iops[count].i2o_version =
+ iop->status_block->i2o_version;
+ sys_tbl->iops[count].iop_state =
+ iop->status_block->iop_state;
+ sys_tbl->iops[count].msg_type =
+ iop->status_block->msg_type;
+ sys_tbl->iops[count].frame_size =
+ iop->status_block->inbound_frame_size;
+ sys_tbl->iops[count].last_changed = sys_tbl_ind - 1; // ??
+ sys_tbl->iops[count].iop_capabilities =
+ iop->status_block->iop_capabilities;
+ sys_tbl->iops[count].inbound_low =
+ (u32)virt_to_phys(iop->post_port);
+ sys_tbl->iops[count].inbound_high = 0; // TODO: 64-bit support
+
+ count++;
+ }
+
+#ifdef DRIVERDEBUG
+ table = (u32*)sys_tbl;
+ for(count = 0; count < (sys_tbl_len >>2); count++)
+ printk(KERN_INFO "sys_tbl[%d] = %0#10x\n", count, table[count]);
+#endif
+
+ return 0;
+}
+
+
/*
* Run time support routines
*/
@@ -1469,11 +1857,11 @@ int i2o_online_controller(struct i2o_controller *c)
* this is simply not worth optimising
*/
-int i2o_post_this(struct i2o_controller *c, int tid, u32 *data, int len)
+int i2o_post_this(struct i2o_controller *c, u32 *data, int len)
{
u32 m;
u32 *msg;
- unsigned long t=jiffies;
+ unsigned long t=jiffies;
do
{
@@ -1485,8 +1873,9 @@ int i2o_post_this(struct i2o_controller *c, int tid, u32 *data, int len)
if(m==0xFFFFFFFF)
{
- printk(KERN_ERR "i2o: controller not responding.\n");
- return -1;
+ printk(KERN_ERR "i2o/iop%d: Timeout waiting for message frame!\n",
+ c->unit);
+ return -ETIMEDOUT;
}
msg = bus_to_virt(c->mem_offset + m);
memcpy(msg, data, len);
@@ -1495,32 +1884,114 @@ int i2o_post_this(struct i2o_controller *c, int tid, u32 *data, int len)
}
/*
- * Post a message and wait for a response flag to be set. This API will
- * change to use wait_queue's one day
+ * Post a message and wait for a response flag to be set.
*/
-
-int i2o_post_wait(struct i2o_controller *c, int tid, u32 *data, int len, int *flag, int timeout)
+int i2o_post_wait(struct i2o_controller *c, u32 *msg, int len, int timeout)
{
- unsigned long t=jiffies;
+ DECLARE_WAIT_QUEUE_HEAD(wq_i2o_post);
+ int status = 0;
+ int flags = 0;
+ int ret = 0;
+ struct i2o_post_wait_data *p1, *p2;
+ struct i2o_post_wait_data *wait_data =
+ kmalloc(sizeof(struct i2o_post_wait_data), GFP_KERNEL);
+
+ if(!wait_data)
+ return -ETIMEDOUT;
+
+ p1 = p2 = NULL;
- *flag = 0;
-
- if(i2o_post_this(c, tid, data, len))
- return I2O_POST_WAIT_TIMEOUT;
-
- while(!*flag && (jiffies-t)<timeout*HZ)
+ /*
+ * The spin locking is needed to keep anyone from playing
+ * with the queue pointers and id while we do the same
+ */
+ spin_lock_irqsave(&post_wait_lock, flags);
+ wait_data->next = post_wait_queue;
+ post_wait_queue = wait_data;
+ wait_data->id = ++post_wait_id;
+ spin_unlock_irqrestore(&post_wait_lock, flags);
+
+ wait_data->wq = &wq_i2o_post;
+ wait_data->status = -ETIMEDOUT;
+
+ msg[3] = (u32)wait_data->id;
+ msg[2] = 0x80000000|(u32)core_context;
+
+ if((ret=i2o_post_this(c, msg, len)))
+ return ret;
+ /*
+ * Go to sleep and wait for timeout or wake_up call
+ */
+ interruptible_sleep_on_timeout(&wq_i2o_post, HZ * timeout);
+
+ /*
+ * Grab transaction status
+ */
+ status = wait_data->status;
+
+ /*
+ * Remove the entry from the queue.
+ * Since i2o_post_wait() may have been called again by
+ * a different thread while we were waiting for this
+ * instance to complete, we're not guaranteed that
+ * this entry is at the head of the queue anymore, so
+ * we need to search for it, find it, and delete it.
+ */
+ spin_lock_irqsave(&post_wait_lock, flags);
+ for(p1 = post_wait_queue; p1; )
{
- schedule();
- mb();
+ if(p1 == wait_data)
+ {
+ if(p2)
+ p2->next = p1->next;
+ else
+ post_wait_queue = p1->next;
+
+ break;
+ }
+ p1 = p1->next;
}
+ spin_unlock_irqrestore(&post_wait_lock, flags);
+
+ kfree(wait_data);
- if (*flag < 0)
- return *flag; /* DetailedStatus */
+ return status;
+}
- if (*flag == 0)
- return I2O_POST_WAIT_TIMEOUT;
-
- return I2O_POST_WAIT_OK;
+/*
+ * i2o_post_wait is completed and we want to wake up the
+ * sleeping proccess. Called by core's reply handler.
+ */
+static void i2o_post_wait_complete(u32 context, int status)
+{
+ struct i2o_post_wait_data *p1 = NULL;
+
+ /*
+ * We need to search through the post_wait
+ * queue to see if the given message is still
+ * outstanding. If not, it means that the IOP
+ * took longer to respond to the message than we
+ * had allowed and timer has already expired.
+ * Not much we can do about that except log
+ * it for debug purposes, increase timeout, and recompile
+ *
+ * Lock needed to keep anyone from moving queue pointers
+ * around while we're looking through them.
+ */
+ spin_lock(&post_wait_lock);
+ for(p1 = post_wait_queue; p1; p1 = p1->next)
+ {
+ if(p1->id == context)
+ {
+ p1->status = status;
+ wake_up_interruptible(p1->wq);
+ spin_unlock(&post_wait_lock);
+ return;
+ }
+ }
+ spin_unlock(&post_wait_lock);
+
+ printk(KERN_DEBUG "i2o_post_wait reply after timeout!");
}
/*
@@ -1543,7 +2014,7 @@ int i2o_issue_claim(struct i2o_controller *c, int tid, int context, int onoff, i
msg[3] = (u32)flag;
msg[4] = type;
- return i2o_post_wait(c, tid, msg, 20, flag,2);
+ return i2o_post_wait(c, msg, 20, 2);
}
/* Issue UTIL_PARAMS_GET or UTIL_PARAMS_SET
@@ -1554,60 +2025,56 @@ int i2o_issue_claim(struct i2o_controller *c, int tid, int context, int onoff, i
* Note that the minimum sized resblk is 8 bytes and contains
* ResultCount, ErrorInfoSize, BlockStatus and BlockSize.
*/
-int i2o_issue_params(int cmd,
- struct i2o_controller *iop, int tid, int context,
- void *opblk, int oplen, void *resblk, int reslen,
- int *flag)
+int i2o_issue_params(int cmd, struct i2o_controller *iop, int tid,
+ void *opblk, int oplen, void *resblk, int reslen)
{
- u32 msg[9];
+u32 msg[9];
u8 *res = (u8 *)resblk;
int res_count;
int blk_size;
int bytes;
int wait_status;
- msg[0] = NINE_WORD_MSG_SIZE | SGL_OFFSET_5;
- msg[1] = cmd << 24 | HOST_TID << 12 | tid;
- msg[2] = context | 0x80000000;
- msg[3] = (u32)flag;
- msg[4] = 0;
- msg[5] = 0x54000000 | oplen; /* OperationBlock */
- msg[6] = virt_to_bus(opblk);
- msg[7] = 0xD0000000 | reslen; /* ResultBlock */
- msg[8] = virt_to_bus(resblk);
-
- wait_status = i2o_post_wait(iop, tid, msg, sizeof(msg), flag, 10);
- if (wait_status < 0)
- return wait_status; /* -DetailedStatus */
-
- if (res[1]&0x00FF0000) /* BlockStatus != SUCCESS */
- {
- printk(KERN_WARNING "%s - Error:\n ErrorInfoSize = 0x%02x, "
- "BlockStatus = 0x%02x, BlockSize = 0x%04x\n",
- (cmd == I2O_CMD_UTIL_PARAMS_SET) ? "PARAMS_SET"
- : "PARAMS_GET",
- res[1]>>24, (res[1]>>16)&0xFF, res[1]&0xFFFF);
- return -((res[1] >> 16) & 0xFF); /* -BlockStatus */
- }
+ msg[0] = NINE_WORD_MSG_SIZE | SGL_OFFSET_5;
+ msg[1] = cmd << 24 | HOST_TID << 12 | tid;
+ msg[4] = 0;
+ msg[5] = 0x54000000 | oplen; /* OperationBlock */
+ msg[6] = virt_to_bus(opblk);
+ msg[7] = 0xD0000000 | reslen; /* ResultBlock */
+ msg[8] = virt_to_bus(resblk);
+
+ wait_status = i2o_post_wait(iop, msg, sizeof(msg), 10);
+ if (wait_status)
+ return wait_status; /* -DetailedStatus */
- res_count = res[0] & 0xFFFF; /* # of resultblocks */
- bytes = 4;
- res += 4;
- while (res_count--)
+ if (res[1]&0x00FF0000) /* BlockStatus != SUCCESS */
+ {
+ printk(KERN_WARNING "%s - Error:\n ErrorInfoSize = 0x%02x, "
+ "BlockStatus = 0x%02x, BlockSize = 0x%04x\n",
+ (cmd == I2O_CMD_UTIL_PARAMS_SET) ? "PARAMS_SET"
+ : "PARAMS_GET",
+ res[1]>>24, (res[1]>>16)&0xFF, res[1]&0xFFFF);
+ return -((res[1] >> 16) & 0xFF); /* -BlockStatus */
+ }
+
+ res_count = res[0] & 0xFFFF; /* # of resultblocks */
+ bytes = 4;
+ res += 4;
+ while (res_count--)
{
blk_size = (res[0] & 0xFFFF) << 2;
bytes += blk_size;
res += blk_size;
}
-
- return bytes; /* total sizeof Result List in bytes */
+
+ return bytes; /* total sizeof Result List in bytes */
}
/*
* Query one scalar group value or a whole scalar group.
*/
-int i2o_query_scalar(struct i2o_controller *iop, int tid, int context,
- int group, int field, void *buf, int buflen, int *flag)
+int i2o_query_scalar(struct i2o_controller *iop, int tid,
+ int group, int field, void *buf, int buflen)
{
u16 opblk[] = { 1, 0, I2O_PARAMS_FIELD_GET, group, 1, field };
u8 resblk[8+buflen]; /* 8 bytes for header */
@@ -1616,8 +2083,8 @@ int i2o_query_scalar(struct i2o_controller *iop, int tid, int context,
if (field == -1) /* whole group */
opblk[4] = -1;
- size = i2o_issue_params(I2O_CMD_UTIL_PARAMS_GET, iop, tid, context,
- opblk, sizeof(opblk), resblk, sizeof(resblk), flag);
+ size = i2o_issue_params(I2O_CMD_UTIL_PARAMS_GET, iop, tid,
+ opblk, sizeof(opblk), resblk, sizeof(resblk));
if (size < 0)
return size;
@@ -1629,38 +2096,38 @@ int i2o_query_scalar(struct i2o_controller *iop, int tid, int context,
/*
* Set a scalar group value or a whole group.
*/
-int i2o_set_scalar(struct i2o_controller *iop, int tid, int context,
- int group, int field, void *buf, int buflen, int *flag)
+int i2o_set_scalar(struct i2o_controller *iop, int tid,
+ int group, int field, void *buf, int buflen)
{
u16 *opblk;
u8 resblk[8+buflen]; /* 8 bytes for header */
int size;
- opblk = kmalloc(buflen+64, GFP_KERNEL);
- if (opblk == NULL)
- {
- printk(KERN_ERR "i2o: no memory for operation buffer.\n");
- return -ENOMEM;
- }
+ opblk = kmalloc(buflen+64, GFP_KERNEL);
+ if (opblk == NULL)
+ {
+ printk(KERN_ERR "i2o: no memory for operation buffer.\n");
+ return -ENOMEM;
+ }
- opblk[0] = 1; /* operation count */
- opblk[1] = 0; /* pad */
- opblk[2] = I2O_PARAMS_FIELD_SET;
- opblk[3] = group;
+ opblk[0] = 1; /* operation count */
+ opblk[1] = 0; /* pad */
+ opblk[2] = I2O_PARAMS_FIELD_SET;
+ opblk[3] = group;
- if(field == -1) { /* whole group */
- opblk[4] = -1;
- memcpy(opblk+5, buf, buflen);
- }
- else /* single field */
- {
- opblk[4] = 1;
- opblk[5] = field;
- memcpy(opblk+6, buf, buflen);
- }
+ if(field == -1) { /* whole group */
+ opblk[4] = -1;
+ memcpy(opblk+5, buf, buflen);
+ }
+ else /* single field */
+ {
+ opblk[4] = 1;
+ opblk[5] = field;
+ memcpy(opblk+6, buf, buflen);
+ }
- size = i2o_issue_params(I2O_CMD_UTIL_PARAMS_SET, iop, tid, context,
- opblk, 12+buflen, resblk, sizeof(resblk), flag);
+ size = i2o_issue_params(I2O_CMD_UTIL_PARAMS_SET, iop, tid,
+ opblk, 12+buflen, resblk, sizeof(resblk));
kfree(opblk);
return size;
@@ -1687,10 +2154,9 @@ int i2o_set_scalar(struct i2o_controller *iop, int tid, int context,
*
* You could also use directly function i2o_issue_params().
*/
-int i2o_query_table(int oper,
- struct i2o_controller *iop, int tid, int context, int group,
+int i2o_query_table(int oper, struct i2o_controller *iop, int tid, int group,
int fieldcount, void *ibuf, int ibuflen,
- void *resblk, int reslen, int *flag)
+ void *resblk, int reslen)
{
u16 *opblk;
int size;
@@ -1709,8 +2175,8 @@ int i2o_query_table(int oper,
opblk[4] = fieldcount;
memcpy(opblk+5, ibuf, ibuflen); /* other params */
- size = i2o_issue_params(I2O_CMD_UTIL_PARAMS_GET,iop, tid, context,
- opblk, 10+ibuflen, resblk, reslen, flag);
+ size = i2o_issue_params(I2O_CMD_UTIL_PARAMS_GET,iop, tid,
+ opblk, 10+ibuflen, resblk, reslen);
kfree(opblk);
return size;
@@ -1720,14 +2186,13 @@ int i2o_query_table(int oper,
* Clear table group, i.e. delete all rows.
*/
-int i2o_clear_table(struct i2o_controller *iop, int tid, int context,
- int group, int *flag)
+int i2o_clear_table(struct i2o_controller *iop, int tid, int group)
{
u16 opblk[] = { 1, 0, I2O_PARAMS_TABLE_CLEAR, group };
u8 resblk[32]; /* min 8 bytes for result header */
- return i2o_issue_params(I2O_CMD_UTIL_PARAMS_SET, iop, tid, context,
- opblk, sizeof(opblk), resblk, sizeof(resblk), flag);
+ return i2o_issue_params(I2O_CMD_UTIL_PARAMS_SET, iop, tid,
+ opblk, sizeof(opblk), resblk, sizeof(resblk));
}
/*
@@ -1739,9 +2204,8 @@ int i2o_clear_table(struct i2o_controller *iop, int tid, int context,
* buf contains fieldindexes, rowcount, keyvalues
*/
-int i2o_row_add_table(struct i2o_controller *iop, int tid, int context,
- int group, int fieldcount, void *buf, int buflen,
- int *flag)
+int i2o_row_add_table(struct i2o_controller *iop, int tid,
+ int group, int fieldcount, void *buf, int buflen)
{
u16 *opblk;
u8 resblk[32]; /* min 8 bytes for header */
@@ -1761,8 +2225,8 @@ int i2o_row_add_table(struct i2o_controller *iop, int tid, int context,
opblk[4] = fieldcount;
memcpy(opblk+5, buf, buflen);
- size = i2o_issue_params(I2O_CMD_UTIL_PARAMS_SET, iop, tid, context,
- opblk, 10+buflen, resblk, sizeof(resblk), flag);
+ size = i2o_issue_params(I2O_CMD_UTIL_PARAMS_SET, iop, tid,
+ opblk, 10+buflen, resblk, sizeof(resblk));
kfree(opblk);
return size;
@@ -1772,9 +2236,8 @@ int i2o_row_add_table(struct i2o_controller *iop, int tid, int context,
* Delete rows from a table group.
*/
-int i2o_row_delete_table(struct i2o_controller *iop, int tid, int context,
- int group, int keycount, void *keys, int keyslen,
- int *flag)
+int i2o_row_delete_table(struct i2o_controller *iop, int tid,
+ int group, int keycount, void *keys, int keyslen)
{
u16 *opblk;
u8 resblk[32]; /* min 8 bytes for header */
@@ -1794,8 +2257,8 @@ int i2o_row_delete_table(struct i2o_controller *iop, int tid, int context,
opblk[4] = keycount;
memcpy(opblk+5, keys, keyslen);
- size = i2o_issue_params(I2O_CMD_UTIL_PARAMS_SET, iop, tid, context,
- opblk, 10+keyslen, resblk, sizeof(resblk), flag);
+ size = i2o_issue_params(I2O_CMD_UTIL_PARAMS_SET, iop, tid,
+ opblk, 10+keyslen, resblk, sizeof(resblk));
kfree(opblk);
return size;
@@ -2134,9 +2597,10 @@ static void i2o_dump_message(u32 *msg)
#ifdef DRIVERDEBUG
int i;
- printk(KERN_INFO "Dumping I2O message @ %p\n", msg);
+ printk(KERN_INFO "Dumping I2O message size %d @ %p\n",
+ msg[0]>>16&0xffff, msg);
for(i = 0; i < ((msg[0]>>16)&0xffff); i++)
- printk(KERN_INFO "\tmsg[%d] = %#10x\n", i, msg[i]);
+ printk(KERN_INFO " msg[%d] = %0#10x\n", i, msg[i]);
#endif
}
@@ -2181,27 +2645,35 @@ MODULE_DESCRIPTION("I2O Core");
int init_module(void)
{
+ printk(KERN_INFO "I2O Core - (C) Copyright 1999 Red Hat Software\n");
if (i2o_install_handler(&i2o_core_handler) < 0)
{
- printk(KERN_ERR "i2o_core: Unable to install core handler.\n");
+ printk(KERN_ERR
+ "i2o_core: Unable to install core handler.\nI2O stack not loaded!");
return 0;
}
core_context = i2o_core_handler.context;
/*
- * Attach core to I2O PCI subsystem
+ * Attach core to I2O PCI transport (and others as they are developed)
*/
#ifdef CONFIG_I2O_PCI_MODULE
if(i2o_pci_core_attach(&i2o_core_functions) < 0)
printk(KERN_INFO "No PCI I2O controllers found\n");
#endif
+ if(i2o_num_controllers)
+ i2o_sys_init();
+
return 0;
}
void cleanup_module(void)
{
+ if(i2o_num_controllers)
+ i2o_sys_shutdown();
+
#ifdef CONFIG_I2O_PCI_MODULE
i2o_pci_core_detach();
#endif
@@ -2220,16 +2692,23 @@ extern int i2o_scsi_init(void);
int __init i2o_init(void)
{
- if (i2o_install_handler(&i2o_core_handler) < 0)
- {
- printk(KERN_ERR "i2o_core: Unable to install core handler.\n");
- return 0;
- }
+ printk(KERN_INFO "Loading I2O Core - (c) Copyright 1999 Red Hat Software\n");
+ if (i2o_install_handler(&i2o_core_handler) < 0)
+ {
+ printk(KERN_ERR
+ "i2o_core: Unable to install core handler.\nI2O stack not loaded!");
+ return 0;
+ }
+
+ core_context = i2o_core_handler.context;
- core_context = i2o_core_handler.context;
#ifdef CONFIG_I2O_PCI
i2o_pci_init();
#endif
+
+ if(i2o_num_controllers)
+ i2o_init();
+
i2o_config_init();
#ifdef CONFIG_I2O_BLOCK
i2o_block_init();
diff --git a/drivers/i2o/i2o_lan.c b/drivers/i2o/i2o_lan.c
index 087ee84bd..60798606a 100644
--- a/drivers/i2o/i2o_lan.c
+++ b/drivers/i2o/i2o_lan.c
@@ -302,7 +302,7 @@ static int i2o_lan_receive_post(struct net_device *dev, u32 count)
: count - total;
msg[0] = I2O_MESSAGE_SIZE(4 + 3 * bucket_count) | SGL_OFFSET_4;
- msg[1] = LAN_RECEIVE_POST<<24 | HOST_TID<<12 | i2o_dev->id;
+ msg[1] = LAN_RECEIVE_POST<<24 | HOST_TID<<12 | i2o_dev->lct_data->tid;
msg[2] = priv->unit << 16 | lan_context; // InitiatorContext
msg[3] = bucket_count; // BucketCount
@@ -343,12 +343,12 @@ static int i2o_lan_reset(struct net_device *dev)
u32 msg[5];
msg[0] = FIVE_WORD_MSG_SIZE | SGL_OFFSET_0;
- msg[1] = LAN_RESET<<24 | HOST_TID<<12 | i2o_dev->id;
+ msg[1] = LAN_RESET<<24 | HOST_TID<<12 | i2o_dev->lct_data->tid;
msg[2] = priv->unit << 16 | lan_context; // InitiatorContext
msg[3] = 0; // TransactionContext
msg[4] = 1 << 16; // return posted buckets
- if (i2o_post_this(iop, i2o_dev->id, msg, sizeof(msg)) < 0)
+ if (i2o_post_this(iop, msg, sizeof(msg)) < 0)
return -ETIMEDOUT;
return 0;
@@ -368,12 +368,12 @@ static int i2o_lan_suspend(struct net_device *dev)
dprintk( "%s: LAN SUSPEND MESSAGE\n", dev->name );
msg[0] = FIVE_WORD_MSG_SIZE | SGL_OFFSET_0;
- msg[1] = LAN_SUSPEND<<24 | HOST_TID<<12 | i2o_dev->id;
+ msg[1] = LAN_SUSPEND<<24 | HOST_TID<<12 | i2o_dev->lct_data->tid;
msg[2] = priv->unit << 16 | lan_context; // InitiatorContext
msg[3] = 0; // TransactionContext
msg[4] = 1 << 16; // return posted buckets
- if (i2o_post_this(iop, i2o_dev->id, msg, sizeof(msg)) < 0)
+ if (i2o_post_this(iop, msg, sizeof(msg))< 0)
return -ETIMEDOUT;
return 0;
@@ -400,8 +400,7 @@ static void i2o_set_batch_mode(struct net_device *dev)
// enable batch mode, toggle automatically
val = 0x00000000;
// val = 0x00000001; // turn off batch mode
- if (i2o_set_scalar(iop, i2o_dev->id, priv->unit << 16 | lan_context, 0x0003, 0,
- &val, 4, &priv->reply_flag) <0)
+ if (i2o_set_scalar(iop, i2o_dev->lct_data->tid, 0x0003, 0, &val, 4) < 0)
printk(KERN_WARNING "Unable to enter I2O LAN batch mode.\n");
else
dprintk(KERN_INFO "%s: I2O LAN batch mode enabled.\n",dev->name);
@@ -414,8 +413,7 @@ static void i2o_set_batch_mode(struct net_device *dev)
/* set LAN_OPERATION attributes */
val = dev->mtu + dev->hard_header_len; // PacketOrphanLimit
- if (i2o_set_scalar(iop, i2o_dev->id, priv->unit << 16 | lan_context, 0x0004, 2,
- &val, 4, &priv->reply_flag) < 0)
+ if (i2o_set_scalar(iop, i2o_dev->lct_data->tid, 0x0004, 2, &val, 4))
printk(KERN_WARNING "i2o_lan: Unable to set PacketOrphanLimit.\n");
else
dprintk(KERN_INFO "%s: PacketOrphanLimit set to %d\n",
@@ -438,7 +436,7 @@ static int i2o_lan_open(struct net_device *dev)
printk(KERN_WARNING "%s: Unable to claim the I2O LAN device.\n", dev->name);
return -EAGAIN;
}
- dprintk(KERN_INFO "%s: I2O LAN device claimed (tid=%d).\n", dev->name, i2o_dev->id);
+ dprintk(KERN_INFO "%s: I2O LAN device claimed (tid=%d).\n", dev->name, i2o_dev->lct_data->tid);
i2o_lan_reset(dev);
@@ -467,7 +465,7 @@ static int i2o_lan_close(struct net_device *dev)
if(i2o_release_device(i2o_dev, &i2o_lan_handler, I2O_CLAIM_PRIMARY))
printk(KERN_WARNING "%s: Unable to unclaim I2O LAN device "
- "(tid=%d)\n", dev->name, i2o_dev->id);
+ "(tid=%d)\n", dev->name, i2o_dev->lct_data->tid);
MOD_DEC_USE_COUNT;
@@ -521,7 +519,7 @@ static int i2o_lan_packet_send(struct sk_buff *skb, struct net_device *dev)
msg = bus_to_virt(iop->mem_offset + m);
msg[0] = SEVEN_WORD_MSG_SIZE | 1<<12 | SGL_OFFSET_4;
- msg[1] = LAN_PACKET_SEND<<24 | HOST_TID<<12 | i2o_dev->id;
+ msg[1] = LAN_PACKET_SEND<<24 | HOST_TID<<12 | i2o_dev->lct_data->tid;
msg[2] = priv->unit << 16 | lan_context; // IntiatorContext
msg[3] = 1 << 4; // TransmitControlWord
@@ -554,8 +552,8 @@ static struct net_device_stats *i2o_lan_get_stats(struct net_device *dev)
u64 val64[16];
u64 supported_group[4] = { 0, 0, 0, 0 };
- if (i2o_query_scalar(iop, i2o_dev->id, priv->unit << 16 | lan_context, 0x0100, -1,
- val64, sizeof(val64), &priv->reply_flag) < 0)
+ if (i2o_query_scalar(iop, i2o_dev->lct_data->tid, 0x0100, -1,
+ val64, sizeof(val64)) < 0)
printk("%s: Unable to query LAN_HISTORICAL_STATS.\n",dev->name);
else {
dprintk("%s: LAN_HISTORICAL_STATS queried.\n",dev->name);
@@ -568,13 +566,13 @@ static struct net_device_stats *i2o_lan_get_stats(struct net_device *dev)
priv->stats.rx_dropped = val64[6];
}
- if (i2o_query_scalar(iop, i2o_dev->id, priv->unit << 16 | lan_context, 0x0180, -1,
- &supported_group, sizeof(supported_group), &priv->reply_flag) < 0)
+ if (i2o_query_scalar(iop, i2o_dev->lct_data->tid, 0x0180, -1,
+ &supported_group, sizeof(supported_group)) < 0)
printk("%s: Unable to query LAN_SUPPORTED_OPTIONAL_HISTORICAL_STATS.\n",dev->name);
if (supported_group[2]) {
- if (i2o_query_scalar(iop, i2o_dev->id, priv->unit << 16 | lan_context, 0x0183, -1,
- val64, sizeof(val64), &priv->reply_flag) < 0)
+ if (i2o_query_scalar(iop, i2o_dev->lct_data->tid, 0x0183, -1,
+ val64, sizeof(val64) ) < 0)
printk("%s: Unable to query LAN_OPTIONAL_RX_HISTORICAL_STATS.\n",dev->name);
else {
dprintk("%s: LAN_OPTIONAL_RX_HISTORICAL_STATS queried.\n",dev->name);
@@ -584,12 +582,12 @@ static struct net_device_stats *i2o_lan_get_stats(struct net_device *dev)
}
}
- if (i2o_dev->subclass == I2O_LAN_ETHERNET)
+ if (i2o_dev->lct_data->sub_class == I2O_LAN_ETHERNET)
{
u64 supported_stats = 0;
- if (i2o_query_scalar(iop, i2o_dev->id, priv->unit << 16 | lan_context, 0x0200, -1,
- val64, sizeof(val64), &priv->reply_flag) < 0)
+ if (i2o_query_scalar(iop, i2o_dev->lct_data->tid, 0x0200, -1,
+ val64, sizeof(val64)) < 0)
printk("%s: Unable to query LAN_802_3_HISTORICAL_STATS.\n",dev->name);
else {
dprintk("%s: LAN_802_3_HISTORICAL_STATS queried.\n",dev->name);
@@ -598,13 +596,13 @@ static struct net_device_stats *i2o_lan_get_stats(struct net_device *dev)
priv->stats.tx_carrier_errors = val64[6];
}
- if (i2o_query_scalar(iop, i2o_dev->id, priv->unit << 16 | lan_context, 0x0280, -1,
- &supported_stats, 8, &priv->reply_flag) < 0)
+ if (i2o_query_scalar(iop, i2o_dev->lct_data->tid, 0x0280, -1,
+ &supported_stats, 8) < 0)
printk("%s: Unable to query LAN_SUPPORTED_802_3_HISTORICAL_STATS\n", dev->name);
if (supported_stats != 0) {
- if (i2o_query_scalar(iop, i2o_dev->id, priv->unit << 16 | lan_context, 0x0281, -1,
- val64, sizeof(val64), &priv->reply_flag) < 0)
+ if (i2o_query_scalar(iop, i2o_dev->lct_data->tid, 0x0281, -1,
+ val64, sizeof(val64)) < 0)
printk("%s: Unable to query LAN_OPTIONAL_802_3_HISTORICAL_STATS.\n",dev->name);
else {
dprintk("%s: LAN_OPTIONAL_802_3_HISTORICAL_STATS queried.\n",dev->name);
@@ -618,10 +616,10 @@ static struct net_device_stats *i2o_lan_get_stats(struct net_device *dev)
}
#ifdef CONFIG_TR
- if (i2o_dev->subclass == I2O_LAN_TR)
+ if (i2o_dev->lct_data->sub_class == I2O_LAN_TR)
{
- if (i2o_query_scalar(iop, i2o_dev->id, priv->unit << 16 | lan_context, 0x0300, -1,
- val64, sizeof(val64), &priv->reply_flag) < 0)
+ if (i2o_query_scalar(iop, i2o_dev->lct_data->tid, 0x0300, -1,
+ val64, sizeof(val64)) < 0)
printk("%s: Unable to query LAN_802_5_HISTORICAL_STATS.\n",dev->name);
else {
struct tr_statistics *stats =
@@ -644,10 +642,10 @@ static struct net_device_stats *i2o_lan_get_stats(struct net_device *dev)
#endif
#ifdef CONFIG_FDDI
- if (i2o_dev->subclass == I2O_LAN_FDDI)
+ if (i2o_dev->lct_data->sub_class == I2O_LAN_FDDI)
{
- if (i2o_query_scalar(iop, i2o_dev->id, priv->unit << 16 | lan_context, 0x0400, -1,
- val64, sizeof(val64), &priv->reply_flag) < 0)
+ if (i2o_query_scalar(iop, i2o_dev->lct_data->tid, 0x0400, -1,
+ val64, sizeof(val64)) < 0)
printk("%s: Unable to query LAN_FDDI_HISTORICAL_STATS.\n",dev->name);
else {
// dprintk("%s: LAN_FDDI_HISTORICAL_STATS queried.\n",dev->name);
@@ -691,8 +689,8 @@ return;
* *because its trying to sleep in an irq - this must be async - Alan
*/
- if (i2o_query_scalar(iop, i2o_dev->id, priv->unit << 16 | lan_context, 0x0001, -1,
- &work32, sizeof(work32), &priv->reply_flag) < 0 )
+ if (i2o_query_scalar(iop, i2o_dev->lct_data->tid, 0x0001, -1,
+ &work32, sizeof(work32)) < 0)
{
printk(KERN_WARNING "i2o_lan: Unable to query "
" LAN_MAC_ADDRESS table.\n");
@@ -734,12 +732,11 @@ return;
mclist = mclist->next;
}
- if (i2o_clear_table(iop, i2o_dev->id, priv->unit << 16 | lan_context, 0x0002,
- &priv->reply_flag) < 0 )
+ if (i2o_clear_table(iop, i2o_dev->lct_data->tid, 0x0002) < 0)
dprintk("%s: Unable to clear LAN_MULTICAST_MAC_ADDRESS table.\n",dev->name);
- if (i2o_row_add_table(iop, i2o_dev->id, priv->unit << 16 | lan_context, 0x0002, -1,
- work32, dev->mc_count*8, &priv->reply_flag) < 0)
+ if (i2o_row_add_table(iop, i2o_dev->lct_data->tid, 0x0002, -1,
+ work32, dev->mc_count*8) < 0)
dprintk("%s: Unable to set LAN_MULTICAST_MAC_ADDRESS table.\n",dev->name);
}
@@ -748,8 +745,8 @@ return;
dprintk(KERN_INFO "i2o_lan: Enabling unicast mode...\n");
}
- if (i2o_set_scalar(iop, i2o_dev->id, priv->unit << 16 | lan_context, 0x0001, 3,
- &filter_mask, 4, &priv->reply_flag) <0)
+ if (i2o_set_scalar(iop, i2o_dev->lct_data->tid, 0x0001, 3,
+ &filter_mask, 4) < 0)
printk(KERN_WARNING "i2o_lan: Unable to set MAC FilterMask.\n");
return;
@@ -764,10 +761,10 @@ struct net_device *i2o_lan_register_device(struct i2o_device *i2o_dev)
unsigned short (*type_trans)(struct sk_buff *, struct net_device *);
void (*unregister_dev)(struct net_device *dev);
- switch (i2o_dev->subclass)
+ switch (i2o_dev->lct_data->sub_class)
{
case I2O_LAN_ETHERNET:
- dev = init_etherdev(NULL, sizeof(struct i2o_lan_local));
+ dev = init_etherdev(NULL, sizeof(struct i2o_lan_local));
if (dev == NULL)
return NULL;
type_trans = eth_type_trans;
@@ -827,7 +824,7 @@ struct net_device *i2o_lan_register_device(struct i2o_device *i2o_dev)
case I2O_LAN_UNKNOWN:
default:
printk(KERN_ERR "i2o_lan: LAN type 0x%08X not supported\n",
- i2o_dev->subclass);
+ i2o_dev->lct_data->sub_class);
return NULL;
}
@@ -840,9 +837,8 @@ struct net_device *i2o_lan_register_device(struct i2o_device *i2o_dev)
i2o_landevs[unit] = dev;
priv->unit = unit;
- if (i2o_query_scalar(i2o_dev->controller, i2o_dev->id,
- priv->unit << 16 | lan_context,
- 0x0001, 0, &hw_addr, 8, &priv->reply_flag) < 0)
+ if (i2o_query_scalar(i2o_dev->controller, i2o_dev->lct_data->tid,
+ 0x0001, 0, &hw_addr, 8) < 0)
{
printk(KERN_ERR "%s: Unable to query hardware address.\n", dev->name);
unit--;
@@ -858,9 +854,8 @@ struct net_device *i2o_lan_register_device(struct i2o_device *i2o_dev)
dev->addr_len = 6;
memcpy(dev->dev_addr, hw_addr, 6);
- if (i2o_query_scalar(i2o_dev->controller, i2o_dev->id,
- priv->unit << 16 | lan_context,
- 0x0007, 2, &max_tx, 4, &priv->reply_flag) < 0)
+ if (i2o_query_scalar(i2o_dev->controller, i2o_dev->lct_data->tid,
+ 0x0007, 2, &max_tx, 4) < 0)
{
printk(KERN_ERR "%s: Unable to query max TX queue.\n", dev->name);
unit--;
@@ -912,7 +907,10 @@ int __init i2o_lan_init(void)
for (i2o_dev=iop->devices;i2o_dev != NULL;i2o_dev=i2o_dev->next)
{
- if (i2o_dev->class != I2O_CLASS_LAN)
+ if (i2o_dev->lct_data->class_id != I2O_CLASS_LAN)
+ continue;
+
+ if(i2o_dev->lct_data->user_tid != 0xFFF)
continue;
if (unit == MAX_LAN_CARDS)
@@ -931,7 +929,7 @@ int __init i2o_lan_init(void)
printk(KERN_INFO "%s: I2O LAN device registered, tid = %d,"
" subclass = 0x%08X, unit = %d.\n",
- dev->name, i2o_dev->id, i2o_dev->subclass,
+ dev->name, i2o_dev->lct_data->tid, i2o_dev->lct_data->sub_class,
((struct i2o_lan_local *)dev->priv)->unit);
}
@@ -955,7 +953,7 @@ void cleanup_module(void)
struct i2o_lan_local *priv = (struct i2o_lan_local *)dev->priv;
struct i2o_device *i2o_dev = priv->i2o_dev;
- switch (i2o_dev->subclass)
+ switch (i2o_dev->lct_data->sub_class)
{
case I2O_LAN_ETHERNET:
unregister_netdev(dev);
@@ -975,7 +973,7 @@ void cleanup_module(void)
#endif
default:
printk(KERN_WARNING "i2o_lan: Spurious I2O LAN subclass 0x%08X.\n",
- i2o_dev->subclass);
+ i2o_dev->lct_data->sub_class);
}
dprintk(KERN_INFO "%s: I2O LAN device unregistered.\n",
diff --git a/drivers/i2o/i2o_pci.c b/drivers/i2o/i2o_pci.c
index f7afa9a46..122c488a9 100644
--- a/drivers/i2o/i2o_pci.c
+++ b/drivers/i2o/i2o_pci.c
@@ -25,6 +25,10 @@
#include <linux/malloc.h>
#include <asm/io.h>
+#ifdef CONFIG_MTRR
+#include <asm/mtrr.h>
+#endif // CONFIG_MTRR
+
#ifdef MODULE
/*
* Core function table
@@ -46,6 +50,11 @@ static void i2o_pci_dispose(struct i2o_controller *c)
if(c->bus.pci.irq > 0)
free_irq(c->bus.pci.irq, c);
iounmap(((u8 *)c->post_port)-0x40);
+
+#ifdef CONFIG_MTRR
+ if(c->bus.pci.mtrr_reg > 0)
+ mtrr_del(c->bus.pci.mtrr_reg, 0, 0);
+#endif
}
/*
@@ -66,6 +75,19 @@ static int i2o_pci_unbind(struct i2o_controller *c, struct i2o_device *dev)
}
/*
+ * Bus specific enable/disable functions
+ */
+static void i2o_pci_enable(struct i2o_controller *c)
+{
+ I2O_IRQ_WRITE32(c, 0);
+}
+
+static void i2o_pci_disable(struct i2o_controller *c)
+{
+ I2O_IRQ_WRITE32(c, 0xFFFFFFFF);
+}
+
+/*
* Bus specific interrupt handler
*/
@@ -81,8 +103,9 @@ static void i2o_pci_interrupt(int irq, void *dev_id, struct pt_regs *r)
/*
* Install a PCI (or in theory AGP) i2o controller
+ *
+ * TODO: Add support for polled controllers
*/
-
int __init i2o_pci_install(struct pci_dev *dev)
{
struct i2o_controller *c=kmalloc(sizeof(struct i2o_controller),
@@ -128,7 +151,7 @@ int __init i2o_pci_install(struct pci_dev *dev)
kfree(c);
return -EINVAL;
}
-
+
c->bus.pci.irq = -1;
c->irq_mask = (volatile u32 *)(mem+0x34);
@@ -141,9 +164,19 @@ int __init i2o_pci_install(struct pci_dev *dev)
c->bind = i2o_pci_bind;
c->unbind = i2o_pci_unbind;
+ c->bus_enable = i2o_pci_enable;
+ c->bus_disable = i2o_pci_disable;
c->type = I2O_TYPE_PCI;
+ /*
+ * Enable Write Combining MTRR for IOP's memory region
+ */
+#ifdef CONFIG_MTRR
+ c->bus.pci.mtrr_reg =
+ mtrr_add(c->mem_phys, size, MTRR_TYPE_WRCOMB, 1);
+#endif
+
I2O_IRQ_WRITE32(c,0xFFFFFFFF);
#ifdef MODULE
@@ -180,6 +213,9 @@ int __init i2o_pci_install(struct pci_dev *dev)
return -EBUSY;
}
}
+
+ printk(KERN_INFO "Installed iop%d at IRQ%d\n", c->unit, dev->irq);
+ I2O_IRQ_WRITE32(c,0x0);
return 0;
}
@@ -211,102 +247,54 @@ int __init i2o_pci_scan(void)
return count?count:-ENODEV;
}
-static void i2o_pci_unload(void)
+#ifdef I2O_HOTPLUG_SUPPORT
+/*
+ * Activate a newly found PCI I2O controller
+ * Not used now, but will be needed in future for
+ * hot plug PCI support
+ */
+static void i2o_pci_activate(i2o_controller * c)
{
int i=0;
struct i2o_controller *c;
- for(i = 0; i < MAX_I2O_CONTROLLERS; i++)
+ if(c->type == I2O_TYPE_PCI)
{
+ I2O_IRQ_WRITE32(c,0);
#ifdef MODULE
- c=core->find(i);
+ if(core->activate(c))
#else
- c=i2o_find_controller(i);
+ if(i2o_activate_controller(c))
#endif /* MODULE */
-
- if(c==NULL)
- continue;
-
-#ifdef MODULE
- core->unlock(c);
-#else
- i2o_unlock_controller(c);
-#endif /* MODULE */
-
- if(c->type == I2O_TYPE_PCI)
+ {
+ printk("I2O: Failed to initialize iop%d\n", c->unit);
#ifdef MODULE
+ core->unlock(c);
core->delete(c);
#else
+ i2o_unlock_controller(c);
i2o_delete_controller(c);
-#endif /* MODULE */
- }
-}
-
-static void i2o_pci_activate(void)
-{
- int i=0;
- struct i2o_controller *c;
-
- for(i = 0; i < MAX_I2O_CONTROLLERS; i++)
- {
-#ifdef MODULE
- c=core->find(i);
-#else
- c=i2o_find_controller(i);
-#endif /* MODULE */
-
- if(c==NULL)
- continue;
-
- if(c->type == I2O_TYPE_PCI)
- {
-#ifdef MODULE
- if(core->activate(c))
-#else
- if(i2o_activate_controller(c))
-#endif /* MODULE */
- {
- printk("I2O: Failed to initialize iop%d\n", c->unit);
-#ifdef MODULE
- core->unlock(c);
- core->delete(c);
-#else
- i2o_unlock_controller(c);
- i2o_delete_controller(c);
#endif
- continue;
- }
- I2O_IRQ_WRITE32(c,0);
+ continue;
}
-#ifdef MODULE
- core->unlock(c);
-#else
- i2o_unlock_controller(c);
-#endif
}
}
-
+#endif // I2O_HOTPLUG_SUPPORT
#ifdef MODULE
int i2o_pci_core_attach(struct i2o_core_func_table *table)
{
- int i;
-
MOD_INC_USE_COUNT;
core = table;
-
- if((i = i2o_pci_scan())<0)
- return -ENODEV;
- i2o_pci_activate();
- return i;
+ return i2o_pci_scan();
}
void i2o_pci_core_detach(void)
{
- i2o_pci_unload();
+ core = NULL;
MOD_DEC_USE_COUNT;
}
@@ -314,16 +302,8 @@ void i2o_pci_core_detach(void)
int init_module(void)
{
printk(KERN_INFO "Linux I2O PCI support (c) 1999 Red Hat Software.\n");
-
-/*
- * Let the core call the scan function for module dependency
- * reasons. See include/linux/i2o.h for the reason why this
- * is done.
- *
- * if(i2o_pci_scan()<0)
- * return -ENODEV;
- * i2o_pci_activate();
- */
+
+ core = NULL;
return 0;
@@ -343,9 +323,6 @@ MODULE_DESCRIPTION("I2O PCI Interface");
void __init i2o_pci_init(void)
{
printk(KERN_INFO "Linux I2O PCI support (c) 1999 Red Hat Software.\n");
- if(i2o_pci_scan()>=0)
- {
- i2o_pci_activate();
- }
+ i2o_pci_scan();
}
#endif
diff --git a/drivers/i2o/i2o_proc.c b/drivers/i2o/i2o_proc.c
index cbb29bc5b..4059a5189 100644
--- a/drivers/i2o/i2o_proc.c
+++ b/drivers/i2o/i2o_proc.c
@@ -1,7 +1,7 @@
/*
* procfs handler for Linux I2O subsystem
*
- * Copyright (c) 1999 Deepak Saxena
+ * (c) Copyright 1999 Deepak Saxena
*
* Originally written by Deepak Saxena(deepak@plexity.net)
*
@@ -790,16 +790,15 @@ int i2o_proc_read_hw(char *buf, char **start, off_t offset, int len,
len = 0;
- token = i2o_query_scalar(c, ADAPTER_TID, proc_context,
+ token = i2o_query_scalar(c, ADAPTER_TID,
0, // ParamGroup 0x0000h
-1, // all fields
&work32,
- sizeof(work32),
- &i2o_proc_token);
+ sizeof(work32));
if(token < 0)
{
- len += sprintf(buf, "Timeout waiting for reply from IOP\n");
+ len += sprintf(buf, "Error waiting for reply from IOP\n");
spin_unlock(&i2o_proc_lock);
return len;
}
@@ -875,10 +874,10 @@ int i2o_proc_read_ddm_table(char *buf, char **start, off_t offset, int len,
len = 0;
token = i2o_query_table(I2O_PARAMS_TABLE_GET,
- c, ADAPTER_TID, proc_context,
+ c, ADAPTER_TID,
0x0003, -1,
NULL, 0,
- &result, sizeof(result), &i2o_proc_token);
+ &result, sizeof(result));
if (token<0)
switch (token)
@@ -941,16 +940,13 @@ int i2o_proc_read_ds(char *buf, char **start, off_t offset, int len,
{
struct i2o_controller *c = (struct i2o_controller*)data;
u32 work32[8];
- int token;
spin_lock(&i2o_proc_lock);
len = 0;
- token = i2o_query_scalar(c, ADAPTER_TID, proc_context, 0x0004, -1,
- &work32, sizeof(work32), &i2o_proc_token);
-
- if (token<0)
+ if(i2o_query_scalar(c, ADAPTER_TID, 0x0004, -1, &work32,
+ sizeof(work32)) < 0)
{
len += sprintf(buf, "Timeout waiting for reply from IOP\n");
spin_unlock(&i2o_proc_lock);
@@ -1009,10 +1005,10 @@ int i2o_proc_read_dst(char *buf, char **start, off_t offset, int len,
len = 0;
token = i2o_query_table(I2O_PARAMS_TABLE_GET,
- c, ADAPTER_TID, proc_context,
+ c, ADAPTER_TID,
0x0005, -1,
NULL, 0,
- &result, sizeof(result), &i2o_proc_token);
+ &result, sizeof(result));
if (token<0)
switch (token)
@@ -1094,10 +1090,10 @@ int i2o_proc_read_groups(char *buf, char **start, off_t offset, int len,
len = 0;
token = i2o_query_table(I2O_PARAMS_TABLE_GET,
- c, ADAPTER_TID, proc_context,
+ c, ADAPTER_TID,
0xF000, -1,
NULL, 0,
- &work16, sizeof(work16), &i2o_proc_token);
+ &work16, sizeof(work16));
if (token<0)
switch (token)
@@ -1181,10 +1177,10 @@ int i2o_proc_read_priv_msgs(char *buf, char **start, off_t offset, int len,
len = 0;
token = i2o_query_table(I2O_PARAMS_TABLE_GET,
- c, ADAPTER_TID, proc_context,
+ c, ADAPTER_TID,
0xF000, -1,
NULL, 0,
- &work16, sizeof(work16), &i2o_proc_token);
+ &work16, sizeof(work16));
if (token<0)
switch (token)
@@ -1243,12 +1239,11 @@ int i2o_proc_read_dev(char *buf, char **start, off_t offset, int len,
len = 0;
- token = i2o_query_scalar(d->controller, d->id, proc_context,
+ token = i2o_query_scalar(d->controller, d->lct_data->tid,
0xF100, // ParamGroup F100h (Device Identity)
-1, // all fields
&work32,
- sizeof(work32),
- &i2o_proc_token);
+ sizeof(work32));
if(token < 0)
{
@@ -1308,12 +1303,11 @@ int i2o_proc_read_ddm(char *buf, char **start, off_t offset, int len,
len = 0;
- token = i2o_query_scalar(d->controller, d->id, proc_context,
+ token = i2o_query_scalar(d->controller, d->lct_data->tid,
0xF101, // ParamGroup F101h (DDM Identity)
-1, // all fields
&work32,
- sizeof(work32),
- &i2o_proc_token);
+ sizeof(work32));
if(token < 0)
{
@@ -1352,12 +1346,11 @@ int i2o_proc_read_uinfo(char *buf, char **start, off_t offset, int len,
len = 0;
- token = i2o_query_scalar(d->controller, d->id, proc_context,
+ token = i2o_query_scalar(d->controller, d->lct_data->tid,
0xF102, // ParamGroup F102h (User Information)
-1, // all fields
&work32,
- sizeof(work32),
- &i2o_proc_token);
+ sizeof(work32));
if(token < 0)
{
@@ -1390,12 +1383,11 @@ int i2o_proc_read_sgl_limits(char *buf, char **start, off_t offset, int len,
len = 0;
- token = i2o_query_scalar(d->controller, d->id, proc_context,
+ token = i2o_query_scalar(d->controller, d->lct_data->tid,
0xF103, // ParamGroup F103h (SGL Operating Limits)
-1, // all fields
&work32,
- sizeof(work32),
- &i2o_proc_token);
+ sizeof(work32));
if(token < 0)
{
@@ -1760,8 +1752,8 @@ int i2o_proc_read_lan_dev_info(char *buf, char **start, off_t offset, int len,
len = 0;
- token = i2o_query_scalar(d->controller, d->id, proc_context,
- 0x0000, -1, &work32, 56*4, &i2o_proc_token);
+ token = i2o_query_scalar(d->controller, d->lct_data->tid,
+ 0x0000, -1, &work32, 56*4);
if(token < 0)
{
len += sprintf(buf, "Timeout waiting for reply from IOP\n");
@@ -1883,8 +1875,8 @@ int i2o_proc_read_lan_mac_addr(char *buf, char **start, off_t offset, int len,
spin_lock(&i2o_proc_lock);
len = 0;
- token = i2o_query_scalar(d->controller, d->id, proc_context,
- 0x0001, -1, &work32, 48*4, &i2o_proc_token);
+ token = i2o_query_scalar(d->controller, d->lct_data->tid,
+ 0x0001, -1, &work32, 48*4);
if(token < 0)
{
len += sprintf(buf, "Timeout waiting for reply from IOP\n");
@@ -1973,9 +1965,8 @@ int i2o_proc_read_lan_mcast_addr(char *buf, char **start, off_t offset,
len = 0;
token = i2o_query_table(I2O_PARAMS_TABLE_GET,
- d->controller, d->id, proc_context, 0x0002, -1,
- NULL, 0, &field32, sizeof(field32),
- &i2o_proc_token);
+ d->controller, d->lct_data->tid, 0x0002, -1,
+ NULL, 0, &field32, sizeof(field32));
if (token<0)
switch (token) {
@@ -2026,8 +2017,8 @@ int i2o_proc_read_lan_batch_control(char *buf, char **start, off_t offset,
spin_lock(&i2o_proc_lock);
len = 0;
- token = i2o_query_scalar(d->controller, d->id, proc_context,
- 0x0003, -1, &work32, 9*4, &i2o_proc_token);
+ token = i2o_query_scalar(d->controller, d->lct_data->tid,
+ 0x0003, -1, &work32, 9*4);
if(token < 0)
{
len += sprintf(buf, "Timeout waiting for reply from IOP\n");
@@ -2086,8 +2077,8 @@ int i2o_proc_read_lan_operation(char *buf, char **start, off_t offset, int len,
spin_lock(&i2o_proc_lock);
len = 0;
- token = i2o_query_scalar(d->controller, d->id, proc_context,
- 0x0004, -1, &work32, 20, &i2o_proc_token);
+ token = i2o_query_scalar(d->controller, d->lct_data->tid,
+ 0x0004, -1, &work32, 20);
if(token < 0)
{
len += sprintf(buf, "Timeout waiting for reply from IOP\n");
@@ -2151,8 +2142,8 @@ int i2o_proc_read_lan_media_operation(char *buf, char **start, off_t offset,
spin_lock(&i2o_proc_lock);
len = 0;
- token = i2o_query_scalar(d->controller, d->id, proc_context,
- 0x0005, -1, &work32, 36, &i2o_proc_token);
+ token = i2o_query_scalar(d->controller, d->lct_data->tid,
+ 0x0005, -1, &work32, 36);
if(token < 0)
{
len += sprintf(buf, "Timeout waiting for reply from IOP\n");
@@ -2225,9 +2216,8 @@ int i2o_proc_read_lan_alt_addr(char *buf, char **start, off_t offset, int len,
len = 0;
token = i2o_query_table(I2O_PARAMS_TABLE_GET,
- d->controller, d->id, proc_context, 0x0006, -1,
- NULL, 0, &field32, sizeof(field32),
- &i2o_proc_token);
+ d->controller, d->lct_data->tid, 0x0006, -1,
+ NULL, 0, &field32, sizeof(field32));
if (token<0)
switch (token) {
@@ -2279,8 +2269,8 @@ int i2o_proc_read_lan_tx_info(char *buf, char **start, off_t offset, int len,
spin_lock(&i2o_proc_lock);
len = 0;
- token = i2o_query_scalar(d->controller, d->id, proc_context,
- 0x0007, -1, &work32, 8*4, &i2o_proc_token);
+ token = i2o_query_scalar(d->controller, d->lct_data->tid,
+ 0x0007, -1, &work32, 8*4);
if(token < 0)
{
len += sprintf(buf, "Timeout waiting for reply from IOP\n");
@@ -2341,8 +2331,8 @@ int i2o_proc_read_lan_rx_info(char *buf, char **start, off_t offset, int len,
spin_lock(&i2o_proc_lock);
len = 0;
- token = i2o_query_scalar(d->controller, d->id, proc_context,
- 0x0008, -1, &work32, 8*4, &i2o_proc_token);
+ token = i2o_query_scalar(d->controller, d->lct_data->tid,
+ 0x0008, -1, &work32, 8*4);
if(token < 0)
{
len += sprintf(buf, "Timeout waiting for reply from IOP\n");
@@ -2376,8 +2366,8 @@ int i2o_proc_read_lan_hist_stats(char *buf, char **start, off_t offset, int len,
spin_lock(&i2o_proc_lock);
len = 0;
- token = i2o_query_scalar(d->controller, d->id, proc_context,
- 0x0100, -1, &work64, 9*8, &i2o_proc_token);
+ token = i2o_query_scalar(d->controller, d->lct_data->tid,
+ 0x0100, -1, &work64, 9*8);
if(token < 0)
{
len += sprintf(buf, "Timeout waiting for reply from IOP\n");
@@ -2421,8 +2411,8 @@ int i2o_proc_read_lan_supp_opt_stats(char *buf, char **start, off_t offset,
len = 0;
- token = i2o_query_scalar(d->controller, d->id, proc_context,
- 0x0180, -1, &work64, 4*8, &i2o_proc_token);
+ token = i2o_query_scalar(d->controller, d->lct_data->tid,
+ 0x0180, -1, &work64, 4*8);
if(token < 0)
{
len += sprintf(buf, "Timeout waiting for reply from IOP\n");
@@ -2461,8 +2451,8 @@ int i2o_proc_read_lan_opt_tx_hist_stats(char *buf, char **start, off_t offset,
len = 0;
- token = i2o_query_scalar(d->controller, d->id, proc_context,
- 0x0182, -1, &work64, 9*8, &i2o_proc_token);
+ token = i2o_query_scalar(d->controller, d->lct_data->tid,
+ 0x0182, -1, &work64, 9*8);
if(token < 0)
{
len += sprintf(buf, "Timeout waiting for reply from IOP\n");
@@ -2506,8 +2496,8 @@ int i2o_proc_read_lan_opt_rx_hist_stats(char *buf, char **start, off_t offset,
len = 0;
- token = i2o_query_scalar(d->controller, d->id, proc_context,
- 0x0183, -1, &work64, 11*8, &i2o_proc_token);
+ token = i2o_query_scalar(d->controller, d->lct_data->tid,
+ 0x0183, -1, &work64, 11*8);
if(token < 0)
{
len += sprintf(buf, "Timeout waiting for reply from IOP\n");
@@ -2555,8 +2545,8 @@ int i2o_proc_read_lan_eth_stats(char *buf, char **start, off_t offset,
len = 0;
- token = i2o_query_scalar(d->controller, d->id, proc_context,
- 0x0200, -1, &work64, 8*8, &i2o_proc_token);
+ token = i2o_query_scalar(d->controller, d->lct_data->tid,
+ 0x0200, -1, &work64, 8*8);
if(token < 0)
{
len += sprintf(buf, "Timeout waiting for reply from IOP\n");
@@ -2597,8 +2587,8 @@ int i2o_proc_read_lan_supp_eth_stats(char *buf, char **start, off_t offset,
len = 0;
- token = i2o_query_scalar(d->controller, d->id, proc_context,
- 0x0280, -1, &work64, 8, &i2o_proc_token);
+ token = i2o_query_scalar(d->controller, d->lct_data->tid,
+ 0x0280, -1, &work64, 8);
if(token < 0)
{
len += sprintf(buf, "Timeout waiting for reply from IOP\n");
@@ -2625,8 +2615,8 @@ int i2o_proc_read_lan_opt_eth_stats(char *buf, char **start, off_t offset,
len = 0;
- token = i2o_query_scalar(d->controller, d->id, proc_context,
- 0x0281, -1, &work64, 3*8, &i2o_proc_token);
+ token = i2o_query_scalar(d->controller, d->lct_data->tid,
+ 0x0281, -1, &work64, 3*8);
if(token < 0)
{
len += sprintf(buf, "Timeout waiting for reply from IOP\n");
@@ -2677,8 +2667,8 @@ int i2o_proc_read_lan_tr_stats(char *buf, char **start, off_t offset,
len = 0;
- token = i2o_query_scalar(d->controller, d->id, proc_context,
- 0x0300, -1, &work64, 13*8, &i2o_proc_token);
+ token = i2o_query_scalar(d->controller, d->lct_data->tid,
+ 0x0300, -1, &work64, 13*8);
if(token < 0)
{
len += sprintf(buf, "Timeout waiting for reply from IOP\n");
@@ -2771,8 +2761,8 @@ int i2o_proc_read_lan_fddi_stats(char *buf, char **start, off_t offset,
len = 0;
- token = i2o_query_scalar(d->controller, d->id, proc_context,
- 0x0400, -1, &work64, 11*8, &i2o_proc_token);
+ token = i2o_query_scalar(d->controller, d->lct_data->tid,
+ 0x0400, -1, &work64, 11*8);
if(token < 0)
{
len += sprintf(buf, "Timeout waiting for reply from IOP\n");
@@ -2853,7 +2843,7 @@ static int i2o_proc_add_controller(struct i2o_controller *pctrl,
for(dev = pctrl->devices; dev; dev = dev->next)
{
- sprintf(buff, "%0#5x", dev->id);
+ sprintf(buff, "%0#5x", dev->lct_data->tid);
dir1 = create_proc_entry(buff, S_IFDIR, dir);
dev->proc_entry = dir1;
@@ -2863,7 +2853,7 @@ static int i2o_proc_add_controller(struct i2o_controller *pctrl,
i2o_proc_create_entries(dev, generic_dev_entries, dir1);
- switch(dev->class)
+ switch(dev->lct_data->class_id)
{
case I2O_CLASS_SCSI_PERIPHERAL:
case I2O_CLASS_RANDOM_BLOCK_STORAGE:
@@ -2871,7 +2861,7 @@ static int i2o_proc_add_controller(struct i2o_controller *pctrl,
break;
case I2O_CLASS_LAN:
i2o_proc_create_entries(dev, lan_entries, dir1);
- switch(dev->subclass)
+ switch(dev->lct_data->sub_class)
{
case I2O_LAN_ETHERNET:
i2o_proc_create_entries(dev, lan_eth_entries,
@@ -2909,14 +2899,14 @@ static void i2o_proc_remove_controller(struct i2o_controller *pctrl,
for(dev=pctrl->devices; dev; dev=dev->next)
{
de=dev->proc_entry;
- sprintf(dev_id, "%0#5x", dev->id);
+ sprintf(dev_id, "%0#5x", dev->lct_data->tid);
/* Would it be safe to remove _files_ even if they are in use? */
if((de) && (!de->count))
{
i2o_proc_remove_entries(generic_dev_entries, de);
- switch(dev->class)
+ switch(dev->lct_data->class_id)
{
case I2O_CLASS_SCSI_PERIPHERAL:
case I2O_CLASS_RANDOM_BLOCK_STORAGE:
@@ -2924,7 +2914,7 @@ static void i2o_proc_remove_controller(struct i2o_controller *pctrl,
break;
case I2O_CLASS_LAN:
i2o_proc_remove_entries(lan_entries, de);
- switch(dev->subclass)
+ switch(dev->lct_data->sub_class)
{
case I2O_LAN_ETHERNET:
i2o_proc_remove_entries(lan_eth_entries, de);
diff --git a/drivers/i2o/i2o_scsi.c b/drivers/i2o/i2o_scsi.c
index 7b309411b..46f7fbfb0 100644
--- a/drivers/i2o/i2o_scsi.c
+++ b/drivers/i2o/i2o_scsi.c
@@ -301,14 +301,12 @@ static int i2o_find_lun(struct i2o_controller *c, struct i2o_device *d, int *tar
{
u8 reply[8];
- if(i2o_query_scalar(c, d->id, scsi_context|0x40000000,
- 0, 3, reply, 4, &lun_done)<0)
+ if(i2o_query_scalar(c, d->lct_data->tid, 0, 3, reply, 4))
return -1;
*target=reply[0];
- if(i2o_query_scalar(c, d->id, scsi_context|0x40000000,
- 0, 4, reply, 8, &lun_done)<0)
+ if(i2o_query_scalar(c, d->lct_data->tid, 0, 4, reply, 8))
return -1;
*lun=reply[1];
@@ -325,7 +323,7 @@ void i2o_scsi_init(struct i2o_controller *c, struct i2o_device *d, struct Scsi_H
int target;
h->controller=c;
- h->bus_task=d->id;
+ h->bus_task=d->lct_data->tid;
for(target=0;target<16;target++)
for(lun=0;lun<8;lun++)
@@ -334,34 +332,33 @@ void i2o_scsi_init(struct i2o_controller *c, struct i2o_device *d, struct Scsi_H
for(unit=c->devices;unit!=NULL;unit=unit->next)
{
dprintk(("Class %03X, parent %d, want %d.\n",
- unit->class, unit->parent, d->id));
+ unit->lct_data->class_id, unit->lct_data->parent, d->lct_data->tid));
/* Only look at scsi and fc devices */
- if ( (unit->class != I2O_CLASS_SCSI_PERIPHERAL)
- && (unit->class != I2O_CLASS_FIBRE_CHANNEL_PERIPHERAL)
+ if ( (unit->lct_data->class_id != I2O_CLASS_SCSI_PERIPHERAL)
+ && (unit->lct_data->class_id != I2O_CLASS_FIBRE_CHANNEL_PERIPHERAL)
)
continue;
/* On our bus ? */
dprintk(("Found a disk.\n"));
- if ( (unit->parent == d->id)
- || (unit->parent == d->parent)
+ if ((unit->lct_data->parent_tid == d->lct_data->tid)
+ || (unit->lct_data->parent_tid == d->lct_data->parent_tid)
)
{
u16 limit;
dprintk(("Its ours.\n"));
if(i2o_find_lun(c, unit, &target, &lun)==-1)
{
- printk(KERN_ERR "i2o_scsi: Unable to get lun for tid %d.\n", d->id);
+ printk(KERN_ERR "i2o_scsi: Unable to get lun for tid %d.\n", d->lct_data->tid);
continue;
}
dprintk(("Found disk %d %d.\n", target, lun));
- h->task[target][lun]=unit->id;
+ h->task[target][lun]=unit->lct_data->tid;
h->tagclock[target][lun]=jiffies;
/* Get the max fragments/request */
- i2o_query_scalar(c, d->id, scsi_context|0x40000000,
- 0xF103, 3, &limit, 2, &lun_done);
+ i2o_query_scalar(c, d->lct_data->tid, 0xF103, 3, &limit, 2);
/* sanity */
if ( limit == 0 )
@@ -435,8 +432,8 @@ int i2o_scsi_detect(Scsi_Host_Template * tpnt)
/*
* bus_adapter, SCSI (obsolete), or FibreChannel busses only
*/
- if( (d->class!=I2O_CLASS_BUS_ADAPTER_PORT) // bus_adapter
- && (d->class!=I2O_CLASS_FIBRE_CHANNEL_PORT) // FC_PORT
+ if( (d->lct_data->class_id!=I2O_CLASS_BUS_ADAPTER_PORT) // bus_adapter
+ && (d->lct_data->class_id!=I2O_CLASS_FIBRE_CHANNEL_PORT) // FC_PORT
)
continue;
diff --git a/drivers/macintosh/macserial.c b/drivers/macintosh/macserial.c
index 720932cc9..39a27107f 100644
--- a/drivers/macintosh/macserial.c
+++ b/drivers/macintosh/macserial.c
@@ -2584,7 +2584,9 @@ void unregister_serial(int line)
* ------------------------------------------------------------
*/
#ifdef CONFIG_SERIAL_CONSOLE
-
+#ifdef CONFIG_SERIAL
+#error Cannot build serial console with macserial and serial drivers
+#endif
/*
* Print a string to the serial port trying not to disturb
@@ -2843,7 +2845,7 @@ static struct console sercons = {
/*
* Register console.
*/
-long __init serial_console_init(long kmem_start, long kmem_end)
+void __init serial_console_init(void)
{
register_console(&sercons);
return kmem_start;
diff --git a/drivers/misc/acpi.c b/drivers/misc/acpi.c
index 03c39fb61..093a7bbb8 100644
--- a/drivers/misc/acpi.c
+++ b/drivers/misc/acpi.c
@@ -29,8 +29,13 @@
#include <linux/sched.h>
#include <linux/wait.h>
#include <linux/spinlock.h>
+#include <linux/ioport.h>
+#include <linux/slab.h>
+#include <linux/pci.h>
#include <asm/uaccess.h>
#include <asm/io.h>
+#include <linux/sysctl.h>
+#include <linux/delay.h>
#include <linux/acpi.h>
/*
@@ -49,7 +54,26 @@
#define DECLARE_WAIT_QUEUE_HEAD(x) struct wait_queue * x = NULL
#endif
+static int acpi_do_ulong(ctl_table *ctl,
+ int write,
+ struct file *file,
+ void *buffer,
+ size_t *len);
+static int acpi_do_event_reg(ctl_table *ctl,
+ int write,
+ struct file *file,
+ void *buffer,
+ size_t *len);
+static int acpi_do_event(ctl_table *ctl,
+ int write,
+ struct file *file,
+ void *buffer,
+ size_t *len);
+
+static struct ctl_table_header *acpi_sysctl = NULL;
+
static struct acpi_facp *acpi_facp = NULL;
+static int acpi_fake_facp = 0;
static unsigned long acpi_facp_addr = 0;
static unsigned long acpi_dsdt_addr = 0;
@@ -57,15 +81,64 @@ static spinlock_t acpi_event_lock = SPIN_LOCK_UNLOCKED;
static volatile u32 acpi_pm1_status = 0;
static volatile u32 acpi_gpe_status = 0;
static volatile u32 acpi_gpe_level = 0;
-static DECLARE_WAIT_QUEUE_HEAD(acpi_wait_event);
+static DECLARE_WAIT_QUEUE_HEAD(acpi_event_wait);
/* Make it impossible to enter L2/L3 until after we've initialized */
static unsigned long acpi_p_lvl2_lat = ~0UL;
static unsigned long acpi_p_lvl3_lat = ~0UL;
/* Initialize to guaranteed harmless port read */
-static u16 acpi_p_lvl2 = 0x80;
-static u16 acpi_p_lvl3 = 0x80;
+static unsigned long acpi_p_lvl2 = 0x80;
+static unsigned long acpi_p_lvl3 = 0x80;
+
+static struct ctl_table acpi_table[] =
+{
+ {ACPI_FACP, "facp",
+ &acpi_facp_addr, sizeof(acpi_facp_addr),
+ 0400, NULL, &acpi_do_ulong},
+
+ {ACPI_DSDT, "dsdt",
+ &acpi_dsdt_addr, sizeof(acpi_dsdt_addr),
+ 0400, NULL, &acpi_do_ulong},
+
+ {ACPI_PM1_ENABLE, "pm1_enable",
+ NULL, 0,
+ 0600, NULL, &acpi_do_event_reg},
+
+ {ACPI_GPE_ENABLE, "gpe_enable",
+ NULL, 0,
+ 0600, NULL, &acpi_do_event_reg},
+
+ {ACPI_GPE_LEVEL, "gpe_level",
+ NULL, 0,
+ 0600, NULL, &acpi_do_event_reg},
+
+ {ACPI_EVENT, "event", NULL, 0, 0400, NULL, &acpi_do_event},
+
+ {ACPI_P_LVL2, "p_lvl2",
+ &acpi_p_lvl2, sizeof(acpi_p_lvl2),
+ 0600, NULL, &acpi_do_ulong},
+
+ {ACPI_P_LVL3, "p_lvl3",
+ &acpi_p_lvl3, sizeof(acpi_p_lvl3),
+ 0600, NULL, &acpi_do_ulong},
+
+ {ACPI_P_LVL2_LAT, "p_lvl2_lat",
+ &acpi_p_lvl2_lat, sizeof(acpi_p_lvl2_lat),
+ 0600, NULL, &acpi_do_ulong},
+
+ {ACPI_P_LVL3_LAT, "p_lvl3_lat",
+ &acpi_p_lvl3_lat, sizeof(acpi_p_lvl3_lat),
+ 0600, NULL, &acpi_do_ulong},
+
+ {0}
+};
+
+static struct ctl_table acpi_dir_table[] =
+{
+ {CTL_ACPI, "acpi", NULL, 0, 0500, acpi_table},
+ {0}
+};
/*
@@ -73,7 +146,9 @@ static u16 acpi_p_lvl3 = 0x80;
*/
static u32 acpi_read_pm1_control(struct acpi_facp *facp)
{
- u32 value = inw(facp->pm1a_cnt);
+ u32 value = 0;
+ if (facp->pm1a_cnt)
+ value = inw(facp->pm1a_cnt);
if (facp->pm1b_cnt)
value |= inw(facp->pm1b_cnt);
return value;
@@ -84,7 +159,9 @@ static u32 acpi_read_pm1_control(struct acpi_facp *facp)
*/
static u32 acpi_read_pm1_status(struct acpi_facp *facp)
{
- u32 value = inw(facp->pm1a_evt);
+ u32 value = 0;
+ if (facp->pm1a_evt)
+ value = inw(facp->pm1a_evt);
if (facp->pm1b_evt)
value |= inw(facp->pm1b_evt);
return value;
@@ -95,7 +172,8 @@ static u32 acpi_read_pm1_status(struct acpi_facp *facp)
*/
static void acpi_write_pm1_status(struct acpi_facp *facp, u32 value)
{
- outw(value, facp->pm1a_evt);
+ if (facp->pm1a_evt)
+ outw(value, facp->pm1a_evt);
if (facp->pm1b_evt)
outw(value, facp->pm1b_evt);
}
@@ -106,7 +184,9 @@ static void acpi_write_pm1_status(struct acpi_facp *facp, u32 value)
static u32 acpi_read_pm1_enable(struct acpi_facp *facp)
{
int offset = facp->pm1_evt_len >> 1;
- u32 value = inw(facp->pm1a_evt + offset);
+ u32 value = 0;
+ if (facp->pm1a_evt)
+ value = inw(facp->pm1a_evt + offset);
if (facp->pm1b_evt)
value |= inw(facp->pm1b_evt + offset);
return value;
@@ -118,7 +198,8 @@ static u32 acpi_read_pm1_enable(struct acpi_facp *facp)
static void acpi_write_pm1_enable(struct acpi_facp *facp, u32 value)
{
int offset = facp->pm1_evt_len >> 1;
- outw(value, facp->pm1a_evt + offset);
+ if (facp->pm1a_evt)
+ outw(value, facp->pm1a_evt + offset);
if (facp->pm1b_evt)
outw(value, facp->pm1b_evt + offset);
}
@@ -136,9 +217,11 @@ static u32 acpi_read_gpe_status(struct acpi_facp *facp)
for (i = size - 1; i >= 0; i--)
value = (value << 8) | inb(facp->gpe1 + i);
}
- size = facp->gpe0_len >> 1;
- for (i = size - 1; i >= 0; i--)
- value = (value << 8) | inb(facp->gpe0 + i);
+ if (facp->gpe0) {
+ size = facp->gpe0_len >> 1;
+ for (i = size - 1; i >= 0; i--)
+ value = (value << 8) | inb(facp->gpe0 + i);
+ }
return value;
}
@@ -149,10 +232,12 @@ static void acpi_write_gpe_status(struct acpi_facp *facp, u32 value)
{
int i, size;
- size = facp->gpe0_len >> 1;
- for (i = 0; i < size; i++) {
- outb(value & 0xff, facp->gpe0 + i);
- value >>= 8;
+ if (facp->gpe0) {
+ size = facp->gpe0_len >> 1;
+ for (i = 0; i < size; i++) {
+ outb(value & 0xff, facp->gpe0 + i);
+ value >>= 8;
+ }
}
if (facp->gpe1) {
size = facp->gpe1_len >> 1;
@@ -178,9 +263,11 @@ static u32 acpi_read_gpe_enable(struct acpi_facp *facp)
value = (value << 8) | inb(facp->gpe1 + offset + i);
}
}
- size = facp->gpe0_len >> 1;
- for (i = size - 1; i >= 0; i--)
- value = (value << 8) | inb(facp->gpe0 + offset + i);
+ if (facp->gpe0) {
+ size = facp->gpe0_len >> 1;
+ for (i = size - 1; i >= 0; i--)
+ value = (value << 8) | inb(facp->gpe0 + offset + i);
+ }
return value;
}
@@ -192,9 +279,11 @@ static void acpi_write_gpe_enable(struct acpi_facp *facp, u32 value)
int i, offset;
offset = facp->gpe0_len >> 1;
- for (i = 0; i < offset; i++) {
- outb(value & 0xff, facp->gpe0 + offset + i);
- value >>= 8;
+ if (facp->gpe0) {
+ for (i = 0; i < offset; i++) {
+ outb(value & 0xff, facp->gpe0 + offset + i);
+ value >>= 8;
+ }
}
if (facp->gpe1) {
offset = facp->gpe1_len >> 1;
@@ -238,9 +327,9 @@ static void acpi_unmap_table(struct acpi_table *table)
}
/*
- * Locate and map ACPI tables (FACP, DSDT, ...)
+ * Locate and map ACPI tables
*/
-static int __init acpi_map_tables(void)
+static int __init acpi_find_tables(void)
{
struct acpi_rsdp *rsdp;
struct acpi_table *rsdt;
@@ -251,8 +340,8 @@ static int __init acpi_map_tables(void)
// search BIOS memory for RSDP
for (i = ACPI_BIOS_ROM_BASE; i < ACPI_BIOS_ROM_END; i += 16) {
rsdp = (struct acpi_rsdp *) phys_to_virt(i);
- if (rsdp->signature[0] == ACPI_RSDP1_SIG &&
- rsdp->signature[1] == ACPI_RSDP2_SIG) {
+ if (rsdp->signature[0] == ACPI_RSDP1_SIG
+ && rsdp->signature[1] == ACPI_RSDP2_SIG) {
char oem[7];
int j;
@@ -270,14 +359,13 @@ static int __init acpi_map_tables(void)
break;
}
}
- if (i >= ACPI_BIOS_ROM_END) {
- printk(KERN_ERR "ACPI: no RSDP found\n");
+ if (i >= ACPI_BIOS_ROM_END)
return -ENODEV;
- }
+
// fetch RSDT from RSDP
rsdt = acpi_map_table(rsdp->rsdt);
if (!rsdt || rsdt->signature != ACPI_RSDT_SIG) {
- printk(KERN_ERR "ACPI: no RSDT found\n");
+ printk(KERN_ERR "ACPI: missing RSDT\n");
acpi_unmap_table(rsdt);
return -ENODEV;
}
@@ -288,11 +376,11 @@ static int __init acpi_map_tables(void)
while (rsdt_entry_count) {
struct acpi_table *dt = acpi_map_table(*rsdt_entry);
if (dt && dt->signature == ACPI_FACP_SIG) {
- acpi_facp = (struct acpi_facp *) dt;
+ acpi_facp = (struct acpi_facp*) dt;
acpi_facp_addr = *rsdt_entry;
acpi_dsdt_addr = acpi_facp->dsdt;
- break;
- } else {
+ }
+ else {
acpi_unmap_table(dt);
}
rsdt_entry++;
@@ -302,22 +390,89 @@ static int __init acpi_map_tables(void)
acpi_unmap_table(rsdt);
if (!acpi_facp) {
- printk(KERN_ERR "ACPI: no FACP found\n");
+ printk(KERN_ERR "ACPI: missing FACP\n");
return -ENODEV;
}
return 0;
}
/*
- * Unmap ACPI tables (FACP, DSDT, ...)
+ * Unmap or destroy ACPI tables
*/
-static void acpi_unmap_tables(void)
+static void acpi_destroy_tables(void)
{
- acpi_idle = NULL;
+ if (!acpi_fake_facp)
+ acpi_unmap_table((struct acpi_table*) acpi_facp);
+ else
+ kfree(acpi_facp);
+}
+
+/*
+ * Locate PIIX4 device and create a fake FACP
+ */
+static int __init acpi_find_piix4(void)
+{
+ struct pci_dev *dev;
+ u32 base;
+ u16 cmd;
+ u8 pmregmisc;
+
+ dev = pci_find_device(PCI_VENDOR_ID_INTEL,
+ PCI_DEVICE_ID_INTEL_82371AB_3,
+ NULL);
+ if (!dev)
+ return -ENODEV;
+
+ pci_read_config_word(dev, PCI_COMMAND, &cmd);
+ if (!(cmd & PCI_COMMAND_IO))
+ return -ENODEV;
+
+ pci_read_config_byte(dev, ACPI_PIIX4_PMREGMISC, &pmregmisc);
+ if (!(pmregmisc & ACPI_PIIX4_PMIOSE))
+ return -ENODEV;
+
+ pci_read_config_dword(dev, 0x40, &base);
+ if (!(base & PCI_BASE_ADDRESS_SPACE_IO))
+ return -ENODEV;
+
+ base &= PCI_BASE_ADDRESS_IO_MASK;
+ if (!base)
+ return -ENODEV;
+
+ printk(KERN_INFO "ACPI: found PIIX4 at 0x%04x\n", base);
+
+ acpi_facp = kmalloc(sizeof(struct acpi_facp), GFP_KERNEL);
+ if (!acpi_facp)
+ return -ENOMEM;
+
+ acpi_fake_facp = 1;
+ memset(acpi_facp, 0, sizeof(struct acpi_facp));
+ acpi_facp->int_model = ACPI_PIIX4_INT_MODEL;
+ acpi_facp->sci_int = ACPI_PIIX4_SCI_INT;
+ acpi_facp->smi_cmd = ACPI_PIIX4_SMI_CMD;
+ acpi_facp->acpi_enable = ACPI_PIIX4_ACPI_ENABLE;
+ acpi_facp->acpi_disable = ACPI_PIIX4_ACPI_DISABLE;
+ acpi_facp->s4bios_req = ACPI_PIIX4_S4BIOS_REQ;
+ acpi_facp->pm1a_evt = base + ACPI_PIIX4_PM1_EVT;
+ acpi_facp->pm1a_cnt = base + ACPI_PIIX4_PM1_CNT;
+ acpi_facp->pm2_cnt = ACPI_PIIX4_PM2_CNT;
+ acpi_facp->pm_tmr = base + ACPI_PIIX4_PM_TMR;
+ acpi_facp->gpe0 = base + ACPI_PIIX4_GPE0;
+ acpi_facp->pm1_evt_len = ACPI_PIIX4_PM1_EVT_LEN;
+ acpi_facp->pm1_cnt_len = ACPI_PIIX4_PM1_CNT_LEN;
+ acpi_facp->pm2_cnt_len = ACPI_PIIX4_PM2_CNT_LEN;
+ acpi_facp->pm_tm_len = ACPI_PIIX4_PM_TM_LEN;
+ acpi_facp->gpe0_len = ACPI_PIIX4_GPE0_LEN;
+ acpi_facp->p_lvl2_lat = ~0;
+ acpi_facp->p_lvl3_lat = ~0;
+
+ acpi_facp_addr = virt_to_phys(acpi_facp);
acpi_dsdt_addr = 0;
- acpi_facp_addr = 0;
- acpi_unmap_table((struct acpi_table *) acpi_facp);
- acpi_facp = NULL;
+
+ acpi_p_lvl2 = base + ACPI_PIIX4_P_LVL2;
+ acpi_p_lvl3 = base + ACPI_PIIX4_P_LVL3;
+
+ return 0;
}
/*
@@ -355,25 +510,7 @@ static void acpi_irq(int irq, void *dev_id, struct pt_regs *regs)
acpi_pm1_status |= pm1_status;
acpi_gpe_status |= gpe_status;
spin_unlock_irqrestore(&acpi_event_lock, flags);
- wake_up_interruptible(&acpi_wait_event);
-}
-
-/*
- * Handle open of /dev/acpi
- */
-static int acpi_open(struct inode *inode, struct file *file)
-{
- MOD_INC_USE_COUNT;
- return 0;
-}
-
-/*
- * Handle close of /dev/acpi
- */
-static int acpi_release(struct inode *inode, struct file *file)
-{
- MOD_DEC_USE_COUNT;
- return 0;
+ wake_up_interruptible(&acpi_event_wait);
}
/*
@@ -389,7 +526,8 @@ static inline int acpi_is_enabled(struct acpi_facp *facp)
*/
static int acpi_enable(struct acpi_facp *facp)
{
- outb(facp->acpi_enable, facp->smi_cmd);
+ if (facp->smi_cmd)
+ outb(facp->acpi_enable, facp->smi_cmd);
return (acpi_is_enabled(facp) ? 0:-1);
}
@@ -404,132 +542,29 @@ static int acpi_disable(struct acpi_facp *facp)
acpi_write_gpe_status(facp, acpi_read_gpe_status(facp));
acpi_write_pm1_enable(facp, 0);
acpi_write_pm1_status(facp, acpi_read_pm1_status(facp));
-
- outb(facp->acpi_disable, facp->smi_cmd);
+
+ if (facp->smi_cmd)
+ outb(facp->acpi_disable, facp->smi_cmd);
return (acpi_is_enabled(facp) ? -1:0);
}
/*
- * Handle command to /dev/acpi
+ * Idle loop
*/
-static int acpi_ioctl(struct inode *inode,
- struct file *file,
- unsigned cmd,
- unsigned long arg)
-{
- int status = -EINVAL;
-
- if (!capable(CAP_SYS_ADMIN))
- return -EPERM;
-
- switch (cmd) {
- case ACPI_FIND_TABLES:
- status = verify_area(VERIFY_WRITE,
- (void *) arg,
- sizeof(struct acpi_find_tables));
- if (!status) {
- struct acpi_find_tables *rqst
- = (struct acpi_find_tables *) arg;
- put_user(acpi_facp_addr, &rqst->facp);
- put_user(acpi_dsdt_addr, &rqst->dsdt);
- status = 0;
- }
- break;
- case ACPI_ENABLE_EVENT:
- status = verify_area(VERIFY_READ,
- (void *) arg,
- sizeof(struct acpi_enable_event));
- if (!status) {
- struct acpi_enable_event *rqst
- = (struct acpi_enable_event *) arg;
- u32 pm1_enable, gpe_enable, gpe_level;
- u32 pm1_enabling, gpe_enabling;
-
- get_user(pm1_enable, &rqst->pm1_enable);
- get_user(gpe_enable, &rqst->gpe_enable);
- get_user(gpe_level, &rqst->gpe_level);
- gpe_level &= gpe_enable;
-
- // clear previously disabled events before enabling
- pm1_enabling = (pm1_enable
- & ~acpi_read_pm1_enable(acpi_facp));
- acpi_write_pm1_status(acpi_facp, pm1_enabling);
- gpe_enabling = (gpe_enable &
- ~acpi_read_gpe_enable(acpi_facp));
- while (acpi_read_gpe_status(acpi_facp) & gpe_enabling)
- acpi_write_gpe_status(acpi_facp, gpe_enabling);
-
- status = 0;
-
- if (pm1_enable || gpe_enable) {
- // enable ACPI unless it is already
- if (!acpi_is_enabled(acpi_facp)
- && acpi_enable(acpi_facp)) {
- status = -EBUSY;
- }
- }
- else {
- // disable ACPI unless it is already
- if (acpi_is_enabled(acpi_facp)
- && acpi_disable(acpi_facp)) {
- status = -EBUSY;
- }
- }
-
- if (!status)
- {
- acpi_write_pm1_enable(acpi_facp, pm1_enable);
- acpi_write_gpe_enable(acpi_facp, gpe_enable);
- acpi_gpe_level = gpe_level;
- }
- }
- break;
- case ACPI_WAIT_EVENT:
- status = verify_area(VERIFY_WRITE,
- (void *) arg,
- sizeof(struct acpi_wait_event));
- if (!status) {
- struct acpi_wait_event *rqst
- = (struct acpi_wait_event *) arg;
- u32 pm1_status = 0;
- u32 gpe_status = 0;
-
- for (;;) {
- unsigned long flags;
-
- // we need an atomic exchange here
- spin_lock_irqsave(&acpi_event_lock, flags);
- pm1_status = acpi_pm1_status;
- acpi_pm1_status = 0;
- gpe_status = acpi_gpe_status;
- acpi_gpe_status = 0;
- spin_unlock_irqrestore(&acpi_event_lock,
- flags);
-
- if (pm1_status || gpe_status)
- break;
-
- // wait for an event to arrive
- interruptible_sleep_on(&acpi_wait_event);
- if (signal_pending(current))
- return -ERESTARTSYS;
- }
-
- put_user(pm1_status, &rqst->pm1_status);
- put_user(gpe_status, &rqst->gpe_status);
- status = 0;
- }
- break;
- }
- return status;
-}
-
static void acpi_idle_handler(void)
{
- unsigned long time;
static int sleep_level = 1;
+ u32 timer, pm2_cnt;
+ unsigned long time;
- time = inl(acpi_facp->pm_tmr);
+ // get current time (fallback to CPU cycles if no PM timer)
+ timer = acpi_facp->pm_tmr;
+ if (timer)
+ time = inl(timer);
+ else
+ time = get_cycles();
+
+ // sleep
switch (sleep_level) {
case 1:
__asm__ __volatile__("sti ; hlt": : :"memory");
@@ -538,18 +573,25 @@ static void acpi_idle_handler(void)
inb(acpi_p_lvl2);
break;
case 3:
- /* Disable PCI arbitration while sleeping,
- to avoid DMA corruption? */
- if (acpi_facp->pm2_cnt) {
- unsigned int port = acpi_facp->pm2_cnt;
- outb(inb(port) | ACPI_ARB_DIS, port);
+ pm2_cnt = acpi_facp->pm2_cnt;
+ if (pm2_cnt) {
+ /* Disable PCI arbitration while sleeping,
+ to avoid DMA corruption? */
+ outb(inb(pm2_cnt) | ACPI_ARB_DIS, pm2_cnt);
+ inb(acpi_p_lvl3);
+ outb(inb(pm2_cnt) & ~ACPI_ARB_DIS, pm2_cnt);
+ }
+ else {
inb(acpi_p_lvl3);
- outb(inb(port) & ~ACPI_ARB_DIS, port);
- break;
}
- inb(acpi_p_lvl3);
+ break;
}
- time = (inl(acpi_facp->pm_tmr) - time) & ACPI_TMR_MASK;
+
+ // calculate time spent sleeping (fallback to CPU cycles)
+ if (timer)
+ time = (inl(timer) - time) & ACPI_TMR_MASK;
+ else
+ time = ACPI_CPU_TO_TMR_TICKS(get_cycles() - time);
if (time > acpi_p_lvl3_lat)
sleep_level = 3;
@@ -559,50 +601,24 @@ static void acpi_idle_handler(void)
sleep_level = 1;
}
-static struct file_operations acpi_fops =
-{
- NULL, /* llseek */
- NULL, /* read */
- NULL, /* write */
- NULL, /* readdir */
- NULL, /* poll */
- acpi_ioctl, /* ioctl */
- NULL, /* mmap */
- acpi_open, /* open */
- NULL, /* flush */
- acpi_release, /* release */
- NULL, /* fsync */
- NULL, /* fasync */
- NULL, /* check_media_change */
- NULL, /* revalidate */
- NULL, /* lock */
-};
-
-static struct miscdevice acpi_device =
-{
- ACPI_MINOR_DEV,
- "acpi",
- &acpi_fops,
- NULL,
- NULL
-};
-
/*
* Claim ACPI I/O ports
*/
static int acpi_claim_ioports(struct acpi_facp *facp)
{
// we don't get a guarantee of contiguity for any of the ACPI registers
- request_region(facp->pm1a_evt, facp->pm1_evt_len, "acpi");
+ if (facp->pm1a_evt)
+ request_region(facp->pm1a_evt, facp->pm1_evt_len, "acpi");
if (facp->pm1b_evt)
request_region(facp->pm1b_evt, facp->pm1_evt_len, "acpi");
- request_region(facp->pm1a_cnt, facp->pm1_cnt_len, "acpi");
+ if (facp->pm1a_cnt)
+ request_region(facp->pm1a_cnt, facp->pm1_cnt_len, "acpi");
if (facp->pm1b_cnt)
request_region(facp->pm1b_cnt, facp->pm1_cnt_len, "acpi");
- if (facp->pm2_cnt)
- request_region(facp->pm2_cnt, facp->pm2_cnt_len, "acpi");
- request_region(facp->pm_tmr, facp->pm_tm_len, "acpi");
- request_region(facp->gpe0, facp->gpe0_len, "acpi");
+ if (facp->pm_tmr)
+ request_region(facp->pm_tmr, facp->pm_tm_len, "acpi");
+ if (facp->gpe0)
+ request_region(facp->gpe0, facp->gpe0_len, "acpi");
if (facp->gpe1)
request_region(facp->gpe1, facp->gpe1_len, "acpi");
@@ -615,16 +631,18 @@ static int acpi_claim_ioports(struct acpi_facp *facp)
static int acpi_release_ioports(struct acpi_facp *facp)
{
// we don't get a guarantee of contiguity for any of the ACPI registers
- release_region(facp->pm1a_evt, facp->pm1_evt_len);
+ if (facp->pm1a_evt)
+ release_region(facp->pm1a_evt, facp->pm1_evt_len);
if (facp->pm1b_evt)
release_region(facp->pm1b_evt, facp->pm1_evt_len);
- release_region(facp->pm1a_cnt, facp->pm1_cnt_len);
+ if (facp->pm1a_cnt)
+ release_region(facp->pm1a_cnt, facp->pm1_cnt_len);
if (facp->pm1b_cnt)
release_region(facp->pm1b_cnt, facp->pm1_cnt_len);
- if (facp->pm2_cnt)
- release_region(facp->pm2_cnt, facp->pm2_cnt_len);
- release_region(facp->pm_tmr, facp->pm_tm_len);
- release_region(facp->gpe0, facp->gpe0_len);
+ if (facp->pm_tmr)
+ release_region(facp->pm_tmr, facp->pm_tm_len);
+ if (facp->gpe0)
+ release_region(facp->gpe0, facp->gpe0_len);
if (facp->gpe1)
release_region(facp->gpe1, facp->gpe1_len);
@@ -632,28 +650,224 @@ static int acpi_release_ioports(struct acpi_facp *facp)
}
/*
+ * Examine/modify value
+ */
+static int acpi_do_ulong(ctl_table *ctl,
+ int write,
+ struct file *file,
+ void *buffer,
+ size_t *len)
+{
+ char str[2 * sizeof(unsigned long) + 4], *strend;
+ unsigned long val;
+ int size;
+
+ if (!write) {
+ if (file->f_pos) {
+ *len = 0;
+ return 0;
+ }
+
+ val = *(unsigned long*) ctl->data;
+ size = sprintf(str, "0x%08lx\n", val);
+ if (*len >= size) {
+ copy_to_user(buffer, str, size);
+ *len = size;
+ }
+ else
+ *len = 0;
+ }
+ else {
+ size = sizeof(str) - 1;
+ if (size > *len)
+ size = *len;
+ copy_from_user(str, buffer, size);
+ str[size] = '\0';
+ val = simple_strtoul(str, &strend, 0);
+ if (strend == str)
+ return -EINVAL;
+ *(unsigned long*) ctl->data = val;
+ }
+
+ file->f_pos += *len;
+ return 0;
+}
+
+/*
+ * Examine/modify event register
+ */
+static int acpi_do_event_reg(ctl_table *ctl,
+ int write,
+ struct file *file,
+ void *buffer,
+ size_t *len)
+{
+ char str[2 * sizeof(u32) + 4], *strend;
+ u32 val, enabling;
+ int size;
+
+ if (!write) {
+ if (file->f_pos) {
+ *len = 0;
+ return 0;
+ }
+
+ val = 0;
+ switch (ctl->ctl_name) {
+ case ACPI_PM1_ENABLE:
+ val = acpi_read_pm1_enable(acpi_facp);
+ break;
+ case ACPI_GPE_ENABLE:
+ val = acpi_read_gpe_enable(acpi_facp);
+ break;
+ case ACPI_GPE_LEVEL:
+ val = acpi_gpe_level;
+ break;
+ }
+
+ size = sprintf(str, "0x%08x\n", val);
+ if (*len >= size) {
+ copy_to_user(buffer, str, size);
+ *len = size;
+ }
+ else
+ *len = 0;
+ }
+ else
+ {
+ // fetch user value
+ size = sizeof(str) - 1;
+ if (size > *len)
+ size = *len;
+ copy_from_user(str, buffer, size);
+ str[size] = '\0';
+ val = (u32) simple_strtoul(str, &strend, 0);
+ if (strend == str)
+ return -EINVAL;
+
+ // store value in register
+ switch (ctl->ctl_name) {
+ case ACPI_PM1_ENABLE:
+ // clear previously disabled events
+ enabling = (val
+ & ~acpi_read_pm1_enable(acpi_facp));
+ acpi_write_pm1_status(acpi_facp, enabling);
+
+ if (val) {
+ // enable ACPI unless it is already
+ if (!acpi_is_enabled(acpi_facp))
+ acpi_enable(acpi_facp);
+ }
+ else if (!acpi_read_gpe_enable(acpi_facp)) {
+ // disable ACPI unless it is already
+ if (acpi_is_enabled(acpi_facp))
+ acpi_disable(acpi_facp);
+ }
+
+ acpi_write_pm1_enable(acpi_facp, val);
+ break;
+ case ACPI_GPE_ENABLE:
+ // clear previously disabled events
+ enabling = (val
+ & ~acpi_read_gpe_enable(acpi_facp));
+ while (acpi_read_gpe_status(acpi_facp) & enabling)
+ acpi_write_gpe_status(acpi_facp, enabling);
+
+ if (val) {
+ // enable ACPI unless it is already
+ if (!acpi_is_enabled(acpi_facp))
+ acpi_enable(acpi_facp);
+ }
+ else if (!acpi_read_pm1_enable(acpi_facp)) {
+ // disable ACPI unless it is already
+ if (acpi_is_enabled(acpi_facp))
+ acpi_disable(acpi_facp);
+ }
+
+ acpi_write_gpe_enable(acpi_facp, val);
+ break;
+ case ACPI_GPE_LEVEL:
+ acpi_gpe_level = val;
+ break;
+ }
+ }
+
+ file->f_pos += *len;
+ return 0;
+}
+
+/*
+ * Wait for next event
+ */
+static int acpi_do_event(ctl_table *ctl,
+ int write,
+ struct file *file,
+ void *buffer,
+ size_t *len)
+{
+ u32 pm1_status = 0, gpe_status = 0;
+ char str[4 * sizeof(u32) + 6];
+ int size;
+
+ if (write)
+ return -EPERM;
+ if (*len < sizeof(str)) {
+ *len = 0;
+ return 0;
+ }
+
+ for (;;) {
+ unsigned long flags;
+
+ // we need an atomic exchange here
+ spin_lock_irqsave(&acpi_event_lock, flags);
+ pm1_status = acpi_pm1_status;
+ acpi_pm1_status = 0;
+ gpe_status = acpi_gpe_status;
+ acpi_gpe_status = 0;
+ spin_unlock_irqrestore(&acpi_event_lock, flags);
+
+ if (pm1_status || gpe_status)
+ break;
+
+ // wait for an event to arrive
+ interruptible_sleep_on(&acpi_event_wait);
+ if (signal_pending(current))
+ return -ERESTARTSYS;
+ }
+
+ size = sprintf(str, "0x%08x 0x%08x\n", pm1_status, gpe_status);
+ copy_to_user(buffer, str, size);
+ *len = size;
+ file->f_pos += size;
+
+ return 0;
+}
+
+/*
* Initialize and enable ACPI
*/
static int __init acpi_init(void)
{
- if (acpi_map_tables())
+ if (acpi_find_tables() && acpi_find_piix4()) {
+ // no ACPI tables and not PIIX4
return -ENODEV;
+ }
- if (request_irq(acpi_facp->sci_int,
- acpi_irq,
- SA_INTERRUPT | SA_SHIRQ,
- "acpi",
- NULL)) {
+ if (acpi_facp->sci_int
+ && request_irq(acpi_facp->sci_int,
+ acpi_irq,
+ SA_INTERRUPT | SA_SHIRQ,
+ "acpi",
+ NULL)) {
printk(KERN_ERR "ACPI: SCI (IRQ%d) allocation failed\n",
acpi_facp->sci_int);
- acpi_unmap_tables();
+ acpi_destroy_tables();
return -ENODEV;
}
acpi_claim_ioports(acpi_facp);
-
- if (misc_register(&acpi_device))
- printk(KERN_ERR "ACPI: misc. register failed\n");
+ acpi_sysctl = register_sysctl_table(acpi_dir_table, 1);
/*
* Set up the ACPI idle function. Note that we can't really
@@ -664,7 +878,9 @@ static int __init acpi_init(void)
if (smp_num_cpus > 1)
return 0;
#endif
+
acpi_idle = acpi_idle_handler;
+
return 0;
}
@@ -673,11 +889,16 @@ static int __init acpi_init(void)
*/
static void __exit acpi_exit(void)
{
- misc_deregister(&acpi_device);
+ acpi_idle = NULL;
+
+ unregister_sysctl_table(acpi_sysctl);
acpi_disable(acpi_facp);
acpi_release_ioports(acpi_facp);
- free_irq(acpi_facp->sci_int, NULL);
- acpi_unmap_tables();
+
+ if (acpi_facp->sci_int)
+ free_irq(acpi_facp->sci_int, NULL);
+
+ acpi_destroy_tables();
}
#ifdef MODULE
diff --git a/drivers/net/Config.in b/drivers/net/Config.in
index d54f8fd30..0757aa349 100644
--- a/drivers/net/Config.in
+++ b/drivers/net/Config.in
@@ -46,6 +46,7 @@ if [ "$CONFIG_NET_ETHERNET" = "y" ]; then
if [ "$CONFIG_PPC" = "y" ]; then
tristate ' MACE (Power Mac ethernet) support' CONFIG_MACE
tristate ' BMAC (G3 ethernet) support' CONFIG_BMAC
+ tristate ' Symbios 53c885 (Synergy ethernet) support' CONFIG_NCR885E
fi
if [ "$CONFIG_ZORRO" = "y" ]; then
tristate ' Ariadne support' CONFIG_ARIADNE
@@ -217,6 +218,7 @@ fi
tristate 'PPP (point-to-point protocol) support' CONFIG_PPP
if [ ! "$CONFIG_PPP" = "n" ]; then
dep_tristate ' PPP support for async serial ports' CONFIG_PPP_ASYNC $CONFIG_PPP
+ dep_tristate ' PPP support for sync tty ports' CONFIG_PPP_SYNC_TTY $CONFIG_PPP
dep_tristate ' PPP Deflate compression' CONFIG_PPP_DEFLATE $CONFIG_PPP
dep_tristate ' PPP BSD-Compress compression' CONFIG_PPP_BSDCOMP m
fi
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index fe9208d4d..12fbc99f3 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -299,6 +299,13 @@ CONFIG_SLHC_BUILTIN = y
MX_OBJS += ppp_async.o
endif
endif
+ ifeq ($(CONFIG_PPP_SYNC_TTY),y)
+ LX_OBJS += ppp_synctty.o
+ else
+ ifeq ($(CONFIG_PPP_SYNC_TTY),m)
+ MX_OBJS += ppp_synctty.o
+ endif
+ endif
ifeq ($(CONFIG_PPP_DEFLATE),y)
CONFIG_PPPDEF_BUILTIN = y
else
@@ -316,6 +323,9 @@ else
ifeq ($(CONFIG_PPP_ASYNC),m)
MX_OBJS += ppp_async.o
endif
+ ifeq ($(CONFIG_PPP_SYNC_TTY),m)
+ MX_OBJS += ppp_synctty.o
+ endif
ifeq ($(CONFIG_PPP_DEFLATE),m)
CONFIG_PPPDEF_MODULE = y
endif
@@ -1031,6 +1041,14 @@ else
endif
endif
+ifeq ($(CONFIG_NCR885E),y)
+L_OBJS += ncr885e.o
+else
+ ifeq ($(CONFIG_NCR885E),m)
+ M_OBJS += ncr885e.o
+ endif
+endif
+
ifeq ($(CONFIG_ADAPTEC_STARFIRE),y)
L_OBJS += starfire.o
else
diff --git a/drivers/net/arcnet.c b/drivers/net/arcnet.c
index 353b44dc8..906d3fab7 100644
--- a/drivers/net/arcnet.c
+++ b/drivers/net/arcnet.c
@@ -1,184 +1,184 @@
-/* $Id: arcnet.c,v 1.34 1997/11/09 11:04:55 mj Exp $
-
- Written 1994-1996 by Avery Pennarun,
- derived from skeleton.c by Donald Becker.
-
- **********************
-
- The original copyright was as follows:
-
- skeleton.c Written 1993 by Donald Becker.
- Copyright 1993 United States Government as represented by the
- Director, National Security Agency. This software may only be used
- and distributed according to the terms of the GNU Public License as
- modified by SRC, incorporated herein by reference.
-
- **********************
-
- v3.02 (98/06/07)
- - Use register_netdevice() instead of register_netdev() to create
- new devices for RFC1051 and Ethernet encapsulation in arcnet_open.
- Likewise for unregistering them later. This avoids the deadlock
- encountered because the original routines call rtnl_lock() when
- it's already locked. [dw]
-
- v3.01 (98/04/17)
- - Interrupt handler now also checks dev->[se]dev are non-NULL
- to avoid crashes in interrupts during card init. [dw]
-
- v3.00 (97/11/09)
- - Minor cleanup of debugging messages. [mj]
-
- v2.93 ALPHA (97/11/06)
- - irq2dev mapping removed.
- - Interrupt handler now checks whether dev->priv is non-null in order
- to avoid crashes in interrupts which come during card init. [mj]
-
- v2.92 ALPHA (97/09/02)
- - Code cleanup [Martin Mares <mj@atrey.karlin.mff.cuni.cz>]
- - Better probing for the COM90xx chipset, although only as
- a temporary solution until we implement adding of all found
- devices at once. [mj]
-
- v2.91 ALPHA (97/08/19)
- - Add counting of octets in/out.
-
- v2.90 ALPHA (97/08/08)
- - Add support for kernel command line parsing so that chipset
- drivers are usable when compiled in.
-
- v2.80 ALPHA (97/08/01)
- - Split source into multiple files; generic arcnet support and
- individual chipset drivers. <Dave@imladris.demon.co.uk>
-
- v2.61 ALPHA (97/07/30) by David Woodhouse (Dave@imladris.demon.co.uk)
- for Nortel (Northern Telecom).
- - Added support for IO-mapped modes and for SMC COM20020 chipset.
- - Fixed (avoided) race condition in send_packet routines which was
- discovered when the buffer copy routines got slow (?).
- - Fixed support for device naming at load time.
- - Added backplane, clock and timeout options for COM20020.
- - Added support for promiscuous mode.
-
- v2.60 ALPHA (96/11/23)
- - Added patch from Vojtech Pavlik <vojtech@atrey.karlin.mff.cuni.cz>
- and Martin Mares <mj@k332.feld.cvut.cz> to make the driver work
- with the new Linux 2.1.x memory management. I modified their
- patch quite a bit though; bugs are my fault. More changes should
- be made to get eliminate any remaining phys_to_virt calls.
- - Quietly ignore protocol id's 0, 1, 8, and 243. Thanks to Jake
- Messinger <jake@ams.com> for reporting these codes and their
- meanings.
- - Smarter shmem probe for cards with 4k mirrors. (does it work?)
- - Initial support for RIM I type cards which use no I/O ports at
- all. To use this option, you need to compile with RIM_I_MODE
- enabled. Thanks to Kolja Waschk <kawk@yo.com> for explaining
- RIM I programming to me. Now, does my RIM I code actually
- work?
-
- v2.56 (96/10/18)
- - Turned arc0e/arc0s startup messages back on by default, as most
- people will probably not notice the additional devices
- otherwise. This causes undue confusion.
- - Fixed a tiny but noticeable bug in the packet debugging routines
- (thanks Tomasz)
-
- The following has been SUMMARIZED. The complete ChangeLog is
- available in the full Linux-ARCnet package at
- http://www.worldvisions.ca/~apenwarr/arcnet
-
- v2.50 (96/02/24)
- - Massively improved autoprobe routines; they now work even as a
- module. Thanks to Vojtech Pavlik <Vojtech.Pavlik@st.mff.cuni.cz>
- for his ideas and help in this area.
- - Changed printk's around quite a lot.
-
- v2.22 (95/12/08)
- - Major cleanups, speedups, and better code-sharing.
- - Eliminated/changed many useless/meaningless/scary debug messages
- (and, in most cases, the bugs that caused them).
- - Better IPX support.
- - lp->stats updated properly.
- - RECON checking now by default only prints a message if there are
- excessive errors (ie. your cable is probably broken).
- - New RFC1051-compliant "arc0s" virtual device by Tomasz
- Motylewski.
- - Excess debug messages can be compiled out to reduce code size.
-
- v2.00 (95/09/06)
- - ARCnet RECON messages are now detected and logged as "carrier"
- errors.
- - The TXACK flag is now checked, and errors are logged.
- - Debug levels are now completely different. See the README.
- - Massive code cleanups, with several no-longer-necessary and some
- completely useless options removed.
- - Multiprotocol support. You can now use the "arc0e" device to
- send "Ethernet-Encapsulation" packets, which are compatible with
- Windows for Workgroups and LAN Manager, and possibly other
- software. See the README for more information.
-
- v1.02 (95/06/21)
- - A fix to make "exception" packets sent from Linux receivable
- on other systems. (The protocol_id byte was sometimes being set
- incorrectly, and Linux wasn't checking it on receive so it
- didn't show up)
-
- v1.01 (95/03/24)
- - Fixed some IPX-related bugs. (Thanks to Tomasz Motylewski
- <motyl@tichy.ch.uj.edu.pl> for the patches to make arcnet work
- with dosemu!)
-
- v1.00 (95/02/15)
- - Initial non-alpha release.
-
-
- TO DO: (semi-prioritized)
-
- - Use cleaner "architecture-independent" shared memory access.
- This is half-done in ARCnet 2.60, but still uses some
- undocumented i386 stuff. (We shouldn't call phys_to_virt,
- for example.)
- - Allow use of RFC1051 or Ether devices without RFC1201.
- - Keep separate stats for each device.
- - Support "arpless" mode like NetBSD does, and as recommended
- by the (obsoleted) RFC1051.
- - Smarter recovery from RECON-during-transmit conditions. (ie.
- retransmit immediately)
- - Add support for the new 1.3.x IP header cache, and other features.
- - Replace setting of debug level with the "metric" flag hack by
- something that still exists. SIOCDEVPRIVATE is a good candidate,
- but it would require an extra user-level utility.
-
- - What about cards with shared memory that can be "turned off?"
- (or that have none at all, like the SMC PC500longboard)
- Does this work now, with IO_MAPPED_BUFFERS?
-
- - Autoconfigure PDI5xxPlus cards. (I now have a PDI508Plus to play
- with temporarily.) Update: yes, the Pure Data config program
- for DOS works fine, but the PDI508Plus I have doesn't! :)
- - ATA protocol support??
- - VINES TCP/IP encapsulation?? (info needed)
-
- Sources:
- - Crynwr arcnet.com/arcether.com packet drivers.
- - arcnet.c v0.00 dated 1/1/94 and apparently by
- Donald Becker - it didn't work :)
- - skeleton.c v0.05 dated 11/16/93 by Donald Becker
- (from Linux Kernel 1.1.45)
- - RFC's 1201 and 1051 - re: TCP/IP over ARCnet
- - The official ARCnet COM9026 data sheets (!) thanks to Ken
- Cornetet <kcornete@nyx10.cs.du.edu>
- - The official ARCnet COM20020 data sheets.
- - Information on some more obscure ARCnet controller chips, thanks
- to the nice people at SMC.
- - net/inet/eth.c (from kernel 1.1.50) for header-building info.
- - Alternate Linux ARCnet source by V.Shergin <vsher@sao.stavropol.su>
- - Textual information and more alternate source from Joachim Koenig
- <jojo@repas.de>
-*/
+/* $Id: arcnet.c,v 1.34 1997/11/09 11:04:55 mj Exp $
+
+ Written 1994-1996 by Avery Pennarun,
+ derived from skeleton.c by Donald Becker.
+
+ **********************
+
+ The original copyright was as follows:
+
+ skeleton.c Written 1993 by Donald Becker.
+ Copyright 1993 United States Government as represented by the
+ Director, National Security Agency. This software may only be used
+ and distributed according to the terms of the GNU Public License as
+ modified by SRC, incorporated herein by reference.
+
+ **********************
+
+ v3.02 (98/06/07)
+ - Use register_netdevice() instead of register_netdev() to create
+ new devices for RFC1051 and Ethernet encapsulation in arcnet_open.
+ Likewise for unregistering them later. This avoids the deadlock
+ encountered because the original routines call rtnl_lock() when
+ it's already locked. [dw]
+
+ v3.01 (98/04/17)
+ - Interrupt handler now also checks dev->[se]dev are non-NULL
+ to avoid crashes in interrupts during card init. [dw]
+
+ v3.00 (97/11/09)
+ - Minor cleanup of debugging messages. [mj]
+
+ v2.93 ALPHA (97/11/06)
+ - irq2dev mapping removed.
+ - Interrupt handler now checks whether dev->priv is non-null in order
+ to avoid crashes in interrupts which come during card init. [mj]
+
+ v2.92 ALPHA (97/09/02)
+ - Code cleanup [Martin Mares <mj@atrey.karlin.mff.cuni.cz>]
+ - Better probing for the COM90xx chipset, although only as
+ a temporary solution until we implement adding of all found
+ devices at once. [mj]
+
+ v2.91 ALPHA (97/08/19)
+ - Add counting of octets in/out.
+
+ v2.90 ALPHA (97/08/08)
+ - Add support for kernel command line parsing so that chipset
+ drivers are usable when compiled in.
+
+ v2.80 ALPHA (97/08/01)
+ - Split source into multiple files; generic arcnet support and
+ individual chipset drivers. <Dave@imladris.demon.co.uk>
+
+ v2.61 ALPHA (97/07/30) by David Woodhouse (Dave@imladris.demon.co.uk)
+ for Nortel (Northern Telecom).
+ - Added support for IO-mapped modes and for SMC COM20020 chipset.
+ - Fixed (avoided) race condition in send_packet routines which was
+ discovered when the buffer copy routines got slow (?).
+ - Fixed support for device naming at load time.
+ - Added backplane, clock and timeout options for COM20020.
+ - Added support for promiscuous mode.
+
+ v2.60 ALPHA (96/11/23)
+ - Added patch from Vojtech Pavlik <vojtech@atrey.karlin.mff.cuni.cz>
+ and Martin Mares <mj@k332.feld.cvut.cz> to make the driver work
+ with the new Linux 2.1.x memory management. I modified their
+ patch quite a bit though; bugs are my fault. More changes should
+ be made to get eliminate any remaining phys_to_virt calls.
+ - Quietly ignore protocol id's 0, 1, 8, and 243. Thanks to Jake
+ Messinger <jake@ams.com> for reporting these codes and their
+ meanings.
+ - Smarter shmem probe for cards with 4k mirrors. (does it work?)
+ - Initial support for RIM I type cards which use no I/O ports at
+ all. To use this option, you need to compile with RIM_I_MODE
+ enabled. Thanks to Kolja Waschk <kawk@yo.com> for explaining
+ RIM I programming to me. Now, does my RIM I code actually
+ work?
+
+ v2.56 (96/10/18)
+ - Turned arc0e/arc0s startup messages back on by default, as most
+ people will probably not notice the additional devices
+ otherwise. This causes undue confusion.
+ - Fixed a tiny but noticeable bug in the packet debugging routines
+ (thanks Tomasz)
+
+ The following has been SUMMARIZED. The complete ChangeLog is
+ available in the full Linux-ARCnet package at
+ http://www.worldvisions.ca/~apenwarr/arcnet
+
+ v2.50 (96/02/24)
+ - Massively improved autoprobe routines; they now work even as a
+ module. Thanks to Vojtech Pavlik <Vojtech.Pavlik@st.mff.cuni.cz>
+ for his ideas and help in this area.
+ - Changed printk's around quite a lot.
+
+ v2.22 (95/12/08)
+ - Major cleanups, speedups, and better code-sharing.
+ - Eliminated/changed many useless/meaningless/scary debug messages
+ (and, in most cases, the bugs that caused them).
+ - Better IPX support.
+ - lp->stats updated properly.
+ - RECON checking now by default only prints a message if there are
+ excessive errors (ie. your cable is probably broken).
+ - New RFC1051-compliant "arc0s" virtual device by Tomasz
+ Motylewski.
+ - Excess debug messages can be compiled out to reduce code size.
+
+ v2.00 (95/09/06)
+ - ARCnet RECON messages are now detected and logged as "carrier"
+ errors.
+ - The TXACK flag is now checked, and errors are logged.
+ - Debug levels are now completely different. See the README.
+ - Massive code cleanups, with several no-longer-necessary and some
+ completely useless options removed.
+ - Multiprotocol support. You can now use the "arc0e" device to
+ send "Ethernet-Encapsulation" packets, which are compatible with
+ Windows for Workgroups and LAN Manager, and possibly other
+ software. See the README for more information.
+
+ v1.02 (95/06/21)
+ - A fix to make "exception" packets sent from Linux receivable
+ on other systems. (The protocol_id byte was sometimes being set
+ incorrectly, and Linux wasn't checking it on receive so it
+ didn't show up)
+
+ v1.01 (95/03/24)
+ - Fixed some IPX-related bugs. (Thanks to Tomasz Motylewski
+ <motyl@tichy.ch.uj.edu.pl> for the patches to make arcnet work
+ with dosemu!)
+
+ v1.00 (95/02/15)
+ - Initial non-alpha release.
+
+
+ TO DO: (semi-prioritized)
+
+ - Use cleaner "architecture-independent" shared memory access.
+ This is half-done in ARCnet 2.60, but still uses some
+ undocumented i386 stuff. (We shouldn't call phys_to_virt,
+ for example.)
+ - Allow use of RFC1051 or Ether devices without RFC1201.
+ - Keep separate stats for each device.
+ - Support "arpless" mode like NetBSD does, and as recommended
+ by the (obsoleted) RFC1051.
+ - Smarter recovery from RECON-during-transmit conditions. (ie.
+ retransmit immediately)
+ - Add support for the new 1.3.x IP header cache, and other features.
+ - Replace setting of debug level with the "metric" flag hack by
+ something that still exists. SIOCDEVPRIVATE is a good candidate,
+ but it would require an extra user-level utility.
+
+ - What about cards with shared memory that can be "turned off?"
+ (or that have none at all, like the SMC PC500longboard)
+ Does this work now, with IO_MAPPED_BUFFERS?
+
+ - Autoconfigure PDI5xxPlus cards. (I now have a PDI508Plus to play
+ with temporarily.) Update: yes, the Pure Data config program
+ for DOS works fine, but the PDI508Plus I have doesn't! :)
+ - ATA protocol support??
+ - VINES TCP/IP encapsulation?? (info needed)
+
+ Sources:
+ - Crynwr arcnet.com/arcether.com packet drivers.
+ - arcnet.c v0.00 dated 1/1/94 and apparently by
+ Donald Becker - it didn't work :)
+ - skeleton.c v0.05 dated 11/16/93 by Donald Becker
+ (from Linux Kernel 1.1.45)
+ - RFC's 1201 and 1051 - re: TCP/IP over ARCnet
+ - The official ARCnet COM9026 data sheets (!) thanks to Ken
+ Cornetet <kcornete@nyx10.cs.du.edu>
+ - The official ARCnet COM20020 data sheets.
+ - Information on some more obscure ARCnet controller chips, thanks
+ to the nice people at SMC.
+ - net/inet/eth.c (from kernel 1.1.50) for header-building info.
+ - Alternate Linux ARCnet source by V.Shergin <vsher@sao.stavropol.su>
+ - Textual information and more alternate source from Joachim Koenig
+ <jojo@repas.de>
+ */
static const char *version =
- "arcnet.c: v3.02 98/06/07 Avery Pennarun <apenwarr@worldvisions.ca> et al.\n";
+"arcnet.c: v3.02 98/06/07 Avery Pennarun <apenwarr@worldvisions.ca> et al.\n";
#include <linux/module.h>
#include <linux/config.h>
@@ -230,15 +230,15 @@ static const char *version =
#define ARCSTATUS ((*lp->astatus)(dev))
#define ACOMMAND(x) ((*lp->acommand)(dev, x))
-int arcnet_debug=ARCNET_DEBUG;
+int arcnet_debug = ARCNET_DEBUG;
/* Exported function prototypes */
#ifdef MODULE
-int init_module(void);
+int init_module(void);
void cleanup_module(void);
#else
-void arcnet_init(void);
+int arcnet_init(void);
static int init_module(void);
#ifdef CONFIG_ARCNET_COM90xx
extern char com90xx_explicit;
@@ -247,13 +247,13 @@ extern int arc90xx_probe(struct net_device *dev);
#endif
void arcnet_tx_done(struct net_device *dev, struct arcnet_local *lp);
-void arcnet_use_count (int open);
+void arcnet_use_count(int open);
void arcnet_setup(struct net_device *dev);
void arcnet_makename(char *device);
void arcnetA_continue_tx(struct net_device *dev);
-int arcnet_go_tx(struct net_device *dev,int enable_irq);
-void arcnet_interrupt(int irq,void *dev_id,struct pt_regs *regs);
-void arcnet_rx(struct arcnet_local *lp, u_char *arcsoft, short length, int saddr, int daddr);
+int arcnet_go_tx(struct net_device *dev, int enable_irq);
+void arcnet_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+void arcnet_rx(struct arcnet_local *lp, u_char * arcsoft, short length, int saddr, int daddr);
EXPORT_SYMBOL(arcnet_debug);
EXPORT_SYMBOL(arcnet_tx_done);
@@ -266,32 +266,32 @@ EXPORT_SYMBOL(arcnet_interrupt);
EXPORT_SYMBOL(arcnet_rx);
#if ARCNET_DEBUG_MAX & D_SKB
-void arcnet_dump_skb(struct net_device *dev,struct sk_buff *skb,
- char *desc);
+void arcnet_dump_skb(struct net_device *dev, struct sk_buff *skb,
+ char *desc);
EXPORT_SYMBOL(arcnet_dump_skb);
#else
-# define arcnet_dump_skb(dev,skb,desc) ;
+#define arcnet_dump_skb(dev,skb,desc) ;
#endif
#if (ARCNET_DEBUG_MAX & D_RX) || (ARCNET_DEBUG_MAX & D_TX)
-void arcnet_dump_packet(struct net_device *dev,u_char *buffer,int ext,
- char *desc);
+void arcnet_dump_packet(struct net_device *dev, u_char * buffer, int ext,
+ char *desc);
EXPORT_SYMBOL(arcnet_dump_packet);
#else
-# define arcnet_dump_packet(dev,buffer,ext,desc) ;
+#define arcnet_dump_packet(dev,buffer,ext,desc) ;
#endif
/* Internal function prototypes */
static int arcnet_open(struct net_device *dev);
static int arcnet_close(struct net_device *dev);
-static int arcnetA_header(struct sk_buff *skb,struct net_device *dev,
- unsigned short type,void *daddr,void *saddr,unsigned len);
+static int arcnetA_header(struct sk_buff *skb, struct net_device *dev,
+ unsigned short type, void *daddr, void *saddr, unsigned len);
static int arcnetA_rebuild_header(struct sk_buff *skb);
-static int arcnet_send_packet_bad(struct sk_buff *skb,struct net_device *dev);
+static int arcnet_send_packet_bad(struct sk_buff *skb, struct net_device *dev);
static int arcnetA_send_packet(struct sk_buff *skb, struct net_device *dev);
-static void arcnetA_rx(struct net_device *dev,u_char *buf,
- int length,u_char saddr, u_char daddr);
+static void arcnetA_rx(struct net_device *dev, u_char * buf,
+ int length, u_char saddr, u_char daddr);
static struct net_device_stats *arcnet_get_stats(struct net_device *dev);
static unsigned short arcnetA_type_trans(struct sk_buff *skb,
struct net_device *dev);
@@ -302,8 +302,8 @@ static unsigned short arcnetA_type_trans(struct sk_buff *skb,
static int arcnetE_init(struct net_device *dev);
static int arcnetE_open_close(struct net_device *dev);
static int arcnetE_send_packet(struct sk_buff *skb, struct net_device *dev);
-static void arcnetE_rx(struct net_device *dev,u_char *arcsoft,
- int length,u_char saddr, u_char daddr);
+static void arcnetE_rx(struct net_device *dev, u_char * arcsoft,
+ int length, u_char saddr, u_char daddr);
#endif
@@ -312,12 +312,12 @@ static void arcnetE_rx(struct net_device *dev,u_char *arcsoft,
static int arcnetS_init(struct net_device *dev);
static int arcnetS_open_close(struct net_device *dev);
static int arcnetS_send_packet(struct sk_buff *skb, struct net_device *dev);
-static void arcnetS_rx(struct net_device *dev,u_char *buf,
- int length,u_char saddr, u_char daddr);
-static int arcnetS_header(struct sk_buff *skb,struct net_device *dev,
- unsigned short type,void *daddr,void *saddr,unsigned len);
+static void arcnetS_rx(struct net_device *dev, u_char * buf,
+ int length, u_char saddr, u_char daddr);
+static int arcnetS_header(struct sk_buff *skb, struct net_device *dev,
+ unsigned short type, void *daddr, void *saddr, unsigned len);
static int arcnetS_rebuild_header(struct sk_buff *skb);
-static unsigned short arcnetS_type_trans(struct sk_buff *skb,struct net_device *dev);
+static unsigned short arcnetS_type_trans(struct sk_buff *skb, struct net_device *dev);
#endif
@@ -330,22 +330,21 @@ static unsigned short arcnetS_type_trans(struct sk_buff *skb,struct net_device *
/* Dump the contents of an sk_buff
*/
#if ARCNET_DEBUG_MAX & D_SKB
-void arcnet_dump_skb(struct net_device *dev,struct sk_buff *skb,char *desc)
+void arcnet_dump_skb(struct net_device *dev, struct sk_buff *skb, char *desc)
{
int i;
long flags;
save_flags(flags);
cli();
- printk(KERN_DEBUG "%6s: skb dump (%s) follows:",dev->name,desc);
- for(i=0; i<skb->len; i++)
- {
- if (i%16==0)
- printk("\n" KERN_DEBUG "[%04X] ",i);
- printk("%02X ",((u_char *)skb->data)[i]);
+ printk(KERN_DEBUG "%6s: skb dump (%s) follows:", dev->name, desc);
+ for (i = 0; i < skb->len; i++) {
+ if (i % 16 == 0)
+ printk("\n" KERN_DEBUG "[%04X] ", i);
+ printk("%02X ", ((u_char *) skb->data)[i]);
}
- printk("\n");
- restore_flags(flags);
+ printk("\n");
+ restore_flags(flags);
}
#endif
@@ -353,19 +352,18 @@ void arcnet_dump_skb(struct net_device *dev,struct sk_buff *skb,char *desc)
/* Dump the contents of an ARCnet buffer
*/
#if (ARCNET_DEBUG_MAX & D_RX) || (ARCNET_DEBUG_MAX & D_TX)
-void arcnet_dump_packet(struct net_device *dev,u_char *buffer,int ext,char *desc)
+void arcnet_dump_packet(struct net_device *dev, u_char * buffer, int ext, char *desc)
{
int i;
long flags;
save_flags(flags);
cli();
- printk(KERN_DEBUG "%6s: packet dump (%s) follows:",dev->name,desc);
- for (i=0; i<256+(ext!=0)*256; i++)
- {
- if (i%16==0)
- printk("\n" KERN_DEBUG "[%04X] ",i);
- printk("%02X ",buffer[i]);
+ printk(KERN_DEBUG "%6s: packet dump (%s) follows:", dev->name, desc);
+ for (i = 0; i < 256 + (ext != 0) * 256; i++) {
+ if (i % 16 == 0)
+ printk("\n" KERN_DEBUG "[%04X] ", i);
+ printk("%02X ", buffer[i]);
}
printk("\n");
restore_flags(flags);
@@ -386,24 +384,24 @@ void arcnet_setup(struct net_device *dev)
{
dev_init_buffers(dev);
- dev->broadcast[0] = 0x00; /* for us, broadcasts are address 0 */
- dev->addr_len = 1;
- dev->type = ARPHRD_ARCNET;
- dev->tx_queue_len = 30;
+ dev->broadcast[0] = 0x00; /* for us, broadcasts are address 0 */
+ dev->addr_len = 1;
+ dev->type = ARPHRD_ARCNET;
+ dev->tx_queue_len = 30;
/* New-style flags. */
- dev->flags = IFF_BROADCAST;
+ dev->flags = IFF_BROADCAST;
/* Put in this stuff here, so we don't have to export the symbols
* to the chipset drivers.
*/
- dev->open=arcnet_open;
- dev->stop=arcnet_close;
- dev->hard_start_xmit=arcnetA_send_packet;
- dev->get_stats=arcnet_get_stats;
- dev->hard_header=arcnetA_header;
- dev->rebuild_header=arcnetA_rebuild_header;
+ dev->open = arcnet_open;
+ dev->stop = arcnet_close;
+ dev->hard_start_xmit = arcnetA_send_packet;
+ dev->get_stats = arcnet_get_stats;
+ dev->hard_header = arcnetA_header;
+ dev->rebuild_header = arcnetA_rebuild_header;
}
@@ -420,167 +418,164 @@ void arcnet_setup(struct net_device *dev)
* registers that "should" only need to be set once at boot, so that
* there is non-reboot way to recover if something goes wrong.
*/
-static int
-arcnet_open(struct net_device *dev)
+static int arcnet_open(struct net_device *dev)
{
- struct arcnet_local *lp = (struct arcnet_local *)dev->priv;
-
- /* if (dev->metric>=1000)
- * {
- * arcnet_debug=dev->metric-1000;
- * printk(KERN_INFO "%6s: debug level set to %d\n",dev->name,arcnet_debug);
- * dev->metric=1;
- *}
- */
- BUGMSG(D_INIT,"arcnet_open: resetting card.\n");
-
- /* try to put the card in a defined state - if it fails the first
- * time, actually reset it.
- */
- if ((*lp->arcnet_reset)(dev,0) && (*lp->arcnet_reset)(dev,1))
- return -ENODEV;
-
- dev->tbusy=0;
- dev->interrupt=0;
- lp->intx=0;
- lp->in_txhandler=0;
-
- /* The RFC1201 driver is the default - just store */
- lp->adev=dev;
-
- /* we're started */
- dev->start=1;
+ struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
+
+ /* if (dev->metric>=1000)
+ * {
+ * arcnet_debug=dev->metric-1000;
+ * printk(KERN_INFO "%6s: debug level set to %d\n",dev->name,arcnet_debug);
+ * dev->metric=1;
+ *}
+ */
+ BUGMSG(D_INIT, "arcnet_open: resetting card.\n");
+
+ /* try to put the card in a defined state - if it fails the first
+ * time, actually reset it.
+ */
+ if ((*lp->arcnet_reset) (dev, 0) && (*lp->arcnet_reset) (dev, 1))
+ return -ENODEV;
+
+ dev->tbusy = 0;
+ dev->interrupt = 0;
+ lp->intx = 0;
+ lp->in_txhandler = 0;
+
+ /* The RFC1201 driver is the default - just store */
+ lp->adev = dev;
+
+ /* we're started */
+ dev->start = 1;
#ifdef CONFIG_ARCNET_ETH
- /* Initialize the ethernet-encap protocol driver */
- lp->edev=(struct net_device *)kmalloc(sizeof(struct net_device),GFP_KERNEL);
- if (lp->edev == NULL)
- return -ENOMEM;
- memcpy(lp->edev,dev,sizeof(struct net_device));
- lp->edev->type=ARPHRD_ETHER;
- lp->edev->name=(char *)kmalloc(10,GFP_KERNEL);
- if (lp->edev->name == NULL) {
- kfree(lp->edev);
- lp->edev = NULL;
- return -ENOMEM;
- }
- sprintf(lp->edev->name,"%se",dev->name);
- lp->edev->init=arcnetE_init;
- register_netdevice(lp->edev);
+ /* Initialize the ethernet-encap protocol driver */
+ lp->edev = (struct net_device *) kmalloc(sizeof(struct net_device), GFP_KERNEL);
+ if (lp->edev == NULL)
+ return -ENOMEM;
+ memcpy(lp->edev, dev, sizeof(struct net_device));
+ lp->edev->type = ARPHRD_ETHER;
+ lp->edev->name = (char *) kmalloc(10, GFP_KERNEL);
+ if (lp->edev->name == NULL) {
+ kfree(lp->edev);
+ lp->edev = NULL;
+ return -ENOMEM;
+ }
+ sprintf(lp->edev->name, "%se", dev->name);
+ lp->edev->init = arcnetE_init;
+ register_netdevice(lp->edev);
#endif
#ifdef CONFIG_ARCNET_1051
- /* Initialize the RFC1051-encap protocol driver */
- lp->sdev=(struct net_device *)kmalloc(sizeof(struct net_device)+10,GFP_KERNEL);
- if(lp->sdev == NULL)
- {
+ /* Initialize the RFC1051-encap protocol driver */
+ lp->sdev = (struct net_device *) kmalloc(sizeof(struct net_device) + 10, GFP_KERNEL);
+ if (lp->sdev == NULL) {
#ifdef CONFIG_ARCNET_ETH
- if(lp->edev)
- kfree(lp->edev);
- lp->edev=NULL;
- return -ENOMEM;
-#endif
- }
- memcpy(lp->sdev,dev,sizeof(struct net_device));
- lp->sdev->name=(char *)(lp+1);
- sprintf(lp->sdev->name,"%ss",dev->name);
- lp->sdev->init=arcnetS_init;
- register_netdevice(lp->sdev);
+ if (lp->edev)
+ kfree(lp->edev);
+ lp->edev = NULL;
+ return -ENOMEM;
+#endif
+ }
+ memcpy(lp->sdev, dev, sizeof(struct net_device));
+ lp->sdev->name = (char *) (lp + 1);
+ sprintf(lp->sdev->name, "%ss", dev->name);
+ lp->sdev->init = arcnetS_init;
+ register_netdevice(lp->sdev);
#endif
- /* Enable TX if we need to */
- if (lp->en_dis_able_TX)
- (*lp->en_dis_able_TX)(dev, 1);
+ /* Enable TX if we need to */
+ if (lp->en_dis_able_TX)
+ (*lp->en_dis_able_TX) (dev, 1);
- /* make sure we're ready to receive IRQ's.
- * arcnet_reset sets this for us, but if we receive one before
- * START is set to 1, it could be ignored. So, we turn IRQ's
- * off, then on again to clean out the IRQ controller.
- */
+ /* make sure we're ready to receive IRQ's.
+ * arcnet_reset sets this for us, but if we receive one before
+ * START is set to 1, it could be ignored. So, we turn IRQ's
+ * off, then on again to clean out the IRQ controller.
+ */
- AINTMASK(0);
- udelay(1); /* give it time to set the mask before
- * we reset it again. (may not even be
- * necessary)
- */
- SETMASK;
+ AINTMASK(0);
+ udelay(1); /* give it time to set the mask before
+ * we reset it again. (may not even be
+ * necessary)
+ */
+ SETMASK;
- /* Let it increase its use count */
- (*lp->openclose_device)(1);
+ /* Let it increase its use count */
+ (*lp->openclose_device) (1);
- return 0;
+ return 0;
}
/* The inverse routine to arcnet_open - shuts down the card.
*/
-static int
-arcnet_close(struct net_device *dev)
+static int arcnet_close(struct net_device *dev)
{
- struct arcnet_local *lp = (struct arcnet_local *)dev->priv;
+ struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
- if (test_and_set_bit(0, (int *)&dev->tbusy))
- BUGMSG(D_NORMAL, "arcnet_close: tbusy already set!\n");
+ if (test_and_set_bit(0, (int *) &dev->tbusy))
+ BUGMSG(D_NORMAL, "arcnet_close: tbusy already set!\n");
- dev->start=0;
+ dev->start = 0;
#ifdef CONFIG_ARCNET_1051
- lp->sdev->tbusy=1;
- lp->sdev->start=0;
+ lp->sdev->tbusy = 1;
+ lp->sdev->start = 0;
#endif
#ifdef CONFIG_ARCNET_ETH
- lp->edev->tbusy=1;
- lp->edev->start=0;
+ lp->edev->tbusy = 1;
+ lp->edev->start = 0;
#endif
- /* Shut down the card */
+ /* Shut down the card */
- /* Disable TX if we need to */
- if (lp->en_dis_able_TX)
- (*lp->en_dis_able_TX)(dev, 0);
+ /* Disable TX if we need to */
+ if (lp->en_dis_able_TX)
+ (*lp->en_dis_able_TX) (dev, 0);
- (*lp->arcnet_reset)(dev, 3); /* reset IRQ won't run if START=0 */
+ (*lp->arcnet_reset) (dev, 3); /* reset IRQ won't run if START=0 */
#if 0
- lp->intmask=0;
- SETMASK; /* no IRQ's (except RESET, of course) */
- ACOMMAND(NOTXcmd); /* stop transmit */
- ACOMMAND(NORXcmd); /* disable receive */
+ lp->intmask = 0;
+ SETMASK; /* no IRQ's (except RESET, of course) */
+ ACOMMAND(NOTXcmd); /* stop transmit */
+ ACOMMAND(NORXcmd); /* disable receive */
#endif
- /* reset more flags */
- dev->interrupt=0;
+ /* reset more flags */
+ dev->interrupt = 0;
#ifdef CONFIG_ARCNET_ETH
- lp->edev->interrupt=0;
+ lp->edev->interrupt = 0;
#endif
#ifdef CONFIG_ARCNET_1051
- lp->sdev->interrupt=0;
+ lp->sdev->interrupt = 0;
#endif
- /* do NOT free lp->adev!! It's static! */
- lp->adev=NULL;
+ /* do NOT free lp->adev!! It's static! */
+ lp->adev = NULL;
#ifdef CONFIG_ARCNET_ETH
- /* free the ethernet-encap protocol device */
- lp->edev->priv=NULL;
- unregister_netdevice(lp->edev);
- kfree(lp->edev->name);
- kfree(lp->edev);
- lp->edev=NULL;
+ /* free the ethernet-encap protocol device */
+ lp->edev->priv = NULL;
+ unregister_netdevice(lp->edev);
+ kfree(lp->edev->name);
+ kfree(lp->edev);
+ lp->edev = NULL;
#endif
#ifdef CONFIG_ARCNET_1051
- /* free the RFC1051-encap protocol device */
- lp->sdev->priv=NULL;
- unregister_netdevice(lp->sdev);
- kfree(lp->sdev);
- lp->sdev=NULL;
+ /* free the RFC1051-encap protocol device */
+ lp->sdev->priv = NULL;
+ unregister_netdevice(lp->sdev);
+ kfree(lp->sdev);
+ lp->sdev = NULL;
#endif
- /* Update the statistics here. (not necessary in ARCnet) */
+ /* Update the statistics here. (not necessary in ARCnet) */
- /* Decrease the use count */
- (*lp->openclose_device)(0);
+ /* Decrease the use count */
+ (*lp->openclose_device) (0);
- return 0;
+ return 0;
}
@@ -592,241 +587,213 @@ arcnet_close(struct net_device *dev)
/* Generic error checking routine for arcnet??_send_packet
*/
-static int
-arcnet_send_packet_bad(struct sk_buff *skb, struct net_device *dev)
+static int arcnet_send_packet_bad(struct sk_buff *skb, struct net_device *dev)
{
- struct arcnet_local *lp = (struct arcnet_local *)dev->priv;
-
- BUGMSG(D_DURING,"transmit requested (status=%Xh, inTX=%d)\n",
- ARCSTATUS,lp->intx);
-
- if (lp->in_txhandler)
- {
- BUGMSG(D_NORMAL,"send_packet called while in txhandler!\n");
- lp->stats.tx_dropped++;
- return 1;
- }
-
- if (lp->intx>1)
- {
- BUGMSG(D_NORMAL,"send_packet called while intx!\n");
- lp->stats.tx_dropped++;
- return 1;
- }
-
- if (test_bit(0, (int *)&dev->tbusy))
- {
- /* If we get here, some higher level has decided we are broken.
- There should really be a "kick me" function call instead. */
- int tickssofar = jiffies - dev->trans_start;
-
- int status=ARCSTATUS;
-
- if (tickssofar < TX_TIMEOUT)
- {
- BUGMSG(D_DURING,"premature kickme! (status=%Xh ticks=%d o.skb=%ph numsegs=%d segnum=%d\n",
- status,tickssofar,lp->outgoing.skb,
- lp->outgoing.numsegs,
- lp->outgoing.segnum);
- return 1;
- }
+ struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
- lp->intmask &= ~TXFREEflag;
- SETMASK;
+ BUGMSG(D_DURING, "transmit requested (status=%Xh, inTX=%d)\n",
+ ARCSTATUS, lp->intx);
- if (status&TXFREEflag) /* transmit _DID_ finish */
- {
- BUGMSG(D_NORMAL,"tx timeout - missed IRQ? (status=%Xh, ticks=%d, mask=%Xh, dest=%02Xh)\n",
- status,tickssofar,lp->intmask,lp->lasttrans_dest);
- lp->stats.tx_errors++;
+ if (lp->in_txhandler) {
+ BUGMSG(D_NORMAL, "send_packet called while in txhandler!\n");
+ lp->stats.tx_dropped++;
+ return 1;
}
- else
- {
- BUGMSG(D_EXTRA,"tx timed out (status=%Xh, tickssofar=%d, intmask=%Xh, dest=%02Xh)\n",
- status,tickssofar,lp->intmask,lp->lasttrans_dest);
- lp->stats.tx_errors++;
- lp->stats.tx_aborted_errors++;
-
- ACOMMAND(NOTXcmd);
+ if (lp->intx > 1) {
+ BUGMSG(D_NORMAL, "send_packet called while intx!\n");
+ lp->stats.tx_dropped++;
+ return 1;
}
+ if (test_bit(0, (int *) &dev->tbusy)) {
+ /* If we get here, some higher level has decided we are broken.
+ There should really be a "kick me" function call instead. */
+ int tickssofar = jiffies - dev->trans_start;
+
+ int status = ARCSTATUS;
+
+ if (tickssofar < TX_TIMEOUT) {
+ BUGMSG(D_DURING, "premature kickme! (status=%Xh ticks=%d o.skb=%ph numsegs=%d segnum=%d\n",
+ status, tickssofar, lp->outgoing.skb,
+ lp->outgoing.numsegs,
+ lp->outgoing.segnum);
+ return 1;
+ }
+ lp->intmask &= ~TXFREEflag;
+ SETMASK;
+
+ if (status & TXFREEflag) { /* transmit _DID_ finish */
+ BUGMSG(D_NORMAL, "tx timeout - missed IRQ? (status=%Xh, ticks=%d, mask=%Xh, dest=%02Xh)\n",
+ status, tickssofar, lp->intmask, lp->lasttrans_dest);
+ lp->stats.tx_errors++;
+ } else {
+ BUGMSG(D_EXTRA, "tx timed out (status=%Xh, tickssofar=%d, intmask=%Xh, dest=%02Xh)\n",
+ status, tickssofar, lp->intmask, lp->lasttrans_dest);
+ lp->stats.tx_errors++;
+ lp->stats.tx_aborted_errors++;
+
+ ACOMMAND(NOTXcmd);
+ }
- if (lp->outgoing.skb)
- {
- dev_kfree_skb(lp->outgoing.skb);
- lp->stats.tx_dropped++;
- }
- lp->outgoing.skb=NULL;
+ if (lp->outgoing.skb) {
+ dev_kfree_skb(lp->outgoing.skb);
+ lp->stats.tx_dropped++;
+ }
+ lp->outgoing.skb = NULL;
#ifdef CONFIG_ARCNET_ETH
- lp->edev->tbusy=0;
+ lp->edev->tbusy = 0;
#endif
#ifdef CONFIG_ARCNET_1051
- lp->sdev->tbusy=0;
+ lp->sdev->tbusy = 0;
#endif
- if (!test_and_clear_bit(0,(int *)&dev->tbusy))
- BUGMSG(D_EXTRA, "after timing out, tbusy was clear!\n");
-
- lp->txready=0;
- lp->sending=0;
-
- return 1;
- }
-
- if (lp->txready) /* transmit already in progress! */
- {
- BUGMSG(D_NORMAL,"trying to start new packet while busy! (status=%Xh)\n",
- ARCSTATUS);
- lp->intmask &= ~TXFREEflag;
- SETMASK;
- ACOMMAND(NOTXcmd); /* abort current send */
- (*lp->inthandler)(dev); /* fake an interrupt */
- lp->stats.tx_errors++;
- lp->stats.tx_fifo_errors++;
- lp->txready=0; /* we definitely need this line! */
-
- return 1;
- }
-
- /* Block a timer-based transmit from overlapping. This could better be
- done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */
- if (test_and_set_bit(0, (int *)&lp->adev->tbusy))
- {
- BUGMSG(D_NORMAL,"transmitter called with busy bit set! (status=%Xh, inTX=%d, tickssofar=%ld)\n",
- ARCSTATUS,lp->intx,jiffies-dev->trans_start);
- lp->stats.tx_errors++;
- lp->stats.tx_fifo_errors++;
- return -EBUSY;
- }
+ if (!test_and_clear_bit(0, (int *) &dev->tbusy))
+ BUGMSG(D_EXTRA, "after timing out, tbusy was clear!\n");
+
+ lp->txready = 0;
+ lp->sending = 0;
+
+ return 1;
+ }
+ if (lp->txready) { /* transmit already in progress! */
+ BUGMSG(D_NORMAL, "trying to start new packet while busy! (status=%Xh)\n",
+ ARCSTATUS);
+ lp->intmask &= ~TXFREEflag;
+ SETMASK;
+ ACOMMAND(NOTXcmd); /* abort current send */
+ (*lp->inthandler) (dev); /* fake an interrupt */
+ lp->stats.tx_errors++;
+ lp->stats.tx_fifo_errors++;
+ lp->txready = 0; /* we definitely need this line! */
+
+ return 1;
+ }
+ /* Block a timer-based transmit from overlapping. This could better be
+ done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */
+ if (test_and_set_bit(0, (int *) &lp->adev->tbusy)) {
+ BUGMSG(D_NORMAL, "transmitter called with busy bit set! (status=%Xh, inTX=%d, tickssofar=%ld)\n",
+ ARCSTATUS, lp->intx, jiffies - dev->trans_start);
+ lp->stats.tx_errors++;
+ lp->stats.tx_fifo_errors++;
+ return -EBUSY;
+ }
#ifdef CONFIG_ARCNET_1051
- lp->sdev->tbusy=1;
+ lp->sdev->tbusy = 1;
#endif
#ifdef CONFIG_ARCNET_ETH
- lp->edev->tbusy=1;
+ lp->edev->tbusy = 1;
#endif
- return 0;
+ return 0;
}
/* Called by the kernel in order to transmit a packet.
*/
-static int
-arcnetA_send_packet(struct sk_buff *skb, struct net_device *dev)
+static int arcnetA_send_packet(struct sk_buff *skb, struct net_device *dev)
{
- struct arcnet_local *lp = (struct arcnet_local *)dev->priv;
- int bad,oldmask=0;
- struct Outgoing *out=&(lp->outgoing);
-
- lp->intx++;
-
- oldmask |= lp->intmask;
- lp->intmask=0;
- SETMASK;
-
- bad=arcnet_send_packet_bad(skb,dev);
- if (bad)
- {
- lp->intx--;
- lp->intmask=oldmask;
- SETMASK;
- return bad;
- }
-
- /* arcnet_send_packet_pad has already set tbusy - don't bother here. */
-
- lp->intmask = oldmask & ~TXFREEflag;
- SETMASK;
-
- out->length = 1 < skb->len ? skb->len : 1;
- out->hdr=(struct ClientData*)skb->data;
- out->skb=skb;
-
- BUGLVL(D_SKB) arcnet_dump_skb(dev,skb,"tx");
-
- out->hdr->sequence=(lp->sequence++);
-
- /* fits in one packet? */
- if (out->length-EXTRA_CLIENTDATA<=XMTU)
- {
- BUGMSG(D_DURING,"not splitting %d-byte packet. (split_flag=%d)\n",
- out->length,out->hdr->split_flag);
- if (out->hdr->split_flag)
- BUGMSG(D_NORMAL,"short packet has split_flag set?! (split_flag=%d)\n",
- out->hdr->split_flag);
- out->numsegs=1;
- out->segnum=1;
- (*lp->prepare_tx)(dev,
- ((char *)out->hdr)+EXTRA_CLIENTDATA,
- sizeof(struct ClientData)-EXTRA_CLIENTDATA,
- ((char *)skb->data)+sizeof(struct ClientData),
- out->length-sizeof(struct ClientData),
- out->hdr->daddr,1,0);
-
- /* done right away */
- lp->stats.tx_bytes += out->skb->len;
- dev_kfree_skb(out->skb);
- out->skb=NULL;
-
- if (arcnet_go_tx(dev,1))
- {
- /* inform upper layers */
- arcnet_tx_done(dev, lp);
- }
- }
- else /* too big for one - split it */
- {
- int maxsegsize=XMTU-4;
-
- out->data=(u_char *)skb->data
- + sizeof(struct ClientData);
- out->dataleft=out->length-sizeof(struct ClientData);
- out->numsegs=(out->dataleft+maxsegsize-1)/maxsegsize;
- out->segnum=0;
-
- BUGMSG(D_TX,"packet (%d bytes) split into %d fragments:\n",
- out->length,out->numsegs);
-
- /* if a packet waiting, launch it */
- arcnet_go_tx(dev,1);
-
- if (!lp->txready)
- {
- /* prepare a packet, launch it and prepare
- * another.
- */
- arcnetA_continue_tx(dev);
- if (arcnet_go_tx(dev,1))
- {
- arcnetA_continue_tx(dev);
- arcnet_go_tx(dev,1);
- }
+ struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
+ int bad, oldmask = 0;
+ struct Outgoing *out = &(lp->outgoing);
+
+ lp->intx++;
+
+ oldmask |= lp->intmask;
+ lp->intmask = 0;
+ SETMASK;
+
+ bad = arcnet_send_packet_bad(skb, dev);
+ if (bad) {
+ lp->intx--;
+ lp->intmask = oldmask;
+ SETMASK;
+ return bad;
}
+ /* arcnet_send_packet_pad has already set tbusy - don't bother here. */
+
+ lp->intmask = oldmask & ~TXFREEflag;
+ SETMASK;
- /* if segnum==numsegs, the transmission is finished;
- * free the skb right away.
- */
-
- if (out->segnum==out->numsegs)
- {
- /* transmit completed */
- out->segnum++;
- if (out->skb)
- {
- lp->stats.tx_bytes += skb->len;
- dev_kfree_skb(out->skb);
- }
- out->skb=NULL;
+ out->length = 1 < skb->len ? skb->len : 1;
+ out->hdr = (struct ClientData *) skb->data;
+ out->skb = skb;
+
+ BUGLVL(D_SKB) arcnet_dump_skb(dev, skb, "tx");
+
+ out->hdr->sequence = (lp->sequence++);
+
+ /* fits in one packet? */
+ if (out->length - EXTRA_CLIENTDATA <= XMTU) {
+ BUGMSG(D_DURING, "not splitting %d-byte packet. (split_flag=%d)\n",
+ out->length, out->hdr->split_flag);
+ if (out->hdr->split_flag)
+ BUGMSG(D_NORMAL, "short packet has split_flag set?! (split_flag=%d)\n",
+ out->hdr->split_flag);
+ out->numsegs = 1;
+ out->segnum = 1;
+ (*lp->prepare_tx) (dev,
+ ((char *) out->hdr) + EXTRA_CLIENTDATA,
+ sizeof(struct ClientData) - EXTRA_CLIENTDATA,
+ ((char *) skb->data) + sizeof(struct ClientData),
+ out->length - sizeof(struct ClientData),
+ out->hdr->daddr, 1, 0);
+
+ /* done right away */
+ lp->stats.tx_bytes += out->skb->len;
+ dev_kfree_skb(out->skb);
+ out->skb = NULL;
+
+ if (arcnet_go_tx(dev, 1)) {
+ /* inform upper layers */
+ arcnet_tx_done(dev, lp);
+ }
+ } else { /* too big for one - split it */
+ int maxsegsize = XMTU - 4;
+
+ out->data = (u_char *) skb->data
+ + sizeof(struct ClientData);
+ out->dataleft = out->length - sizeof(struct ClientData);
+ out->numsegs = (out->dataleft + maxsegsize - 1) / maxsegsize;
+ out->segnum = 0;
+
+ BUGMSG(D_TX, "packet (%d bytes) split into %d fragments:\n",
+ out->length, out->numsegs);
+
+ /* if a packet waiting, launch it */
+ arcnet_go_tx(dev, 1);
+
+ if (!lp->txready) {
+ /* prepare a packet, launch it and prepare
+ * another.
+ */
+ arcnetA_continue_tx(dev);
+ if (arcnet_go_tx(dev, 1)) {
+ arcnetA_continue_tx(dev);
+ arcnet_go_tx(dev, 1);
+ }
+ }
+ /* if segnum==numsegs, the transmission is finished;
+ * free the skb right away.
+ */
+
+ if (out->segnum == out->numsegs) {
+ /* transmit completed */
+ out->segnum++;
+ if (out->skb) {
+ lp->stats.tx_bytes += skb->len;
+ dev_kfree_skb(out->skb);
+ }
+ out->skb = NULL;
+ }
}
- }
- dev->trans_start=jiffies;
- lp->intx--;
+ dev->trans_start = jiffies;
+ lp->intx--;
- /* make sure we didn't ignore a TX IRQ while we were in here */
- lp->intmask |= TXFREEflag;
- SETMASK;
+ /* make sure we didn't ignore a TX IRQ while we were in here */
+ lp->intmask |= TXFREEflag;
+ SETMASK;
- return 0;
+ return 0;
}
@@ -836,44 +803,41 @@ arcnetA_send_packet(struct sk_buff *skb, struct net_device *dev)
*/
void arcnetA_continue_tx(struct net_device *dev)
{
- struct arcnet_local *lp = (struct arcnet_local *)dev->priv;
- int maxsegsize=XMTU-4;
- struct Outgoing *out=&(lp->outgoing);
-
- BUGMSG(D_DURING,"continue_tx called (status=%Xh, intx=%d, intxh=%d, intmask=%Xh\n",
- ARCSTATUS,lp->intx,lp->in_txhandler,lp->intmask);
-
- if (lp->txready)
- {
- BUGMSG(D_NORMAL,"continue_tx: called with packet in buffer!\n");
- return;
- }
-
- if (out->segnum>=out->numsegs)
- {
- BUGMSG(D_NORMAL,"continue_tx: building segment %d of %d!\n",
- out->segnum+1,out->numsegs);
- }
-
- if (!out->segnum) /* first packet */
- out->hdr->split_flag=((out->numsegs-2)<<1)+1;
- else
- out->hdr->split_flag=out->segnum<<1;
-
- out->seglen=maxsegsize;
- if (out->seglen>out->dataleft) out->seglen=out->dataleft;
-
- BUGMSG(D_TX,"building packet #%d (%d bytes) of %d (%d total), splitflag=%d\n",
- out->segnum+1,out->seglen,out->numsegs,
- out->length,out->hdr->split_flag);
-
- (*lp->prepare_tx)(dev,((char *)out->hdr)+EXTRA_CLIENTDATA,
- sizeof(struct ClientData)-EXTRA_CLIENTDATA,
- out->data,out->seglen,out->hdr->daddr,1,0);
-
- out->dataleft-=out->seglen;
- out->data+=out->seglen;
- out->segnum++;
+ struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
+ int maxsegsize = XMTU - 4;
+ struct Outgoing *out = &(lp->outgoing);
+
+ BUGMSG(D_DURING, "continue_tx called (status=%Xh, intx=%d, intxh=%d, intmask=%Xh\n",
+ ARCSTATUS, lp->intx, lp->in_txhandler, lp->intmask);
+
+ if (lp->txready) {
+ BUGMSG(D_NORMAL, "continue_tx: called with packet in buffer!\n");
+ return;
+ }
+ if (out->segnum >= out->numsegs) {
+ BUGMSG(D_NORMAL, "continue_tx: building segment %d of %d!\n",
+ out->segnum + 1, out->numsegs);
+ }
+ if (!out->segnum) /* first packet */
+ out->hdr->split_flag = ((out->numsegs - 2) << 1) + 1;
+ else
+ out->hdr->split_flag = out->segnum << 1;
+
+ out->seglen = maxsegsize;
+ if (out->seglen > out->dataleft)
+ out->seglen = out->dataleft;
+
+ BUGMSG(D_TX, "building packet #%d (%d bytes) of %d (%d total), splitflag=%d\n",
+ out->segnum + 1, out->seglen, out->numsegs,
+ out->length, out->hdr->split_flag);
+
+ (*lp->prepare_tx) (dev, ((char *) out->hdr) + EXTRA_CLIENTDATA,
+ sizeof(struct ClientData) - EXTRA_CLIENTDATA,
+ out->data, out->seglen, out->hdr->daddr, 1, 0);
+
+ out->dataleft -= out->seglen;
+ out->data += out->seglen;
+ out->segnum++;
}
@@ -887,36 +851,34 @@ void arcnetA_continue_tx(struct net_device *dev)
* to the card; TXFREEflag is always OR'ed into the memory variable either
* way.
*/
-int arcnet_go_tx(struct net_device *dev,int enable_irq)
+int arcnet_go_tx(struct net_device *dev, int enable_irq)
{
- struct arcnet_local *lp=(struct arcnet_local *)dev->priv;
+ struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
- BUGMSG(D_DURING,"go_tx: status=%Xh, intmask=%Xh, txready=%d, sending=%d\n",
- ARCSTATUS,lp->intmask,lp->txready,lp->sending);
+ BUGMSG(D_DURING, "go_tx: status=%Xh, intmask=%Xh, txready=%d, sending=%d\n",
+ ARCSTATUS, lp->intmask, lp->txready, lp->sending);
- if (lp->sending || !lp->txready)
- {
- if (enable_irq && lp->sending)
- {
+ if (lp->sending || !lp->txready) {
+ if (enable_irq && lp->sending) {
lp->intmask |= TXFREEflag;
SETMASK;
}
return 0;
}
-
/* start sending */
- ACOMMAND(TXcmd|(lp->txready<<3));
+ ACOMMAND(TXcmd | (lp->txready << 3));
lp->stats.tx_packets++;
- lp->txready=0;
+ lp->txready = 0;
lp->sending++;
- lp->lasttrans_dest=lp->lastload_dest;
- lp->lastload_dest=0;
+ lp->lasttrans_dest = lp->lastload_dest;
+ lp->lastload_dest = 0;
lp->intmask |= TXFREEflag;
- if (enable_irq) SETMASK;
+ if (enable_irq)
+ SETMASK;
return 1;
}
@@ -933,85 +895,75 @@ int arcnet_go_tx(struct net_device *dev,int enable_irq)
* interrupts. Establish which device needs attention, and call the correct
* chipset interrupt handler.
*/
-void
-arcnet_interrupt(int irq,void *dev_id,struct pt_regs *regs)
+void arcnet_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
struct net_device *dev = dev_id;
struct arcnet_local *lp;
- if (dev==NULL)
- {
- BUGMSG(D_DURING, "arcnet: irq %d for unknown device.\n", irq);
- return;
- }
-
- BUGMSG(D_DURING,"in arcnet_interrupt\n");
-
- lp=(struct arcnet_local *)dev->priv;
- if (!lp)
- {
- BUGMSG(D_DURING, "arcnet: irq ignored.\n");
- return;
- }
+ if (dev == NULL) {
+ BUGMSG(D_DURING, "arcnet: irq %d for unknown device.\n", irq);
+ return;
+ }
+ BUGMSG(D_DURING, "in arcnet_interrupt\n");
+ lp = (struct arcnet_local *) dev->priv;
+ if (!lp) {
+ BUGMSG(D_DURING, "arcnet: irq ignored.\n");
+ return;
+ }
/* RESET flag was enabled - if !dev->start, we must clear it right
* away (but nothing else) since inthandler() is never called.
*/
- if (!dev->start)
- {
- if (ARCSTATUS & RESETflag)
- ACOMMAND(CFLAGScmd|RESETclear);
- return;
- }
-
-
- if (test_and_set_bit(0, (int *)&dev->interrupt))
- {
- BUGMSG(D_NORMAL,"DRIVER PROBLEM! Nested arcnet interrupts!\n");
- return; /* don't even try. */
- }
+ if (!dev->start) {
+ if (ARCSTATUS & RESETflag)
+ ACOMMAND(CFLAGScmd | RESETclear);
+ return;
+ }
+ if (test_and_set_bit(0, (int *) &dev->interrupt)) {
+ BUGMSG(D_NORMAL, "DRIVER PROBLEM! Nested arcnet interrupts!\n");
+ return; /* don't even try. */
+ }
#ifdef CONFIG_ARCNET_1051
if (lp->sdev)
- lp->sdev->interrupt=1;
+ lp->sdev->interrupt = 1;
#endif
#ifdef CONFIG_ARCNET_ETH
if (lp->edev)
- lp->edev->interrupt=1;
+ lp->edev->interrupt = 1;
#endif
/* Call the "real" interrupt handler. */
- (*lp->inthandler)(dev);
+ (*lp->inthandler) (dev);
#ifdef CONFIG_ARCNET_ETH
if (lp->edev)
- lp->edev->interrupt=0;
+ lp->edev->interrupt = 0;
#endif
#ifdef CONFIG_ARCNET_1051
if (lp->sdev)
- lp->sdev->interrupt=0;
+ lp->sdev->interrupt = 0;
#endif
- if (!test_and_clear_bit(0, (int *)&dev->interrupt))
- BUGMSG(D_NORMAL, "Someone cleared our dev->interrupt flag!\n");
+ if (!test_and_clear_bit(0, (int *) &dev->interrupt))
+ BUGMSG(D_NORMAL, "Someone cleared our dev->interrupt flag!\n");
}
void arcnet_tx_done(struct net_device *dev, struct arcnet_local *lp)
{
- if (dev->tbusy)
- {
+ if (dev->tbusy) {
#ifdef CONFIG_ARCNET_ETH
- lp->edev->tbusy=0;
+ lp->edev->tbusy = 0;
#endif
#ifdef CONFIG_ARCNET_1051
- lp->sdev->tbusy=0;
+ lp->sdev->tbusy = 0;
#endif
- if (!test_and_clear_bit(0, (int *)&dev->tbusy))
- BUGMSG(D_NORMAL, "In arcnet_tx_done: Someone cleared our dev->tbusy"
- " flag!\n");
+ if (!test_and_clear_bit(0, (int *) &dev->tbusy))
+ BUGMSG(D_NORMAL, "In arcnet_tx_done: Someone cleared our dev->tbusy"
+ " flag!\n");
- mark_bh(NET_BH);
- }
+ mark_bh(NET_BH);
+ }
}
@@ -1026,53 +978,52 @@ void arcnet_tx_done(struct net_device *dev, struct arcnet_local *lp)
* protocol ID found.
*/
-void arcnet_rx(struct arcnet_local *lp, u_char *arcsoft, short length, int saddr, int daddr)
+void arcnet_rx(struct arcnet_local *lp, u_char * arcsoft, short length, int saddr, int daddr)
{
- struct net_device *dev=lp->adev;
-
- BUGMSG(D_DURING,"received packet from %02Xh to %02Xh (%d bytes)\n",
- saddr,daddr,length);
-
- /* call the right receiver for the protocol */
- switch (arcsoft[0])
- {
- case ARC_P_IP:
- case ARC_P_ARP:
- case ARC_P_RARP:
- case ARC_P_IPX:
- case ARC_P_NOVELL_EC:
- arcnetA_rx(lp->adev,arcsoft,length,saddr,daddr);
- break;
+ struct net_device *dev = lp->adev;
+
+ BUGMSG(D_DURING, "received packet from %02Xh to %02Xh (%d bytes)\n",
+ saddr, daddr, length);
+
+ /* call the right receiver for the protocol */
+ switch (arcsoft[0]) {
+ case ARC_P_IP:
+ case ARC_P_ARP:
+ case ARC_P_RARP:
+ case ARC_P_IPX:
+ case ARC_P_NOVELL_EC:
+ arcnetA_rx(lp->adev, arcsoft, length, saddr, daddr);
+ break;
#ifdef CONFIG_ARCNET_ETH
- case ARC_P_ETHER:
- arcnetE_rx(lp->edev,arcsoft,length,saddr,daddr);
- break;
+ case ARC_P_ETHER:
+ arcnetE_rx(lp->edev, arcsoft, length, saddr, daddr);
+ break;
#endif
#ifdef CONFIG_ARCNET_1051
- case ARC_P_IP_RFC1051:
- case ARC_P_ARP_RFC1051:
- arcnetS_rx(lp->sdev,arcsoft,length,saddr,daddr);
- break;
+ case ARC_P_IP_RFC1051:
+ case ARC_P_ARP_RFC1051:
+ arcnetS_rx(lp->sdev, arcsoft, length, saddr, daddr);
+ break;
#endif
- case ARC_P_DATAPOINT_BOOT:
- case ARC_P_DATAPOINT_MOUNT:
- break;
- case ARC_P_POWERLAN_BEACON:
- case ARC_P_POWERLAN_BEACON2:
- break;
- case ARC_P_LANSOFT: /* don't understand. fall through. */
- default:
- BUGMSG(D_EXTRA,"received unknown protocol %d (%Xh) from station %d.\n",
- arcsoft[0],arcsoft[0],saddr);
- lp->stats.rx_errors++;
- lp->stats.rx_crc_errors++;
- break;
- }
-
- /* If any worth-while packets have been received, a mark_bh(NET_BH)
- * has been done by netif_rx and Linux will handle them after we
- * return.
- */
+ case ARC_P_DATAPOINT_BOOT:
+ case ARC_P_DATAPOINT_MOUNT:
+ break;
+ case ARC_P_POWERLAN_BEACON:
+ case ARC_P_POWERLAN_BEACON2:
+ break;
+ case ARC_P_LANSOFT: /* don't understand. fall through. */
+ default:
+ BUGMSG(D_EXTRA, "received unknown protocol %d (%Xh) from station %d.\n",
+ arcsoft[0], arcsoft[0], saddr);
+ lp->stats.rx_errors++;
+ lp->stats.rx_crc_errors++;
+ break;
+ }
+
+ /* If any worth-while packets have been received, a mark_bh(NET_BH)
+ * has been done by netif_rx and Linux will handle them after we
+ * return.
+ */
}
@@ -1081,275 +1032,238 @@ void arcnet_rx(struct arcnet_local *lp, u_char *arcsoft, short length, int saddr
/* Packet receiver for "standard" RFC1201-style packets
*/
-static void
-arcnetA_rx(struct net_device *dev,u_char *buf,
- int length, u_char saddr, u_char daddr)
+static void arcnetA_rx(struct net_device *dev, u_char * buf,
+ int length, u_char saddr, u_char daddr)
{
- struct arcnet_local *lp = (struct arcnet_local *)dev->priv;
- struct sk_buff *skb;
- struct ClientData *arcsoft,*soft;
-
- BUGMSG(D_DURING,"it's an RFC1201 packet (length=%d)\n",
- length);
-
- /* compensate for EXTRA_CLIENTDATA (which isn't actually in the
- * packet)
- */
- arcsoft=(struct ClientData *)(buf-EXTRA_CLIENTDATA);
- length+=EXTRA_CLIENTDATA;
-
- if (arcsoft->split_flag==0xFF) /* Exception Packet */
- {
- BUGMSG(D_DURING,"compensating for exception packet\n");
-
- /* skip over 4-byte junkola */
- arcsoft=(struct ClientData *)
- ((u_char *)arcsoft + 4);
- length-=4;
- }
-
- if (!arcsoft->split_flag) /* not split */
- {
- struct Incoming *in=&lp->incoming[saddr];
-
- BUGMSG(D_RX,"incoming is not split (splitflag=%d)\n",
- arcsoft->split_flag);
-
- if (in->skb) /* already assembling one! */
- {
- BUGMSG(D_EXTRA,"aborting assembly (seq=%d) for unsplit packet (splitflag=%d, seq=%d)\n",
- in->sequence,arcsoft->split_flag,
- arcsoft->sequence);
- lp->aborted_seq=arcsoft->sequence;
- kfree_skb(in->skb);
- lp->stats.rx_errors++;
- lp->stats.rx_missed_errors++;
- in->skb=NULL;
+ struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
+ struct sk_buff *skb;
+ struct ClientData *arcsoft, *soft;
+
+ BUGMSG(D_DURING, "it's an RFC1201 packet (length=%d)\n",
+ length);
+
+ /* compensate for EXTRA_CLIENTDATA (which isn't actually in the
+ * packet)
+ */
+ arcsoft = (struct ClientData *) (buf - EXTRA_CLIENTDATA);
+ length += EXTRA_CLIENTDATA;
+
+ if (arcsoft->split_flag == 0xFF) { /* Exception Packet */
+ BUGMSG(D_DURING, "compensating for exception packet\n");
+
+ /* skip over 4-byte junkola */
+ arcsoft = (struct ClientData *)
+ ((u_char *) arcsoft + 4);
+ length -= 4;
}
+ if (!arcsoft->split_flag) { /* not split */
+ struct Incoming *in = &lp->incoming[saddr];
+
+ BUGMSG(D_RX, "incoming is not split (splitflag=%d)\n",
+ arcsoft->split_flag);
+
+ if (in->skb) { /* already assembling one! */
+ BUGMSG(D_EXTRA, "aborting assembly (seq=%d) for unsplit packet (splitflag=%d, seq=%d)\n",
+ in->sequence, arcsoft->split_flag,
+ arcsoft->sequence);
+ lp->aborted_seq = arcsoft->sequence;
+ kfree_skb(in->skb);
+ lp->stats.rx_errors++;
+ lp->stats.rx_missed_errors++;
+ in->skb = NULL;
+ }
+ in->sequence = arcsoft->sequence;
- in->sequence=arcsoft->sequence;
-
- skb = alloc_skb(length, GFP_ATOMIC);
- if (skb == NULL) {
- BUGMSG(D_NORMAL,"Memory squeeze, dropping packet.\n");
- lp->stats.rx_dropped++;
- return;
- }
- soft=(struct ClientData *)skb->data;
-
- skb_put(skb,length);
- skb->dev = dev;
-
- memcpy((u_char *)soft+EXTRA_CLIENTDATA,
- (u_char *)arcsoft+EXTRA_CLIENTDATA,
- length-EXTRA_CLIENTDATA);
- soft->daddr=daddr;
- soft->saddr=saddr;
-
- /* ARP packets have problems when sent from DOS.
- * source address is always 0 on some systems! So we take
- * the hardware source addr (which is impossible to fumble)
- * and insert it ourselves.
- */
- if (soft->protocol_id == ARC_P_ARP)
- {
- struct arphdr *arp=(struct arphdr *)
- ((char *)soft+sizeof(struct ClientData));
-
- /* make sure addresses are the right length */
- if (arp->ar_hln==1 && arp->ar_pln==4)
- {
- char *cptr=(char *)(arp)+sizeof(struct arphdr);
-
- if (!*cptr) /* is saddr = 00? */
- {
- BUGMSG(D_EXTRA,"ARP source address was 00h, set to %02Xh.\n",
- saddr);
- lp->stats.rx_crc_errors++;
- *cptr=saddr;
+ skb = alloc_skb(length, GFP_ATOMIC);
+ if (skb == NULL) {
+ BUGMSG(D_NORMAL, "Memory squeeze, dropping packet.\n");
+ lp->stats.rx_dropped++;
+ return;
}
- else
- {
- BUGMSG(D_DURING,"ARP source address (%Xh) is fine.\n",
- *cptr);
+ soft = (struct ClientData *) skb->data;
+
+ skb_put(skb, length);
+ skb->dev = dev;
+
+ memcpy((u_char *) soft + EXTRA_CLIENTDATA,
+ (u_char *) arcsoft + EXTRA_CLIENTDATA,
+ length - EXTRA_CLIENTDATA);
+ soft->daddr = daddr;
+ soft->saddr = saddr;
+
+ /* ARP packets have problems when sent from DOS.
+ * source address is always 0 on some systems! So we take
+ * the hardware source addr (which is impossible to fumble)
+ * and insert it ourselves.
+ */
+ if (soft->protocol_id == ARC_P_ARP) {
+ struct arphdr *arp = (struct arphdr *)
+ ((char *) soft + sizeof(struct ClientData));
+
+ /* make sure addresses are the right length */
+ if (arp->ar_hln == 1 && arp->ar_pln == 4) {
+ char *cptr = (char *) (arp) + sizeof(struct arphdr);
+
+ if (!*cptr) { /* is saddr = 00? */
+ BUGMSG(D_EXTRA, "ARP source address was 00h, set to %02Xh.\n",
+ saddr);
+ lp->stats.rx_crc_errors++;
+ *cptr = saddr;
+ } else {
+ BUGMSG(D_DURING, "ARP source address (%Xh) is fine.\n",
+ *cptr);
+ }
+ } else {
+ BUGMSG(D_NORMAL, "funny-shaped ARP packet. (%Xh, %Xh)\n",
+ arp->ar_hln, arp->ar_pln);
+ lp->stats.rx_errors++;
+ lp->stats.rx_crc_errors++;
+ }
}
- }
- else
- {
- BUGMSG(D_NORMAL,"funny-shaped ARP packet. (%Xh, %Xh)\n",
- arp->ar_hln,arp->ar_pln);
- lp->stats.rx_errors++;
- lp->stats.rx_crc_errors++;
- }
- }
+ BUGLVL(D_SKB) arcnet_dump_skb(dev, skb, "rx");
+
+ lp->stats.rx_bytes += skb->len;
+ skb->protocol = arcnetA_type_trans(skb, dev);
+ netif_rx(skb);
+ } else { /* split packet */
+ /* NOTE: MSDOS ARP packet correction should only need to
+ * apply to unsplit packets, since ARP packets are so short.
+ *
+ * My interpretation of the RFC1201 (ARCnet) document is that
+ * if a packet is received out of order, the entire assembly
+ * process should be aborted.
+ *
+ * The RFC also mentions "it is possible for successfully
+ * received packets to be retransmitted." As of 0.40 all
+ * previously received packets are allowed, not just the
+ * most recent one.
+ *
+ * We allow multiple assembly processes, one for each
+ * ARCnet card possible on the network. Seems rather like
+ * a waste of memory. Necessary?
+ */
- BUGLVL(D_SKB) arcnet_dump_skb(dev,skb,"rx");
-
- lp->stats.rx_bytes += skb->len;
- skb->protocol=arcnetA_type_trans(skb,dev);
- netif_rx(skb);
- }
- else /* split packet */
- {
- /* NOTE: MSDOS ARP packet correction should only need to
- * apply to unsplit packets, since ARP packets are so short.
- *
- * My interpretation of the RFC1201 (ARCnet) document is that
- * if a packet is received out of order, the entire assembly
- * process should be aborted.
- *
- * The RFC also mentions "it is possible for successfully
- * received packets to be retransmitted." As of 0.40 all
- * previously received packets are allowed, not just the
- * most recent one.
- *
- * We allow multiple assembly processes, one for each
- * ARCnet card possible on the network. Seems rather like
- * a waste of memory. Necessary?
- */
-
- struct Incoming *in=&lp->incoming[saddr];
-
- BUGMSG(D_RX,"packet is split (splitflag=%d, seq=%d)\n",
- arcsoft->split_flag,in->sequence);
-
- if (in->skb && in->sequence!=arcsoft->sequence)
- {
- BUGMSG(D_EXTRA,"wrong seq number (saddr=%d, expected=%d, seq=%d, splitflag=%d)\n",
- saddr,in->sequence,arcsoft->sequence,
- arcsoft->split_flag);
- kfree_skb(in->skb);
- in->skb=NULL;
- lp->stats.rx_errors++;
- lp->stats.rx_missed_errors++;
- in->lastpacket=in->numpackets=0;
- }
+ struct Incoming *in = &lp->incoming[saddr];
- if (arcsoft->split_flag & 1) /* first packet in split */
- {
- BUGMSG(D_RX,"brand new splitpacket (splitflag=%d)\n",
- arcsoft->split_flag);
- if (in->skb) /* already assembling one! */
- {
- BUGMSG(D_EXTRA,"aborting previous (seq=%d) assembly (splitflag=%d, seq=%d)\n",
- in->sequence,arcsoft->split_flag,
- arcsoft->sequence);
- lp->stats.rx_errors++;
- lp->stats.rx_missed_errors++;
- kfree_skb(in->skb);
- }
-
- in->sequence=arcsoft->sequence;
- in->numpackets=((unsigned)arcsoft->split_flag>>1)+2;
- in->lastpacket=1;
-
- if (in->numpackets>16)
- {
- BUGMSG(D_EXTRA,"incoming packet more than 16 segments; dropping. (splitflag=%d)\n",
- arcsoft->split_flag);
- lp->stats.rx_errors++;
- lp->stats.rx_length_errors++;
- return;
- }
-
- in->skb=skb=alloc_skb(508*in->numpackets
- + sizeof(struct ClientData),
- GFP_ATOMIC);
- if (skb == NULL) {
- BUGMSG(D_NORMAL,"(split) memory squeeze, dropping packet.\n");
- lp->stats.rx_dropped++;
- return;
- }
-
- soft=(struct ClientData *)skb->data;
-
- skb_put(skb,sizeof(struct ClientData));
- skb->dev=dev;
-
- memcpy((u_char *)soft+EXTRA_CLIENTDATA,
- (u_char *)arcsoft+EXTRA_CLIENTDATA,
- sizeof(struct ClientData)-EXTRA_CLIENTDATA);
- soft->split_flag=0; /* final packet won't be split */
- }
- else /* not first packet */
- {
- int packetnum=((unsigned)arcsoft->split_flag>>1) + 1;
-
- /* if we're not assembling, there's no point
- * trying to continue.
- */
- if (!in->skb)
- {
- if (lp->aborted_seq != arcsoft->sequence)
- {
- BUGMSG(D_EXTRA,"can't continue split without starting first! (splitflag=%d, seq=%d, aborted=%d)\n",
- arcsoft->split_flag,arcsoft->sequence, lp->aborted_seq);
- lp->stats.rx_errors++;
- lp->stats.rx_missed_errors++;
+ BUGMSG(D_RX, "packet is split (splitflag=%d, seq=%d)\n",
+ arcsoft->split_flag, in->sequence);
+
+ if (in->skb && in->sequence != arcsoft->sequence) {
+ BUGMSG(D_EXTRA, "wrong seq number (saddr=%d, expected=%d, seq=%d, splitflag=%d)\n",
+ saddr, in->sequence, arcsoft->sequence,
+ arcsoft->split_flag);
+ kfree_skb(in->skb);
+ in->skb = NULL;
+ lp->stats.rx_errors++;
+ lp->stats.rx_missed_errors++;
+ in->lastpacket = in->numpackets = 0;
}
- return;
- }
-
- in->lastpacket++;
- if (packetnum!=in->lastpacket) /* not the right flag! */
- {
- /* harmless duplicate? ignore. */
- if (packetnum<=in->lastpacket-1)
- {
- BUGMSG(D_EXTRA,"duplicate splitpacket ignored! (splitflag=%d)\n",
- arcsoft->split_flag);
- lp->stats.rx_errors++;
- lp->stats.rx_frame_errors++;
- return;
+ if (arcsoft->split_flag & 1) { /* first packet in split */
+ BUGMSG(D_RX, "brand new splitpacket (splitflag=%d)\n",
+ arcsoft->split_flag);
+ if (in->skb) { /* already assembling one! */
+ BUGMSG(D_EXTRA, "aborting previous (seq=%d) assembly (splitflag=%d, seq=%d)\n",
+ in->sequence, arcsoft->split_flag,
+ arcsoft->sequence);
+ lp->stats.rx_errors++;
+ lp->stats.rx_missed_errors++;
+ kfree_skb(in->skb);
+ }
+ in->sequence = arcsoft->sequence;
+ in->numpackets = ((unsigned) arcsoft->split_flag >> 1) + 2;
+ in->lastpacket = 1;
+
+ if (in->numpackets > 16) {
+ BUGMSG(D_EXTRA, "incoming packet more than 16 segments; dropping. (splitflag=%d)\n",
+ arcsoft->split_flag);
+ lp->stats.rx_errors++;
+ lp->stats.rx_length_errors++;
+ return;
+ }
+ in->skb = skb = alloc_skb(508 * in->numpackets
+ + sizeof(struct ClientData),
+ GFP_ATOMIC);
+ if (skb == NULL) {
+ BUGMSG(D_NORMAL, "(split) memory squeeze, dropping packet.\n");
+ lp->stats.rx_dropped++;
+ return;
+ }
+ soft = (struct ClientData *) skb->data;
+
+ skb_put(skb, sizeof(struct ClientData));
+ skb->dev = dev;
+
+ memcpy((u_char *) soft + EXTRA_CLIENTDATA,
+ (u_char *) arcsoft + EXTRA_CLIENTDATA,
+ sizeof(struct ClientData) - EXTRA_CLIENTDATA);
+ soft->split_flag = 0; /* final packet won't be split */
+ } else { /* not first packet */
+ int packetnum = ((unsigned) arcsoft->split_flag >> 1) + 1;
+
+ /* if we're not assembling, there's no point
+ * trying to continue.
+ */
+ if (!in->skb) {
+ if (lp->aborted_seq != arcsoft->sequence) {
+ BUGMSG(D_EXTRA, "can't continue split without starting first! (splitflag=%d, seq=%d, aborted=%d)\n",
+ arcsoft->split_flag, arcsoft->sequence, lp->aborted_seq);
+ lp->stats.rx_errors++;
+ lp->stats.rx_missed_errors++;
+ }
+ return;
+ }
+ in->lastpacket++;
+ if (packetnum != in->lastpacket) { /* not the right flag! */
+ /* harmless duplicate? ignore. */
+ if (packetnum <= in->lastpacket - 1) {
+ BUGMSG(D_EXTRA, "duplicate splitpacket ignored! (splitflag=%d)\n",
+ arcsoft->split_flag);
+ lp->stats.rx_errors++;
+ lp->stats.rx_frame_errors++;
+ return;
+ }
+ /* "bad" duplicate, kill reassembly */
+ BUGMSG(D_EXTRA, "out-of-order splitpacket, reassembly (seq=%d) aborted (splitflag=%d, seq=%d)\n",
+ in->sequence, arcsoft->split_flag,
+ arcsoft->sequence);
+ lp->aborted_seq = arcsoft->sequence;
+ kfree_skb(in->skb);
+ in->skb = NULL;
+ lp->stats.rx_errors++;
+ lp->stats.rx_missed_errors++;
+ in->lastpacket = in->numpackets = 0;
+ return;
+ }
+ soft = (struct ClientData *) in->skb->data;
}
- /* "bad" duplicate, kill reassembly */
- BUGMSG(D_EXTRA,"out-of-order splitpacket, reassembly (seq=%d) aborted (splitflag=%d, seq=%d)\n",
- in->sequence,arcsoft->split_flag,
- arcsoft->sequence);
- lp->aborted_seq=arcsoft->sequence;
- kfree_skb(in->skb);
- in->skb=NULL;
- lp->stats.rx_errors++;
- lp->stats.rx_missed_errors++;
- in->lastpacket=in->numpackets=0;
- return;
- }
-
- soft=(struct ClientData *)in->skb->data;
- }
+ skb = in->skb;
+
+ memcpy(skb->data + skb->len,
+ (u_char *) arcsoft + sizeof(struct ClientData),
+ length - sizeof(struct ClientData));
+ skb_put(skb, length - sizeof(struct ClientData));
- skb=in->skb;
-
- memcpy(skb->data+skb->len,
- (u_char *)arcsoft+sizeof(struct ClientData),
- length-sizeof(struct ClientData));
- skb_put(skb,length-sizeof(struct ClientData));
-
- soft->daddr=daddr;
- soft->saddr=saddr;
-
- /* are we done? */
- if (in->lastpacket == in->numpackets)
- {
- if (!skb || !in->skb)
- {
- BUGMSG(D_NORMAL,"?!? done reassembling packet, no skb? (skb=%ph, in->skb=%ph)\n",
- skb,in->skb);
- }
- else
- {
- in->skb=NULL;
- in->lastpacket=in->numpackets=0;
-
- BUGLVL(D_SKB) arcnet_dump_skb(dev,skb,"rx");
-
- lp->stats.rx_bytes += skb->len;
- skb->protocol=arcnetA_type_trans(skb,dev);
- netif_rx(skb);
- }
+ soft->daddr = daddr;
+ soft->saddr = saddr;
+
+ /* are we done? */
+ if (in->lastpacket == in->numpackets) {
+ if (!skb || !in->skb) {
+ BUGMSG(D_NORMAL, "?!? done reassembling packet, no skb? (skb=%ph, in->skb=%ph)\n",
+ skb, in->skb);
+ } else {
+ in->skb = NULL;
+ in->lastpacket = in->numpackets = 0;
+
+ BUGLVL(D_SKB) arcnet_dump_skb(dev, skb, "rx");
+
+ lp->stats.rx_bytes += skb->len;
+ skb->protocol = arcnetA_type_trans(skb, dev);
+ netif_rx(skb);
+ }
+ }
}
- }
}
@@ -1359,89 +1273,86 @@ arcnetA_rx(struct net_device *dev,u_char *buf,
* *
****************************************************************************/
-/* Get the current statistics. This may be called with the card open or
+/* Get the current statistics. This may be called with the card open or
* closed.
*/
static struct net_device_stats *arcnet_get_stats(struct net_device *dev)
{
- struct arcnet_local *lp = (struct arcnet_local *)dev->priv;
+ struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
- return &lp->stats;
+ return &lp->stats;
}
/* Create the ARCnet ClientData header for an arbitrary protocol layer
- *
- * saddr=NULL means use device source address (always will anyway)
- * daddr=NULL means leave destination address (eg unresolved arp)
+
+ * saddr=NULL means use device source address (always will anyway)
+ * daddr=NULL means leave destination address (eg unresolved arp)
*/
-static int arcnetA_header(struct sk_buff *skb,struct net_device *dev,
- unsigned short type,void *daddr,void *saddr,unsigned len)
+static int arcnetA_header(struct sk_buff *skb, struct net_device *dev,
+ unsigned short type, void *daddr, void *saddr, unsigned len)
{
- struct ClientData *head = (struct ClientData *)
- skb_push(skb,dev->hard_header_len);
- struct arcnet_local *lp=(struct arcnet_local *)(dev->priv);
-
- BUGMSG(D_DURING,"create header from %d to %d; protocol %d (%Xh); size %u.\n",
- saddr ? *(u_char*)saddr : -1,
- daddr ? *(u_char*)daddr : -1,
- type,type,len);
-
- /* set the protocol ID according to RFC1201 */
- switch(type)
- {
- case ETH_P_IP:
- head->protocol_id=ARC_P_IP;
- break;
- case ETH_P_ARP:
- head->protocol_id=ARC_P_ARP;
- break;
- case ETH_P_RARP:
- head->protocol_id=ARC_P_RARP;
- break;
- case ETH_P_IPX:
- case ETH_P_802_3:
- case ETH_P_802_2:
- head->protocol_id=ARC_P_IPX;
- break;
- case ETH_P_ATALK:
- head->protocol_id=ARC_P_ATALK;
- break;
- default:
- BUGMSG(D_NORMAL,"I don't understand protocol %d (%Xh)\n",
- type,type);
- lp->stats.tx_errors++;
- lp->stats.tx_aborted_errors++;
- return 0;
- }
-
- /*
- * Set the source hardware address.
- *
- * This is pretty pointless for most purposes, but it can help
- * in debugging. saddr is stored in the ClientData header and
- * removed before sending the packet (since ARCnet does not allow
- * us to change the source address in the actual packet sent)
- */
- if(saddr)
- head->saddr=((u_char*)saddr)[0];
- else
- head->saddr=((u_char*)(dev->dev_addr))[0];
-
- head->split_flag=0; /* split packets are done elsewhere */
- head->sequence=0; /* so are sequence numbers */
-
- /* supposedly if daddr is NULL, we should ignore it... */
- if(daddr)
- {
- head->daddr=((u_char*)daddr)[0];
- return dev->hard_header_len;
- }
- else
- head->daddr=0; /* better fill one in anyway */
-
- return -dev->hard_header_len;
+ struct ClientData *head = (struct ClientData *)
+ skb_push(skb, dev->hard_header_len);
+ struct arcnet_local *lp = (struct arcnet_local *) (dev->priv);
+
+ BUGMSG(D_DURING, "create header from %d to %d; protocol %d (%Xh); size %u.\n",
+ saddr ? *(u_char *) saddr : -1,
+ daddr ? *(u_char *) daddr : -1,
+ type, type, len);
+
+ /* set the protocol ID according to RFC1201 */
+ switch (type) {
+ case ETH_P_IP:
+ head->protocol_id = ARC_P_IP;
+ break;
+ case ETH_P_ARP:
+ head->protocol_id = ARC_P_ARP;
+ break;
+ case ETH_P_RARP:
+ head->protocol_id = ARC_P_RARP;
+ break;
+ case ETH_P_IPX:
+ case ETH_P_802_3:
+ case ETH_P_802_2:
+ head->protocol_id = ARC_P_IPX;
+ break;
+ case ETH_P_ATALK:
+ head->protocol_id = ARC_P_ATALK;
+ break;
+ default:
+ BUGMSG(D_NORMAL, "I don't understand protocol %d (%Xh)\n",
+ type, type);
+ lp->stats.tx_errors++;
+ lp->stats.tx_aborted_errors++;
+ return 0;
+ }
+
+ /*
+ * Set the source hardware address.
+ *
+ * This is pretty pointless for most purposes, but it can help
+ * in debugging. saddr is stored in the ClientData header and
+ * removed before sending the packet (since ARCnet does not allow
+ * us to change the source address in the actual packet sent)
+ */
+ if (saddr)
+ head->saddr = ((u_char *) saddr)[0];
+ else
+ head->saddr = ((u_char *) (dev->dev_addr))[0];
+
+ head->split_flag = 0; /* split packets are done elsewhere */
+ head->sequence = 0; /* so are sequence numbers */
+
+ /* supposedly if daddr is NULL, we should ignore it... */
+ if (daddr) {
+ head->daddr = ((u_char *) daddr)[0];
+ return dev->hard_header_len;
+ } else
+ head->daddr = 0; /* better fill one in anyway */
+
+ return -dev->hard_header_len;
}
@@ -1451,86 +1362,84 @@ static int arcnetA_header(struct sk_buff *skb,struct net_device *dev,
*/
static int arcnetA_rebuild_header(struct sk_buff *skb)
{
- struct ClientData *head = (struct ClientData *)skb->data;
- struct net_device *dev=skb->dev;
- struct arcnet_local *lp=(struct arcnet_local *)(dev->priv);
+ struct ClientData *head = (struct ClientData *) skb->data;
+ struct net_device *dev = skb->dev;
+ struct arcnet_local *lp = (struct arcnet_local *) (dev->priv);
#ifdef CONFIG_INET
- int status;
+ int status;
#endif
- /*
- * Only ARP and IP are currently supported
- *
- * FIXME: Anyone want to spec IPv6 over ARCnet ?
- */
-
- if(head->protocol_id != ARC_P_IP)
- {
- BUGMSG(D_NORMAL,"I don't understand protocol type %d (%Xh) addresses!\n",
- head->protocol_id,head->protocol_id);
- lp->stats.tx_errors++;
- lp->stats.tx_aborted_errors++;
- head->daddr=0;
- /*memcpy(eth->h_source, dev->dev_addr, dev->addr_len);*/
- return 0;
- }
-
- /*
- * Try to get ARP to resolve the header.
- */
+ /*
+ * Only ARP and IP are currently supported
+ *
+ * FIXME: Anyone want to spec IPv6 over ARCnet ?
+ */
+
+ if (head->protocol_id != ARC_P_IP) {
+ BUGMSG(D_NORMAL, "I don't understand protocol type %d (%Xh) addresses!\n",
+ head->protocol_id, head->protocol_id);
+ lp->stats.tx_errors++;
+ lp->stats.tx_aborted_errors++;
+ head->daddr = 0;
+ /*memcpy(eth->h_source, dev->dev_addr, dev->addr_len); */
+ return 0;
+ }
+ /*
+ * Try to get ARP to resolve the header.
+ */
#ifdef CONFIG_INET
- BUGMSG(D_DURING,"rebuild header from %d to %d; protocol %Xh\n",
- head->saddr,head->daddr,head->protocol_id);
- status=arp_find(&(head->daddr),skb)? 1 : 0;
- BUGMSG(D_DURING," rebuilt: from %d to %d; protocol %Xh\n",
- head->saddr,head->daddr,head->protocol_id);
- return status;
+ BUGMSG(D_DURING, "rebuild header from %d to %d; protocol %Xh\n",
+ head->saddr, head->daddr, head->protocol_id);
+ status = arp_find(&(head->daddr), skb) ? 1 : 0;
+ BUGMSG(D_DURING, " rebuilt: from %d to %d; protocol %Xh\n",
+ head->saddr, head->daddr, head->protocol_id);
+ return status;
#else
- return 0;
+ return 0;
#endif
}
/* Determine a packet's protocol ID.
- *
+
* With ARCnet we have to convert everything to Ethernet-style stuff.
*/
-static unsigned short arcnetA_type_trans(struct sk_buff *skb,struct net_device *dev)
+static unsigned short arcnetA_type_trans(struct sk_buff *skb, struct net_device *dev)
{
- struct ClientData *head;
- struct arcnet_local *lp=(struct arcnet_local *) (dev->priv);
-
- /* Pull off the arcnet header. */
- skb->mac.raw=skb->data;
- skb_pull(skb,dev->hard_header_len);
- head=(struct ClientData *)skb->mac.raw;
-
- if (head->daddr==0)
- skb->pkt_type=PACKET_BROADCAST;
- else if (dev->flags&IFF_PROMISC)
- {
- /* if we're not sending to ourselves :) */
- if (head->daddr != dev->dev_addr[0])
- skb->pkt_type=PACKET_OTHERHOST;
- }
-
- /* now return the protocol number */
- switch (head->protocol_id)
- {
- case ARC_P_IP: return htons(ETH_P_IP);
- case ARC_P_ARP: return htons(ETH_P_ARP);
- case ARC_P_RARP: return htons(ETH_P_RARP);
-
- case ARC_P_IPX:
- case ARC_P_NOVELL_EC:
- return htons(ETH_P_802_3);
- default:
- lp->stats.rx_errors++;
- lp->stats.rx_crc_errors++;
- return 0;
- }
-
- return htons(ETH_P_IP);
+ struct ClientData *head;
+ struct arcnet_local *lp = (struct arcnet_local *) (dev->priv);
+
+ /* Pull off the arcnet header. */
+ skb->mac.raw = skb->data;
+ skb_pull(skb, dev->hard_header_len);
+ head = (struct ClientData *) skb->mac.raw;
+
+ if (head->daddr == 0)
+ skb->pkt_type = PACKET_BROADCAST;
+ else if (dev->flags & IFF_PROMISC) {
+ /* if we're not sending to ourselves :) */
+ if (head->daddr != dev->dev_addr[0])
+ skb->pkt_type = PACKET_OTHERHOST;
+ }
+ /* now return the protocol number */
+ switch (head->protocol_id) {
+ case ARC_P_IP:
+ return htons(ETH_P_IP);
+ case ARC_P_ARP:
+ return htons(ETH_P_ARP);
+ case ARC_P_RARP:
+ return htons(ETH_P_RARP);
+
+ case ARC_P_IPX:
+ case ARC_P_NOVELL_EC:
+ return htons(ETH_P_802_3);
+ default:
+ lp->stats.rx_errors++;
+ lp->stats.rx_crc_errors++;
+ return 0;
+ }
+
+ return htons(ETH_P_IP);
}
@@ -1545,17 +1454,17 @@ static unsigned short arcnetA_type_trans(struct sk_buff *skb,struct net_device *
*/
static int arcnetE_init(struct net_device *dev)
{
- struct arcnet_local *lp = (struct arcnet_local *)dev->priv;
+ struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
- ether_setup(dev); /* we're emulating ether here, not ARCnet */
- dev->dev_addr[0]=0;
- dev->dev_addr[5]=lp->stationid;
- dev->mtu=512-sizeof(struct archdr)-dev->hard_header_len-1;
- dev->open=arcnetE_open_close;
- dev->stop=arcnetE_open_close;
- dev->hard_start_xmit=arcnetE_send_packet;
+ ether_setup(dev); /* we're emulating ether here, not ARCnet */
+ dev->dev_addr[0] = 0;
+ dev->dev_addr[5] = lp->stationid;
+ dev->mtu = 512 - sizeof(struct archdr) - dev->hard_header_len - 1;
+ dev->open = arcnetE_open_close;
+ dev->stop = arcnetE_open_close;
+ dev->hard_start_xmit = arcnetE_send_packet;
- return 0;
+ return 0;
}
@@ -1564,86 +1473,77 @@ static int arcnetE_init(struct net_device *dev)
*/
static int arcnetE_open_close(struct net_device *dev)
{
- return 0;
+ return 0;
}
/* Called by the kernel in order to transmit an ethernet-type packet.
*/
-static int
-arcnetE_send_packet(struct sk_buff *skb, struct net_device *dev)
+static int arcnetE_send_packet(struct sk_buff *skb, struct net_device *dev)
{
- struct arcnet_local *lp = (struct arcnet_local *)dev->priv;
- int bad,oldmask=0;
- u_char daddr;
- short offset,length=skb->len+1;
- u_char proto=ARC_P_ETHER;
-
- lp->intx++;
-
- oldmask |= lp->intmask;
- lp->intmask=0;
- SETMASK;
-
- bad=arcnet_send_packet_bad(skb,dev);
- if (bad)
- {
- lp->intx--;
- lp->intmask=oldmask;
- SETMASK;
- return bad;
- }
-
- /* arcnet_send_packet_pad has already set tbusy - don't bother here. */
-
- lp->intmask=oldmask;
- SETMASK;
-
- if (length>XMTU)
- {
- BUGMSG(D_NORMAL,"MTU must be <= 493 for ethernet encap (length=%d).\n",
- length);
- BUGMSG(D_NORMAL,"transmit aborted.\n");
-
- dev_kfree_skb(skb);
- lp->intx--;
- return 0;
- }
-
- BUGMSG(D_DURING,"starting tx sequence...\n");
-
- /* broadcasts have address FF:FF:FF:FF:FF:FF in etherspeak */
- if (((struct ethhdr*)(skb->data))->h_dest[0] == 0xFF)
- daddr=0;
- else
- daddr=((struct ethhdr*)(skb->data))->h_dest[5];
-
- /* load packet into shared memory */
- offset=512-length;
- if (length>MTU) /* long/exception packet */
- {
- if (length<MinTU) offset-=3;
- }
- else /* short packet */
- {
- offset-=256;
- }
-
- BUGMSG(D_DURING," length=%Xh, offset=%Xh\n",
- length,offset);
-
- (*lp->prepare_tx)(dev, &proto, 1, skb->data, length-1, daddr, 0,
- offset);
+ struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
+ int bad, oldmask = 0;
+ u_char daddr;
+ short offset, length = skb->len + 1;
+ u_char proto = ARC_P_ETHER;
+
+ lp->intx++;
+
+ oldmask |= lp->intmask;
+ lp->intmask = 0;
+ SETMASK;
+
+ bad = arcnet_send_packet_bad(skb, dev);
+ if (bad) {
+ lp->intx--;
+ lp->intmask = oldmask;
+ SETMASK;
+ return bad;
+ }
+ /* arcnet_send_packet_pad has already set tbusy - don't bother here. */
- dev_kfree_skb(skb);
+ lp->intmask = oldmask;
+ SETMASK;
+
+ if (length > XMTU) {
+ BUGMSG(D_NORMAL, "MTU must be <= 493 for ethernet encap (length=%d).\n",
+ length);
+ BUGMSG(D_NORMAL, "transmit aborted.\n");
+
+ dev_kfree_skb(skb);
+ lp->intx--;
+ return 0;
+ }
+ BUGMSG(D_DURING, "starting tx sequence...\n");
+
+ /* broadcasts have address FF:FF:FF:FF:FF:FF in etherspeak */
+ if (((struct ethhdr *) (skb->data))->h_dest[0] == 0xFF)
+ daddr = 0;
+ else
+ daddr = ((struct ethhdr *) (skb->data))->h_dest[5];
+
+ /* load packet into shared memory */
+ offset = 512 - length;
+ if (length > MTU) { /* long/exception packet */
+ if (length < MinTU)
+ offset -= 3;
+ } else { /* short packet */
+ offset -= 256;
+ }
- if (arcnet_go_tx(dev,1))
- {
- /* inform upper layers */
- arcnet_tx_done(lp->adev, lp);
- }
+ BUGMSG(D_DURING, " length=%Xh, offset=%Xh\n",
+ length, offset);
- dev->trans_start=jiffies;
+ (*lp->prepare_tx) (dev, &proto, 1, skb->data, length - 1, daddr, 0,
+ offset);
+
+ dev_kfree_skb(skb);
+
+ if (arcnet_go_tx(dev, 1)) {
+ /* inform upper layers */
+ arcnet_tx_done(lp->adev, lp);
+ }
+ dev->trans_start = jiffies;
lp->intx--;
/* make sure we didn't ignore a TX IRQ while we were in here */
@@ -1656,37 +1556,35 @@ arcnetE_send_packet(struct sk_buff *skb, struct net_device *dev)
/* Packet receiver for ethernet-encap packets.
*/
-static void
-arcnetE_rx(struct net_device *dev,u_char *arcsoft,
- int length,u_char saddr, u_char daddr)
+static void arcnetE_rx(struct net_device *dev, u_char * arcsoft,
+ int length, u_char saddr, u_char daddr)
{
- struct arcnet_local *lp = (struct arcnet_local *)dev->priv;
+ struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
struct sk_buff *skb;
- BUGMSG(D_DURING,"it's an ethernet-encap packet (length=%d)\n",
- length);
-
- skb = alloc_skb(length, GFP_ATOMIC);
- if (skb == NULL) {
- BUGMSG(D_NORMAL,"Memory squeeze, dropping packet.\n");
- lp->stats.rx_dropped++;
- return;
- }
+ BUGMSG(D_DURING, "it's an ethernet-encap packet (length=%d)\n",
+ length);
- skb_put(skb,length);
+ skb = alloc_skb(length, GFP_ATOMIC);
+ if (skb == NULL) {
+ BUGMSG(D_NORMAL, "Memory squeeze, dropping packet.\n");
+ lp->stats.rx_dropped++;
+ return;
+ }
+ skb_put(skb, length);
- skb->dev = dev;
+ skb->dev = dev;
- memcpy(skb->data,(u_char *)arcsoft+1,length-1);
+ memcpy(skb->data, (u_char *) arcsoft + 1, length - 1);
- BUGLVL(D_SKB) arcnet_dump_skb(dev,skb,"rx");
+ BUGLVL(D_SKB) arcnet_dump_skb(dev, skb, "rx");
lp->stats.rx_bytes += skb->len;
- skb->protocol=eth_type_trans(skb,dev);
- netif_rx(skb);
+ skb->protocol = eth_type_trans(skb, dev);
+ netif_rx(skb);
}
-#endif /* CONFIG_ARCNET_ETH */
+#endif /* CONFIG_ARCNET_ETH */
#ifdef CONFIG_ARCNET_1051
/****************************************************************************
@@ -1699,22 +1597,22 @@ arcnetE_rx(struct net_device *dev,u_char *arcsoft,
*/
static int arcnetS_init(struct net_device *dev)
{
- struct arcnet_local *lp = (struct arcnet_local *)dev->priv;
-
- arcnet_setup(dev);
-
- /* And now fill particular fields with arcnet values */
- dev->dev_addr[0]=lp->stationid;
- dev->hard_header_len=sizeof(struct S_ClientData);
- dev->mtu=512-sizeof(struct archdr)-dev->hard_header_len
- + S_EXTRA_CLIENTDATA;
- dev->open=arcnetS_open_close;
- dev->stop=arcnetS_open_close;
- dev->hard_start_xmit=arcnetS_send_packet;
- dev->hard_header=arcnetS_header;
- dev->rebuild_header=arcnetS_rebuild_header;
-
- return 0;
+ struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
+
+ arcnet_setup(dev);
+
+ /* And now fill particular fields with arcnet values */
+ dev->dev_addr[0] = lp->stationid;
+ dev->hard_header_len = sizeof(struct S_ClientData);
+ dev->mtu = 512 - sizeof(struct archdr) - dev->hard_header_len
+ + S_EXTRA_CLIENTDATA;
+ dev->open = arcnetS_open_close;
+ dev->stop = arcnetS_open_close;
+ dev->hard_start_xmit = arcnetS_send_packet;
+ dev->hard_header = arcnetS_header;
+ dev->rebuild_header = arcnetS_rebuild_header;
+
+ return 0;
}
@@ -1723,171 +1621,160 @@ static int arcnetS_init(struct net_device *dev)
*/
static int arcnetS_open_close(struct net_device *dev)
{
- return 0;
+ return 0;
}
/* Called by the kernel in order to transmit an RFC1051-type packet.
*/
-static int
-arcnetS_send_packet(struct sk_buff *skb, struct net_device *dev)
+static int arcnetS_send_packet(struct sk_buff *skb, struct net_device *dev)
{
- struct arcnet_local *lp = (struct arcnet_local *)dev->priv;
- int bad,length;
- struct S_ClientData *hdr=(struct S_ClientData *)skb->data;
-
- lp->intx++;
-
- bad=arcnet_send_packet_bad(skb,dev);
- if (bad)
- {
- lp->intx--;
- return bad;
- }
-
- /* arcnet_send_packet_pad has already set tbusy - don't bother here. */
-
- length = 1 < skb->len ? skb->len : 1;
-
- BUGLVL(D_SKB) arcnet_dump_skb(dev,skb,"tx");
-
- /* fits in one packet? */
- if (length-S_EXTRA_CLIENTDATA<=XMTU)
- {
- (*lp->prepare_tx)(dev,
- skb->data+S_EXTRA_CLIENTDATA,
- sizeof(struct S_ClientData)-S_EXTRA_CLIENTDATA,
- skb->data+sizeof(struct S_ClientData),
- length-sizeof(struct S_ClientData),
- hdr->daddr,0,0);
-
- /* done right away */
- dev_kfree_skb(skb);
-
- if (arcnet_go_tx(dev,1))
- {
- /* inform upper layers */
- arcnet_tx_done(lp->adev, lp);
+ struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
+ int bad, length;
+ struct S_ClientData *hdr = (struct S_ClientData *) skb->data;
+
+ lp->intx++;
+
+ bad = arcnet_send_packet_bad(skb, dev);
+ if (bad) {
+ lp->intx--;
+ return bad;
}
- }
- else /* too big for one - not accepted */
- {
- BUGMSG(D_NORMAL,"packet too long (length=%d)\n",
- length);
- dev_kfree_skb(skb);
- lp->stats.tx_dropped++;
- arcnet_tx_done(lp->adev, lp);
- }
-
- dev->trans_start=jiffies;
- lp->intx--;
-
- /* make sure we didn't ignore a TX IRQ while we were in here */
- lp->intmask |= TXFREEflag;
- SETMASK;
-
- return 0;
+ /* arcnet_send_packet_pad has already set tbusy - don't bother here. */
+
+ length = 1 < skb->len ? skb->len : 1;
+
+ BUGLVL(D_SKB) arcnet_dump_skb(dev, skb, "tx");
+
+ /* fits in one packet? */
+ if (length - S_EXTRA_CLIENTDATA <= XMTU) {
+ (*lp->prepare_tx) (dev,
+ skb->data + S_EXTRA_CLIENTDATA,
+ sizeof(struct S_ClientData) - S_EXTRA_CLIENTDATA,
+ skb->data + sizeof(struct S_ClientData),
+ length - sizeof(struct S_ClientData),
+ hdr->daddr, 0, 0);
+
+ /* done right away */
+ dev_kfree_skb(skb);
+
+ if (arcnet_go_tx(dev, 1)) {
+ /* inform upper layers */
+ arcnet_tx_done(lp->adev, lp);
+ }
+ } else { /* too big for one - not accepted */
+ BUGMSG(D_NORMAL, "packet too long (length=%d)\n",
+ length);
+ dev_kfree_skb(skb);
+ lp->stats.tx_dropped++;
+ arcnet_tx_done(lp->adev, lp);
+ }
+
+ dev->trans_start = jiffies;
+ lp->intx--;
+
+ /* make sure we didn't ignore a TX IRQ while we were in here */
+ lp->intmask |= TXFREEflag;
+ SETMASK;
+
+ return 0;
}
/* Packet receiver for RFC1051 packets;
*/
-static void
-arcnetS_rx(struct net_device *dev,u_char *buf,
- int length,u_char saddr, u_char daddr)
+static void arcnetS_rx(struct net_device *dev, u_char * buf,
+ int length, u_char saddr, u_char daddr)
{
- struct arcnet_local *lp = (struct arcnet_local *)dev->priv;
- struct sk_buff *skb;
- struct S_ClientData *arcsoft,*soft;
-
- arcsoft=(struct S_ClientData *)(buf-S_EXTRA_CLIENTDATA);
- length+=S_EXTRA_CLIENTDATA;
-
- BUGMSG(D_DURING,"it's an RFC1051 packet (length=%d)\n",
- length);
-
- { /* was "if not split" in A protocol, S is never split */
-
- skb = alloc_skb(length, GFP_ATOMIC);
- if (skb == NULL) {
- BUGMSG(D_NORMAL,"Memory squeeze, dropping packet.\n");
- lp->stats.rx_dropped++;
- return;
- }
- soft=(struct S_ClientData *)skb->data;
- skb_put(skb,length);
-
- memcpy((u_char *)soft + sizeof(struct S_ClientData) - S_EXTRA_CLIENTDATA,
- (u_char *)arcsoft + sizeof(struct S_ClientData) -S_EXTRA_CLIENTDATA,
- length - sizeof(struct S_ClientData) + S_EXTRA_CLIENTDATA);
- soft->protocol_id=arcsoft->protocol_id;
- soft->daddr=daddr;
- soft->saddr=saddr;
- skb->dev = dev; /* is already lp->sdev */
-
- BUGLVL(D_SKB) arcnet_dump_skb(dev,skb,"rx");
-
- lp->stats.rx_bytes += skb->len;
- skb->protocol=arcnetS_type_trans(skb,dev);
- netif_rx(skb);
- }
+ struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
+ struct sk_buff *skb;
+ struct S_ClientData *arcsoft, *soft;
+
+ arcsoft = (struct S_ClientData *) (buf - S_EXTRA_CLIENTDATA);
+ length += S_EXTRA_CLIENTDATA;
+
+ BUGMSG(D_DURING, "it's an RFC1051 packet (length=%d)\n",
+ length);
+
+ { /* was "if not split" in A protocol, S is never split */
+
+ skb = alloc_skb(length, GFP_ATOMIC);
+ if (skb == NULL) {
+ BUGMSG(D_NORMAL, "Memory squeeze, dropping packet.\n");
+ lp->stats.rx_dropped++;
+ return;
+ }
+ soft = (struct S_ClientData *) skb->data;
+ skb_put(skb, length);
+
+ memcpy((u_char *) soft + sizeof(struct S_ClientData) - S_EXTRA_CLIENTDATA,
+ (u_char *) arcsoft + sizeof(struct S_ClientData) - S_EXTRA_CLIENTDATA,
+ length - sizeof(struct S_ClientData) + S_EXTRA_CLIENTDATA);
+ soft->protocol_id = arcsoft->protocol_id;
+ soft->daddr = daddr;
+ soft->saddr = saddr;
+ skb->dev = dev; /* is already lp->sdev */
+
+ BUGLVL(D_SKB) arcnet_dump_skb(dev, skb, "rx");
+
+ lp->stats.rx_bytes += skb->len;
+ skb->protocol = arcnetS_type_trans(skb, dev);
+ netif_rx(skb);
+ }
}
/* Create the ARCnet ClientData header for an arbitrary protocol layer
- *
- * saddr=NULL means use device source address (always will anyway)
- * daddr=NULL means leave destination address (eg unresolved arp)
+
+ * saddr=NULL means use device source address (always will anyway)
+ * daddr=NULL means leave destination address (eg unresolved arp)
*/
-static int arcnetS_header(struct sk_buff *skb,struct net_device *dev,
- unsigned short type,void *daddr,void *saddr,unsigned len)
+static int arcnetS_header(struct sk_buff *skb, struct net_device *dev,
+ unsigned short type, void *daddr, void *saddr, unsigned len)
{
- struct S_ClientData *head = (struct S_ClientData *)
- skb_push(skb,dev->hard_header_len);
- struct arcnet_local *lp=(struct arcnet_local *)(dev->priv);
-
- /* set the protocol ID according to RFC1051 */
- switch(type)
- {
- case ETH_P_IP:
- head->protocol_id=ARC_P_IP_RFC1051;
- BUGMSG(D_DURING,"S_header: IP_RFC1051 packet.\n");
- break;
- case ETH_P_ARP:
- head->protocol_id=ARC_P_ARP_RFC1051;
- BUGMSG(D_DURING,"S_header: ARP_RFC1051 packet.\n");
- break;
- default:
- BUGMSG(D_NORMAL,"I don't understand protocol %d (%Xh)\n",
- type,type);
- lp->stats.tx_errors++;
- lp->stats.tx_aborted_errors++;
- return 0;
- }
-
- /*
- * Set the source hardware address.
- *
- * This is pretty pointless for most purposes, but it can help
- * in debugging. saddr is stored in the ClientData header and
- * removed before sending the packet (since ARCnet does not allow
- * us to change the source address in the actual packet sent)
- */
- if(saddr)
- head->saddr=((u_char*)saddr)[0];
- else
- head->saddr=((u_char*)(dev->dev_addr))[0];
-
- /* supposedly if daddr is NULL, we should ignore it... */
- if(daddr)
- {
- head->daddr=((u_char*)daddr)[0];
+ struct S_ClientData *head = (struct S_ClientData *)
+ skb_push(skb, dev->hard_header_len);
+ struct arcnet_local *lp = (struct arcnet_local *) (dev->priv);
+
+ /* set the protocol ID according to RFC1051 */
+ switch (type) {
+ case ETH_P_IP:
+ head->protocol_id = ARC_P_IP_RFC1051;
+ BUGMSG(D_DURING, "S_header: IP_RFC1051 packet.\n");
+ break;
+ case ETH_P_ARP:
+ head->protocol_id = ARC_P_ARP_RFC1051;
+ BUGMSG(D_DURING, "S_header: ARP_RFC1051 packet.\n");
+ break;
+ default:
+ BUGMSG(D_NORMAL, "I don't understand protocol %d (%Xh)\n",
+ type, type);
+ lp->stats.tx_errors++;
+ lp->stats.tx_aborted_errors++;
+ return 0;
+ }
+
+ /*
+ * Set the source hardware address.
+ *
+ * This is pretty pointless for most purposes, but it can help
+ * in debugging. saddr is stored in the ClientData header and
+ * removed before sending the packet (since ARCnet does not allow
+ * us to change the source address in the actual packet sent)
+ */
+ if (saddr)
+ head->saddr = ((u_char *) saddr)[0];
+ else
+ head->saddr = ((u_char *) (dev->dev_addr))[0];
+
+ /* supposedly if daddr is NULL, we should ignore it... */
+ if (daddr) {
+ head->daddr = ((u_char *) daddr)[0];
return dev->hard_header_len;
- }
- else
- head->daddr=0; /* better fill one in anyway */
+ } else
+ head->daddr = 0; /* better fill one in anyway */
- return -dev->hard_header_len;
+ return -dev->hard_header_len;
}
@@ -1897,75 +1784,73 @@ static int arcnetS_header(struct sk_buff *skb,struct net_device *dev,
*/
static int arcnetS_rebuild_header(struct sk_buff *skb)
{
- struct net_device *dev=skb->dev;
- struct S_ClientData *head = (struct S_ClientData *)skb->data;
- struct arcnet_local *lp=(struct arcnet_local *)(dev->priv);
-
- /*
- * Only ARP and IP are currently supported
- */
-
- if(head->protocol_id != ARC_P_IP_RFC1051)
- {
- BUGMSG(D_NORMAL,"I don't understand protocol type %d (%Xh) addresses!\n",
- head->protocol_id,head->protocol_id);
- lp->stats.tx_errors++;
- lp->stats.tx_aborted_errors++;
- head->daddr=0;
- /*memcpy(eth->h_source, dev->dev_addr, dev->addr_len);*/
- return 0;
- }
-
- /*
- * Try to get ARP to resolve the header.
- */
+ struct net_device *dev = skb->dev;
+ struct S_ClientData *head = (struct S_ClientData *) skb->data;
+ struct arcnet_local *lp = (struct arcnet_local *) (dev->priv);
+
+ /*
+ * Only ARP and IP are currently supported
+ */
+
+ if (head->protocol_id != ARC_P_IP_RFC1051) {
+ BUGMSG(D_NORMAL, "I don't understand protocol type %d (%Xh) addresses!\n",
+ head->protocol_id, head->protocol_id);
+ lp->stats.tx_errors++;
+ lp->stats.tx_aborted_errors++;
+ head->daddr = 0;
+ /*memcpy(eth->h_source, dev->dev_addr, dev->addr_len); */
+ return 0;
+ }
+ /*
+ * Try to get ARP to resolve the header.
+ */
#ifdef CONFIG_INET
- return arp_find(&(head->daddr),skb)? 1 : 0;
+ return arp_find(&(head->daddr), skb) ? 1 : 0;
#else
- return 0;
+ return 0;
#endif
}
/* Determine a packet's protocol ID.
- *
+
* With ARCnet we have to convert everything to Ethernet-style stuff.
*/
-unsigned short arcnetS_type_trans(struct sk_buff *skb,struct net_device *dev)
+unsigned short arcnetS_type_trans(struct sk_buff *skb, struct net_device *dev)
{
- struct S_ClientData *head;
- struct arcnet_local *lp=(struct arcnet_local *) (dev->priv);
-
- /* Pull off the arcnet header. */
- skb->mac.raw=skb->data;
- skb_pull(skb,dev->hard_header_len);
- head=(struct S_ClientData *)skb->mac.raw;
-
- if (head->daddr==0)
- skb->pkt_type=PACKET_BROADCAST;
- else if (dev->flags&IFF_PROMISC)
- {
- /* if we're not sending to ourselves :) */
- if (head->daddr != dev->dev_addr[0])
- skb->pkt_type=PACKET_OTHERHOST;
- }
-
- /* now return the protocol number */
- switch (head->protocol_id)
- {
- case ARC_P_IP_RFC1051: return htons(ETH_P_IP);
- case ARC_P_ARP_RFC1051: return htons(ETH_P_ARP);
- case ARC_P_ATALK: return htons(ETH_P_ATALK); /* untested appletalk */
- default:
- lp->stats.rx_errors++;
- lp->stats.rx_crc_errors++;
- return 0;
- }
-
- return htons(ETH_P_IP);
+ struct S_ClientData *head;
+ struct arcnet_local *lp = (struct arcnet_local *) (dev->priv);
+
+ /* Pull off the arcnet header. */
+ skb->mac.raw = skb->data;
+ skb_pull(skb, dev->hard_header_len);
+ head = (struct S_ClientData *) skb->mac.raw;
+
+ if (head->daddr == 0)
+ skb->pkt_type = PACKET_BROADCAST;
+ else if (dev->flags & IFF_PROMISC) {
+ /* if we're not sending to ourselves :) */
+ if (head->daddr != dev->dev_addr[0])
+ skb->pkt_type = PACKET_OTHERHOST;
+ }
+ /* now return the protocol number */
+ switch (head->protocol_id) {
+ case ARC_P_IP_RFC1051:
+ return htons(ETH_P_IP);
+ case ARC_P_ARP_RFC1051:
+ return htons(ETH_P_ARP);
+ case ARC_P_ATALK:
+ return htons(ETH_P_ATALK); /* untested appletalk */
+ default:
+ lp->stats.rx_errors++;
+ lp->stats.rx_crc_errors++;
+ return 0;
+ }
+
+ return htons(ETH_P_IP);
}
-#endif /* CONFIG_ARCNET_1051 */
+#endif /* CONFIG_ARCNET_1051 */
/****************************************************************************
@@ -1978,15 +1863,15 @@ unsigned short arcnetS_type_trans(struct sk_buff *skb,struct net_device *dev)
void cleanup_module(void)
{
- printk("Generic arcnet support removed.\n");
+ printk("Generic arcnet support removed.\n");
}
void arcnet_use_count(int open)
{
- if (open)
- MOD_INC_USE_COUNT;
- else
- MOD_DEC_USE_COUNT;
+ if (open)
+ MOD_INC_USE_COUNT;
+ else
+ MOD_DEC_USE_COUNT;
}
#else
@@ -1996,54 +1881,52 @@ void arcnet_use_count(int open)
}
struct net_device arcnet_devs[MAX_ARCNET_DEVS];
-int arcnet_num_devs=0;
+int arcnet_num_devs = 0;
char arcnet_dev_names[MAX_ARCNET_DEVS][10];
-void __init arcnet_init(void)
+int __init arcnet_init(void)
{
- int c;
+ int c;
- init_module();
+ init_module();
- /* Don't register_netdev here. The chain hasn't been initialised. */
+ /* Don't register_netdev here. The chain hasn't been initialised. */
#ifdef CONFIG_ARCNET_COM90xx
- if ((!com90xx_explicit) && arcnet_num_devs < MAX_ARCNET_DEVS)
- {
- arcnet_devs[arcnet_num_devs].init=arc90xx_probe;
- arcnet_devs[arcnet_num_devs].name=
- (char *)&arcnet_dev_names[arcnet_num_devs];
- arcnet_num_devs++;
- }
+ if ((!com90xx_explicit) && arcnet_num_devs < MAX_ARCNET_DEVS) {
+ arcnet_devs[arcnet_num_devs].init = arc90xx_probe;
+ arcnet_devs[arcnet_num_devs].name =
+ (char *) &arcnet_dev_names[arcnet_num_devs];
+ arcnet_num_devs++;
+ }
#endif
- if (!arcnet_num_devs)
- {
- printk("Don't forget to load the chipset driver.\n");
- return;
- }
-
- /* Link into the device chain */
+ if (!arcnet_num_devs) {
+ printk("Don't forget to load the chipset driver.\n");
+ return 0;
+ }
+ /* Link into the device chain */
- /* Q: Should we put ourselves at the beginning or the end of the chain? */
- /* Probably the end, because we're not so fast, but... */
+ /* Q: Should we put ourselves at the beginning or the end of the chain? */
+ /* Probably the end, because we're not so fast, but... */
- for (c=0; c< (arcnet_num_devs-1); c++)
- arcnet_devs[c].next=&arcnet_devs[c+1];
+ for (c = 0; c < (arcnet_num_devs - 1); c++)
+ arcnet_devs[c].next = &arcnet_devs[c + 1];
- write_lock_bh(&dev_base_lock);
- arcnet_devs[c].next=dev_base;
- dev_base=&arcnet_devs[0];
- write_unlock_bh(&dev_base_lock);
+ write_lock_bh(&dev_base_lock);
+ arcnet_devs[c].next = dev_base;
+ dev_base = &arcnet_devs[0];
+ write_unlock_bh(&dev_base_lock);
- /* Give names to those without them */
+ /* Give names to those without them */
- for (c=0; c< arcnet_num_devs; c++)
- if (!arcnet_dev_names[c][0])
- arcnet_makename((char *)&arcnet_dev_names[c]);
+ for (c = 0; c < arcnet_num_devs; c++)
+ if (!arcnet_dev_names[c][0])
+ arcnet_makename((char *) &arcnet_dev_names[c]);
+ return 0;
}
-#endif /* MODULE */
+#endif /* MODULE */
#ifdef MODULE
@@ -2053,48 +1936,46 @@ static int __init init_module(void)
#endif
{
#ifdef ALPHA_WARNING
- BUGLVL(D_EXTRA)
- {
- printk("arcnet: ***\n");
- printk("arcnet: * Read arcnet.txt for important release notes!\n");
- printk("arcnet: *\n");
- printk("arcnet: * This is an ALPHA version! (Last stable release: v2.56) E-mail me if\n");
- printk("arcnet: * you have any questions, comments, or bug reports.\n");
- printk("arcnet: ***\n");
- }
+ BUGLVL(D_EXTRA) {
+ printk("arcnet: ***\n");
+ printk("arcnet: * Read arcnet.txt for important release notes!\n");
+ printk("arcnet: *\n");
+ printk("arcnet: * This is an ALPHA version! (Last stable release: v2.56) E-mail me if\n");
+ printk("arcnet: * you have any questions, comments, or bug reports.\n");
+ printk("arcnet: ***\n");
+ }
#endif
- printk("%sAvailable protocols: ARCnet RFC1201"
+ printk("%sAvailable protocols: ARCnet RFC1201"
#ifdef CONFIG_ARCNET_ETH
- ", Ethernet-Encap"
+ ", Ethernet-Encap"
#endif
#ifdef CONFIG_ARCNET_1051
- ", ARCnet RFC1051"
+ ", ARCnet RFC1051"
#endif
#ifdef MODULE
- ".\nDon't forget to load the chipset driver"
+ ".\nDon't forget to load the chipset driver"
#endif
- ".\n",version);
- return 0;
+ ".\n", version);
+ return 0;
}
void arcnet_makename(char *device)
{
- struct net_device *dev;
- int arcnum;
-
- arcnum = 0;
- for (;;)
- {
- sprintf(device, "arc%d", arcnum);
- read_lock_bh(&dev_base_lock);
- for (dev = dev_base; dev; dev=dev->next)
- if (dev->name != device && !strcmp(dev->name, device))
- break;
- read_unlock_bh(&dev_base_lock);
- if (!dev)
- return;
- arcnum++;
- }
+ struct net_device *dev;
+ int arcnum;
+
+ arcnum = 0;
+ for (;;) {
+ sprintf(device, "arc%d", arcnum);
+ read_lock_bh(&dev_base_lock);
+ for (dev = dev_base; dev; dev = dev->next)
+ if (dev->name != device && !strcmp(dev->name, device))
+ break;
+ read_unlock_bh(&dev_base_lock);
+ if (!dev)
+ return;
+ arcnum++;
+ }
}
diff --git a/drivers/net/irda/actisys.c b/drivers/net/irda/actisys.c
index f83fce38c..10d6cf208 100644
--- a/drivers/net/irda/actisys.c
+++ b/drivers/net/irda/actisys.c
@@ -7,7 +7,7 @@
* Status: Experimental.
* Author: Dag Brattli <dagb@cs.uit.no>
* Created at: Wed Oct 21 20:02:35 1998
- * Modified at: Sat Jun 26 16:57:57 1999
+ * Modified at: Mon Oct 18 23:37:06 1999
* Modified by: Dag Brattli <dagb@cs.uit.no>
*
* Copyright (c) 1998-1999 Dag Brattli, All Rights Reserved.
@@ -32,33 +32,31 @@
#include <net/irda/irda.h>
#include <net/irda/irmod.h>
#include <net/irda/irda_device.h>
-#include <net/irda/dongle.h>
-static void actisys_reset(struct irda_device *dev);
-static void actisys_open(struct irda_device *idev, int type);
-static void actisys_close(struct irda_device *dev);
-static void actisys_change_speed( struct irda_device *dev, __u32 speed);
-static void actisys_init_qos(struct irda_device *idev, struct qos_info *qos);
+static int actisys_change_speed(struct irda_task *task);
+static int actisys_reset(struct irda_task *task);
+static void actisys_open(dongle_t *self, struct qos_info *qos);
+static void actisys_close(dongle_t *self);
/* These are the baudrates supported */
-static __u32 baud_rates[] = { 9600, 19200, 57600, 115200, 38400};
+static __u32 baud_rates[] = { 9600, 19200, 57600, 115200, 38400 };
-static struct dongle dongle = {
- ACTISYS_DONGLE,
+static struct dongle_reg dongle = {
+ Q_NULL,
+ IRDA_ACTISYS_DONGLE,
actisys_open,
actisys_close,
actisys_reset,
actisys_change_speed,
- actisys_init_qos,
};
-static struct dongle dongle_plus = {
- ACTISYS_PLUS_DONGLE,
+static struct dongle_reg dongle_plus = {
+ Q_NULL,
+ IRDA_ACTISYS_PLUS_DONGLE,
actisys_open,
actisys_close,
actisys_reset,
actisys_change_speed,
- actisys_init_qos,
};
int __init actisys_init(void)
@@ -82,20 +80,23 @@ void actisys_cleanup(void)
irda_device_unregister_dongle(&dongle_plus);
}
-static void actisys_open(struct irda_device *idev, int type)
+static void actisys_open(dongle_t *self, struct qos_info *qos)
{
- strcat(idev->description, " <-> actisys");
+ qos->baud_rate.bits &= IR_9600|IR_19200|IR_38400|IR_57600|IR_115200;
- idev->io.dongle_id = type;
- idev->flags |= IFF_DONGLE;
+ /* Remove support for 38400 if this is not a 220L+ dongle */
+ if (self->issue->type == IRDA_ACTISYS_DONGLE)
+ qos->baud_rate.bits &= ~IR_38400;
+
+ qos->min_turn_time.bits &= 0x40; /* Needs 0.01 ms */
MOD_INC_USE_COUNT;
}
-static void actisys_close(struct irda_device *idev)
+static void actisys_close(dongle_t *self)
{
/* Power off dongle */
- irda_device_set_dtr_rts(idev, FALSE, FALSE);
+ self->set_dtr_rts(self->dev, FALSE, FALSE);
MOD_DEC_USE_COUNT;
}
@@ -107,52 +108,84 @@ static void actisys_close(struct irda_device *idev)
* To cycle through the available baud rates, pulse RTS low for a few
* ms.
*/
-static void actisys_change_speed(struct irda_device *idev, __u32 speed)
+static int actisys_change_speed(struct irda_task *task)
{
- __u32 current_baudrate;
+ dongle_t *self = (dongle_t *) task->instance;
+ __u32 speed = (__u32) task->param;
+ __u32 current_speed;
int index = 0;
+ int ret = 0;
- DEBUG(4, __FUNCTION__ "()\n");
+ IRDA_DEBUG(4, __FUNCTION__ "()\n");
- ASSERT(idev != NULL, return;);
- ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;);
-
- current_baudrate = idev->qos.baud_rate.value;
+ current_speed = self->speed;
/* Find the correct baudrate index for the currently used baudrate */
- while (current_baudrate != baud_rates[index])
+ while (current_speed != baud_rates[index])
index++;
- DEBUG( 4, __FUNCTION__ "(), index=%d\n", index);
+ IRDA_DEBUG(4, __FUNCTION__ "(), index=%d\n", index);
- /* Cycle through avaiable baudrates until we reach the correct one */
- while (current_baudrate != speed) {
- DEBUG(4, __FUNCTION__ "(), current baudrate = %d\n",
+ switch (task->state) {
+ case IRDA_TASK_INIT:
+ /* Lock dongle */
+ if (irda_lock((void *) &self->busy) == FALSE) {
+ IRDA_DEBUG(0, __FUNCTION__ "(), busy!\n");
+ ret = MSECS_TO_JIFFIES(100);
+ break;
+ }
+
+ IRDA_DEBUG(4, __FUNCTION__ "(), current baudrate = %d\n",
baud_rates[index]);
/* Set DTR, clear RTS */
- irda_device_set_dtr_rts(idev, TRUE, FALSE);
+ self->set_dtr_rts(self->dev, TRUE, FALSE);
- /* Wait at a few ms */
- current->state = TASK_INTERRUPTIBLE;
- schedule_timeout(MSECS_TO_JIFFIES(20));
+ irda_task_next_state(task, IRDA_TASK_WAIT1);
+ /* Wait at a few ms */
+ ret = MSECS_TO_JIFFIES(20);
+ break;
+ case IRDA_TASK_WAIT1:
/* Set DTR, Set RTS */
- irda_device_set_dtr_rts(idev, TRUE, TRUE);
+ self->set_dtr_rts(self->dev, TRUE, TRUE);
- /* Wait at a few ms again */
- current->state = TASK_INTERRUPTIBLE;
- schedule_timeout(MSECS_TO_JIFFIES(20));
+ irda_task_next_state(task, IRDA_TASK_WAIT2);
+ /* Wait at a few ms again */
+ ret = MSECS_TO_JIFFIES(20);
+ break;
+ case IRDA_TASK_WAIT2:
/* Go to next baudrate */
- if (idev->io.dongle_id == ACTISYS_DONGLE)
+ if (self->issue->type == IRDA_ACTISYS_DONGLE)
index = (index+1) % 4; /* IR-220L */
else
index = (index+1) % 5; /* IR-220L+ */
- current_baudrate = baud_rates[index];
+ current_speed = baud_rates[index];
+
+ /* Check if we need to go some more rounds */
+ if (current_speed != speed)
+ irda_task_next_state(task, IRDA_TASK_INIT);
+ else {
+ irda_task_next_state(task, IRDA_TASK_DONE);
+ self->busy = 0;
+ }
+ break;
+ default:
+ ERROR(__FUNCTION__ "(), unknown state %d\n", task->state);
+ irda_task_next_state(task, IRDA_TASK_DONE);
+ self->busy = 0;
+ ret = -1;
+ break;
}
- DEBUG(4, __FUNCTION__ "(), current baudrate = %d\n", baud_rates[index]);
+
+ self->speed = speed;
+
+ IRDA_DEBUG(4, __FUNCTION__ "(), current baudrate = %d\n",
+ baud_rates[index]);
+
+ return ret;
}
/*
@@ -162,45 +195,42 @@ static void actisys_change_speed(struct irda_device *idev, __u32 speed)
* called with a process context!
*
* 1. Clear DTR for a few ms.
- *
*/
-static void actisys_reset(struct irda_device *idev)
+static int actisys_reset(struct irda_task *task)
{
- ASSERT(idev != NULL, return;);
- ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;);
-
- /* Clear DTR */
- irda_device_set_dtr_rts(idev, FALSE, TRUE);
+ dongle_t *self = (dongle_t *) task->instance;
+ int ret = 0;
- /* Sleep 10-20 ms*/
- current->state = TASK_INTERRUPTIBLE;
- schedule_timeout(MSECS_TO_JIFFIES(20));
-
- /* Go back to normal mode */
- irda_device_set_dtr_rts(idev, TRUE, TRUE);
-
- idev->qos.baud_rate.value = 9600;
-}
+ ASSERT(task != NULL, return -1;);
-/*
- * Function actisys_init_qos (qos)
- *
- * Initialize QoS capabilities
- *
- */
-static void actisys_init_qos(struct irda_device *idev, struct qos_info *qos)
-{
- qos->baud_rate.bits &= IR_9600|IR_19200|IR_38400|IR_57600|IR_115200;
+ switch (task->state) {
+ case IRDA_TASK_INIT:
+ /* Clear DTR */
+ self->set_dtr_rts(self->dev, FALSE, TRUE);
+
+ irda_task_next_state(task, IRDA_TASK_WAIT);
- /* Remove support for 38400 if this is not a 220L+ dongle */
- if (idev->io.dongle_id == ACTISYS_DONGLE)
- qos->baud_rate.bits &= ~IR_38400;
+ /* Sleep 10-20 ms*/
+ ret = MSECS_TO_JIFFIES(20);
+ break;
+ case IRDA_TASK_WAIT:
+ /* Go back to normal mode */
+ self->set_dtr_rts(self->dev, TRUE, TRUE);
- qos->min_turn_time.bits &= 0x40; /* Needs 0.01 ms */
+ irda_task_next_state(task, IRDA_TASK_DONE);
+
+ self->speed = 9600;
+ break;
+ default:
+ ERROR(__FUNCTION__ "(), unknown state %d\n", task->state);
+ irda_task_next_state(task, IRDA_TASK_DONE);
+ ret = -1;
+ break;
+ }
+ return ret;
}
#ifdef MODULE
-
MODULE_AUTHOR("Dag Brattli <dagb@cs.uit.no>");
MODULE_DESCRIPTION("ACTiSYS IR-220L and IR-220L+ dongle driver");
@@ -225,5 +255,4 @@ void cleanup_module(void)
{
actisys_cleanup();
}
-
-#endif
+#endif /* MODULE */
diff --git a/drivers/net/irda/airport.c b/drivers/net/irda/airport.c
index edfc2e6e6..a1eee252b 100644
--- a/drivers/net/irda/airport.c
+++ b/drivers/net/irda/airport.c
@@ -56,7 +56,7 @@ int __init airport_init(void)
{
int ret;
- DEBUG(2, __FUNCTION__ "()\n");
+ IRDA_DEBUG(2, __FUNCTION__ "()\n");
ret = irda_device_register_dongle(&dongle);
if (ret < 0)
return ret;
@@ -65,17 +65,17 @@ int __init airport_init(void)
void airport_cleanup(void)
{
- DEBUG(2, __FUNCTION__ "()\n");
+ IRDA_DEBUG(2, __FUNCTION__ "()\n");
irda_device_unregister_dongle(&dongle);
}
static void airport_open(struct irda_device *idev, int type)
{
- DEBUG(2, __FUNCTION__ "(,%d)\n", type);
+ IRDA_DEBUG(2, __FUNCTION__ "(,%d)\n", type);
if (strlen(idev->description) < sizeof(idev->description) - 13)
strcat(idev->description, " <-> airport");
else
- DEBUG(0, __FUNCTION__ " description too long: %s\n",
+ IRDA_DEBUG(0, __FUNCTION__ " description too long: %s\n",
idev->description);
idev->io.dongle_id = type;
@@ -86,7 +86,7 @@ static void airport_open(struct irda_device *idev, int type)
static void airport_close(struct irda_device *idev)
{
- DEBUG(2, __FUNCTION__ "()\n");
+ IRDA_DEBUG(2, __FUNCTION__ "()\n");
/* Power off dongle */
irda_device_set_dtr_rts(idev, FALSE, FALSE);
@@ -95,13 +95,13 @@ static void airport_close(struct irda_device *idev)
static void airport_set_command_mode(struct irda_device *idev)
{
- DEBUG(2, __FUNCTION__ "()\n");
+ IRDA_DEBUG(2, __FUNCTION__ "()\n");
irda_device_set_dtr_rts(idev, FALSE, TRUE);
}
static void airport_set_normal_mode(struct irda_device *idev)
{
- DEBUG(2, __FUNCTION__ "()\n");
+ IRDA_DEBUG(2, __FUNCTION__ "()\n");
irda_device_set_dtr_rts(idev, TRUE, TRUE);
}
@@ -109,7 +109,7 @@ static void airport_set_normal_mode(struct irda_device *idev)
void airport_write_char(struct irda_device *idev, unsigned char c)
{
int actual;
- DEBUG(2, __FUNCTION__ "(,0x%x)\n", c & 0xff);
+ IRDA_DEBUG(2, __FUNCTION__ "(,0x%x)\n", c & 0xff);
actual = idev->raw_write(idev, &c, 1);
ASSERT(actual == 1, return;);
}
@@ -120,22 +120,22 @@ static int airport_waitfor_char(struct irda_device *idev, unsigned char c)
{
int i, found = FALSE;
int before;
- DEBUG(2, __FUNCTION__ "(,0x%x)\n", c);
+ IRDA_DEBUG(2, __FUNCTION__ "(,0x%x)\n", c);
/* Sleep approx. 10 ms */
before = jiffies;
current->state = TASK_INTERRUPTIBLE;
schedule_timeout(MSECS_TO_JIFFIES(20));
- DEBUG(4, __FUNCTION__ " waited %ldms\n",
+ IRDA_DEBUG(4, __FUNCTION__ " waited %ldms\n",
JIFFIES_TO_MSECS(jiffies - before));
for ( i = 0 ; !found && i < idev->rx_buff.len ; i++ ) {
- /* DEBUG(6, __FUNCTION__ " 0x02x\n", idev->rx_buff.data[i]); */
+ /* IRDA_DEBUG(6, __FUNCTION__ " 0x02x\n", idev->rx_buff.data[i]); */
found = c == idev->rx_buff.data[i];
}
idev->rx_buff.len = 0;
- DEBUG(2, __FUNCTION__ " returns %s\n", (found ? "true" : "false"));
+ IRDA_DEBUG(2, __FUNCTION__ " returns %s\n", (found ? "true" : "false"));
return found;
}
@@ -144,7 +144,7 @@ static int airport_check_command_mode(struct irda_device *idev)
int i;
int found = FALSE;
- DEBUG(2, __FUNCTION__ "()\n");
+ IRDA_DEBUG(2, __FUNCTION__ "()\n");
current->state = TASK_INTERRUPTIBLE;
schedule_timeout(MSECS_TO_JIFFIES(20));
airport_set_command_mode(idev);
@@ -160,9 +160,9 @@ static int airport_check_command_mode(struct irda_device *idev)
}
if (found) {
- DEBUG(2, __FUNCTION__ " OK. (%d)\n", i);
+ IRDA_DEBUG(2, __FUNCTION__ " OK. (%d)\n", i);
} else {
- DEBUG(0, __FUNCTION__ " FAILED!\n");
+ IRDA_DEBUG(0, __FUNCTION__ " FAILED!\n");
}
return found;
}
@@ -173,7 +173,7 @@ static int airport_write_register(struct irda_device *idev, unsigned char reg)
int ok = FALSE;
int i;
- DEBUG(4, __FUNCTION__ "(,0x%x)\n", reg);
+ IRDA_DEBUG(4, __FUNCTION__ "(,0x%x)\n", reg);
airport_check_command_mode(idev);
for ( i = 0 ; i < 6 ; i++ ) {
@@ -191,9 +191,9 @@ static int airport_write_register(struct irda_device *idev, unsigned char reg)
airport_set_normal_mode(idev);
if (ok) {
- DEBUG(4, __FUNCTION__ "(,0x%x) returns OK\n", reg);
+ IRDA_DEBUG(4, __FUNCTION__ "(,0x%x) returns OK\n", reg);
} else {
- DEBUG(0, __FUNCTION__ "(,0x%x) returns False!\n", reg);
+ IRDA_DEBUG(0, __FUNCTION__ "(,0x%x) returns False!\n", reg);
}
return ok;
}
@@ -209,7 +209,7 @@ static void airport_change_speed(struct irda_device *idev, __u32 speed)
__u32 current_baudrate;
int baudcode;
- DEBUG(4, __FUNCTION__ "(,%d)\n", speed);
+ IRDA_DEBUG(4, __FUNCTION__ "(,%d)\n", speed);
ASSERT(idev != NULL, return;);
ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;);
@@ -224,16 +224,16 @@ static void airport_change_speed(struct irda_device *idev, __u32 speed)
case 57600: baudcode = 0x60; break;
case 115200: baudcode = 0x70; break;
default:
- DEBUG(0, __FUNCTION__ " bad baud rate: %d\n", speed);
+ IRDA_DEBUG(0, __FUNCTION__ " bad baud rate: %d\n", speed);
return;
}
current_baudrate = idev->qos.baud_rate.value;
- DEBUG(4, __FUNCTION__ " current baudrate: %d\n", current_baudrate);
+ IRDA_DEBUG(4, __FUNCTION__ " current baudrate: %d\n", current_baudrate);
/* The dongle falls back to 9600 baud */
if (current_baudrate != 9600) {
- DEBUG(4, __FUNCTION__ " resetting speed to 9600 baud\n");
+ IRDA_DEBUG(4, __FUNCTION__ " resetting speed to 9600 baud\n");
ASSERT(idev->change_speed , return;);
idev->change_speed(idev, 9600);
idev->qos.baud_rate.value = 9600;
@@ -247,11 +247,11 @@ static void airport_change_speed(struct irda_device *idev, __u32 speed)
if (airport_write_register(idev, baudcode|0x01)) {
/* ok */
} else {
- DEBUG(0, __FUNCTION__
+ IRDA_DEBUG(0, __FUNCTION__
" Cannot set new speed in second register\n");
}
} else {
- DEBUG(0, __FUNCTION__
+ IRDA_DEBUG(0, __FUNCTION__
" Cannot set new speed in first register\n");
}
@@ -260,7 +260,7 @@ static void airport_change_speed(struct irda_device *idev, __u32 speed)
/* How do I signal an error in these functions? */
- DEBUG(4, __FUNCTION__ " returning\n");
+ IRDA_DEBUG(4, __FUNCTION__ " returning\n");
}
@@ -275,7 +275,7 @@ static void airport_reset(struct irda_device *idev)
{
int ok;
- DEBUG(2, __FUNCTION__ "()\n");
+ IRDA_DEBUG(2, __FUNCTION__ "()\n");
ASSERT(idev != NULL, return;);
ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;);
ASSERT(idev->set_raw_mode /* The airport needs this */, return;);
@@ -286,10 +286,10 @@ static void airport_reset(struct irda_device *idev)
airport_set_normal_mode(idev);
/* Sleep 2000 ms */
- DEBUG(2, __FUNCTION__ " waiting for powerup\n");
+ IRDA_DEBUG(2, __FUNCTION__ " waiting for powerup\n");
current->state = TASK_INTERRUPTIBLE;
schedule_timeout(MSECS_TO_JIFFIES(2000));
- DEBUG(2, __FUNCTION__ " finished waiting for powerup\n");
+ IRDA_DEBUG(2, __FUNCTION__ " finished waiting for powerup\n");
/* set dongle speed to 9600 */
ok = TRUE;
@@ -322,12 +322,12 @@ static void airport_reset(struct irda_device *idev)
current->state = TASK_INTERRUPTIBLE;
schedule_timeout(MSECS_TO_JIFFIES(20));
- DEBUG(4, __FUNCTION__ " waited 20ms\n");
+ IRDA_DEBUG(4, __FUNCTION__ " waited 20ms\n");
idev->qos.baud_rate.value = 9600;
if (!ok)
MESSAGE(__FUNCTION__ "() failed.\n");
- DEBUG(2, __FUNCTION__ " returning.\n");
+ IRDA_DEBUG(2, __FUNCTION__ " returning.\n");
}
/*
diff --git a/drivers/net/irda/esi.c b/drivers/net/irda/esi.c
index f531c1af4..bc6f28da7 100644
--- a/drivers/net/irda/esi.c
+++ b/drivers/net/irda/esi.c
@@ -1,27 +1,33 @@
/*********************************************************************
*
* Filename: esi.c
- * Version: 1.4
+ * Version: 1.5
* Description: Driver for the Extended Systems JetEye PC dongle
* Status: Experimental.
- * Author: Thomas Davis, <ratbert@radiks.net>
+ * Author: Dag Brattli <dagb@cs.uit.no>
* Created at: Sat Feb 21 18:54:38 1998
- * Modified at: Sat Jun 26 16:50:17 1999
+ * Modified at: Mon Oct 18 12:35:43 1999
* Modified by: Dag Brattli <dagb@cs.uit.no>
- * Sources: esi.c
- *
- * Copyright (c) 1998-1999, Dag Brattli, <dagb@cs.uit.no>
- * Copyright (c) 1998, Thomas Davis, <ratbert@radiks.net>,
+ *
+ * Copyright (c) 1999 Dag Brattli, <dagb@cs.uit.no>,
+ * Copyright (c) 1998 Thomas Davis, <ratbert@radiks.net>,
* All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
- *
- * I, Thomas Davis, provide no warranty for any of this software.
- * This material is provided "AS-IS" and at no charge.
- *
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
********************************************************************/
#include <linux/module.h>
@@ -34,22 +40,19 @@
#include <net/irda/irda.h>
#include <net/irda/irmod.h>
#include <net/irda/irda_device.h>
-#include <net/irda/irtty.h>
-#include <net/irda/dongle.h>
-static void esi_open(struct irda_device *idev, int type);
-static void esi_close(struct irda_device *driver);
-static void esi_change_speed(struct irda_device *idev, __u32 speed);
-static void esi_reset(struct irda_device *idev);
-static void esi_qos_init(struct irda_device *idev, struct qos_info *qos);
+static void esi_open(dongle_t *self, struct qos_info *qos);
+static void esi_close(dongle_t *self);
+static int esi_change_speed(struct irda_task *task);
+static int esi_reset(struct irda_task *task);
-static struct dongle dongle = {
- ESI_DONGLE,
+static struct dongle_reg dongle = {
+ Q_NULL,
+ IRDA_ESI_DONGLE,
esi_open,
esi_close,
esi_reset,
esi_change_speed,
- esi_qos_init,
};
int __init esi_init(void)
@@ -62,37 +65,40 @@ void esi_cleanup(void)
irda_device_unregister_dongle(&dongle);
}
-static void esi_open(struct irda_device *idev, int type)
+static void esi_open(dongle_t *self, struct qos_info *qos)
{
- strcat(idev->description, " <-> esi");
-
- idev->io.dongle_id = type;
- idev->flags |= IFF_DONGLE;
+ qos->baud_rate.bits &= IR_9600|IR_19200|IR_115200;
+ qos->min_turn_time.bits &= 0x01; /* Needs at least 10 ms */
MOD_INC_USE_COUNT;
}
-static void esi_close(struct irda_device *idev)
+static void esi_close(dongle_t *dongle)
{
/* Power off dongle */
- irda_device_set_dtr_rts(idev, FALSE, FALSE);
+ dongle->set_dtr_rts(dongle->dev, FALSE, FALSE);
MOD_DEC_USE_COUNT;
}
/*
- * Function esi_change_speed (idev, speed)
+ * Function esi_change_speed (task)
*
* Set the speed for the Extended Systems JetEye PC ESI-9680 type dongle
*
*/
-static void esi_change_speed(struct irda_device *idev, __u32 speed)
+static int esi_change_speed(struct irda_task *task)
{
+ dongle_t *self = (dongle_t *) task->instance;
+ __u32 speed = (__u32) task->param;
int dtr, rts;
- ASSERT(idev != NULL, return;);
- ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;);
-
+ /* Lock dongle */
+ if (irda_lock((void *) &self->busy) == FALSE) {
+ IRDA_DEBUG(0, __FUNCTION__ "(), busy!\n");
+ return MSECS_TO_JIFFIES(100);
+ }
+
switch (speed) {
case 19200:
dtr = TRUE;
@@ -109,28 +115,34 @@ static void esi_change_speed(struct irda_device *idev, __u32 speed)
}
/* Change speed of dongle */
- irda_device_set_dtr_rts(idev, dtr, rts);
-}
+ self->set_dtr_rts(self->dev, dtr, rts);
+ self->speed = speed;
-static void esi_reset( struct irda_device *idev)
-{
- /* Empty */
+ irda_task_next_state(task, IRDA_TASK_DONE);
+
+ /* Unlock */
+ self->busy = 0;
+
+ return 0;
}
/*
- * Function esi_qos_init (qos)
+ * Function esi_reset (task)
*
- * Init QoS capabilities for the dongle
+ * Reset dongle;
*
*/
-static void esi_qos_init(struct irda_device *idev, struct qos_info *qos)
+static int esi_reset(struct irda_task *task)
{
- qos->baud_rate.bits &= IR_9600|IR_19200|IR_115200;
- qos->min_turn_time.bits &= 0x01; /* Needs at least 10 ms */
+ dongle_t *self = (dongle_t *) task->instance;
+
+ self->set_dtr_rts(self->dev, FALSE, FALSE);
+ irda_task_next_state(task, IRDA_TASK_DONE);
+
+ return 0;
}
#ifdef MODULE
-
MODULE_AUTHOR("Dag Brattli <dagb@cs.uit.no>");
MODULE_DESCRIPTION("Extended Systems JetEye PC dongle driver");
@@ -155,6 +167,5 @@ void cleanup_module(void)
{
esi_cleanup();
}
-
-#endif
+#endif /* MODULE */
diff --git a/drivers/net/irda/girbil.c b/drivers/net/irda/girbil.c
index 2d1d1f269..4fa2ec59f 100644
--- a/drivers/net/irda/girbil.c
+++ b/drivers/net/irda/girbil.c
@@ -6,7 +6,7 @@
* Status: Experimental.
* Author: Dag Brattli <dagb@cs.uit.no>
* Created at: Sat Feb 6 21:02:33 1999
- * Modified at: Sun Jul 18 12:09:26 1999
+ * Modified at: Mon Oct 18 22:15:20 1999
* Modified by: Dag Brattli <dagb@cs.uit.no>
*
* Copyright (c) 1999 Dag Brattli, All Rights Reserved.
@@ -32,13 +32,11 @@
#include <net/irda/irmod.h>
#include <net/irda/irda_device.h>
#include <net/irda/irtty.h>
-#include <net/irda/dongle.h>
-static void girbil_reset(struct irda_device *dev);
-static void girbil_open(struct irda_device *dev, int type);
-static void girbil_close(struct irda_device *dev);
-static void girbil_change_speed(struct irda_device *dev, __u32 speed);
-static void girbil_init_qos(struct irda_device *idev, struct qos_info *qos);
+static int girbil_reset(struct irda_task *task);
+static void girbil_open(dongle_t *self, struct qos_info *qos);
+static void girbil_close(dongle_t *self);
+static int girbil_change_speed(struct irda_task *task);
/* Control register 1 */
#define GIRBIL_TXEN 0x01 /* Enable transmitter */
@@ -67,13 +65,13 @@ static void girbil_init_qos(struct irda_device *idev, struct qos_info *qos);
/* Control register 2 (0x5) */
#define GIRBIL_LOAD 0x51 /* Load the new baud rate value */
-static struct dongle dongle = {
- GIRBIL_DONGLE,
+static struct dongle_reg dongle = {
+ Q_NULL,
+ IRDA_GIRBIL_DONGLE,
girbil_open,
girbil_close,
girbil_reset,
girbil_change_speed,
- girbil_init_qos,
};
int __init girbil_init(void)
@@ -86,20 +84,18 @@ void girbil_cleanup(void)
irda_device_unregister_dongle(&dongle);
}
-static void girbil_open(struct irda_device *idev, int type)
+static void girbil_open(dongle_t *self, struct qos_info *qos)
{
- strcat(idev->description, " <-> girbil");
+ qos->baud_rate.bits &= IR_9600|IR_19200|IR_38400|IR_57600|IR_115200;
+ qos->min_turn_time.bits &= 0x03;
- idev->io.dongle_id = type;
- idev->flags |= IFF_DONGLE;
-
MOD_INC_USE_COUNT;
}
-static void girbil_close(struct irda_device *idev)
+static void girbil_close(dongle_t *self)
{
/* Power off dongle */
- irda_device_set_dtr_rts(idev, FALSE, FALSE);
+ self->set_dtr_rts(self->dev, FALSE, FALSE);
MOD_DEC_USE_COUNT;
}
@@ -111,47 +107,80 @@ static void girbil_close(struct irda_device *idev)
* function must be called with a process context!
*
*/
-static void girbil_change_speed(struct irda_device *idev, __u32 speed)
+static int girbil_change_speed(struct irda_task *task)
{
+ dongle_t *self = (dongle_t *) task->instance;
+ __u32 speed = (__u32) task->param;
__u8 control[2];
-
- ASSERT(idev != NULL, return;);
- ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;);
-
- switch (speed) {
- case 9600:
- default:
- control[0] = GIRBIL_9600;
+ int ret = 0;
+
+ switch (task->state) {
+ case IRDA_TASK_INIT:
+ /* Lock dongle */
+ if (irda_lock((void *) &self->busy) == FALSE) {
+ IRDA_DEBUG(0, __FUNCTION__ "(), busy!\n");
+ return MSECS_TO_JIFFIES(100);
+ }
+
+ /* Need to reset the dongle and go to 9600 bps before
+ programming */
+ if (irda_task_execute(self, girbil_reset, NULL, task,
+ (void *) speed))
+ {
+ /* Dongle need more time to reset */
+ irda_task_next_state(task, IRDA_TASK_CHILD_WAIT);
+
+ /* Give reset 1 sec to finish */
+ ret = MSECS_TO_JIFFIES(1000);
+ }
break;
- case 19200:
- control[0] = GIRBIL_19200;
+ case IRDA_TASK_CHILD_WAIT:
+ WARNING(__FUNCTION__ "(), resetting dongle timed out!\n");
+ ret = -1;
break;
- case 34800:
- control[0] = GIRBIL_38400;
+ case IRDA_TASK_CHILD_DONE:
+ /* Set DTR and Clear RTS to enter command mode */
+ self->set_dtr_rts(self->dev, FALSE, TRUE);
+
+ switch (speed) {
+ case 9600:
+ default:
+ control[0] = GIRBIL_9600;
+ break;
+ case 19200:
+ control[0] = GIRBIL_19200;
+ break;
+ case 34800:
+ control[0] = GIRBIL_38400;
+ break;
+ case 57600:
+ control[0] = GIRBIL_57600;
+ break;
+ case 115200:
+ control[0] = GIRBIL_115200;
+ break;
+ }
+ control[1] = GIRBIL_LOAD;
+
+ /* Write control bytes */
+ self->write(self->dev, control, 2);
+ irda_task_next_state(task, IRDA_TASK_WAIT);
+ ret = MSECS_TO_JIFFIES(100);
break;
- case 57600:
- control[0] = GIRBIL_57600;
+ case IRDA_TASK_WAIT:
+ /* Go back to normal mode */
+ self->set_dtr_rts(self->dev, TRUE, TRUE);
+ irda_task_next_state(task, IRDA_TASK_DONE);
+ self->busy = 0;
break;
- case 115200:
- control[0] = GIRBIL_115200;
+ default:
+ ERROR(__FUNCTION__ "(), unknown state %d\n", task->state);
+ irda_task_next_state(task, IRDA_TASK_DONE);
+ self->busy = 0;
+ ret = -1;
break;
}
- control[1] = GIRBIL_LOAD;
-
- /* Need to reset the dongle and go to 9600 bps before programming */
- girbil_reset(idev);
-
- /* Set DTR and Clear RTS to enter command mode */
- irda_device_set_dtr_rts(idev, FALSE, TRUE);
-
- /* Write control bytes */
- irda_device_raw_write(idev, control, 2);
-
- current->state = TASK_INTERRUPTIBLE;
- schedule_timeout(MSECS_TO_JIFFIES(100));
-
- /* Go back to normal mode */
- irda_device_set_dtr_rts(idev, TRUE, TRUE);
+ return ret;
}
/*
@@ -164,54 +193,47 @@ static void girbil_change_speed(struct irda_device *idev, __u32 speed)
* 0. set RTS, and wait at least 5 ms
* 1. clear RTS
*/
-void girbil_reset(struct irda_device *idev)
+static int girbil_reset(struct irda_task *task)
{
+ dongle_t *self = (dongle_t *) task->instance;
__u8 control = GIRBIL_TXEN | GIRBIL_RXEN;
-
- ASSERT(idev != NULL, return;);
- ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;);
-
- /* Make sure the IrDA chip also goes to defalt speed */
- if (idev->change_speed)
- idev->change_speed(idev, 9600);
-
- /* Reset dongle */
- irda_device_set_dtr_rts(idev, TRUE, FALSE);
-
- /* Sleep at least 5 ms */
- current->state = TASK_INTERRUPTIBLE;
- schedule_timeout(MSECS_TO_JIFFIES(10));
-
- /* Set DTR and clear RTS to enter command mode */
- irda_device_set_dtr_rts(idev, FALSE, TRUE);
-
- current->state = TASK_INTERRUPTIBLE;
- schedule_timeout(MSECS_TO_JIFFIES(10));
-
- /* Write control byte */
- irda_device_raw_write(idev, &control, 1);
-
- current->state = TASK_INTERRUPTIBLE;
- schedule_timeout(MSECS_TO_JIFFIES(20));
-
- /* Go back to normal mode */
- irda_device_set_dtr_rts(idev, TRUE, TRUE);
-}
-
-/*
- * Function girbil_init_qos (qos)
- *
- * Initialize QoS capabilities
- *
- */
-static void girbil_init_qos(struct irda_device *idev, struct qos_info *qos)
-{
- qos->baud_rate.bits &= IR_9600|IR_19200|IR_38400|IR_57600|IR_115200;
- qos->min_turn_time.bits &= 0x03;
+ int ret = 0;
+
+ switch (task->state) {
+ case IRDA_TASK_INIT:
+ /* Reset dongle */
+ self->set_dtr_rts(self->dev, TRUE, FALSE);
+ irda_task_next_state(task, IRDA_TASK_WAIT1);
+ /* Sleep at least 5 ms */
+ ret = MSECS_TO_JIFFIES(10);
+ break;
+ case IRDA_TASK_WAIT1:
+ /* Set DTR and clear RTS to enter command mode */
+ self->set_dtr_rts(self->dev, FALSE, TRUE);
+ irda_task_next_state(task, IRDA_TASK_WAIT2);
+ ret = MSECS_TO_JIFFIES(10);
+ break;
+ case IRDA_TASK_WAIT2:
+ /* Write control byte */
+ self->write(self->dev, &control, 1);
+ irda_task_next_state(task, IRDA_TASK_WAIT3);
+ ret = MSECS_TO_JIFFIES(20);
+ break;
+ case IRDA_TASK_WAIT3:
+ /* Go back to normal mode */
+ self->set_dtr_rts(self->dev, TRUE, TRUE);
+ irda_task_next_state(task, IRDA_TASK_DONE);
+ break;
+ default:
+ ERROR(__FUNCTION__ "(), unknown state %d\n", task->state);
+ irda_task_next_state(task, IRDA_TASK_DONE);
+ ret = -1;
+ break;
+ }
+ return ret;
}
#ifdef MODULE
-
MODULE_AUTHOR("Dag Brattli <dagb@cs.uit.no>");
MODULE_DESCRIPTION("Greenwich GIrBIL dongle driver");
@@ -236,5 +258,4 @@ void cleanup_module(void)
{
girbil_cleanup();
}
-
#endif /* MODULE */
diff --git a/drivers/net/irda/irport.c b/drivers/net/irda/irport.c
index b60241a40..d4f4f6d71 100644
--- a/drivers/net/irda/irport.c
+++ b/drivers/net/irda/irport.c
@@ -6,7 +6,7 @@
* Status: Experimental.
* Author: Dag Brattli <dagb@cs.uit.no>
* Created at: Sun Aug 3 13:49:59 1997
- * Modified at: Tue Aug 31 13:54:27 1999
+ * Modified at: Wed Oct 20 00:07:42 1999
* Modified by: Dag Brattli <dagb@cs.uit.no>
* Sources: serial.c by Linus Torvalds
*
@@ -48,6 +48,7 @@
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/spinlock.h>
+#include <linux/rtnetlink.h>
#include <asm/system.h>
#include <asm/bitops.h>
@@ -69,22 +70,22 @@ static unsigned int irq[] = { 0, 0, 0, 0 };
static unsigned int qos_mtt_bits = 0x03;
-static struct irda_device *dev_self[] = { NULL, NULL, NULL, NULL};
+static struct irport_cb *dev_self[] = { NULL, NULL, NULL, NULL};
static char *driver_name = "irport";
static int irport_open(int i, unsigned int iobase, unsigned int irq);
-static int irport_close(struct irda_device *idev);
+static int irport_close(struct irport_cb *self);
-static void irport_write_wakeup(struct irda_device *idev);
+static void irport_write_wakeup(struct irport_cb *self);
static int irport_write(int iobase, int fifo_size, __u8 *buf, int len);
-static void irport_receive(struct irda_device *idev);
+static void irport_receive(struct irport_cb *self);
static int irport_net_init(struct net_device *dev);
static int irport_net_open(struct net_device *dev);
static int irport_net_close(struct net_device *dev);
-static int irport_is_receiving(struct irda_device *idev);
-static void irport_set_dtr_rts(struct irda_device *idev, int dtr, int rts);
-static int irport_raw_write(struct irda_device *idev, __u8 *buf, int len);
+static int irport_is_receiving(struct irport_cb *self);
+static void irport_set_dtr_rts(struct net_device *dev, int dtr, int rts);
+static int irport_raw_write(struct net_device *dev, __u8 *buf, int len);
int __init irport_init(void)
{
@@ -114,7 +115,7 @@ static void irport_cleanup(void)
{
int i;
- DEBUG( 4, __FUNCTION__ "()\n");
+ IRDA_DEBUG( 4, __FUNCTION__ "()\n");
for (i=0; i < 4; i++) {
if (dev_self[i])
@@ -125,108 +126,154 @@ static void irport_cleanup(void)
static int irport_open(int i, unsigned int iobase, unsigned int irq)
{
- struct irda_device *idev;
+ struct net_device *dev;
+ struct irport_cb *self;
int ret;
+ int err;
- DEBUG( 0, __FUNCTION__ "()\n");
-
-/* if (irport_probe(iobase, irq) == -1) */
-/* return -1; */
+ IRDA_DEBUG(0, __FUNCTION__ "()\n");
/*
* Allocate new instance of the driver
*/
- idev = kmalloc(sizeof(struct irda_device), GFP_KERNEL);
- if (idev == NULL) {
- printk( KERN_ERR "IrDA: Can't allocate memory for "
- "IrDA control block!\n");
+ self = kmalloc(sizeof(struct irport_cb), GFP_KERNEL);
+ if (!self) {
+ ERROR(__FUNCTION__ "(), can't allocate memory for "
+ "control block!\n");
return -ENOMEM;
}
- memset(idev, 0, sizeof(struct irda_device));
+ memset(self, 0, sizeof(struct irport_cb));
+ spin_lock_init(&self->lock);
+
/* Need to store self somewhere */
- dev_self[i] = idev;
+ dev_self[i] = self;
/* Initialize IO */
- idev->io.iobase2 = iobase;
- idev->io.irq2 = irq;
- idev->io.io_ext = IO_EXTENT;
- idev->io.fifo_size = 16;
-
- idev->netdev.base_addr = iobase;
- idev->netdev.irq = irq;
+ self->io.iobase2 = iobase;
+ self->io.irq2 = irq;
+ self->io.io_ext = IO_EXTENT;
+ self->io.fifo_size = 16;
/* Lock the port that we need */
- ret = check_region(idev->io.iobase2, idev->io.io_ext);
+ ret = check_region(self->io.iobase2, self->io.io_ext);
if (ret < 0) {
- DEBUG(0, __FUNCTION__ "(), can't get iobase of 0x%03x\n",
- idev->io.iobase2);
- /* irport_cleanup(self->idev); */
+ IRDA_DEBUG(0, __FUNCTION__ "(), can't get iobase of 0x%03x\n",
+ self->io.iobase2);
+ /* irport_cleanup(self->self); */
return -ENODEV;
}
- request_region(idev->io.iobase2, idev->io.io_ext, idev->name);
+ request_region(self->io.iobase2, self->io.io_ext, driver_name);
/* Initialize QoS for this device */
- irda_init_max_qos_capabilies(&idev->qos);
+ irda_init_max_qos_capabilies(&self->qos);
- idev->qos.baud_rate.bits = IR_9600|IR_19200|IR_38400|IR_57600|
+ self->qos.baud_rate.bits = IR_9600|IR_19200|IR_38400|IR_57600|
IR_115200;
- idev->qos.min_turn_time.bits = qos_mtt_bits;
- irda_qos_bits_to_value(&idev->qos);
+ self->qos.min_turn_time.bits = qos_mtt_bits;
+ irda_qos_bits_to_value(&self->qos);
- idev->flags = IFF_SIR|IFF_PIO;
+ self->flags = IFF_SIR|IFF_PIO;
- /* Specify which buffer allocation policy we need */
- idev->rx_buff.flags = GFP_KERNEL;
- idev->tx_buff.flags = GFP_KERNEL;
-
- idev->rx_buff.truesize = 4000;
- idev->tx_buff.truesize = 4000;
+ /* Specify how much memory we want */
+ self->rx_buff.truesize = 4000;
+ self->tx_buff.truesize = 4000;
- /* Initialize callbacks */
- idev->change_speed = irport_change_speed;
- idev->wait_until_sent = irport_wait_until_sent;
- idev->is_receiving = irport_is_receiving;
- idev->set_dtr_rts = irport_set_dtr_rts;
- idev->raw_write = irport_raw_write;
+ /* Allocate memory if needed */
+ if (self->rx_buff.truesize > 0) {
+ self->rx_buff.head = (__u8 *) kmalloc(self->rx_buff.truesize,
+ GFP_KERNEL);
+ if (self->rx_buff.head == NULL)
+ return -ENOMEM;
+ memset(self->rx_buff.head, 0, self->rx_buff.truesize);
+ }
+ if (self->tx_buff.truesize > 0) {
+ self->tx_buff.head = (__u8 *) kmalloc(self->tx_buff.truesize,
+ GFP_KERNEL);
+ if (self->tx_buff.head == NULL) {
+ kfree(self->rx_buff.head);
+ return -ENOMEM;
+ }
+ memset(self->tx_buff.head, 0, self->tx_buff.truesize);
+ }
+ self->rx_buff.in_frame = FALSE;
+ self->rx_buff.state = OUTSIDE_FRAME;
+ self->tx_buff.data = self->tx_buff.head;
+ self->rx_buff.data = self->rx_buff.head;
+ self->mode = IRDA_IRLAP;
+
+ if (!(dev = dev_alloc("irda%d", &err))) {
+ ERROR(__FUNCTION__ "(), dev_alloc() failed!\n");
+ return -ENOMEM;
+ }
+ /* dev_alloc doesn't clear the struct, so lets do a little hack */
+ memset(((__u8*)dev)+sizeof(char*),0,sizeof(struct net_device)-sizeof(char*));
+
+ dev->priv = (void *) self;
+ self->netdev = dev;
/* Override the network functions we need to use */
- idev->netdev.init = irport_net_init;
- idev->netdev.hard_start_xmit = irport_hard_xmit;
- idev->netdev.open = irport_net_open;
- idev->netdev.stop = irport_net_close;
+ dev->init = irport_net_init;
+ dev->hard_start_xmit = irport_hard_xmit;
+ dev->open = irport_net_open;
+ dev->stop = irport_net_close;
+
+ /* Make ifconfig display some details */
+ dev->base_addr = iobase;
+ dev->irq = irq;
+
+ rtnl_lock();
+ err = register_netdevice(dev);
+ rtnl_unlock();
+ if (err) {
+ ERROR(__FUNCTION__ "(), register_netdev() failed!\n");
+ return -1;
+ }
+ MESSAGE("IrDA: Registered device %s\n", dev->name);
- /* Open the IrDA device */
- irda_device_open(idev, driver_name, NULL);
-
return 0;
}
-static int irport_close(struct irda_device *idev)
+static int irport_close(struct irport_cb *self)
{
- ASSERT(idev != NULL, return -1;);
- ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return -1;);
+ ASSERT(self != NULL, return -1;);
- /* Release the IO-port that this driver is using */
- DEBUG(0 , __FUNCTION__ "(), Releasing Region %03x\n",
- idev->io.iobase2);
- release_region(idev->io.iobase2, idev->io.io_ext);
+ /* We are not using any dongle anymore! */
+ if (self->dongle)
+ irda_device_dongle_cleanup(self->dongle);
+ self->dongle = NULL;
+
+ /* Remove netdevice */
+ if (self->netdev) {
+ rtnl_lock();
+ unregister_netdevice(self->netdev);
+ rtnl_unlock();
+ }
- irda_device_close(idev);
+ /* Release the IO-port that this driver is using */
+ IRDA_DEBUG(0 , __FUNCTION__ "(), Releasing Region %03x\n",
+ self->io.iobase2);
+ release_region(self->io.iobase2, self->io.io_ext);
- kfree(idev);
+ if (self->tx_buff.head)
+ kfree(self->tx_buff.head);
+
+ if (self->rx_buff.head)
+ kfree(self->rx_buff.head);
+
+ kfree(self);
return 0;
}
-void irport_start(struct irda_device *idev, int iobase)
+void irport_start(struct irport_cb *self, int iobase)
{
unsigned long flags;
- spin_lock_irqsave(&idev->lock, flags);
+ spin_lock_irqsave(&self->lock, flags);
- irport_stop(idev, iobase);
+ irport_stop(self, iobase);
/* Initialize UART */
outb(UART_LCR_WLEN8, iobase+UART_LCR); /* Reset DLAB */
@@ -235,14 +282,14 @@ void irport_start(struct irda_device *idev, int iobase)
/* Turn on interrups */
outb(UART_IER_RLSI | UART_IER_RDI |UART_IER_THRI, iobase+UART_IER);
- spin_unlock_irqrestore(&idev->lock, flags);
+ spin_unlock_irqrestore(&self->lock, flags);
}
-void irport_stop(struct irda_device *idev, int iobase)
+void irport_stop(struct irport_cb *self, int iobase)
{
unsigned long flags;
- spin_lock_irqsave(&idev->lock, flags);
+ spin_lock_irqsave(&self->lock, flags);
/* Reset UART */
outb(0, iobase+UART_MCR);
@@ -250,7 +297,7 @@ void irport_stop(struct irda_device *idev, int iobase)
/* Turn off interrupts */
outb(0, iobase+UART_IER);
- spin_unlock_irqrestore(&idev->lock, flags);
+ spin_unlock_irqrestore(&self->lock, flags);
}
/*
@@ -261,18 +308,18 @@ void irport_stop(struct irda_device *idev, int iobase)
*/
int irport_probe(int iobase)
{
- DEBUG(4, __FUNCTION__ "(), iobase=%#x\n", iobase);
+ IRDA_DEBUG(4, __FUNCTION__ "(), iobase=%#x\n", iobase);
return 0;
}
/*
- * Function irport_change_speed (idev, speed)
+ * Function irport_change_speed (self, speed)
*
* Set speed of IrDA port to specified baudrate
*
*/
-void irport_change_speed(struct irda_device *idev, __u32 speed)
+void irport_change_speed(struct irport_cb *self, __u32 speed)
{
unsigned long flags;
int iobase;
@@ -280,17 +327,16 @@ void irport_change_speed(struct irda_device *idev, __u32 speed)
int lcr; /* Line control reg */
int divisor;
- DEBUG(2, __FUNCTION__ "(), Setting speed to: %d\n", speed);
+ IRDA_DEBUG(2, __FUNCTION__ "(), Setting speed to: %d\n", speed);
- ASSERT(idev != NULL, return;);
- ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;);
+ ASSERT(self != NULL, return;);
- iobase = idev->io.iobase2;
+ iobase = self->io.iobase2;
/* Update accounting for new speed */
- idev->io.baudrate = speed;
+ self->io.speed = speed;
- spin_lock_irqsave(&idev->lock, flags);
+ spin_lock_irqsave(&self->lock, flags);
/* Turn off interrupts */
outb(0, iobase+UART_IER);
@@ -304,7 +350,7 @@ void irport_change_speed(struct irda_device *idev, __u32 speed)
* almost 1,7 ms at 19200 bps. At speeds above that we can just forget
* about this timeout since it will always be fast enough.
*/
- if (idev->io.baudrate < 38400)
+ if (self->io.speed < 38400)
fcr |= UART_FCR_TRIGGER_1;
else
fcr |= UART_FCR_TRIGGER_14;
@@ -321,7 +367,7 @@ void irport_change_speed(struct irda_device *idev, __u32 speed)
/* Turn on interrups */
outb(/*UART_IER_RLSI|*/UART_IER_RDI/*|UART_IER_THRI*/, iobase+UART_IER);
- spin_unlock_irqrestore(&idev->lock, flags);
+ spin_unlock_irqrestore(&self->lock, flags);
}
/*
@@ -331,39 +377,38 @@ void irport_change_speed(struct irda_device *idev, __u32 speed)
* more packets to send, we send them here.
*
*/
-static void irport_write_wakeup(struct irda_device *idev)
+static void irport_write_wakeup(struct irport_cb *self)
{
int actual = 0;
int iobase;
int fcr;
- ASSERT(idev != NULL, return;);
- ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;);
+ ASSERT(self != NULL, return;);
- DEBUG(4, __FUNCTION__ "()\n");
+ IRDA_DEBUG(4, __FUNCTION__ "()\n");
/* Finished with frame? */
- if (idev->tx_buff.len > 0) {
+ if (self->tx_buff.len > 0) {
/* Write data left in transmit buffer */
- actual = irport_write(idev->io.iobase2, idev->io.fifo_size,
- idev->tx_buff.data, idev->tx_buff.len);
- idev->tx_buff.data += actual;
- idev->tx_buff.len -= actual;
+ actual = irport_write(self->io.iobase2, self->io.fifo_size,
+ self->tx_buff.data, self->tx_buff.len);
+ self->tx_buff.data += actual;
+ self->tx_buff.len -= actual;
} else {
- iobase = idev->io.iobase2;
+ iobase = self->io.iobase2;
/*
* Now serial buffer is almost free & we can start
* transmission of another packet
*/
- idev->netdev.tbusy = 0; /* Unlock */
- idev->stats.tx_packets++;
+ self->netdev->tbusy = 0; /* Unlock */
+ self->stats.tx_packets++;
/* Schedule network layer, so we can get some more frames */
mark_bh(NET_BH);
fcr = UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_RCVR;
- if (idev->io.baudrate < 38400)
+ if (self->io.speed < 38400)
fcr |= UART_FCR_TRIGGER_1;
else
fcr |= UART_FCR_TRIGGER_14;
@@ -391,7 +436,7 @@ static int irport_write(int iobase, int fifo_size, __u8 *buf, int len)
/* Tx FIFO should be empty! */
if (!(inb(iobase+UART_LSR) & UART_LSR_THRE)) {
- DEBUG(0, __FUNCTION__ "(), failed, fifo not empty!\n");
+ IRDA_DEBUG(0, __FUNCTION__ "(), failed, fifo not empty!\n");
return -1;
}
@@ -415,19 +460,19 @@ static int irport_write(int iobase, int fifo_size, __u8 *buf, int len)
*/
int irport_hard_xmit(struct sk_buff *skb, struct net_device *dev)
{
- struct irda_device *idev;
+ struct irport_cb *self;
unsigned long flags;
int actual = 0;
int iobase;
+ __u32 speed;
ASSERT(dev != NULL, return 0;);
- idev = (struct irda_device *) dev->priv;
+ self = (struct irport_cb *) dev->priv;
- ASSERT(idev != NULL, return 0;);
- ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return 0;);
+ ASSERT(self != NULL, return 0;);
- iobase = idev->io.iobase2;
+ iobase = self->io.iobase2;
/* Lock transmit buffer */
if (irda_lock((void *) &dev->tbusy) == FALSE) {
@@ -436,28 +481,32 @@ int irport_hard_xmit(struct sk_buff *skb, struct net_device *dev)
return -EBUSY;
WARNING("%s: transmit timed out\n", dev->name);
- irport_start(idev, iobase);
- irport_change_speed(idev, idev->io.baudrate);
+ irport_start(self, iobase);
+ irport_change_speed(self, self->io.speed );
dev->trans_start = jiffies;
}
- spin_lock_irqsave(&idev->lock, flags);
+ /* Check if we need to change the speed */
+ if ((speed = irda_get_speed(skb)) != self->io.speed)
+ irport_change_speed(self, speed);
+
+ spin_lock_irqsave(&self->lock, flags);
/* Init tx buffer */
- idev->tx_buff.data = idev->tx_buff.head;
+ self->tx_buff.data = self->tx_buff.head;
/* Copy skb to tx_buff while wrapping, stuffing and making CRC */
- idev->tx_buff.len = async_wrap_skb(skb, idev->tx_buff.data,
- idev->tx_buff.truesize);
+ self->tx_buff.len = async_wrap_skb(skb, self->tx_buff.data,
+ self->tx_buff.truesize);
- idev->tx_buff.data += actual;
- idev->tx_buff.len -= actual;
+ self->tx_buff.data += actual;
+ self->tx_buff.len -= actual;
/* Turn on transmit finished interrupt. Will fire immediately! */
outb(UART_IER_THRI, iobase+UART_IER);
- spin_unlock_irqrestore(&idev->lock, flags);
+ spin_unlock_irqrestore(&self->lock, flags);
dev_kfree_skb(skb);
@@ -465,30 +514,31 @@ int irport_hard_xmit(struct sk_buff *skb, struct net_device *dev)
}
/*
- * Function irport_receive (idev)
+ * Function irport_receive (self)
*
* Receive one frame from the infrared port
*
*/
-static void irport_receive(struct irda_device *idev)
+static void irport_receive(struct irport_cb *self)
{
int boguscount = 0;
int iobase;
- ASSERT(idev != NULL, return;);
+ ASSERT(self != NULL, return;);
- iobase = idev->io.iobase2;
+ iobase = self->io.iobase2;
/*
* Receive all characters in Rx FIFO, unwrap and unstuff them.
* async_unwrap_char will deliver all found frames
*/
do {
- async_unwrap_char(idev, inb(iobase+UART_RX));
+ async_unwrap_char(self->netdev, &self->rx_buff,
+ inb(iobase+UART_RX));
/* Make sure we don't stay here to long */
if (boguscount++ > 32) {
- DEBUG(2,__FUNCTION__ "(), breaking!\n");
+ IRDA_DEBUG(2,__FUNCTION__ "(), breaking!\n");
break;
}
} while (inb(iobase+UART_LSR) & UART_LSR_DR);
@@ -501,45 +551,47 @@ static void irport_receive(struct irda_device *idev)
*/
void irport_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
- struct irda_device *idev = (struct irda_device *) dev_id;
+ struct net_device *dev = (struct net_device *) dev_id;
+ struct irport_cb *self;
+ int boguscount = 0;
int iobase;
int iir, lsr;
- int boguscount = 0;
- if (!idev) {
+ if (!dev) {
WARNING(__FUNCTION__ "() irq %d for unknown device.\n", irq);
return;
}
+ self = (struct irport_cb *) dev->priv;
- spin_lock(&idev->lock);
+ spin_lock(&self->lock);
- idev->netdev.interrupt = 1;
+ dev->interrupt = 1;
- iobase = idev->io.iobase2;
+ iobase = self->io.iobase2;
iir = inb(iobase+UART_IIR) & UART_IIR_ID;
while (iir) {
/* Clear interrupt */
lsr = inb(iobase+UART_LSR);
- DEBUG(4, __FUNCTION__ "(), iir=%02x, lsr=%02x, iobase=%#x\n",
+ IRDA_DEBUG(4, __FUNCTION__ "(), iir=%02x, lsr=%02x, iobase=%#x\n",
iir, lsr, iobase);
switch (iir) {
case UART_IIR_RLSI:
- DEBUG(2, __FUNCTION__ "(), RLSI\n");
+ IRDA_DEBUG(2, __FUNCTION__ "(), RLSI\n");
break;
case UART_IIR_RDI:
/* Receive interrupt */
- irport_receive(idev);
+ irport_receive(self);
break;
case UART_IIR_THRI:
if (lsr & UART_LSR_THRE)
/* Transmitter ready for data */
- irport_write_wakeup(idev);
+ irport_write_wakeup(self);
break;
default:
- DEBUG(0, __FUNCTION__ "(), unhandled IIR=%#x\n", iir);
+ IRDA_DEBUG(0, __FUNCTION__ "(), unhandled IIR=%#x\n", iir);
break;
}
@@ -549,9 +601,9 @@ void irport_interrupt(int irq, void *dev_id, struct pt_regs *regs)
iir = inb(iobase + UART_IIR) & UART_IIR_ID;
}
- idev->netdev.interrupt = 0;
+ dev->interrupt = 0;
- spin_unlock(&idev->lock);
+ spin_unlock(&self->lock);
}
static int irport_net_init(struct net_device *dev)
@@ -572,24 +624,32 @@ static int irport_net_init(struct net_device *dev)
*/
static int irport_net_open(struct net_device *dev)
{
- struct irda_device *idev;
+ struct irport_cb *self;
int iobase;
ASSERT(dev != NULL, return -1;);
- idev = (struct irda_device *) dev->priv;
+ self = (struct irport_cb *) dev->priv;
- iobase = idev->io.iobase2;
+ iobase = self->io.iobase2;
- if (request_irq(idev->io.irq2, irport_interrupt, 0, idev->name,
- (void *) idev))
+ if (request_irq(self->io.irq2, irport_interrupt, 0, dev->name,
+ (void *) dev))
return -EAGAIN;
- irport_start(idev, iobase);
- irda_device_net_open(dev);
+ irport_start(self, iobase);
+
+ /* Ready to play! */
+ dev->tbusy = 0;
+ dev->interrupt = 0;
+ dev->start = 1;
+
+ /*
+ * Open new IrLAP layer instance, now that everything should be
+ * initialized properly
+ */
+ self->irlap = irlap_open(dev, &self->qos);
- /* Change speed to make sure dongles follow us again */
- if (idev->change_speed)
- idev->change_speed(idev, 9600);
+ /* FIXME: change speed of dongle */
MOD_INC_USE_COUNT;
@@ -597,30 +657,37 @@ static int irport_net_open(struct net_device *dev)
}
/*
- * Function irport_net_close (idev)
+ * Function irport_net_close (self)
*
*
*
*/
static int irport_net_close(struct net_device *dev)
{
- struct irda_device *idev;
+ struct irport_cb *self;
int iobase;
- DEBUG(4, __FUNCTION__ "()\n");
+ IRDA_DEBUG(4, __FUNCTION__ "()\n");
ASSERT(dev != NULL, return -1;);
- idev = (struct irda_device *) dev->priv;
+ self = (struct irport_cb *) dev->priv;
- ASSERT(idev != NULL, return -1;);
- ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return -1;)
+ ASSERT(self != NULL, return -1;);
- iobase = idev->io.iobase2;
+ iobase = self->io.iobase2;
- irda_device_net_close(dev);
- irport_stop(idev, iobase);
+ /* Stop device */
+ dev->tbusy = 1;
+ dev->start = 0;
- free_irq(idev->io.irq2, idev);
+ /* Stop and remove instance of IrLAP */
+ if (self->irlap)
+ irlap_close(self->irlap);
+ self->irlap = NULL;
+
+ irport_stop(self, iobase);
+
+ free_irq(self->io.irq2, dev);
MOD_DEC_USE_COUNT;
@@ -628,34 +695,36 @@ static int irport_net_close(struct net_device *dev)
}
/*
- * Function irport_wait_until_sent (idev)
+ * Function irport_wait_until_sent (self)
*
* Delay exectution until finished transmitting
*
*/
-void irport_wait_until_sent(struct irda_device *idev)
+#if 0
+void irport_wait_until_sent(struct irport_cb *self)
{
int iobase;
- iobase = idev->io.iobase2;
+ iobase = self->io.iobase2;
/* Wait until Tx FIFO is empty */
while (!(inb(iobase+UART_LSR) & UART_LSR_THRE)) {
- DEBUG(2, __FUNCTION__ "(), waiting!\n");
+ IRDA_DEBUG(2, __FUNCTION__ "(), waiting!\n");
current->state = TASK_INTERRUPTIBLE;
schedule_timeout(MSECS_TO_JIFFIES(60));
}
}
+#endif
/*
- * Function irport_is_receiving (idev)
+ * Function irport_is_receiving (self)
*
* Returns true is we are currently receiving data
*
*/
-static int irport_is_receiving(struct irda_device *idev)
+static int irport_is_receiving(struct irport_cb *self)
{
- return (idev->rx_buff.state != OUTSIDE_FRAME);
+ return (self->rx_buff.state != OUTSIDE_FRAME);
}
/*
@@ -664,14 +733,14 @@ static int irport_is_receiving(struct irda_device *idev)
* This function can be used by dongles etc. to set or reset the status
* of the dtr and rts lines
*/
-static void irport_set_dtr_rts(struct irda_device *idev, int dtr, int rts)
+static void irport_set_dtr_rts(struct net_device *dev, int dtr, int rts)
{
+ struct irport_cb *self = dev->priv;
int iobase;
- ASSERT(idev != NULL, return;);
- ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;);
+ ASSERT(self != NULL, return;);
- iobase = idev->io.iobase2;
+ iobase = self->io.iobase2;
if (dtr)
dtr = UART_MCR_DTR;
@@ -681,19 +750,19 @@ static void irport_set_dtr_rts(struct irda_device *idev, int dtr, int rts)
outb(dtr|rts|UART_MCR_OUT2, iobase+UART_MCR);
}
-static int irport_raw_write(struct irda_device *idev, __u8 *buf, int len)
+static int irport_raw_write(struct net_device *dev, __u8 *buf, int len)
{
- int iobase;
+ struct irport_cb *self = (struct irport_cb *) dev->priv;
int actual = 0;
+ int iobase;
- ASSERT(idev != NULL, return -1;);
- ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return -1;);
+ ASSERT(self != NULL, return -1;);
- iobase = idev->io.iobase2;
+ iobase = self->io.iobase2;
/* Tx FIFO should be empty! */
if (!(inb(iobase+UART_LSR) & UART_LSR_THRE)) {
- DEBUG( 0, __FUNCTION__ "(), failed, fifo not empty!\n");
+ IRDA_DEBUG( 0, __FUNCTION__ "(), failed, fifo not empty!\n");
return -1;
}
@@ -708,33 +777,20 @@ static int irport_raw_write(struct irda_device *idev, __u8 *buf, int len)
}
#ifdef MODULE
-
MODULE_PARM(io, "1-4i");
MODULE_PARM(irq, "1-4i");
MODULE_AUTHOR("Dag Brattli <dagb@cs.uit.no>");
MODULE_DESCRIPTION("Half duplex serial driver for IrDA SIR mode");
-/*
- * Function cleanup_module (void)
- *
- *
- *
- */
void cleanup_module(void)
{
irport_cleanup();
}
-/*
- * Function init_module (void)
- *
- *
- */
int init_module(void)
{
return irport_init();
}
-
#endif /* MODULE */
diff --git a/drivers/net/irda/irtty.c b/drivers/net/irda/irtty.c
index 6a439a1a8..b6a9dad59 100644
--- a/drivers/net/irda/irtty.c
+++ b/drivers/net/irda/irtty.c
@@ -6,7 +6,7 @@
* Status: Experimental.
* Author: Dag Brattli <dagb@cs.uit.no>
* Created at: Tue Dec 9 21:18:38 1997
- * Modified at: Tue Sep 28 08:39:29 1999
+ * Modified at: Wed Oct 20 00:05:43 1999
* Modified by: Dag Brattli <dagb@cs.uit.no>
* Sources: slip.c by Laurence Culhane, <loz@holmes.demon.co.uk>
* Fred N. van Kempen, <waltje@uwalt.nl.mugnet.org>
@@ -29,6 +29,8 @@
#include <linux/tty.h>
#include <linux/init.h>
#include <linux/skbuff.h>
+#include <linux/if_arp.h>
+#include <linux/rtnetlink.h>
#include <asm/segment.h>
#include <asm/uaccess.h>
@@ -36,7 +38,6 @@
#include <net/irda/irda.h>
#include <net/irda/irtty.h>
#include <net/irda/wrapper.h>
-#include <net/irda/irlap.h>
#include <net/irda/timer.h>
#include <net/irda/irda_device.h>
@@ -46,27 +47,31 @@ static struct tty_ldisc irda_ldisc;
static int qos_mtt_bits = 0x03; /* 5 ms or more */
+/* Network device fuction prototypes */
static int irtty_hard_xmit(struct sk_buff *skb, struct net_device *dev);
-static void irtty_wait_until_sent(struct irda_device *driver);
-static int irtty_is_receiving(struct irda_device *idev);
-static void irtty_set_dtr_rts(struct irda_device *idev, int dtr, int rts);
-static int irtty_raw_write(struct irda_device *idev, __u8 *buf, int len);
-static int irtty_raw_read(struct irda_device *idev, __u8 *buf, int len,
- int timeout);
-static void irtty_set_raw_mode(struct irda_device *dev, int mode);
static int irtty_net_init(struct net_device *dev);
static int irtty_net_open(struct net_device *dev);
static int irtty_net_close(struct net_device *dev);
+static int irtty_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
+static struct net_device_stats *irtty_net_get_stats(struct net_device *dev);
+/* Line discipline function prototypes */
static int irtty_open(struct tty_struct *tty);
static void irtty_close(struct tty_struct *tty);
static int irtty_ioctl(struct tty_struct *, void *, int, void *);
static int irtty_receive_room(struct tty_struct *tty);
-static void irtty_change_speed(struct irda_device *dev, __u32 speed);
static void irtty_write_wakeup(struct tty_struct *tty);
-
static void irtty_receive_buf(struct tty_struct *, const unsigned char *,
char *, int);
+
+/* IrDA specific function protoctypes */
+static int irtty_is_receiving(struct irtty_cb *self);
+static int irtty_set_dtr_rts(struct net_device *dev, int dtr, int rts);
+static int irtty_raw_write(struct net_device *dev, __u8 *buf, int len);
+static int irtty_raw_read(struct net_device *dev, __u8 *buf, int len);
+static int irtty_set_mode(struct net_device *dev, int mode);
+static int irtty_change_speed(struct irda_task *task);
+
char *driver_name = "irtty";
int __init irtty_init(void)
@@ -140,13 +145,16 @@ static void irtty_cleanup(void)
*/
static int irtty_open(struct tty_struct *tty)
{
+ struct net_device *dev;
struct irtty_cb *self;
char name[16];
+ int err;
ASSERT(tty != NULL, return -EEXIST;);
/* First make sure we're not already connected. */
self = (struct irtty_cb *) tty->disc_data;
+
if (self != NULL && self->magic == IRTTY_MAGIC)
return -EEXIST;
@@ -168,9 +176,8 @@ static int irtty_open(struct tty_struct *tty)
sprintf(name, "%s%d", tty->driver.name,
MINOR(tty->device) - tty->driver.minor_start +
tty->driver.name_base);
-
- /* hashbin_insert( irtty, (QUEUE*) self, 0, self->name); */
- hashbin_insert(irtty, (QUEUE*) self, (int) self, NULL);
+
+ hashbin_insert(irtty, (queue_t *) self, (int) self, NULL);
if (tty->driver.flush_buffer)
tty->driver.flush_buffer(tty);
@@ -179,11 +186,7 @@ static int irtty_open(struct tty_struct *tty)
tty->ldisc.flush_buffer(tty);
self->magic = IRTTY_MAGIC;
-
- /*
- * Initialize driver
- */
- self->idev.rx_buff.state = OUTSIDE_FRAME;
+ self->rx_buff.state = OUTSIDE_FRAME;
/*
* Initialize QoS capabilities, we fill in all the stuff that
@@ -191,40 +194,71 @@ static int irtty_open(struct tty_struct *tty)
* that are not device dependent (such as link disconnect time) so
* this parameter can be set by IrLAP (or the user) instead. DB
*/
- irda_init_max_qos_capabilies(&self->idev.qos);
+ irda_init_max_qos_capabilies(&self->qos);
/* The only value we must override it the baudrate */
- self->idev.qos.baud_rate.bits = IR_9600|IR_19200|IR_38400|IR_57600|
+ self->qos.baud_rate.bits = IR_9600|IR_19200|IR_38400|IR_57600|
IR_115200;
- self->idev.qos.min_turn_time.bits = qos_mtt_bits;
- self->idev.flags = IFF_SIR | IFF_PIO;
- irda_qos_bits_to_value(&self->idev.qos);
-
- /* Specify which buffer allocation policy we need */
- self->idev.rx_buff.flags = GFP_KERNEL;
- self->idev.tx_buff.flags = GFP_KERNEL;
+ self->qos.min_turn_time.bits = qos_mtt_bits;
+ self->flags = IFF_SIR | IFF_PIO;
+ irda_qos_bits_to_value(&self->qos);
/* Specify how much memory we want */
- self->idev.rx_buff.truesize = 4000;
- self->idev.tx_buff.truesize = 4000;
-
- /* Initialize callbacks */
- self->idev.change_speed = irtty_change_speed;
- self->idev.is_receiving = irtty_is_receiving;
- self->idev.wait_until_sent = irtty_wait_until_sent;
- self->idev.set_dtr_rts = irtty_set_dtr_rts;
- self->idev.set_raw_mode = irtty_set_raw_mode;
- self->idev.raw_write = irtty_raw_write;
- self->idev.raw_read = irtty_raw_read;
+ self->rx_buff.truesize = 4000;
+ self->tx_buff.truesize = 4000;
+
+ /* Allocate memory if needed */
+ if (self->rx_buff.truesize > 0) {
+ self->rx_buff.head = (__u8 *) kmalloc(self->rx_buff.truesize,
+ GFP_KERNEL);
+ if (self->rx_buff.head == NULL)
+ return -ENOMEM;
+ memset(self->rx_buff.head, 0, self->rx_buff.truesize);
+ }
+ if (self->tx_buff.truesize > 0) {
+ self->tx_buff.head = (__u8 *) kmalloc(self->tx_buff.truesize,
+ GFP_KERNEL);
+ if (self->tx_buff.head == NULL) {
+ kfree(self->rx_buff.head);
+ return -ENOMEM;
+ }
+ memset(self->tx_buff.head, 0, self->tx_buff.truesize);
+ }
+
+ self->magic = IRTTY_MAGIC;
+
+ self->rx_buff.in_frame = FALSE;
+ self->rx_buff.state = OUTSIDE_FRAME;
+ self->tx_buff.data = self->tx_buff.head;
+ self->rx_buff.data = self->rx_buff.head;
+
+ if (!(dev = dev_alloc("irda%d", &err))) {
+ ERROR(__FUNCTION__ "(), dev_alloc() failed!\n");
+ return -ENOMEM;
+ }
+ /* dev_alloc doesn't clear the struct */
+ memset(((__u8*)dev)+sizeof(char*),0,sizeof(struct net_device)-sizeof(char*));
+
+ dev->priv = (void *) self;
+ self->netdev = dev;
/* Override the network functions we need to use */
- self->idev.netdev.init = irtty_net_init;
- self->idev.netdev.hard_start_xmit = irtty_hard_xmit;
- self->idev.netdev.open = irtty_net_open;
- self->idev.netdev.stop = irtty_net_close;
+ dev->init = irtty_net_init;
+ dev->hard_start_xmit = irtty_hard_xmit;
+ dev->open = irtty_net_open;
+ dev->stop = irtty_net_close;
+ dev->get_stats = irtty_net_get_stats;
+ dev->do_ioctl = irtty_net_ioctl;
+
+ rtnl_lock();
+ err = register_netdevice(dev);
+ rtnl_unlock();
+ if (err) {
+ ERROR(__FUNCTION__ "(), register_netdev() failed!\n");
+ return -1;
+ }
- /* Open the IrDA device */
- irda_device_open(&self->idev, name, self);
+ MESSAGE("IrDA: Registered device %s\n", dev->name);
MOD_INC_USE_COUNT;
@@ -245,39 +279,50 @@ static void irtty_close(struct tty_struct *tty)
/* First make sure we're connected. */
ASSERT(self != NULL, return;);
ASSERT(self->magic == IRTTY_MAGIC, return;);
-
- /* Remove driver */
- irda_device_close(&self->idev);
-
+
/* Stop tty */
tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP);
tty->disc_data = 0;
-
+
+ /* We are not using any dongle anymore! */
+ if (self->dongle)
+ irda_device_dongle_cleanup(self->dongle);
+ self->dongle = NULL;
+
+ /* Remove netdevice */
+ if (self->netdev) {
+ rtnl_lock();
+ unregister_netdevice(self->netdev);
+ rtnl_unlock();
+ }
+
self->tty = NULL;
self->magic = 0;
self = hashbin_remove(irtty, (int) self, NULL);
-
- if (self != NULL)
- kfree(self);
+ if (self->tx_buff.head)
+ kfree(self->tx_buff.head);
+
+ if (self->rx_buff.head)
+ kfree(self->rx_buff.head);
+
+ kfree(self);
+
MOD_DEC_USE_COUNT;
}
/*
- * Function irtty_stop_receiver (irda_device, stop)
+ * Function irtty_stop_receiver (self, stop)
*
*
*
*/
-static void irtty_stop_receiver(struct irda_device *idev, int stop)
+static void irtty_stop_receiver(struct irtty_cb *self, int stop)
{
struct termios old_termios;
- struct irtty_cb *self;
int cflag;
- self = (struct irtty_cb *) idev->priv;
-
old_termios = *(self->tty->termios);
cflag = self->tty->termios->c_cflag;
@@ -291,24 +336,16 @@ static void irtty_stop_receiver(struct irda_device *idev, int stop)
}
/*
- * Function irtty_change_speed (self, speed)
+ * Function irtty_do_change_speed (self, speed)
*
- * Change the speed of the serial port. The driver layer must check that
- * all transmission has finished using the irtty_wait_until_sent()
- * function.
+ * Change the speed of the serial port.
*/
-static void irtty_change_speed(struct irda_device *idev, __u32 speed)
+static void __irtty_change_speed(struct irtty_cb *self, __u32 speed)
{
struct termios old_termios;
- struct irtty_cb *self;
int cflag;
- DEBUG(4, __FUNCTION__ "(), <%ld>\n", jiffies);
-
- ASSERT(idev != NULL, return;);
- ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;);
-
- self = (struct irtty_cb *) idev->priv;
+ IRDA_DEBUG(0, __FUNCTION__ "(), <%ld>\n", jiffies);
ASSERT(self != NULL, return;);
ASSERT(self->magic == IRTTY_MAGIC, return;);
@@ -318,7 +355,7 @@ static void irtty_change_speed(struct irda_device *idev, __u32 speed)
cflag &= ~CBAUD;
- DEBUG(4, __FUNCTION__ "(), Setting speed to %d\n", speed);
+ IRDA_DEBUG(0, __FUNCTION__ "(), Setting speed to %d\n", speed);
switch (speed) {
case 1200:
@@ -350,6 +387,81 @@ static void irtty_change_speed(struct irda_device *idev, __u32 speed)
self->tty->termios->c_cflag = cflag;
self->tty->driver.set_termios(self->tty, &old_termios);
+
+ self->io.speed = speed;
+}
+
+/*
+ * Function irtty_change_speed (instance, state, param)
+ *
+ * State machine for changing speed of the device. We do it this way since
+ * we cannot use schedule_timeout() when we are in interrupt context
+ */
+static int irtty_change_speed(struct irda_task *task)
+{
+ struct irtty_cb *self;
+ __u32 speed = (__u32) task->param;
+ int ret = 0;
+
+ IRDA_DEBUG(2, __FUNCTION__ "(), <%ld>\n", jiffies);
+
+ self = (struct irtty_cb *) task->instance;
+
+ ASSERT(self != NULL, return -1;);
+
+ switch (task->state) {
+ case IRDA_TASK_INIT:
+ case IRDA_TASK_WAIT:
+ /* Are we ready to change speed yet? */
+ if (self->tty->driver.chars_in_buffer(self->tty)) {
+ task->state = IRDA_TASK_WAIT;
+
+ /* Try again later */
+ ret = MSECS_TO_JIFFIES(20);
+ break;
+ }
+
+ if (self->dongle)
+ irda_task_next_state(task, IRDA_TASK_CHILD_INIT);
+ else
+ irda_task_next_state(task, IRDA_TASK_CHILD_DONE);
+ break;
+ case IRDA_TASK_CHILD_INIT:
+ /* Go to default speed */
+ __irtty_change_speed(self, 9600);
+
+ /* Change speed of dongle */
+ if (irda_task_execute(self->dongle,
+ self->dongle->issue->change_speed,
+ NULL, task, (void *) speed))
+ {
+ /* Dongle need more time to change its speed */
+ irda_task_next_state(task, IRDA_TASK_CHILD_WAIT);
+
+ /* Give dongle 1 sec to finish */
+ ret = MSECS_TO_JIFFIES(1000);
+ } else
+ /* Child finished immediately */
+ irda_task_next_state(task, IRDA_TASK_CHILD_DONE);
+ break;
+ case IRDA_TASK_CHILD_WAIT:
+ WARNING(__FUNCTION__
+ "(), changing speed of dongle timed out!\n");
+ ret = -1;
+ break;
+ case IRDA_TASK_CHILD_DONE:
+ /* Finally we are ready to change the speed */
+ __irtty_change_speed(self, speed);
+
+ irda_task_next_state(task, IRDA_TASK_DONE);
+ break;
+ default:
+ ERROR(__FUNCTION__ "(), unknown state %d\n", task->state);
+ irda_task_next_state(task, IRDA_TASK_DONE);
+ ret = -1;
+ break;
+ }
+ return ret;
}
/*
@@ -360,9 +472,11 @@ static void irtty_change_speed(struct irda_device *idev, __u32 speed)
*/
static int irtty_ioctl(struct tty_struct *tty, void *file, int cmd, void *arg)
{
+ dongle_t *dongle;
+ struct irtty_info info;
struct irtty_cb *self;
- int err = 0;
int size = _IOC_SIZE(cmd);
+ int err = 0;
self = (struct irtty_cb *) tty->disc_data;
@@ -370,13 +484,13 @@ static int irtty_ioctl(struct tty_struct *tty, void *file, int cmd, void *arg)
ASSERT(self->magic == IRTTY_MAGIC, return -EBADR;);
if (_IOC_DIR(cmd) & _IOC_READ)
- err = verify_area( VERIFY_WRITE, (void *) arg, size);
+ err = verify_area(VERIFY_WRITE, (void *) arg, size);
else if (_IOC_DIR(cmd) & _IOC_WRITE)
- err = verify_area( VERIFY_READ, (void *) arg, size);
+ err = verify_area(VERIFY_READ, (void *) arg, size);
if (err)
return err;
- switch(cmd) {
+ switch (cmd) {
case TCGETS:
case TCGETA:
return n_tty_ioctl(tty, (struct file *) file, cmd,
@@ -384,7 +498,34 @@ static int irtty_ioctl(struct tty_struct *tty, void *file, int cmd, void *arg)
break;
case IRTTY_IOCTDONGLE:
/* Initialize dongle */
- irda_device_init_dongle(&self->idev, (int) arg);
+ dongle = irda_device_dongle_init(self->netdev, (int) arg);
+ if (!dongle)
+ break;
+
+ /* Initialize callbacks */
+ dongle->set_mode = irtty_set_mode;
+ dongle->read = irtty_raw_read;
+ dongle->write = irtty_raw_write;
+ dongle->set_dtr_rts = irtty_set_dtr_rts;
+
+ /* Bind dongle */
+ self->dongle = dongle;
+
+ /* Now initialize the dongle! */
+ dongle->issue->open(dongle, &self->qos);
+
+ /* Reset dongle */
+ irda_task_execute(dongle, dongle->issue->reset, NULL, NULL,
+ NULL);
+ break;
+ case IRTTY_IOCGET:
+ ASSERT(self->netdev != NULL, return -1;);
+
+ memset(&info, 0, sizeof(struct irtty_info));
+ strncpy(info.name, self->netdev->name, 5);
+
+ if (copy_to_user(arg, &info, sizeof(struct irtty_info)))
+ return -EFAULT;
break;
default:
return -ENOIOCTLCMD;
@@ -405,34 +546,61 @@ static void irtty_receive_buf(struct tty_struct *tty, const unsigned char *cp,
{
struct irtty_cb *self = (struct irtty_cb *) tty->disc_data;
- DEBUG(5, __FUNCTION__ "(,,,count=%d)\n", count);
/* Read the characters out of the buffer */
while (count--) {
/*
* Characters received with a parity error, etc?
*/
if (fp && *fp++) {
- DEBUG( 0, "Framing or parity error!\n");
- irda_device_set_media_busy(&self->idev.netdev, TRUE);
-
+ IRDA_DEBUG(0, "Framing or parity error!\n");
+ irda_device_set_media_busy(self->netdev, TRUE);
+
cp++;
continue;
}
+
+ switch (self->mode) {
+ case IRDA_IRLAP:
+ /* Unwrap and destuff one byte */
+ async_unwrap_char(self->netdev, &self->rx_buff, *cp++);
+ break;
+ case IRDA_RAW:
+ /* What should we do when the buffer is full? */
+ if (self->rx_buff.len == self->rx_buff.truesize)
+ self->rx_buff.len = 0;
+
+ self->rx_buff.data[self->rx_buff.len++] = *cp++;
+ break;
+ default:
+ break;
+ }
+ }
+}
- DEBUG(6, __FUNCTION__ " char=0x%02x\n", *cp);
- if (self->idev.raw_mode) {
- struct irda_device *idev = &self->idev;
+/*
+ * Function irtty_change_speed_complete (task)
+ *
+ * Called when the change speed operation completes
+ *
+ */
+static int irtty_change_speed_complete(struct irda_task *task)
+{
+ struct irtty_cb *self;
- /* What should we do when the buffer is full? */
- if (idev->rx_buff.len == idev->rx_buff.truesize)
- idev->rx_buff.len = 0;
+ IRDA_DEBUG(0, __FUNCTION__ "()\n");
- idev->rx_buff.data[idev->rx_buff.len++] = *cp++;
- } else {
- /* Unwrap and destuff one byte */
- async_unwrap_char(&self->idev, *cp++);
- }
- }
+ self = (struct irtty_cb *) task->instance;
+
+ ASSERT(self != NULL, return -1;);
+ ASSERT(self->netdev != NULL, return -1;);
+
+ /* Finished changing speed, so we are not busy any longer */
+ self->netdev->tbusy = 0;
+
+ /* Signal network layer so it can try to send the frame */
+ mark_bh(NET_BH);
+
+ return 0;
}
/*
@@ -444,29 +612,34 @@ static void irtty_receive_buf(struct tty_struct *tty, const unsigned char *cp,
static int irtty_hard_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct irtty_cb *self;
- struct irda_device *idev;
int actual = 0;
+ __u32 speed;
- idev = (struct irda_device *) dev->priv;
-
- ASSERT(idev != NULL, return 0;);
- ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return -1;);
-
- self = (struct irtty_cb *) idev->priv;
-
+ self = (struct irtty_cb *) dev->priv;
ASSERT(self != NULL, return 0;);
- ASSERT(self->magic == IRTTY_MAGIC, return 0;);
/* Lock transmit buffer */
if (irda_lock((void *) &dev->tbusy) == FALSE)
return -EBUSY;
+
+ /* Check if we need to change the speed */
+ if ((speed = irda_get_speed(skb)) != self->io.speed) {
+ if (irda_task_execute(self, irtty_change_speed,
+ irtty_change_speed_complete, NULL,
+ (void *) speed))
+ /*
+ * Task not finished yet, so make the netdevice
+ * layer requeue the frame
+ */
+ return -EBUSY;
+ }
/* Init tx buffer*/
- idev->tx_buff.data = idev->tx_buff.head;
+ self->tx_buff.data = self->tx_buff.head;
/* Copy skb to tx_buff while wrapping, stuffing and making CRC */
- idev->tx_buff.len = async_wrap_skb(skb, idev->tx_buff.data,
- idev->tx_buff.truesize);
+ self->tx_buff.len = async_wrap_skb(skb, self->tx_buff.data,
+ self->tx_buff.truesize);
self->tty->flags |= (1 << TTY_DO_WRITE_WAKEUP);
@@ -474,22 +647,22 @@ static int irtty_hard_xmit(struct sk_buff *skb, struct net_device *dev)
if (self->tty->driver.write)
actual = self->tty->driver.write(self->tty, 0,
- idev->tx_buff.data,
- idev->tx_buff.len);
+ self->tx_buff.data,
+ self->tx_buff.len);
/* Hide the part we just transmitted */
- idev->tx_buff.data += actual;
- idev->tx_buff.len -= actual;
+ self->tx_buff.data += actual;
+ self->tx_buff.len -= actual;
- idev->stats.tx_packets++;
- idev->stats.tx_bytes += idev->tx_buff.len;
+ self->stats.tx_packets++;
+ self->stats.tx_bytes += self->tx_buff.len;
#if 0
/*
* Did we transmit the whole frame? Commented out for now since
* I must check if this optimalization really works. DB.
*/
- if ((idev->tx_buff.len) == 0) {
- DEBUG( 4, "irtty_xmit_buf: finished with frame!\n");
+ if ((self->tx_buff.len) == 0) {
+ IRDA_DEBUG( 4, "irtty_xmit_buf: finished with frame!\n");
self->tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP);
irda_unlock( &self->tbusy);
}
@@ -507,7 +680,7 @@ static int irtty_hard_xmit(struct sk_buff *skb, struct net_device *dev)
*/
static int irtty_receive_room(struct tty_struct *tty)
{
- DEBUG(0, __FUNCTION__ "()\n");
+ IRDA_DEBUG(0, __FUNCTION__ "()\n");
return 65536; /* We can handle an infinite amount of data. :-) */
}
@@ -521,7 +694,6 @@ static int irtty_receive_room(struct tty_struct *tty)
static void irtty_write_wakeup(struct tty_struct *tty)
{
struct irtty_cb *self = (struct irtty_cb *) tty->disc_data;
- struct irda_device *idev;
int actual = 0;
/*
@@ -530,26 +702,24 @@ static void irtty_write_wakeup(struct tty_struct *tty)
ASSERT(self != NULL, return;);
ASSERT(self->magic == IRTTY_MAGIC, return;);
- idev = &self->idev;
-
/* Finished with frame? */
- if (idev->tx_buff.len > 0) {
+ if (self->tx_buff.len > 0) {
/* Write data left in transmit buffer */
- actual = tty->driver.write(tty, 0, idev->tx_buff.data,
- idev->tx_buff.len);
+ actual = tty->driver.write(tty, 0, self->tx_buff.data,
+ self->tx_buff.len);
- idev->tx_buff.data += actual;
- idev->tx_buff.len -= actual;
+ self->tx_buff.data += actual;
+ self->tx_buff.len -= actual;
} else {
/*
* Now serial buffer is almost free & we can start
* transmission of another packet
*/
- DEBUG(5, __FUNCTION__ "(), finished with frame!\n");
+ IRDA_DEBUG(5, __FUNCTION__ "(), finished with frame!\n");
tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP);
- idev->netdev.tbusy = 0; /* Unlock */
+ self->netdev->tbusy = 0; /* Unlock */
/* Tell network layer that we want more frames */
mark_bh(NET_BH);
@@ -557,34 +727,14 @@ static void irtty_write_wakeup(struct tty_struct *tty)
}
/*
- * Function irtty_is_receiving (idev)
+ * Function irtty_is_receiving (self)
*
* Return TRUE is we are currently receiving a frame
*
*/
-static int irtty_is_receiving(struct irda_device *idev)
+static int irtty_is_receiving(struct irtty_cb *self)
{
- return (idev->rx_buff.state != OUTSIDE_FRAME);
-}
-
-/*
- * Function irtty_change_speed_ready (idev)
- *
- * Are we completely finished with transmitting frames so its possible
- * to change the speed of the serial port. Warning this function must
- * be called with a process context!
- */
-static void irtty_wait_until_sent(struct irda_device *idev)
-{
- struct irtty_cb *self = (struct irtty_cb *) idev->priv;
-
- ASSERT(self != NULL, return;);
- ASSERT(self->magic == IRTTY_MAGIC, return;);
-
- DEBUG(4, "Chars in buffer %d\n",
- self->tty->driver.chars_in_buffer(self->tty));
-
- tty_wait_until_sent(self->tty, 0);
+ return (self->rx_buff.state != OUTSIDE_FRAME);
}
/*
@@ -593,15 +743,14 @@ static void irtty_wait_until_sent(struct irda_device *idev)
* This function can be used by dongles etc. to set or reset the status
* of the dtr and rts lines
*/
-static void irtty_set_dtr_rts(struct irda_device *idev, int dtr, int rts)
+static int irtty_set_dtr_rts(struct net_device *dev, int dtr, int rts)
{
- struct tty_struct *tty;
struct irtty_cb *self;
+ struct tty_struct *tty;
mm_segment_t fs;
int arg = 0;
- self = (struct irtty_cb *) idev->priv;
-
+ self = (struct irtty_cb *) dev->priv;
tty = self->tty;
#ifdef TIOCM_OUT2 /* Not defined for ARM */
@@ -627,52 +776,62 @@ static void irtty_set_dtr_rts(struct irda_device *idev, int dtr, int rts)
ERROR(__FUNCTION__ "(), error doing ioctl!\n");
}
set_fs(fs);
+
+ return 0;
}
/*
- * Function irtty_set_raw_mode (idev, status)
+ * Function irtty_set_mode (self, status)
*
* For the airport dongle, we need support for reading raw characters
* from the IrDA device. This function switches between those modes.
* FALSE is the default mode, and will then treat incoming data as IrDA
* packets.
*/
-void irtty_set_raw_mode(struct irda_device *idev, int status)
+int irtty_set_mode(struct net_device *dev, int mode)
{
struct irtty_cb *self;
- DEBUG(2, __FUNCTION__ "(), status=%s\n", status ? "TRUE" : "FALSE");
+ self = (struct irtty_cb *) dev->priv;
- ASSERT(idev != NULL, return;);
- ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;);
-
- self = (struct irtty_cb *) idev->priv;
+ ASSERT(self != NULL, return -1;);
+ IRDA_DEBUG(2, __FUNCTION__ "(), mode=%s\n", infrared_mode[mode]);
+
/* save status for driver */
- self->idev.raw_mode = status;
+ self->mode = mode;
/* reset the buffer state */
- idev->rx_buff.data = idev->rx_buff.head;
- idev->rx_buff.len = 0;
- idev->rx_buff.state = OUTSIDE_FRAME;
+ self->rx_buff.data = self->rx_buff.head;
+ self->rx_buff.len = 0;
+ self->rx_buff.state = OUTSIDE_FRAME;
+
+ return 0;
}
/*
- * Function irtty_raw_read (idev, buf, len)
+ * Function irtty_raw_read (self, buf, len)
*
* Receive incomming data. This function sleeps, so it must only be
* called with a process context. Timeout is currently defined to be
* a multiple of 10 ms.
*/
-static int irtty_raw_read(struct irda_device *idev, __u8 *buf, int len,
- int timeout)
+static int irtty_raw_read(struct net_device *dev, __u8 *buf, int len)
{
+ struct irtty_cb *self;
int count;
- buf = idev->rx_buff.data;
+ self = (struct irtty_cb *) dev->priv;
+
+ ASSERT(self != NULL, return 0;);
+ ASSERT(self->magic == IRTTY_MAGIC, return 0;);
+
+ return 0;
+#if 0
+ buf = self->rx_buff.data;
/* Wait for the requested amount of data to arrive */
- while (len < idev->rx_buff.len) {
+ while (len < self->rx_buff.len) {
current->state = TASK_INTERRUPTIBLE;
schedule_timeout(MSECS_TO_JIFFIES(10));
@@ -680,30 +839,27 @@ static int irtty_raw_read(struct irda_device *idev, __u8 *buf, int len,
break;
}
- count = idev->rx_buff.len < len ? idev->rx_buff.len : len;
+ count = self->rx_buff.len < len ? self->rx_buff.len : len;
/*
* Reset the state, this mean that a raw read is sort of a
* datagram read, and _not_ a stream style read. Be aware of the
* difference. Implementing it the other way will just be painful ;-)
*/
- idev->rx_buff.data = idev->rx_buff.head;
- idev->rx_buff.len = 0;
- idev->rx_buff.state = OUTSIDE_FRAME;
-
+ self->rx_buff.data = self->rx_buff.head;
+ self->rx_buff.len = 0;
+ self->rx_buff.state = OUTSIDE_FRAME;
+#endif
/* Return the amount we were able to get */
return count;
}
-static int irtty_raw_write(struct irda_device *idev, __u8 *buf, int len)
+static int irtty_raw_write(struct net_device *dev, __u8 *buf, int len)
{
struct irtty_cb *self;
int actual = 0;
- ASSERT(idev != NULL, return 0;);
- ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return -1;);
-
- self = (struct irtty_cb *) idev->priv;
+ self = (struct irtty_cb *) dev->priv;
ASSERT(self != NULL, return 0;);
ASSERT(self->magic == IRTTY_MAGIC, return 0;);
@@ -714,8 +870,6 @@ static int irtty_raw_write(struct irda_device *idev, __u8 *buf, int len)
return actual;
}
-
-
static int irtty_net_init(struct net_device *dev)
{
/* Set up to be a normal IrDA network device driver */
@@ -728,12 +882,26 @@ static int irtty_net_init(struct net_device *dev)
static int irtty_net_open(struct net_device *dev)
{
- struct irda_device *idev = dev->priv;
+ struct irtty_cb *self = (struct irtty_cb *) dev->priv;
- irda_device_net_open(dev);
+ ASSERT(self != NULL, return -1;);
+ ASSERT(self->magic == IRTTY_MAGIC, return -1;);
+
+ IRDA_DEBUG(0, __FUNCTION__ "()\n");
+
+ /* Ready to play! */
+ dev->tbusy = 0;
+ dev->interrupt = 0;
+ dev->start = 1;
/* Make sure we can receive more data */
- irtty_stop_receiver(idev, FALSE);
+ irtty_stop_receiver(self, FALSE);
+
+ /*
+ * Open new IrLAP layer instance, now that everything should be
+ * initialized properly
+ */
+ self->irlap = irlap_open(dev, &self->qos);
MOD_INC_USE_COUNT;
@@ -742,18 +910,105 @@ static int irtty_net_open(struct net_device *dev)
static int irtty_net_close(struct net_device *dev)
{
- struct irda_device *idev = dev->priv;
+ struct irtty_cb *self = (struct irtty_cb *) dev->priv;
+
+ ASSERT(self != NULL, return -1;);
+ ASSERT(self->magic == IRTTY_MAGIC, return -1;);
/* Make sure we don't receive more data */
- irtty_stop_receiver(idev, TRUE);
+ irtty_stop_receiver(self, TRUE);
- irda_device_net_close(dev);
+ /* Stop device */
+ dev->tbusy = 1;
+ dev->start = 0;
+
+ /* Stop and remove instance of IrLAP */
+ if (self->irlap)
+ irlap_close(self->irlap);
+ self->irlap = NULL;
MOD_DEC_USE_COUNT;
return 0;
}
+/*
+ * Function irtty_net_ioctl (dev, rq, cmd)
+ *
+ * Process IOCTL commands for this device
+ *
+ */
+static int irtty_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
+{
+ struct if_irda_req *irq = (struct if_irda_req *) rq;
+ struct irtty_cb *self;
+ dongle_t *dongle;
+ unsigned long flags;
+ int ret = 0;
+
+ ASSERT(dev != NULL, return -1;);
+
+ self = dev->priv;
+
+ ASSERT(self != NULL, return -1;);
+ ASSERT(self->magic == IRTTY_MAGIC, return -1;);
+
+ IRDA_DEBUG(2, __FUNCTION__ "(), %s, (cmd=0x%X)\n", dev->name, cmd);
+
+ /* Disable interrupts & save flags */
+ save_flags(flags);
+ cli();
+
+ switch (cmd) {
+ case SIOCSBANDWIDTH: /* Set bandwidth */
+ irda_task_execute(self, irtty_change_speed, NULL, NULL,
+ (void *) irq->ifr_baudrate);
+ break;
+ case SIOCSDONGLE: /* Set dongle */
+ /* Initialize dongle */
+ dongle = irda_device_dongle_init(dev, irq->ifr_dongle);
+ if (!dongle)
+ break;
+
+ dongle->set_mode = irtty_set_mode;
+ dongle->read = irtty_raw_read;
+ dongle->write = irtty_raw_write;
+ dongle->set_dtr_rts = irtty_set_dtr_rts;
+
+ self->dongle = dongle;
+
+ /* Now initialize the dongle! */
+ dongle->issue->open(dongle, &self->qos);
+
+ /* Reset dongle */
+ irda_task_execute(dongle, dongle->issue->reset, NULL, NULL,
+ NULL);
+ break;
+ case SIOCSMEDIABUSY: /* Set media busy */
+ irda_device_set_media_busy(self->netdev, TRUE);
+ break;
+ case SIOCGRECEIVING: /* Check if we are receiving right now */
+ irq->ifr_receiving = irtty_is_receiving(self);
+ break;
+ case SIOCSDTRRTS:
+ irtty_set_dtr_rts(dev, irq->ifr_dtr, irq->ifr_rts);
+ break;
+ default:
+ ret = -EOPNOTSUPP;
+ }
+
+ restore_flags(flags);
+
+ return ret;
+}
+
+static struct net_device_stats *irtty_net_get_stats(struct net_device *dev)
+{
+ struct irtty_cb *self = (struct irtty_cb *) dev->priv;
+
+ return &self->stats;
+}
+
#ifdef MODULE
MODULE_AUTHOR("Dag Brattli <dagb@cs.uit.no>");
diff --git a/drivers/net/irda/litelink.c b/drivers/net/irda/litelink.c
index 203838cea..f5da3faf6 100644
--- a/drivers/net/irda/litelink.c
+++ b/drivers/net/irda/litelink.c
@@ -6,7 +6,7 @@
* Status: Stable
* Author: Dag Brattli <dagb@cs.uit.no>
* Created at: Fri May 7 12:50:33 1999
- * Modified at: Sat Jun 26 17:01:05 1999
+ * Modified at: Mon Oct 18 12:45:51 1999
* Modified by: Dag Brattli <dagb@cs.uit.no>
*
* Copyright (c) 1999 Dag Brattli, All Rights Reserved.
@@ -37,27 +37,25 @@
#include <net/irda/irda.h>
#include <net/irda/irmod.h>
#include <net/irda/irda_device.h>
-#include <net/irda/dongle.h>
#define MIN_DELAY 25 /* 15 us, but wait a little more to be sure */
#define MAX_DELAY 10000 /* 1 ms */
-static void litelink_open(struct irda_device *idev, int type);
-static void litelink_close(struct irda_device *dev);
-static void litelink_change_speed(struct irda_device *dev, __u32);
-static void litelink_reset(struct irda_device *dev);
-static void litelink_init_qos(struct irda_device *idev, struct qos_info *qos);
+static void litelink_open(dongle_t *self, struct qos_info *qos);
+static void litelink_close(dongle_t *self);
+static int litelink_change_speed(struct irda_task *task);
+static int litelink_reset(struct irda_task *task);
/* These are the baudrates supported */
static __u32 baud_rates[] = { 115200, 57600, 38400, 19200, 9600 };
-static struct dongle dongle = {
- LITELINK_DONGLE,
+static struct dongle_reg dongle = {
+ Q_NULL,
+ IRDA_LITELINK_DONGLE,
litelink_open,
litelink_close,
litelink_reset,
litelink_change_speed,
- litelink_init_qos,
};
int __init litelink_init(void)
@@ -70,114 +68,102 @@ void litelink_cleanup(void)
irda_device_unregister_dongle(&dongle);
}
-static void litelink_open(struct irda_device *idev, int type)
+static void litelink_open(dongle_t *self, struct qos_info *qos)
{
- strcat(idev->description, " <-> litelink");
-
- idev->io.dongle_id = type;
- idev->flags |= IFF_DONGLE;
+ qos->baud_rate.bits &= IR_9600|IR_19200|IR_38400|IR_57600|IR_115200;
+ qos->min_turn_time.bits &= 0x40; /* Needs 0.01 ms */
MOD_INC_USE_COUNT;
}
-static void litelink_close(struct irda_device *idev)
+static void litelink_close(dongle_t *self)
{
/* Power off dongle */
- irda_device_set_dtr_rts(idev, FALSE, FALSE);
+ self->set_dtr_rts(self->dev, FALSE, FALSE);
MOD_DEC_USE_COUNT;
}
/*
- * Function litelink_change_speed (idev, speed)
+ * Function litelink_change_speed (task)
*
* Change speed of the Litelink dongle. To cycle through the available
* baud rates, pulse RTS low for a few ms.
*/
-static void litelink_change_speed(struct irda_device *idev, __u32 speed)
+static int litelink_change_speed(struct irda_task *task)
{
+ dongle_t *self = (dongle_t *) task->instance;
+ __u32 speed = (__u32) task->param;
int i;
- ASSERT(idev != NULL, return;);
- ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;);
-
/* Clear RTS to reset dongle */
- irda_device_set_dtr_rts(idev, TRUE, FALSE);
+ self->set_dtr_rts(self->dev, TRUE, FALSE);
/* Sleep a minimum of 15 us */
udelay(MIN_DELAY);
/* Go back to normal mode */
- irda_device_set_dtr_rts(idev, TRUE, TRUE);
+ self->set_dtr_rts(self->dev, TRUE, TRUE);
/* Sleep a minimum of 15 us */
udelay(MIN_DELAY);
/* Cycle through avaiable baudrates until we reach the correct one */
for (i=0; i<5 && baud_rates[i] != speed; i++) {
-
/* Set DTR, clear RTS */
- irda_device_set_dtr_rts(idev, FALSE, TRUE);
+ self->set_dtr_rts(self->dev, FALSE, TRUE);
/* Sleep a minimum of 15 us */
udelay(MIN_DELAY);
/* Set DTR, Set RTS */
- irda_device_set_dtr_rts(idev, TRUE, TRUE);
+ self->set_dtr_rts(self->dev, TRUE, TRUE);
/* Sleep a minimum of 15 us */
udelay(MIN_DELAY);
}
+
+ irda_task_next_state(task, IRDA_TASK_DONE);
+
+ return 0;
}
/*
- * Function litelink_reset (dev)
+ * Function litelink_reset (task)
*
* Reset the Litelink type dongle. Warning, this function must only be
* called with a process context!
*
*/
-static void litelink_reset(struct irda_device *idev)
+static int litelink_reset(struct irda_task *task)
{
- ASSERT(idev != NULL, return;);
- ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;);
-
+ dongle_t *self = (dongle_t *) task->instance;
+
/* Power on dongle */
- irda_device_set_dtr_rts(idev, TRUE, TRUE);
+ self->set_dtr_rts(self->dev, TRUE, TRUE);
/* Sleep a minimum of 15 us */
udelay(MIN_DELAY);
/* Clear RTS to reset dongle */
- irda_device_set_dtr_rts(idev, TRUE, FALSE);
+ self->set_dtr_rts(self->dev, TRUE, FALSE);
/* Sleep a minimum of 15 us */
udelay(MIN_DELAY);
/* Go back to normal mode */
- irda_device_set_dtr_rts(idev, TRUE, TRUE);
+ self->set_dtr_rts(self->dev, TRUE, TRUE);
/* Sleep a minimum of 15 us */
udelay(MIN_DELAY);
/* This dongles speed defaults to 115200 bps */
- idev->qos.baud_rate.value = 115200;
-}
+ self->speed = 115200;
-/*
- * Function litelink_init_qos (qos)
- *
- * Initialize QoS capabilities
- *
- */
-static void litelink_init_qos(struct irda_device *idev, struct qos_info *qos)
-{
- qos->baud_rate.bits &= IR_9600|IR_19200|IR_38400|IR_57600|IR_115200;
- qos->min_turn_time.bits &= 0x40; /* Needs 0.01 ms */
+ return 0;
}
#ifdef MODULE
-
MODULE_AUTHOR("Dag Brattli <dagb@cs.uit.no>");
MODULE_DESCRIPTION("Parallax Litelink dongle driver");
@@ -202,5 +188,4 @@ void cleanup_module(void)
{
litelink_cleanup();
}
-
-#endif
+#endif /* MODULE */
diff --git a/drivers/net/irda/pc87108.c b/drivers/net/irda/pc87108.c
index 3b575d01e..fae329ac9 100644
--- a/drivers/net/irda/pc87108.c
+++ b/drivers/net/irda/pc87108.c
@@ -6,7 +6,7 @@
* Status: Experimental.
* Author: Dag Brattli <dagb@cs.uit.no>
* Created at: Sat Nov 7 21:43:15 1998
- * Modified at: Wed Aug 11 09:26:26 1999
+ * Modified at: Wed Oct 20 00:08:41 1999
* Modified by: Dag Brattli <dagb@cs.uit.no>
*
* Copyright (c) 1998-1999 Dag Brattli <dagb@cs.uit.no>
@@ -29,11 +29,11 @@
*
* __u8 bank;
*
- * bank = inb( iobase+BSR);
+ * bank = inb(iobase+BSR);
*
* do_your_stuff_here();
*
- * outb( bank, iobase+BSR);
+ * outb(bank, iobase+BSR);
*
* If you find bugs in this file, its very likely that the same bug
* will also be in w83977af_ir.c since the implementations is quite
@@ -51,6 +51,7 @@
#include <linux/delay.h>
#include <linux/malloc.h>
#include <linux/init.h>
+#include <linux/rtnetlink.h>
#include <asm/io.h>
#include <asm/dma.h>
@@ -101,19 +102,19 @@ static char *dongle_types[] = {
static int pc87108_open(int i, unsigned int iobase, unsigned int board_addr,
unsigned int irq, unsigned int dma);
#ifdef MODULE
-static int pc87108_close(struct irda_device *idev);
+static int pc87108_close(struct pc87108 *self);
#endif /* MODULE */
static int pc87108_probe(int iobase, int board_addr, int irq, int dma);
-static void pc87108_pio_receive(struct irda_device *idev);
-static int pc87108_dma_receive(struct irda_device *idev);
-static int pc87108_dma_receive_complete(struct irda_device *idev, int iobase);
+static void pc87108_pio_receive(struct pc87108 *self);
+static int pc87108_dma_receive(struct pc87108 *self);
+static int pc87108_dma_receive_complete(struct pc87108 *self, int iobase);
static int pc87108_hard_xmit(struct sk_buff *skb, struct net_device *dev);
static int pc87108_pio_write(int iobase, __u8 *buf, int len, int fifo_size);
-static void pc87108_dma_write(struct irda_device *idev, int iobase);
-static void pc87108_change_speed(struct irda_device *idev, __u32 baud);
+static void pc87108_dma_write(struct pc87108 *self, int iobase);
+static void pc87108_change_speed(struct pc87108 *self, __u32 baud);
static void pc87108_interrupt(int irq, void *dev_id, struct pt_regs *regs);
-static void pc87108_wait_until_sent(struct irda_device *idev);
-static int pc87108_is_receiving(struct irda_device *idev);
+static void pc87108_wait_until_sent(struct pc87108 *self);
+static int pc87108_is_receiving(struct pc87108 *self);
static int pc87108_read_dongle_id (int iobase);
static void pc87108_init_dongle_interface (int iobase, int dongle_id);
@@ -152,11 +153,11 @@ static void pc87108_cleanup(void)
{
int i;
- DEBUG(4, __FUNCTION__ "()\n");
+ IRDA_DEBUG(4, __FUNCTION__ "()\n");
for (i=0; i < 4; i++) {
if (dev_self[i])
- pc87108_close(&(dev_self[i]->idev));
+ pc87108_close(dev_self[i]);
}
}
#endif /* MODULE */
@@ -170,12 +171,13 @@ static void pc87108_cleanup(void)
static int pc87108_open(int i, unsigned int iobase, unsigned int board_addr,
unsigned int irq, unsigned int dma)
{
+ struct net_device *dev;
struct pc87108 *self;
- struct irda_device *idev;
- int ret;
int dongle_id;
+ int ret;
+ int err;
- DEBUG(0, __FUNCTION__ "()\n");
+ IRDA_DEBUG(0, __FUNCTION__ "()\n");
if ((dongle_id = pc87108_probe(iobase, board_addr, irq, dma)) == -1)
return -1;
@@ -194,90 +196,127 @@ static int pc87108_open(int i, unsigned int iobase, unsigned int board_addr,
/* Need to store self somewhere */
dev_self[i] = self;
- idev = &self->idev;
-
/* Initialize IO */
- idev->io.iobase = iobase;
- idev->io.irq = irq;
- idev->io.io_ext = CHIP_IO_EXTENT;
- idev->io.dma = dma;
- idev->io.fifo_size = 32;
+ self->io.iobase = iobase;
+ self->io.irq = irq;
+ self->io.io_ext = CHIP_IO_EXTENT;
+ self->io.dma = dma;
+ self->io.fifo_size = 32;
/* Lock the port that we need */
- ret = check_region(idev->io.iobase, idev->io.io_ext);
+ ret = check_region(self->io.iobase, self->io.io_ext);
if (ret < 0) {
- DEBUG(0, __FUNCTION__ "(), can't get iobase of 0x%03x\n",
- idev->io.iobase);
- /* pc87108_cleanup( self->idev); */
+ IRDA_DEBUG(0, __FUNCTION__ "(), can't get iobase of 0x%03x\n",
+ self->io.iobase);
+ /* pc87108_cleanup(self->self); */
return -ENODEV;
}
- request_region(idev->io.iobase, idev->io.io_ext, idev->name);
+ request_region(self->io.iobase, self->io.io_ext, driver_name);
/* Initialize QoS for this device */
- irda_init_max_qos_capabilies(&idev->qos);
+ irda_init_max_qos_capabilies(&self->qos);
/* The only value we must override it the baudrate */
- idev->qos.baud_rate.bits = IR_9600|IR_19200|IR_38400|IR_57600|
+ self->qos.baud_rate.bits = IR_9600|IR_19200|IR_38400|IR_57600|
IR_115200|IR_576000|IR_1152000|(IR_4000000 << 8);
- idev->qos.min_turn_time.bits = qos_mtt_bits;
- irda_qos_bits_to_value(&idev->qos);
+ self->qos.min_turn_time.bits = qos_mtt_bits;
+ irda_qos_bits_to_value(&self->qos);
- idev->flags = IFF_FIR|IFF_MIR|IFF_SIR|IFF_DMA|IFF_PIO|IFF_DONGLE;
-
- /* Specify which buffer allocation policy we need */
- idev->rx_buff.flags = GFP_KERNEL | GFP_DMA;
- idev->tx_buff.flags = GFP_KERNEL | GFP_DMA;
+ self->flags = IFF_FIR|IFF_MIR|IFF_SIR|IFF_DMA|IFF_PIO|IFF_DONGLE;
/* Max DMA buffer size needed = (data_size + 6) * (window_size) + 6; */
- idev->rx_buff.truesize = 14384;
- idev->tx_buff.truesize = 4000;
+ self->rx_buff.truesize = 14384;
+ self->tx_buff.truesize = 4000;
+
+ /* Allocate memory if needed */
+ if (self->rx_buff.truesize > 0) {
+ self->rx_buff.head = (__u8 *) kmalloc(self->rx_buff.truesize,
+ GFP_KERNEL|GFP_DMA);
+ if (self->rx_buff.head == NULL)
+ return -ENOMEM;
+ memset(self->rx_buff.head, 0, self->rx_buff.truesize);
+ }
+ if (self->tx_buff.truesize > 0) {
+ self->tx_buff.head = (__u8 *) kmalloc(self->tx_buff.truesize,
+ GFP_KERNEL|GFP_DMA);
+ if (self->tx_buff.head == NULL) {
+ kfree(self->rx_buff.head);
+ return -ENOMEM;
+ }
+ memset(self->tx_buff.head, 0, self->tx_buff.truesize);
+ }
+
+ self->rx_buff.in_frame = FALSE;
+ self->rx_buff.state = OUTSIDE_FRAME;
+ self->tx_buff.data = self->tx_buff.head;
+ self->rx_buff.data = self->rx_buff.head;
- /* Initialize callbacks */
- idev->change_speed = pc87108_change_speed;
- idev->wait_until_sent = pc87108_wait_until_sent;
- idev->is_receiving = pc87108_is_receiving;
-
+ if (!(dev = dev_alloc("irda%d", &err))) {
+ ERROR(__FUNCTION__ "(), dev_alloc() failed!\n");
+ return -ENOMEM;
+ }
+ /* dev_alloc doesn't clear the struct, so lets do a little hack */
+ memset(((__u8*)dev)+sizeof(char*),0,sizeof(struct net_device)-sizeof(char*));
+
+ dev->priv = (void *) self;
+ self->netdev = dev;
+
/* Override the network functions we need to use */
- idev->netdev.init = pc87108_net_init;
- idev->netdev.hard_start_xmit = pc87108_hard_xmit;
- idev->netdev.open = pc87108_net_open;
- idev->netdev.stop = pc87108_net_close;
+ dev->init = pc87108_net_init;
+ dev->hard_start_xmit = pc87108_hard_xmit;
+ dev->open = pc87108_net_open;
+ dev->stop = pc87108_net_close;
+
+ rtnl_lock();
+ err = register_netdevice(dev);
+ rtnl_unlock();
+ if (err) {
+ ERROR(__FUNCTION__ "(), register_netdev() failed!\n");
+ return -1;
+ }
- idev->io.dongle_id = dongle_id;
+ MESSAGE("IrDA: Registered device %s\n", dev->name);
+
+ self->io.dongle_id = dongle_id;
pc87108_init_dongle_interface(iobase, dongle_id);
- /* Open the IrDA device */
- irda_device_open(idev, driver_name, self);
-
return 0;
}
#ifdef MODULE
/*
- * Function pc87108_close (idev)
+ * Function pc87108_close (self)
*
* Close driver instance
*
*/
-static int pc87108_close(struct irda_device *idev)
+static int pc87108_close(struct pc87108 *self)
{
- struct pc87108 *self;
int iobase;
- DEBUG( 4, __FUNCTION__ "()\n");
+ IRDA_DEBUG(4, __FUNCTION__ "()\n");
+
+ ASSERT(self != NULL, return -1;);
- ASSERT(idev != NULL, return -1;);
- ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return -1;);
+ iobase = self->io.iobase;
- iobase = idev->io.iobase;
- self = (struct pc87108 *) idev->priv;
+ /* Remove netdevice */
+ if (self->netdev) {
+ rtnl_lock();
+ unregister_netdev(self->netdev);
+ rtnl_unlock();
+ }
/* Release the PORT that this driver is using */
- DEBUG(4, __FUNCTION__ "(), Releasing Region %03x\n", idev->io.iobase);
- release_region(idev->io.iobase, idev->io.io_ext);
+ IRDA_DEBUG(4, __FUNCTION__ "(), Releasing Region %03x\n", self->io.iobase);
+ release_region(self->io.iobase, self->io.io_ext);
- irda_device_close(idev);
+ if (self->tx_buff.head)
+ kfree(self->tx_buff.head);
+
+ if (self->rx_buff.head)
+ kfree(self->rx_buff.head);
kfree(self);
@@ -297,7 +336,7 @@ static int pc87108_probe(int iobase, int board_addr, int irq, int dma)
__u8 temp=0;
int dongle_id;
- DEBUG(4, __FUNCTION__ "()\n");
+ IRDA_DEBUG(4, __FUNCTION__ "()\n");
/* Base Address and Interrupt Control Register BAIC */
outb(0, board_addr);
@@ -326,7 +365,7 @@ static int pc87108_probe(int iobase, int board_addr, int irq, int dma)
case 0: outb(0x08+temp, board_addr+1); break;
case 1: outb(0x10+temp, board_addr+1); break;
case 3: outb(0x18+temp, board_addr+1); break;
- default: DEBUG( 0, __FUNCTION__ "(), invalid dma");
+ default: IRDA_DEBUG(0, __FUNCTION__ "(), invalid dma");
}
/* Mode Control Register MCTL */
@@ -344,13 +383,13 @@ static int pc87108_probe(int iobase, int board_addr, int irq, int dma)
}
/* Switch to advanced mode */
- switch_bank( iobase, BANK2);
+ switch_bank(iobase, BANK2);
outb(ECR1_EXT_SL, iobase+ECR1);
switch_bank(iobase, BANK0);
dongle_id = pc87108_read_dongle_id(iobase);
- DEBUG(0, __FUNCTION__ "(), Found dongle: %s\n",
- dongle_types[ dongle_id]);
+ IRDA_DEBUG(0, __FUNCTION__ "(), Found dongle: %s\n",
+ dongle_types[dongle_id]);
/* Set FIFO threshold to TX17, RX16, reset and enable FIFO's */
switch_bank(iobase, BANK0);
@@ -380,7 +419,7 @@ static int pc87108_probe(int iobase, int board_addr, int irq, int dma)
outb(2048 & 0xff, iobase+4);
outb((2048 >> 8) & 0x1f, iobase+5);
- DEBUG(0, "PC87108 driver loaded. Version: 0x%02x\n", version);
+ IRDA_DEBUG(0, "PC87108 driver loaded. Version: 0x%02x\n", version);
/* Enable receive interrupts */
switch_bank(iobase, BANK0);
@@ -397,14 +436,14 @@ static int pc87108_probe(int iobase, int board_addr, int irq, int dma)
* that the user may have plugged/unplugged the IrDA Dongle.
*
*/
-static int pc87108_read_dongle_id ( int iobase)
+static int pc87108_read_dongle_id (int iobase)
{
int dongle_id;
__u8 bank;
- DEBUG( 4, __FUNCTION__ "()\n");
+ IRDA_DEBUG(4, __FUNCTION__ "()\n");
- bank = inb( iobase+BSR);
+ bank = inb(iobase+BSR);
/* Select Bank 7 */
switch_bank(iobase, BANK7);
@@ -416,7 +455,7 @@ static int pc87108_read_dongle_id ( int iobase)
udelay(50);
/* IRCFG1: read the ID bits */
- dongle_id = inb( iobase+4) & 0x0f;
+ dongle_id = inb(iobase+4) & 0x0f;
#ifdef BROKEN_DONGLE_ID
if (dongle_id == 0x0a)
@@ -426,7 +465,7 @@ static int pc87108_read_dongle_id ( int iobase)
/* Go back to bank 0 before returning */
switch_bank(iobase, BANK0);
- DEBUG(0, __FUNCTION__ "(), Dongle = %#x\n", dongle_id);
+ IRDA_DEBUG(0, __FUNCTION__ "(), Dongle = %#x\n", dongle_id);
outb(bank, iobase+BSR);
@@ -446,49 +485,49 @@ static void pc87108_init_dongle_interface (int iobase, int dongle_id)
int bank;
/* Save current bank */
- bank = inb( iobase+BSR);
+ bank = inb(iobase+BSR);
/* Select Bank 7 */
- switch_bank( iobase, BANK7);
+ switch_bank(iobase, BANK7);
/* IRCFG4: set according to dongle_id */
switch (dongle_id) {
case 0x00: /* same as */
case 0x01: /* Differential serial interface */
- DEBUG( 0, __FUNCTION__ "(), %s not defined by irda yet\n",
+ IRDA_DEBUG(0, __FUNCTION__ "(), %s not defined by irda yet\n",
dongle_types[dongle_id]);
break;
case 0x02: /* same as */
case 0x03: /* Reserved */
- DEBUG( 0, __FUNCTION__ "(), %s not defined by irda yet\n",
+ IRDA_DEBUG(0, __FUNCTION__ "(), %s not defined by irda yet\n",
dongle_types[dongle_id]);
break;
case 0x04: /* Sharp RY5HD01 */
- DEBUG( 0, __FUNCTION__ "(), %s not supported yet\n",
+ IRDA_DEBUG(0, __FUNCTION__ "(), %s not supported yet\n",
dongle_types[dongle_id]);
break;
case 0x05: /* Reserved */
- DEBUG( 0, __FUNCTION__ "(), %s not defined by irda yet",
+ IRDA_DEBUG(0, __FUNCTION__ "(), %s not defined by irda yet",
dongle_types[dongle_id]);
break;
case 0x06: /* Single-ended serial interface */
- DEBUG( 0, __FUNCTION__ "(), %s not defined by irda yet\n",
+ IRDA_DEBUG(0, __FUNCTION__ "(), %s not defined by irda yet\n",
dongle_types[dongle_id]);
break;
case 0x07: /* Consumer-IR only */
- DEBUG( 0, __FUNCTION__ "(), %s is not for IrDA mode\n",
+ IRDA_DEBUG(0, __FUNCTION__ "(), %s is not for IrDA mode\n",
dongle_types[dongle_id]);
break;
case 0x08: /* HP HSDL-2300, HP HSDL-3600/HSDL-3610 */
- DEBUG( 0, __FUNCTION__ "(), %s not supported yet\n",
+ IRDA_DEBUG(0, __FUNCTION__ "(), %s not supported yet\n",
dongle_types[dongle_id]);
break;
case 0x09: /* IBM31T1100 or Temic TFDS6000/TFDS6500 */
- outb_p( 0x28, iobase+7); /* Set irsl[0-2] as output */
+ outb_p(0x28, iobase+7); /* Set irsl[0-2] as output */
break;
case 0x0A: /* same as */
case 0x0B: /* Reserved */
- DEBUG( 0, __FUNCTION__ "(), %s not defined by irda yet\n",
+ IRDA_DEBUG(0, __FUNCTION__ "(), %s not defined by irda yet\n",
dongle_types[dongle_id]);
break;
case 0x0C: /* same as */
@@ -497,28 +536,28 @@ static void pc87108_init_dongle_interface (int iobase, int dongle_id)
* Set irsl0 as input, irsl[1-2] as output, and separate
* inputs are used for SIR and MIR/FIR
*/
- outb( 0x48, iobase+7);
+ outb(0x48, iobase+7);
break;
case 0x0E: /* Supports SIR Mode only */
- outb( 0x28, iobase+7); /* Set irsl[0-2] as output */
+ outb(0x28, iobase+7); /* Set irsl[0-2] as output */
break;
case 0x0F: /* No dongle connected */
- DEBUG( 0, __FUNCTION__ "(), %s\n",
+ IRDA_DEBUG(0, __FUNCTION__ "(), %s\n",
dongle_types[dongle_id]);
- DEBUG( 0, "***\n");
+ IRDA_DEBUG(0, "***\n");
- switch_bank( iobase, BANK0);
- outb( 0x62, iobase+MCR);
+ switch_bank(iobase, BANK0);
+ outb(0x62, iobase+MCR);
break;
default:
- DEBUG( 0, __FUNCTION__ "(), invalid dongle_id %#x", dongle_id);
+ IRDA_DEBUG(0, __FUNCTION__ "(), invalid dongle_id %#x", dongle_id);
}
/* IRCFG1: IRSL1 and 2 are set to IrDA mode */
- outb( 0x00, iobase+4);
+ outb(0x00, iobase+4);
/* Restore bank register */
- outb( bank, iobase+BSR);
+ outb(bank, iobase+BSR);
} /* set_up_dongle_interface */
@@ -528,66 +567,66 @@ static void pc87108_init_dongle_interface (int iobase, int dongle_id)
* Change speed of the attach dongle
*
*/
-static void pc87108_change_dongle_speed( int iobase, int speed, int dongle_id)
+static void pc87108_change_dongle_speed(int iobase, int speed, int dongle_id)
{
unsigned long flags;
__u8 bank;
- DEBUG( 4, __FUNCTION__ "()\n");
+ IRDA_DEBUG(4, __FUNCTION__ "()\n");
/* Save current bank */
- bank = inb( iobase+BSR);
+ bank = inb(iobase+BSR);
/* Select Bank 7 */
- switch_bank( iobase, BANK7);
+ switch_bank(iobase, BANK7);
/* IRCFG1: set according to dongle_id */
switch (dongle_id) {
case 0x00: /* same as */
case 0x01: /* Differential serial interface */
- DEBUG( 0, __FUNCTION__ "(), %s not defined by irda yet\n",
+ IRDA_DEBUG(0, __FUNCTION__ "(), %s not defined by irda yet\n",
dongle_types[dongle_id]);
break;
case 0x02: /* same as */
case 0x03: /* Reserved */
- DEBUG( 0, __FUNCTION__ "(), %s not defined by irda yet\n",
+ IRDA_DEBUG(0, __FUNCTION__ "(), %s not defined by irda yet\n",
dongle_types[dongle_id]);
break;
case 0x04: /* Sharp RY5HD01 */
- DEBUG( 0, __FUNCTION__ "(), %s not supported yet\n",
+ IRDA_DEBUG(0, __FUNCTION__ "(), %s not supported yet\n",
dongle_types[dongle_id]);
case 0x05: /* Reserved */
- DEBUG( 0, __FUNCTION__ "(), %s not defined by irda yet\n",
+ IRDA_DEBUG(0, __FUNCTION__ "(), %s not defined by irda yet\n",
dongle_types[dongle_id]);
break;
case 0x06: /* Single-ended serial interface */
- DEBUG( 0, __FUNCTION__ "(), %s not defined by irda yet\n",
+ IRDA_DEBUG(0, __FUNCTION__ "(), %s not defined by irda yet\n",
dongle_types[dongle_id]);
break;
case 0x07: /* Consumer-IR only */
- DEBUG( 0, __FUNCTION__ "(), %s is not for IrDA mode\n",
+ IRDA_DEBUG(0, __FUNCTION__ "(), %s is not for IrDA mode\n",
dongle_types[dongle_id]);
break;
case 0x08: /* HP HSDL-2300, HP HSDL-3600/HSDL-3610 */
- DEBUG( 0, __FUNCTION__ "(), %s not supported yet\n",
+ IRDA_DEBUG(0, __FUNCTION__ "(), %s not supported yet\n",
dongle_types[dongle_id]);
case 0x09: /* IBM31T1100 or Temic TFDS6000/TFDS6500 */
- switch_bank( iobase, BANK7);
- outb_p( 0x01, iobase+4);
+ switch_bank(iobase, BANK7);
+ outb_p(0x01, iobase+4);
- if ( speed == 4000000) {
+ if (speed == 4000000) {
save_flags(flags);
cli();
- outb( 0x81, iobase+4);
- outb( 0x80, iobase+4);
+ outb(0x81, iobase+4);
+ outb(0x80, iobase+4);
restore_flags(flags);
}
else
- outb_p( 0x00, iobase+4);
+ outb_p(0x00, iobase+4);
break;
case 0x0A: /* same as */
case 0x0B: /* Reserved */
- DEBUG( 0, __FUNCTION__ "(), %s not defined by irda yet\n",
+ IRDA_DEBUG(0, __FUNCTION__ "(), %s not defined by irda yet\n",
dongle_types[dongle_id]);
break;
case 0x0C: /* same as */
@@ -596,78 +635,77 @@ static void pc87108_change_dongle_speed( int iobase, int speed, int dongle_id)
case 0x0E: /* Supports SIR Mode only */
break;
case 0x0F: /* No dongle connected */
- DEBUG( 0, __FUNCTION__ "(), %s is not for IrDA mode\n",
+ IRDA_DEBUG(0, __FUNCTION__ "(), %s is not for IrDA mode\n",
dongle_types[dongle_id]);
- switch_bank( iobase, BANK0);
- outb( 0x62, iobase+MCR);
+ switch_bank(iobase, BANK0);
+ outb(0x62, iobase+MCR);
break;
default:
- DEBUG( 0, __FUNCTION__ "(), invalid data_rate\n");
+ IRDA_DEBUG(0, __FUNCTION__ "(), invalid data_rate\n");
}
/* Restore bank register */
- outb( bank, iobase+BSR);
+ outb(bank, iobase+BSR);
}
/*
- * Function pc87108_change_speed (idev, baud)
+ * Function pc87108_change_speed (self, baud)
*
* Change the speed of the device
*
*/
-static void pc87108_change_speed(struct irda_device *idev, __u32 speed)
+static void pc87108_change_speed(struct pc87108 *self, __u32 speed)
{
__u8 mcr = MCR_SIR;
__u8 bank;
int iobase;
- DEBUG( 4, __FUNCTION__ "()\n");
+ IRDA_DEBUG(4, __FUNCTION__ "()\n");
- ASSERT( idev != NULL, return;);
- ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return;);
+ ASSERT(self != NULL, return;);
- iobase = idev->io.iobase;
+ iobase = self->io.iobase;
/* Update accounting for new speed */
- idev->io.baudrate = speed;
+ self->io.speed = speed;
/* Save current bank */
- bank = inb( iobase+BSR);
+ bank = inb(iobase+BSR);
/* Disable interrupts */
- switch_bank( iobase, BANK0);
- outb( 0, iobase+IER);
+ switch_bank(iobase, BANK0);
+ outb(0, iobase+IER);
/* Select Bank 2 */
- switch_bank( iobase, BANK2);
-
- outb( 0x00, iobase+BGDH);
- switch ( speed) {
- case 9600: outb( 0x0c, iobase+BGDL); break;
- case 19200: outb( 0x06, iobase+BGDL); break;
- case 37600: outb( 0x03, iobase+BGDL); break;
- case 57600: outb( 0x02, iobase+BGDL); break;
- case 115200: outb( 0x01, iobase+BGDL); break;
+ switch_bank(iobase, BANK2);
+
+ outb(0x00, iobase+BGDH);
+ switch (speed) {
+ case 9600: outb(0x0c, iobase+BGDL); break;
+ case 19200: outb(0x06, iobase+BGDL); break;
+ case 37600: outb(0x03, iobase+BGDL); break;
+ case 57600: outb(0x02, iobase+BGDL); break;
+ case 115200: outb(0x01, iobase+BGDL); break;
case 576000:
- switch_bank( iobase, BANK5);
+ switch_bank(iobase, BANK5);
/* IRCR2: MDRS is set */
- outb( inb( iobase+4) | 0x04, iobase+4);
+ outb(inb(iobase+4) | 0x04, iobase+4);
mcr = MCR_MIR;
- DEBUG(0, __FUNCTION__ "(), handling baud of 576000\n");
+ IRDA_DEBUG(0, __FUNCTION__ "(), handling baud of 576000\n");
break;
case 1152000:
mcr = MCR_MIR;
- DEBUG(0, __FUNCTION__ "(), handling baud of 1152000\n");
+ IRDA_DEBUG(0, __FUNCTION__ "(), handling baud of 1152000\n");
break;
case 4000000:
mcr = MCR_FIR;
- DEBUG(0, __FUNCTION__ "(), handling baud of 4000000\n");
+ IRDA_DEBUG(0, __FUNCTION__ "(), handling baud of 4000000\n");
break;
default:
mcr = MCR_FIR;
- DEBUG( 0, __FUNCTION__ "(), unknown baud rate of %d\n", speed);
+ IRDA_DEBUG(0, __FUNCTION__ "(), unknown baud rate of %d\n", speed);
break;
}
@@ -676,34 +714,34 @@ static void pc87108_change_speed(struct irda_device *idev, __u32 speed)
outb(mcr | MCR_TX_DFR, iobase+MCR);
/* Give some hits to the transceiver */
- pc87108_change_dongle_speed( iobase, speed, idev->io.dongle_id);
+ pc87108_change_dongle_speed(iobase, speed, self->io.dongle_id);
/* Set FIFO threshold to TX17, RX16 */
- switch_bank( iobase, BANK0);
- outb( FCR_RXTH| /* Set Rx FIFO threshold */
+ switch_bank(iobase, BANK0);
+ outb(FCR_RXTH| /* Set Rx FIFO threshold */
FCR_TXTH| /* Set Tx FIFO threshold */
FCR_TXSR| /* Reset Tx FIFO */
FCR_RXSR| /* Reset Rx FIFO */
FCR_FIFO_EN, /* Enable FIFOs */
iobase+FCR);
- /* outb( 0xa7, iobase+FCR); */
+ /* outb(0xa7, iobase+FCR); */
/* Set FIFO size to 32 */
- switch_bank( iobase, BANK2);
- outb( EXCR2_RFSIZ|EXCR2_TFSIZ, iobase+EXCR2);
+ switch_bank(iobase, BANK2);
+ outb(EXCR2_RFSIZ|EXCR2_TFSIZ, iobase+EXCR2);
- idev->netdev.tbusy = 0;
+ self->netdev->tbusy = 0;
/* Enable some interrupts so we can receive frames */
- switch_bank( iobase, BANK0);
- if ( speed > 115200) {
- outb( IER_SFIF_IE, iobase+IER);
- pc87108_dma_receive( idev);
+ switch_bank(iobase, BANK0);
+ if (speed > 115200) {
+ outb(IER_SFIF_IE, iobase+IER);
+ pc87108_dma_receive(self);
} else
- outb( IER_RXHDL_IE, iobase+IER);
+ outb(IER_RXHDL_IE, iobase+IER);
/* Restore BSR */
- outb( bank, iobase+BSR);
+ outb(bank, iobase+BSR);
}
/*
@@ -712,107 +750,106 @@ static void pc87108_change_speed(struct irda_device *idev, __u32 speed)
* Transmit the frame!
*
*/
-static int pc87108_hard_xmit( struct sk_buff *skb, struct net_device *dev)
+static int pc87108_hard_xmit(struct sk_buff *skb, struct net_device *dev)
{
- struct irda_device *idev;
+ struct pc87108 *self;
int iobase;
__u8 bank;
int mtt;
- idev = (struct irda_device *) dev->priv;
+ self = (struct pc87108 *) dev->priv;
- ASSERT( idev != NULL, return 0;);
- ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return 0;);
+ ASSERT(self != NULL, return 0;);
- iobase = idev->io.iobase;
+ iobase = self->io.iobase;
- DEBUG(4, __FUNCTION__ "(%ld), skb->len=%d\n", jiffies, (int) skb->len);
+ IRDA_DEBUG(4, __FUNCTION__ "(%ld), skb->len=%d\n", jiffies, (int) skb->len);
/* Lock transmit buffer */
- if ( irda_lock( (void *) &dev->tbusy) == FALSE)
+ if (irda_lock((void *) &dev->tbusy) == FALSE)
return -EBUSY;
/* Save current bank */
- bank = inb( iobase+BSR);
+ bank = inb(iobase+BSR);
/* Decide if we should use PIO or DMA transfer */
- if ( idev->io.baudrate > 115200) {
- idev->tx_buff.data = idev->tx_buff.head;
- memcpy(idev->tx_buff.data, skb->data, skb->len);
- idev->tx_buff.len = skb->len;
+ if (self->io.speed > 115200) {
+ self->tx_buff.data = self->tx_buff.head;
+ memcpy(self->tx_buff.data, skb->data, skb->len);
+ self->tx_buff.len = skb->len;
- mtt = irda_get_mtt( skb);
- if ( mtt > 50) {
+ mtt = irda_get_mtt(skb);
+ if (mtt > 50) {
/* Adjust for timer resolution */
mtt = mtt / 125 + 1;
/* Setup timer */
- switch_bank( iobase, BANK4);
- outb( mtt & 0xff, iobase+TMRL);
- outb(( mtt >> 8) & 0x0f, iobase+TMRH);
+ switch_bank(iobase, BANK4);
+ outb(mtt & 0xff, iobase+TMRL);
+ outb((mtt >> 8) & 0x0f, iobase+TMRH);
/* Start timer */
- outb( IRCR1_TMR_EN, iobase+IRCR1);
- idev->io.direction = IO_XMIT;
+ outb(IRCR1_TMR_EN, iobase+IRCR1);
+ self->io.direction = IO_XMIT;
/* Enable timer interrupt */
- switch_bank( iobase, BANK0);
- outb( IER_TMR_IE, iobase+IER);
+ switch_bank(iobase, BANK0);
+ outb(IER_TMR_IE, iobase+IER);
} else {
/* Use udelay for delays less than 50 us. */
if (mtt)
- udelay( mtt);
+ udelay(mtt);
/* Enable DMA interrupt */
- switch_bank( iobase, BANK0);
- outb( IER_DMA_IE, iobase+IER);
- pc87108_dma_write( idev, iobase);
+ switch_bank(iobase, BANK0);
+ outb(IER_DMA_IE, iobase+IER);
+ pc87108_dma_write(self, iobase);
}
} else {
- idev->tx_buff.len = async_wrap_skb(skb, idev->tx_buff.data,
- idev->tx_buff.truesize);
+ self->tx_buff.len = async_wrap_skb(skb, self->tx_buff.data,
+ self->tx_buff.truesize);
- idev->tx_buff.data = idev->tx_buff.head;
+ self->tx_buff.data = self->tx_buff.head;
/* Add interrupt on tx low level (will fire immediately) */
- switch_bank( iobase, BANK0);
- outb( IER_TXLDL_IE, iobase+IER);
+ switch_bank(iobase, BANK0);
+ outb(IER_TXLDL_IE, iobase+IER);
}
- dev_kfree_skb( skb);
+ dev_kfree_skb(skb);
/* Restore bank register */
- outb( bank, iobase+BSR);
+ outb(bank, iobase+BSR);
return 0;
}
/*
- * Function pc87108_dma_xmit (idev, iobase)
+ * Function pc87108_dma_xmit (self, iobase)
*
* Transmit data using DMA
*
*/
-static void pc87108_dma_write( struct irda_device *idev, int iobase)
+static void pc87108_dma_write(struct pc87108 *self, int iobase)
{
int bsr;
- DEBUG( 4, __FUNCTION__ "()\n");
+ IRDA_DEBUG(4, __FUNCTION__ "()\n");
/* Save current bank */
- bsr = inb( iobase+BSR);
+ bsr = inb(iobase+BSR);
/* Disable DMA */
switch_bank(iobase, BANK0);
- outb( inb( iobase+MCR) & ~MCR_DMA_EN, iobase+MCR);
+ outb(inb(iobase+MCR) & ~MCR_DMA_EN, iobase+MCR);
- setup_dma(idev->io.dma, idev->tx_buff.data, idev->tx_buff.len,
+ setup_dma(self->io.dma, self->tx_buff.data, self->tx_buff.len,
DMA_MODE_WRITE);
- idev->io.direction = IO_XMIT;
+ self->io.direction = IO_XMIT;
/* Choose transmit DMA channel */
switch_bank(iobase, BANK2);
- outb( inb( iobase+ECR1) | ECR1_DMASWP|ECR1_DMANF|ECR1_EXT_SL,
+ outb(inb(iobase+ECR1) | ECR1_DMASWP|ECR1_DMANF|ECR1_EXT_SL,
iobase+ECR1);
/* Enable DMA */
@@ -824,7 +861,7 @@ static void pc87108_dma_write( struct irda_device *idev, int iobase)
}
/*
- * Function pc87108_pio_xmit (idev, iobase)
+ * Function pc87108_pio_xmit (self, iobase)
*
* Transmit data using PIO. Returns the number of bytes that actually
* got transfered
@@ -835,17 +872,17 @@ static int pc87108_pio_write(int iobase, __u8 *buf, int len, int fifo_size)
int actual = 0;
__u8 bank;
- DEBUG( 4, __FUNCTION__ "()\n");
+ IRDA_DEBUG(4, __FUNCTION__ "()\n");
/* Save current bank */
- bank = inb( iobase+BSR);
+ bank = inb(iobase+BSR);
- switch_bank( iobase, BANK0);
- if (!(inb_p( iobase+LSR) & LSR_TXEMP)) {
- DEBUG( 4, __FUNCTION__ "(), warning, FIFO not empty yet!\n");
+ switch_bank(iobase, BANK0);
+ if (!(inb_p(iobase+LSR) & LSR_TXEMP)) {
+ IRDA_DEBUG(4, __FUNCTION__ "(), warning, FIFO not empty yet!\n");
fifo_size -= 17;
- DEBUG( 4, __FUNCTION__ "%d bytes left in tx fifo\n", fifo_size);
+ IRDA_DEBUG(4, __FUNCTION__ "%d bytes left in tx fifo\n", fifo_size);
}
/* Fill FIFO with current frame */
@@ -854,7 +891,7 @@ static int pc87108_pio_write(int iobase, __u8 *buf, int len, int fifo_size)
outb(buf[actual++], iobase+TXD);
}
- DEBUG(4, __FUNCTION__ "(), fifo_size %d ; %d sent of %d\n",
+ IRDA_DEBUG(4, __FUNCTION__ "(), fifo_size %d ; %d sent of %d\n",
fifo_size, actual, len);
/* Restore bank */
@@ -864,74 +901,69 @@ static int pc87108_pio_write(int iobase, __u8 *buf, int len, int fifo_size)
}
/*
- * Function pc87108_dma_xmit_complete (idev)
+ * Function pc87108_dma_xmit_complete (self)
*
* The transfer of a frame in finished. This function will only be called
* by the interrupt handler
*
*/
-static void pc87108_dma_xmit_complete( struct irda_device *idev)
+static void pc87108_dma_xmit_complete(struct pc87108 *self)
{
int iobase;
__u8 bank;
- DEBUG( 4, __FUNCTION__ "()\n");
+ IRDA_DEBUG(4, __FUNCTION__ "()\n");
- ASSERT( idev != NULL, return;);
- ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return;);
+ ASSERT(self != NULL, return;);
- iobase = idev->io.iobase;
+ iobase = self->io.iobase;
/* Save current bank */
- bank = inb( iobase+BSR);
+ bank = inb(iobase+BSR);
/* Disable DMA */
- switch_bank( iobase, BANK0);
- outb( inb(iobase+MCR) & ~MCR_DMA_EN, iobase+MCR);
+ switch_bank(iobase, BANK0);
+ outb(inb(iobase+MCR) & ~MCR_DMA_EN, iobase+MCR);
/* Check for underrrun! */
- if ( inb( iobase+ASCR) & ASCR_TXUR) {
- idev->stats.tx_errors++;
- idev->stats.tx_fifo_errors++;
+ if (inb(iobase+ASCR) & ASCR_TXUR) {
+ self->stats.tx_errors++;
+ self->stats.tx_fifo_errors++;
/* Clear bit, by writing 1 into it */
- outb( ASCR_TXUR, iobase+ASCR);
+ outb(ASCR_TXUR, iobase+ASCR);
} else {
- idev->stats.tx_packets++;
- idev->stats.tx_bytes += idev->tx_buff.len;
+ self->stats.tx_packets++;
+ self->stats.tx_bytes += self->tx_buff.len;
}
/* Unlock tx_buff and request another frame */
- idev->netdev.tbusy = 0; /* Unlock */
- idev->media_busy = FALSE;
+ self->netdev->tbusy = 0; /* Unlock */
/* Tell the network layer, that we can accept more frames */
- mark_bh( NET_BH);
+ mark_bh(NET_BH);
/* Restore bank */
- outb( bank, iobase+BSR);
+ outb(bank, iobase+BSR);
}
/*
- * Function pc87108_dma_receive (idev)
+ * Function pc87108_dma_receive (self)
*
* Get ready for receiving a frame. The device will initiate a DMA
* if it starts to receive a frame.
*
*/
-static int pc87108_dma_receive(struct irda_device *idev)
+static int pc87108_dma_receive(struct pc87108 *self)
{
- struct pc87108 *self;
int iobase;
__u8 bsr;
- ASSERT(idev != NULL, return -1;);
- ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return -1;);
+ ASSERT(self != NULL, return -1;);
- DEBUG(4, __FUNCTION__ "\n");
+ IRDA_DEBUG(4, __FUNCTION__ "\n");
- self = idev->priv;
- iobase = idev->io.iobase;
+ iobase = self->io.iobase;
/* Save current bank */
bsr = inb(iobase+BSR);
@@ -940,12 +972,12 @@ static int pc87108_dma_receive(struct irda_device *idev)
switch_bank(iobase, BANK0);
outb(inb(iobase+MCR) & ~MCR_DMA_EN, iobase+MCR);
- setup_dma(idev->io.dma, idev->rx_buff.data,
- idev->rx_buff.truesize, DMA_MODE_READ);
+ setup_dma(self->io.dma, self->rx_buff.data,
+ self->rx_buff.truesize, DMA_MODE_READ);
/* driver->media_busy = FALSE; */
- idev->io.direction = IO_RECV;
- idev->rx_buff.data = idev->rx_buff.head;
+ self->io.direction = IO_RECV;
+ self->rx_buff.data = self->rx_buff.head;
/* Reset Rx FIFO. This will also flush the ST_FIFO */
outb(FCR_RXTH|FCR_TXTH|FCR_RXSR|FCR_FIFO_EN, iobase+FCR);
@@ -953,7 +985,7 @@ static int pc87108_dma_receive(struct irda_device *idev)
/* Choose DMA Rx, DMA Fairness, and Advanced mode */
switch_bank(iobase, BANK2);
- outb((inb( iobase+ECR1) & ~ECR1_DMASWP)|ECR1_DMANF|ECR1_EXT_SL,
+ outb((inb(iobase+ECR1) & ~ECR1_DMASWP)|ECR1_DMANF|ECR1_EXT_SL,
iobase+ECR1);
/* enable DMA */
@@ -963,40 +995,38 @@ static int pc87108_dma_receive(struct irda_device *idev)
/* Restore bank register */
outb(bsr, iobase+BSR);
- DEBUG(4, __FUNCTION__ "(), done!\n");
+ IRDA_DEBUG(4, __FUNCTION__ "(), done!\n");
return 0;
}
/*
- * Function pc87108_dma_receive_complete (idev)
+ * Function pc87108_dma_receive_complete (self)
*
* Finished with receiving frames
*
*
*/
-static int pc87108_dma_receive_complete(struct irda_device *idev, int iobase)
+static int pc87108_dma_receive_complete(struct pc87108 *self, int iobase)
{
struct sk_buff *skb;
- struct pc87108 *self;
struct st_fifo *st_fifo;
- int len;
__u8 bank;
__u8 status;
+ int len;
- self = idev->priv;
st_fifo = &self->st_fifo;
/* Save current bank */
- bank = inb( iobase+BSR);
+ bank = inb(iobase+BSR);
/* Read status FIFO */
switch_bank(iobase, BANK5);
- while (( status = inb( iobase+FRM_ST)) & FRM_ST_VLD) {
- st_fifo->entries[ st_fifo->tail].status = status;
+ while ((status = inb(iobase+FRM_ST)) & FRM_ST_VLD) {
+ st_fifo->entries[st_fifo->tail].status = status;
- st_fifo->entries[ st_fifo->tail].len = inb(iobase+RFLFL);
- st_fifo->entries[ st_fifo->tail].len |= inb(iobase+RFLFH) << 8;
+ st_fifo->entries[st_fifo->tail].len = inb(iobase+RFLFL);
+ st_fifo->entries[st_fifo->tail].len |= inb(iobase+RFLFH) << 8;
st_fifo->tail++;
st_fifo->len++;
@@ -1016,28 +1046,28 @@ static int pc87108_dma_receive_complete(struct irda_device *idev, int iobase)
if (status & FRM_ST_ERR_MSK) {
if (status & FRM_ST_LOST_FR) {
/* Add number of lost frames to stats */
- idev->stats.rx_errors += len;
+ self->stats.rx_errors += len;
} else {
/* Skip frame */
- idev->stats.rx_errors++;
+ self->stats.rx_errors++;
- idev->rx_buff.data += len;
+ self->rx_buff.data += len;
if (status & FRM_ST_MAX_LEN)
- idev->stats.rx_length_errors++;
+ self->stats.rx_length_errors++;
if (status & FRM_ST_PHY_ERR)
- idev->stats.rx_frame_errors++;
+ self->stats.rx_frame_errors++;
if (status & FRM_ST_BAD_CRC)
- idev->stats.rx_crc_errors++;
+ self->stats.rx_crc_errors++;
}
/* The errors below can be reported in both cases */
if (status & FRM_ST_OVR1)
- idev->stats.rx_fifo_errors++;
+ self->stats.rx_fifo_errors++;
if (status & FRM_ST_OVR2)
- idev->stats.rx_fifo_errors++;
+ self->stats.rx_fifo_errors++;
} else {
/* Check if we have transfered all data to memory */
@@ -1057,10 +1087,10 @@ static int pc87108_dma_receive_complete(struct irda_device *idev, int iobase)
/* Should be OK then */
skb = dev_alloc_skb(len+1);
if (skb == NULL) {
- printk( KERN_INFO __FUNCTION__
+ printk(KERN_INFO __FUNCTION__
"(), memory squeeze, dropping frame.\n");
/* Restore bank register */
- outb( bank, iobase+BSR);
+ outb(bank, iobase+BSR);
return FALSE;
}
@@ -1069,22 +1099,22 @@ static int pc87108_dma_receive_complete(struct irda_device *idev, int iobase)
skb_reserve(skb, 1);
/* Copy frame without CRC */
- if (idev->io.baudrate < 4000000) {
+ if (self->io.speed < 4000000) {
skb_put(skb, len-2);
- memcpy(skb->data, idev->rx_buff.data, len-2);
+ memcpy(skb->data, self->rx_buff.data, len-2);
} else {
skb_put(skb, len-4);
- memcpy(skb->data, idev->rx_buff.data, len-4);
+ memcpy(skb->data, self->rx_buff.data, len-4);
}
/* Move to next frame */
- idev->rx_buff.data += len;
- idev->stats.rx_packets++;
+ self->rx_buff.data += len;
+ self->stats.rx_packets++;
- skb->dev = &idev->netdev;
+ skb->dev = self->netdev;
skb->mac.raw = skb->data;
skb->protocol = htons(ETH_P_IRDA);
- netif_rx( skb);
+ netif_rx(skb);
}
}
/* Restore bank register */
@@ -1094,60 +1124,59 @@ static int pc87108_dma_receive_complete(struct irda_device *idev, int iobase)
}
/*
- * Function pc87108_pio_receive (idev)
+ * Function pc87108_pio_receive (self)
*
* Receive all data in receiver FIFO
*
*/
-static void pc87108_pio_receive( struct irda_device *idev)
+static void pc87108_pio_receive(struct pc87108 *self)
{
__u8 byte = 0x00;
int iobase;
- DEBUG(4, __FUNCTION__ "()\n");
+ IRDA_DEBUG(4, __FUNCTION__ "()\n");
- ASSERT(idev != NULL, return;);
- ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;);
+ ASSERT(self != NULL, return;);
- iobase = idev->io.iobase;
+ iobase = self->io.iobase;
/* Receive all characters in Rx FIFO */
do {
byte = inb(iobase+RXD);
- async_unwrap_char(idev, byte);
+ async_unwrap_char(self->netdev, &self->rx_buff, byte);
} while (inb(iobase+LSR) & LSR_RXDA); /* Data available */
}
/*
- * Function pc87108_sir_interrupt (idev, eir)
+ * Function pc87108_sir_interrupt (self, eir)
*
* Handle SIR interrupt
*
*/
-static __u8 pc87108_sir_interrupt(struct irda_device *idev, int eir)
+static __u8 pc87108_sir_interrupt(struct pc87108 *self, int eir)
{
int actual;
__u8 new_ier = 0;
/* Transmit FIFO low on data */
- if ( eir & EIR_TXLDL_EV) {
+ if (eir & EIR_TXLDL_EV) {
/* Write data left in transmit buffer */
- actual = pc87108_pio_write(idev->io.iobase,
- idev->tx_buff.data,
- idev->tx_buff.len,
- idev->io.fifo_size);
- idev->tx_buff.data += actual;
- idev->tx_buff.len -= actual;
+ actual = pc87108_pio_write(self->io.iobase,
+ self->tx_buff.data,
+ self->tx_buff.len,
+ self->io.fifo_size);
+ self->tx_buff.data += actual;
+ self->tx_buff.len -= actual;
- idev->io.direction = IO_XMIT;
+ self->io.direction = IO_XMIT;
/* Check if finished */
- if (idev->tx_buff.len > 0)
+ if (self->tx_buff.len > 0)
new_ier |= IER_TXLDL_IE;
else {
- idev->netdev.tbusy = 0; /* Unlock */
- idev->stats.tx_packets++;
+ self->netdev->tbusy = 0; /* Unlock */
+ self->stats.tx_packets++;
mark_bh(NET_BH);
@@ -1156,16 +1185,16 @@ static __u8 pc87108_sir_interrupt(struct irda_device *idev, int eir)
}
/* Check if transmission has completed */
- if ( eir & EIR_TXEMP_EV) {
+ if (eir & EIR_TXEMP_EV) {
/* Turn around and get ready to receive some data */
- idev->io.direction = IO_RECV;
+ self->io.direction = IO_RECV;
new_ier |= IER_RXHDL_IE;
}
/* Rx FIFO threshold or timeout */
- if ( eir & EIR_RXHDL_EV) {
- pc87108_pio_receive( idev);
+ if (eir & EIR_RXHDL_EV) {
+ pc87108_pio_receive(self);
/* Keep receiving */
new_ier |= IER_RXHDL_IE;
@@ -1174,22 +1203,22 @@ static __u8 pc87108_sir_interrupt(struct irda_device *idev, int eir)
}
/*
- * Function pc87108_fir_interrupt (idev, eir)
+ * Function pc87108_fir_interrupt (self, eir)
*
* Handle MIR/FIR interrupt
*
*/
-static __u8 pc87108_fir_interrupt( struct irda_device *idev, int iobase,
- int eir)
+static __u8 pc87108_fir_interrupt(struct pc87108 *self, int iobase,
+ int eir)
{
__u8 new_ier = 0;
__u8 bank;
- bank = inb( iobase+BSR);
+ bank = inb(iobase+BSR);
/* Status event, or end of frame detected in FIFO */
if (eir & (EIR_SFIF_EV|EIR_LS_EV)) {
- if (pc87108_dma_receive_complete( idev, iobase)) {
+ if (pc87108_dma_receive_complete(self, iobase)) {
/* Wait for next status FIFO interrupt */
new_ier |= IER_SFIF_IE;
@@ -1197,52 +1226,52 @@ static __u8 pc87108_fir_interrupt( struct irda_device *idev, int iobase,
/* DMA not finished yet */
/* Set timer value, resolution 125 us */
- switch_bank( iobase, BANK4);
- outb( 0x0f, iobase+TMRL); /* 125 us */
- outb( 0x00, iobase+TMRH);
+ switch_bank(iobase, BANK4);
+ outb(0x0f, iobase+TMRL); /* 125 us */
+ outb(0x00, iobase+TMRH);
/* Start timer */
- outb( IRCR1_TMR_EN, iobase+IRCR1);
+ outb(IRCR1_TMR_EN, iobase+IRCR1);
new_ier |= IER_TMR_IE;
}
}
/* Timer finished */
- if ( eir & EIR_TMR_EV) {
+ if (eir & EIR_TMR_EV) {
/* Disable timer */
- switch_bank( iobase, BANK4);
- outb( 0, iobase+IRCR1);
+ switch_bank(iobase, BANK4);
+ outb(0, iobase+IRCR1);
/* Clear timer event */
switch_bank(iobase, BANK0);
- outb( ASCR_CTE, iobase+ASCR);
+ outb(ASCR_CTE, iobase+ASCR);
/* Check if this is a TX timer interrupt */
- if ( idev->io.direction == IO_XMIT) {
- pc87108_dma_write( idev, iobase);
+ if (self->io.direction == IO_XMIT) {
+ pc87108_dma_write(self, iobase);
/* Interrupt on DMA */
new_ier |= IER_DMA_IE;
} else {
/* Check if DMA has now finished */
- pc87108_dma_receive_complete( idev, iobase);
+ pc87108_dma_receive_complete(self, iobase);
new_ier |= IER_SFIF_IE;
}
}
/* Finished with transmission */
- if ( eir & EIR_DMA_EV) {
- pc87108_dma_xmit_complete( idev);
+ if (eir & EIR_DMA_EV) {
+ pc87108_dma_xmit_complete(self);
/* Check if there are more frames to be transmitted */
- if ( irda_device_txqueue_empty( idev)) {
+ if (irda_device_txqueue_empty(self->netdev)) {
/* Prepare for receive */
- pc87108_dma_receive( idev);
+ pc87108_dma_receive(self);
new_ier = IER_LS_IE|IER_SFIF_IE;
}
}
- outb( bank, iobase+BSR);
+ outb(bank, iobase+BSR);
return new_ier;
}
@@ -1255,51 +1284,52 @@ static __u8 pc87108_fir_interrupt( struct irda_device *idev, int iobase,
*/
static void pc87108_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
+ struct net_device *dev = (struct net_device *) dev_id;
+ struct pc87108 *self;
__u8 bsr, eir, ier;
int iobase;
- struct irda_device *idev = (struct irda_device *) dev_id;
-
- if (idev == NULL) {
- printk( KERN_WARNING "%s: irq %d for unknown device.\n",
+ if (!dev) {
+ printk(KERN_WARNING "%s: irq %d for unknown device.\n",
driver_name, irq);
return;
}
+ self = (struct pc87108 *) dev->priv;
- idev->netdev.interrupt = 1;
+ dev->interrupt = 1;
- iobase = idev->io.iobase;
+ iobase = self->io.iobase;
/* Save current bank */
- bsr = inb( iobase+BSR);
+ bsr = inb(iobase+BSR);
- switch_bank( iobase, BANK0);
- ier = inb( iobase+IER);
- eir = inb( iobase+EIR) & ier; /* Mask out the interesting ones */
+ switch_bank(iobase, BANK0);
+ ier = inb(iobase+IER);
+ eir = inb(iobase+EIR) & ier; /* Mask out the interesting ones */
- outb( 0, iobase+IER); /* Disable interrupts */
+ outb(0, iobase+IER); /* Disable interrupts */
- if ( eir) {
+ if (eir) {
/* Dispatch interrupt handler for the current speed */
- if ( idev->io.baudrate > 115200)
- ier = pc87108_fir_interrupt( idev, iobase, eir);
+ if (self->io.speed > 115200)
+ ier = pc87108_fir_interrupt(self, iobase, eir);
else
- ier = pc87108_sir_interrupt( idev, eir);
+ ier = pc87108_sir_interrupt(self, eir);
}
- outb( ier, iobase+IER); /* Restore interrupts */
- outb( bsr, iobase+BSR); /* Restore bank register */
+ outb(ier, iobase+IER); /* Restore interrupts */
+ outb(bsr, iobase+BSR); /* Restore bank register */
- idev->netdev.interrupt = 0;
+ dev->interrupt = 0;
}
/*
- * Function pc87108_wait_until_sent (idev)
+ * Function pc87108_wait_until_sent (self)
*
* This function should put the current thread to sleep until all data
* have been sent, so it is safe to f.eks. change the speed.
*/
-static void pc87108_wait_until_sent( struct irda_device *idev)
+static void pc87108_wait_until_sent(struct pc87108 *self)
{
/* Just delay 60 ms */
current->state = TASK_INTERRUPTIBLE;
@@ -1307,33 +1337,32 @@ static void pc87108_wait_until_sent( struct irda_device *idev)
}
/*
- * Function pc87108_is_receiving (idev)
+ * Function pc87108_is_receiving (self)
*
* Return TRUE is we are currently receiving a frame
*
*/
-static int pc87108_is_receiving( struct irda_device *idev)
+static int pc87108_is_receiving(struct pc87108 *self)
{
int status = FALSE;
int iobase;
__u8 bank;
- ASSERT( idev != NULL, return FALSE;);
- ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return FALSE;);
+ ASSERT(self != NULL, return FALSE;);
- if ( idev->io.baudrate > 115200) {
- iobase = idev->io.iobase;
+ if (self->io.speed > 115200) {
+ iobase = self->io.iobase;
/* Check if rx FIFO is not empty */
- bank = inb( iobase+BSR);
- switch_bank( iobase, BANK2);
- if (( inb( iobase+RXFLV) & 0x3f) != 0) {
+ bank = inb(iobase+BSR);
+ switch_bank(iobase, BANK2);
+ if ((inb(iobase+RXFLV) & 0x3f) != 0) {
/* We are receiving something */
status = TRUE;
}
- outb( bank, iobase+BSR);
+ outb(bank, iobase+BSR);
} else
- status = ( idev->rx_buff.state != OUTSIDE_FRAME);
+ status = (self->rx_buff.state != OUTSIDE_FRAME);
return status;
}
@@ -1344,12 +1373,12 @@ static int pc87108_is_receiving( struct irda_device *idev)
* Initialize network device
*
*/
-static int pc87108_net_init( struct net_device *dev)
+static int pc87108_net_init(struct net_device *dev)
{
- DEBUG( 4, __FUNCTION__ "()\n");
+ IRDA_DEBUG(4, __FUNCTION__ "()\n");
/* Setup to be a normal IrDA network device driver */
- irda_device_setup( dev);
+ irda_device_setup(dev);
/* Insert overrides below this line! */
@@ -1363,46 +1392,54 @@ static int pc87108_net_init( struct net_device *dev)
* Start the device
*
*/
-static int pc87108_net_open( struct net_device *dev)
+static int pc87108_net_open(struct net_device *dev)
{
- struct irda_device *idev;
+ struct pc87108 *self;
int iobase;
__u8 bank;
- DEBUG( 4, __FUNCTION__ "()\n");
+ IRDA_DEBUG(4, __FUNCTION__ "()\n");
- ASSERT( dev != NULL, return -1;);
- idev = (struct irda_device *) dev->priv;
+ ASSERT(dev != NULL, return -1;);
+ self = (struct pc87108 *) dev->priv;
- ASSERT( idev != NULL, return 0;);
- ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return 0;);
+ ASSERT(self != NULL, return 0;);
- iobase = idev->io.iobase;
+ iobase = self->io.iobase;
- if (request_irq( idev->io.irq, pc87108_interrupt, 0, idev->name,
- (void *) idev)) {
+ if (request_irq(self->io.irq, pc87108_interrupt, 0, dev->name,
+ (void *) dev)) {
return -EAGAIN;
}
/*
* Always allocate the DMA channel after the IRQ,
* and clean up on failure.
*/
- if (request_dma(idev->io.dma, idev->name)) {
- free_irq( idev->io.irq, idev);
+ if (request_dma(self->io.dma, dev->name)) {
+ free_irq(self->io.irq, self);
return -EAGAIN;
}
/* Save current bank */
- bank = inb( iobase+BSR);
+ bank = inb(iobase+BSR);
/* turn on interrupts */
- switch_bank( iobase, BANK0);
- outb( IER_LS_IE | IER_RXHDL_IE, iobase+IER);
+ switch_bank(iobase, BANK0);
+ outb(IER_LS_IE | IER_RXHDL_IE, iobase+IER);
/* Restore bank register */
- outb( bank, iobase+BSR);
+ outb(bank, iobase+BSR);
- irda_device_net_open(dev);
+ /* Ready to play! */
+ dev->tbusy = 0;
+ dev->interrupt = 0;
+ dev->start = 1;
+
+ /*
+ * Open new IrLAP layer instance, now that everything should be
+ * initialized properly
+ */
+ self->irlap = irlap_open(dev, &self->qos);
MOD_INC_USE_COUNT;
@@ -1417,23 +1454,29 @@ static int pc87108_net_open( struct net_device *dev)
*/
static int pc87108_net_close(struct net_device *dev)
{
- struct irda_device *idev;
+ struct pc87108 *self;
int iobase;
__u8 bank;
- DEBUG(4, __FUNCTION__ "()\n");
+ IRDA_DEBUG(4, __FUNCTION__ "()\n");
- irda_device_net_close(dev);
-
ASSERT(dev != NULL, return -1;);
- idev = (struct irda_device *) dev->priv;
+ self = (struct pc87108 *) dev->priv;
- ASSERT(idev != NULL, return 0;);
- ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return 0;);
+ ASSERT(self != NULL, return 0;);
+
+ /* Stop device */
+ dev->tbusy = 1;
+ dev->start = 0;
+
+ /* Stop and remove instance of IrLAP */
+ if (self->irlap)
+ irlap_close(self->irlap);
+ self->irlap = NULL;
- iobase = idev->io.iobase;
+ iobase = self->io.iobase;
- disable_dma(idev->io.dma);
+ disable_dma(self->io.dma);
/* Save current bank */
bank = inb(iobase+BSR);
@@ -1442,8 +1485,8 @@ static int pc87108_net_close(struct net_device *dev)
switch_bank(iobase, BANK0);
outb(0, iobase+IER);
- free_irq(idev->io.irq, idev);
- free_dma(idev->io.dma);
+ free_irq(self->io.irq, self);
+ free_dma(self->io.dma);
/* Restore bank register */
outb(bank, iobase+BSR);
diff --git a/drivers/net/irda/smc-ircc.c b/drivers/net/irda/smc-ircc.c
index 00ab408d6..06b2af81b 100644
--- a/drivers/net/irda/smc-ircc.c
+++ b/drivers/net/irda/smc-ircc.c
@@ -106,7 +106,7 @@ int __init ircc_init(void)
{
int i;
- DEBUG(ircc_debug, __FUNCTION__ " -->\n");
+ IRDA_DEBUG(ircc_debug, __FUNCTION__ " -->\n");
for ( i=0; (io[i] < 2000) && (i < 4); i++) {
int ioaddr = io[i];
if (check_region(ioaddr, CHIP_IO_EXTENT))
@@ -114,7 +114,7 @@ int __init ircc_init(void)
if (ircc_open( i, io[i], io2[i]) == 0)
return 0;
}
- DEBUG( ircc_debug, "--> " __FUNCTION__ "\n");
+ IRDA_DEBUG( ircc_debug, "--> " __FUNCTION__ "\n");
return -ENODEV;
}
@@ -130,13 +130,13 @@ static void ircc_cleanup(void)
{
int i;
- DEBUG(ircc_debug, __FUNCTION__ " -->\n");
+ IRDA_DEBUG(ircc_debug, __FUNCTION__ " -->\n");
for ( i=0; i < 4; i++) {
if ( dev_self[i])
ircc_close( &(dev_self[i]->idev));
}
- DEBUG( ircc_debug, "--> " __FUNCTION__ "\n");
+ IRDA_DEBUG( ircc_debug, "--> " __FUNCTION__ "\n");
}
#endif /* MODULE */
@@ -153,10 +153,10 @@ static int ircc_open( int i, unsigned int iobase, unsigned int iobase2)
int ret;
int config;
- DEBUG( ircc_debug, __FUNCTION__ " -->\n");
+ IRDA_DEBUG( ircc_debug, __FUNCTION__ " -->\n");
if ((config = ircc_probe( iobase, iobase2)) == -1) {
- DEBUG(ircc_debug,
+ IRDA_DEBUG(ircc_debug,
__FUNCTION__ ": addr 0x%04x - no device found!\n", iobase);
return -1;
}
@@ -199,14 +199,14 @@ static int ircc_open( int i, unsigned int iobase, unsigned int iobase2)
/* Lock the port that we need */
ret = check_region( idev->io.iobase, idev->io.io_ext);
if ( ret < 0) {
- DEBUG( 0, __FUNCTION__ ": can't get iobase of 0x%03x\n",
+ IRDA_DEBUG( 0, __FUNCTION__ ": can't get iobase of 0x%03x\n",
idev->io.iobase);
/* ircc_cleanup( self->idev); */
return -ENODEV;
}
ret = check_region( idev->io.iobase2, idev->io.io_ext2);
if ( ret < 0) {
- DEBUG( 0, __FUNCTION__ ": can't get iobase of 0x%03x\n",
+ IRDA_DEBUG( 0, __FUNCTION__ ": can't get iobase of 0x%03x\n",
idev->io.iobase2);
/* ircc_cleanup( self->idev); */
return -ENODEV;
@@ -256,7 +256,7 @@ static int ircc_open( int i, unsigned int iobase, unsigned int iobase2)
/* Open the IrDA device */
irda_device_open( idev, driver_name, self);
- DEBUG( ircc_debug, "--> " __FUNCTION__ "\n");
+ IRDA_DEBUG( ircc_debug, "--> " __FUNCTION__ "\n");
return 0;
}
@@ -271,7 +271,7 @@ static int ircc_close( struct irda_device *idev)
{
int iobase;
- DEBUG(ircc_debug, __FUNCTION__ " -->\n");
+ IRDA_DEBUG(ircc_debug, __FUNCTION__ " -->\n");
ASSERT( idev != NULL, return -1;);
ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return -1;);
@@ -291,20 +291,20 @@ static int ircc_close( struct irda_device *idev)
serial_out(iobase, UART_SCE_CFGB, UART_CFGB_IR);
/* Release the PORT that this driver is using */
- DEBUG( ircc_debug,
+ IRDA_DEBUG( ircc_debug,
__FUNCTION__ ": releasing 0x%03x\n", idev->io.iobase);
release_region( idev->io.iobase, idev->io.io_ext);
if ( idev->io.iobase2) {
- DEBUG( ircc_debug, __FUNCTION__ ": releasing 0x%03x\n",
+ IRDA_DEBUG( ircc_debug, __FUNCTION__ ": releasing 0x%03x\n",
idev->io.iobase2);
release_region( idev->io.iobase2, idev->io.io_ext2);
}
irda_device_close( idev);
- DEBUG( ircc_debug, "--> " __FUNCTION__ "\n");
+ IRDA_DEBUG( ircc_debug, "--> " __FUNCTION__ "\n");
return 0;
}
#endif /* MODULE */
@@ -320,7 +320,7 @@ static int ircc_probe(int iobase, int iobase2)
int version = 1;
int low, high, chip, config, dma, irq;
- DEBUG(ircc_debug, __FUNCTION__ " -->\n");
+ IRDA_DEBUG(ircc_debug, __FUNCTION__ " -->\n");
register_bank(iobase, 3);
high = serial_in(iobase, UART_ID_HIGH);
@@ -332,7 +332,7 @@ static int ircc_probe(int iobase, int iobase2)
dma = config & 0x0f;
if (high == 0x10 && low == 0xb8 && (chip == 0xf1 || chip == 0xf2)) {
- DEBUG(0, "SMC IrDA Controller found; IrCC version %d.%d, "
+ IRDA_DEBUG(0, "SMC IrDA Controller found; IrCC version %d.%d, "
"port 0x%04x, dma %d, interrupt %d\n",
chip & 0x0f, version, iobase, dma, irq);
} else {
@@ -341,7 +341,7 @@ static int ircc_probe(int iobase, int iobase2)
serial_out(iobase, UART_MASTER, 0);
- DEBUG(ircc_debug, "--> " __FUNCTION__ "\n");
+ IRDA_DEBUG(ircc_debug, "--> " __FUNCTION__ "\n");
return config;
}
@@ -357,7 +357,7 @@ static void ircc_change_speed( struct irda_device *idev, __u32 speed)
struct ircc_cb *self;
int iobase, ir_mode, select, fast;
- DEBUG(ircc_debug+1, __FUNCTION__ " -->\n");
+ IRDA_DEBUG(ircc_debug+1, __FUNCTION__ " -->\n");
ASSERT(idev != NULL, return;);
ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;);
@@ -374,7 +374,7 @@ static void ircc_change_speed( struct irda_device *idev, __u32 speed)
case 37600:
case 57600:
case 115200:
- DEBUG(ircc_debug+1,
+ IRDA_DEBUG(ircc_debug+1,
__FUNCTION__ ": using irport to change speed to %d\n",
speed);
register_bank(iobase, 0);
@@ -390,22 +390,22 @@ static void ircc_change_speed( struct irda_device *idev, __u32 speed)
ir_mode = UART_CFGA_IRDA_HDLC;
select = 0;
fast = 0;
- DEBUG( ircc_debug, __FUNCTION__ ": handling baud of 576000\n");
+ IRDA_DEBUG( ircc_debug, __FUNCTION__ ": handling baud of 576000\n");
break;
case 1152000:
ir_mode = UART_CFGA_IRDA_HDLC;
select = UART_1152;
fast = 0;
- DEBUG(ircc_debug, __FUNCTION__ ": handling baud of 1152000\n");
+ IRDA_DEBUG(ircc_debug, __FUNCTION__ ": handling baud of 1152000\n");
break;
case 4000000:
ir_mode = UART_CFGA_IRDA_4PPM;
select = 0;
fast = UART_LCR_A_FAST;
- DEBUG(ircc_debug, __FUNCTION__ ": handling baud of 4000000\n");
+ IRDA_DEBUG(ircc_debug, __FUNCTION__ ": handling baud of 4000000\n");
break;
default:
- DEBUG( 0, __FUNCTION__ ": unknown baud rate of %d\n", speed);
+ IRDA_DEBUG( 0, __FUNCTION__ ": unknown baud rate of %d\n", speed);
return;
}
@@ -443,7 +443,7 @@ static void ircc_change_speed( struct irda_device *idev, __u32 speed)
serial_out(iobase, UART_LCR_A, fast);
- DEBUG( ircc_debug, "--> " __FUNCTION__ "\n");
+ IRDA_DEBUG( ircc_debug, "--> " __FUNCTION__ "\n");
}
/*
@@ -458,7 +458,7 @@ static int ircc_hard_xmit( struct sk_buff *skb, struct net_device *dev)
int iobase;
int mtt;
- DEBUG(ircc_debug+1, __FUNCTION__ " -->\n");
+ IRDA_DEBUG(ircc_debug+1, __FUNCTION__ " -->\n");
idev = (struct irda_device *) dev->priv;
ASSERT( idev != NULL, return 0;);
@@ -466,15 +466,15 @@ static int ircc_hard_xmit( struct sk_buff *skb, struct net_device *dev)
iobase = idev->io.iobase;
- DEBUG(ircc_debug+1, __FUNCTION__ "(%ld), skb->len=%d\n", jiffies, (int) skb->len);
+ IRDA_DEBUG(ircc_debug+1, __FUNCTION__ "(%ld), skb->len=%d\n", jiffies, (int) skb->len);
/* Use irport for SIR speeds */
if (idev->io.baudrate <= 115200) {
- DEBUG(ircc_debug+1, __FUNCTION__ ": calling irport_hard_xmit\n");
+ IRDA_DEBUG(ircc_debug+1, __FUNCTION__ ": calling irport_hard_xmit\n");
return irport_hard_xmit(skb, dev);
}
- DEBUG(ircc_debug, __FUNCTION__ ": using dma; len=%d\n", skb->len);
+ IRDA_DEBUG(ircc_debug, __FUNCTION__ ": using dma; len=%d\n", skb->len);
/* Lock transmit buffer */
if (irda_lock((void *) &dev->tbusy) == FALSE)
@@ -502,7 +502,7 @@ static int ircc_hard_xmit( struct sk_buff *skb, struct net_device *dev)
dev_kfree_skb( skb);
- DEBUG( ircc_debug, "--> " __FUNCTION__ "\n");
+ IRDA_DEBUG( ircc_debug, "--> " __FUNCTION__ "\n");
return 0;
}
@@ -516,7 +516,7 @@ static void ircc_dma_write( struct irda_device *idev, int iobase)
{
struct ircc_cb *self;
- DEBUG(ircc_debug, __FUNCTION__ " -->\n");
+ IRDA_DEBUG(ircc_debug, __FUNCTION__ " -->\n");
ASSERT( idev != NULL, return;);
ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return;);
@@ -557,7 +557,7 @@ static void ircc_dma_write( struct irda_device *idev, int iobase)
serial_out(iobase, UART_MASTER, UART_MASTER_INT_EN);
- DEBUG( ircc_debug, "--> " __FUNCTION__ "\n");
+ IRDA_DEBUG( ircc_debug, "--> " __FUNCTION__ "\n");
}
/*
@@ -572,7 +572,7 @@ static void ircc_dma_xmit_complete( struct irda_device *idev, int underrun)
struct ircc_cb *self;
int iobase, d;
- DEBUG(ircc_debug, __FUNCTION__ " -->\n");
+ IRDA_DEBUG(ircc_debug, __FUNCTION__ " -->\n");
ASSERT( idev != NULL, return;);
ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return;);
@@ -585,7 +585,7 @@ static void ircc_dma_xmit_complete( struct irda_device *idev, int underrun)
d = get_dma_residue(idev->io.dma);
- DEBUG(ircc_debug, __FUNCTION__ ": dma residue = %d, len=%d, sent=%d\n",
+ IRDA_DEBUG(ircc_debug, __FUNCTION__ ": dma residue = %d, len=%d, sent=%d\n",
d, idev->tx_buff.len, idev->tx_buff.len - d);
self = idev->priv;
@@ -608,7 +608,7 @@ static void ircc_dma_xmit_complete( struct irda_device *idev, int underrun)
/* Tell the network layer, that we can accept more frames */
mark_bh( NET_BH);
- DEBUG( ircc_debug, "--> " __FUNCTION__ "\n");
+ IRDA_DEBUG( ircc_debug, "--> " __FUNCTION__ "\n");
}
/*
@@ -623,7 +623,7 @@ static int ircc_dma_receive( struct irda_device *idev)
struct ircc_cb *self;
int iobase;
- DEBUG(ircc_debug, __FUNCTION__ " -->\n");
+ IRDA_DEBUG(ircc_debug, __FUNCTION__ " -->\n");
ASSERT( idev != NULL, return -1;);
ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return -1;);
@@ -660,7 +660,7 @@ static int ircc_dma_receive( struct irda_device *idev)
serial_in(iobase, UART_SCE_CFGB) |
UART_CFGB_DMA_ENABLE | UART_CFGB_DMA_BURST);
- DEBUG( ircc_debug, "--> " __FUNCTION__ "\n");
+ IRDA_DEBUG( ircc_debug, "--> " __FUNCTION__ "\n");
return 0;
}
@@ -677,18 +677,18 @@ static int ircc_dma_receive_complete( struct irda_device *idev, int iobase)
struct ircc_cb *self;
int len, msgcnt;
- DEBUG(ircc_debug, __FUNCTION__ " -->\n");
+ IRDA_DEBUG(ircc_debug, __FUNCTION__ " -->\n");
self = idev->priv;
msgcnt = serial_in(idev->io.iobase, UART_LCR_B) & 0x08;
- DEBUG(ircc_debug, __FUNCTION__ ": dma count = %d\n",
+ IRDA_DEBUG(ircc_debug, __FUNCTION__ ": dma count = %d\n",
get_dma_residue(idev->io.dma));
len = idev->rx_buff.truesize - get_dma_residue(idev->io.dma) - 4;
- DEBUG(ircc_debug, __FUNCTION__ ": msgcnt = %d, len=%d\n", msgcnt, len);
+ IRDA_DEBUG(ircc_debug, __FUNCTION__ ": msgcnt = %d, len=%d\n", msgcnt, len);
skb = dev_alloc_skb( len+1);
@@ -715,7 +715,7 @@ static int ircc_dma_receive_complete( struct irda_device *idev, int iobase)
serial_in(idev->io.iobase, UART_SCE_CFGB) &
~UART_CFGB_DMA_ENABLE);
- DEBUG( ircc_debug, "--> " __FUNCTION__ "\n");
+ IRDA_DEBUG( ircc_debug, "--> " __FUNCTION__ "\n");
return TRUE;
}
@@ -731,7 +731,7 @@ static void ircc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
struct irda_device *idev = (struct irda_device *) dev_id;
- DEBUG(ircc_debug+1, __FUNCTION__ " -->\n");
+ IRDA_DEBUG(ircc_debug+1, __FUNCTION__ " -->\n");
if (idev == NULL) {
printk( KERN_WARNING "%s: irq %d for unknown device.\n",
@@ -740,7 +740,7 @@ static void ircc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
}
if (idev->io.baudrate <= 115200) {
- DEBUG(ircc_debug+1, __FUNCTION__
+ IRDA_DEBUG(ircc_debug+1, __FUNCTION__
": routing interrupt to irport_interrupt\n");
return irport_interrupt( irq, dev_id, regs);
}
@@ -757,10 +757,10 @@ static void ircc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
serial_out(iobase, UART_IER, 0);
- DEBUG(ircc_debug, __FUNCTION__ ": iir = 0x%02x\n", iir);
+ IRDA_DEBUG(ircc_debug, __FUNCTION__ ": iir = 0x%02x\n", iir);
if (iir & UART_IIR_EOM) {
- DEBUG(ircc_debug, __FUNCTION__ ": UART_IIR_EOM\n");
+ IRDA_DEBUG(ircc_debug, __FUNCTION__ ": UART_IIR_EOM\n");
if (idev->io.direction == IO_RECV) {
ircc_dma_receive_complete(idev, iobase);
} else {
@@ -770,7 +770,7 @@ static void ircc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
}
if (iir & UART_IIR_ACTIVE_FRAME) {
- DEBUG(ircc_debug, __FUNCTION__ ": UART_IIR_ACTIVE_FRAME\n");
+ IRDA_DEBUG(ircc_debug, __FUNCTION__ ": UART_IIR_ACTIVE_FRAME\n");
idev->rx_buff.state = INSIDE_FRAME;
#if 0
ircc_dma_receive(idev);
@@ -778,7 +778,7 @@ static void ircc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
}
if (iir & UART_IIR_RAW_MODE) {
- DEBUG(ircc_debug, __FUNCTION__ ": IIR RAW mode interrupt.\n");
+ IRDA_DEBUG(ircc_debug, __FUNCTION__ ": IIR RAW mode interrupt.\n");
}
idev->netdev.interrupt = 0;
@@ -787,7 +787,7 @@ static void ircc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
serial_out(iobase, UART_IER, UART_IER_ACTIVE_FRAME|UART_IER_EOM);
serial_out(iobase, UART_MASTER, UART_MASTER_INT_EN);
- DEBUG( ircc_debug, "--> " __FUNCTION__ "\n");
+ IRDA_DEBUG( ircc_debug, "--> " __FUNCTION__ "\n");
}
/*
@@ -798,13 +798,13 @@ static void ircc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
*/
static void ircc_wait_until_sent( struct irda_device *idev)
{
- DEBUG(ircc_debug, __FUNCTION__ " -->\n");
+ IRDA_DEBUG(ircc_debug, __FUNCTION__ " -->\n");
/* Just delay 60 ms */
current->state = TASK_INTERRUPTIBLE;
schedule_timeout(MSECS_TO_JIFFIES(60));
- DEBUG( ircc_debug, "--> " __FUNCTION__ "\n");
+ IRDA_DEBUG( ircc_debug, "--> " __FUNCTION__ "\n");
}
/*
@@ -818,17 +818,17 @@ static int ircc_is_receiving( struct irda_device *idev)
int status = FALSE;
/* int iobase; */
- DEBUG(ircc_debug, __FUNCTION__ " -->\n");
+ IRDA_DEBUG(ircc_debug, __FUNCTION__ " -->\n");
ASSERT( idev != NULL, return FALSE;);
ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return FALSE;);
- DEBUG(ircc_debug, __FUNCTION__ ": dma count = %d\n",
+ IRDA_DEBUG(ircc_debug, __FUNCTION__ ": dma count = %d\n",
get_dma_residue(idev->io.dma));
status = ( idev->rx_buff.state != OUTSIDE_FRAME);
- DEBUG( ircc_debug, "--> " __FUNCTION__ "\n");
+ IRDA_DEBUG( ircc_debug, "--> " __FUNCTION__ "\n");
return status;
}
@@ -841,14 +841,14 @@ static int ircc_is_receiving( struct irda_device *idev)
*/
static int ircc_net_init( struct net_device *dev)
{
- DEBUG(ircc_debug, __FUNCTION__ " -->\n");
+ IRDA_DEBUG(ircc_debug, __FUNCTION__ " -->\n");
/* Setup to be a normal IrDA network device driver */
irda_device_setup( dev);
/* Insert overrides below this line! */
- DEBUG( ircc_debug, "--> " __FUNCTION__ "\n");
+ IRDA_DEBUG( ircc_debug, "--> " __FUNCTION__ "\n");
return 0;
}
@@ -864,7 +864,7 @@ static int ircc_net_open( struct net_device *dev)
struct irda_device *idev;
int iobase;
- DEBUG(ircc_debug, __FUNCTION__ " -->\n");
+ IRDA_DEBUG(ircc_debug, __FUNCTION__ " -->\n");
ASSERT( dev != NULL, return -1;);
idev = (struct irda_device *) dev->priv;
@@ -894,7 +894,7 @@ static int ircc_net_open( struct net_device *dev)
MOD_INC_USE_COUNT;
- DEBUG( ircc_debug, "--> " __FUNCTION__ "\n");
+ IRDA_DEBUG( ircc_debug, "--> " __FUNCTION__ "\n");
return 0;
}
@@ -909,7 +909,7 @@ static int ircc_net_close(struct net_device *dev)
struct irda_device *idev;
int iobase;
- DEBUG(ircc_debug, __FUNCTION__ " -->\n");
+ IRDA_DEBUG(ircc_debug, __FUNCTION__ " -->\n");
ASSERT( dev != NULL, return -1;);
idev = (struct irda_device *) dev->priv;
@@ -930,7 +930,7 @@ static int ircc_net_close(struct net_device *dev)
MOD_DEC_USE_COUNT;
- DEBUG( ircc_debug, "--> " __FUNCTION__ "\n");
+ IRDA_DEBUG( ircc_debug, "--> " __FUNCTION__ "\n");
return 0;
}
diff --git a/drivers/net/irda/tekram.c b/drivers/net/irda/tekram.c
index 6f3c49f6f..35504cfd3 100644
--- a/drivers/net/irda/tekram.c
+++ b/drivers/net/irda/tekram.c
@@ -6,7 +6,7 @@
* Status: Experimental.
* Author: Dag Brattli <dagb@cs.uit.no>
* Created at: Wed Oct 21 20:02:35 1998
- * Modified at: Thu Jul 15 01:17:53 1999
+ * Modified at: Mon Oct 18 23:25:44 1999
* Modified by: Dag Brattli <dagb@cs.uit.no>
*
* Copyright (c) 1998-1999 Dag Brattli, All Rights Reserved.
@@ -29,15 +29,14 @@
#include <linux/init.h>
#include <net/irda/irda.h>
+#include <net/irda/irmod.h>
#include <net/irda/irda_device.h>
#include <net/irda/irtty.h>
-#include <net/irda/dongle.h>
-static void tekram_reset(struct irda_device *dev);
-static void tekram_open(struct irda_device *dev, int type);
-static void tekram_close(struct irda_device *dev);
-static void tekram_change_speed(struct irda_device *dev, __u32 speed);
-static void tekram_init_qos(struct irda_device *idev, struct qos_info *qos);
+static void tekram_open(dongle_t *self, struct qos_info *qos);
+static void tekram_close(dongle_t *self);
+static int tekram_change_speed(struct irda_task *task);
+static int tekram_reset(struct irda_task *task);
#define TEKRAM_115200 0x00
#define TEKRAM_57600 0x01
@@ -47,13 +46,13 @@ static void tekram_init_qos(struct irda_device *idev, struct qos_info *qos);
#define TEKRAM_PW 0x10 /* Pulse select bit */
-static struct dongle dongle = {
- TEKRAM_DONGLE,
+static struct dongle_reg dongle = {
+ Q_NULL,
+ IRDA_TEKRAM_DONGLE,
tekram_open,
tekram_close,
tekram_reset,
tekram_change_speed,
- tekram_init_qos,
};
int __init tekram_init(void)
@@ -66,26 +65,29 @@ void tekram_cleanup(void)
irda_device_unregister_dongle(&dongle);
}
-static void tekram_open(struct irda_device *idev, int type)
+static void tekram_open(dongle_t *self, struct qos_info *qos)
{
- strcat(idev->description, " <-> tekram");
+ IRDA_DEBUG(2, __FUNCTION__ "()\n");
+
+ qos->baud_rate.bits &= IR_9600|IR_19200|IR_38400|IR_57600|IR_115200;
+ qos->min_turn_time.bits &= 0x01; /* Needs at least 10 ms */
+ irda_qos_bits_to_value(qos);
- idev->io.dongle_id = type;
- idev->flags |= IFF_DONGLE;
-
MOD_INC_USE_COUNT;
}
-static void tekram_close(struct irda_device *idev)
-{
+static void tekram_close(dongle_t *self)
+{
+ IRDA_DEBUG(2, __FUNCTION__ "()\n");
+
/* Power off dongle */
- irda_device_set_dtr_rts(idev, FALSE, FALSE);
+ self->set_dtr_rts(self->dev, FALSE, FALSE);
MOD_DEC_USE_COUNT;
}
/*
- * Function tekram_change_speed (tty, speed)
+ * Function tekram_change_speed (dev, state, speed)
*
* Set the speed for the Tekram IRMate 210 type dongle. Warning, this
* function must be called with a process context!
@@ -100,14 +102,16 @@ static void tekram_close(struct irda_device *idev)
* 6. wait at least 50 us, new setting (baud rate, etc) takes effect here
* after
*/
-static void tekram_change_speed(struct irda_device *idev, __u32 speed)
+static int tekram_change_speed(struct irda_task *task)
{
+ dongle_t *self = (dongle_t *) task->instance;
+ __u32 speed = (__u32) task->param;
__u8 byte;
+ int ret = 0;
- DEBUG(4, __FUNCTION__ "()\n");
+ IRDA_DEBUG(2, __FUNCTION__ "()\n");
- ASSERT(idev != NULL, return;);
- ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;);
+ ASSERT(task != NULL, return -1;);
switch (speed) {
default:
@@ -128,24 +132,65 @@ static void tekram_change_speed(struct irda_device *idev, __u32 speed)
break;
}
- /* Need to reset the dongle and go to 9600 bps before programming */
- tekram_reset(idev);
-
- /* Set DTR, Clear RTS */
- irda_device_set_dtr_rts(idev, TRUE, FALSE);
-
- /* Wait at least 7us */
- udelay(10);
+ switch (task->state) {
+ case IRDA_TASK_INIT:
+ /* Lock dongle */
+ if (irda_lock((void *) &self->busy) == FALSE) {
+ IRDA_DEBUG(0, __FUNCTION__ "(), busy!\n");
+ return MSECS_TO_JIFFIES(100);
+ }
+ irda_task_next_state(task, IRDA_TASK_CHILD_INIT);
+ break;
+ case IRDA_TASK_CHILD_INIT:
+ /*
+ * Need to reset the dongle and go to 9600 bps before
+ * programming
+ */
+ if (irda_task_execute(self, tekram_reset, NULL, task,
+ (void *) speed))
+ {
+ /* Dongle need more time to reset */
+ irda_task_next_state(task, IRDA_TASK_CHILD_WAIT);
- /* Write control byte */
- irda_device_raw_write(idev, &byte, 1);
+ /* Give reset 1 sec to finish */
+ ret = MSECS_TO_JIFFIES(1000);
+ } else
+ irda_task_next_state(task, IRDA_TASK_CHILD_DONE);
+ break;
+ case IRDA_TASK_CHILD_WAIT:
+ WARNING(__FUNCTION__ "(), resetting dongle timed out!\n");
+ ret = -1;
+ break;
+ case IRDA_TASK_CHILD_DONE:
+ /* Set DTR, Clear RTS */
+ self->set_dtr_rts(self->dev, TRUE, FALSE);
- /* Wait at least 100 ms */
- current->state = TASK_INTERRUPTIBLE;
- schedule_timeout(MSECS_TO_JIFFIES(100));
-
- /* Set DTR, Set RTS */
- irda_device_set_dtr_rts(idev, TRUE, TRUE);
+ /* Wait at least 7us */
+ udelay(10);
+
+ /* Write control byte */
+ self->write(self->dev, &byte, 1);
+
+ irda_task_next_state(task, IRDA_TASK_WAIT);
+
+ /* Wait at least 100 ms */
+ ret = MSECS_TO_JIFFIES(100);
+ break;
+ case IRDA_TASK_WAIT:
+ /* Set DTR, Set RTS */
+ self->set_dtr_rts(self->dev, TRUE, TRUE);
+
+ irda_task_next_state(task, IRDA_TASK_DONE);
+ self->busy = 0;
+ break;
+ default:
+ ERROR(__FUNCTION__ "(), unknown state %d\n", task->state);
+ irda_task_next_state(task, IRDA_TASK_DONE);
+ self->busy = 0;
+ ret = -1;
+ break;
+ }
+ return ret;
}
/*
@@ -161,50 +206,52 @@ static void tekram_change_speed(struct irda_device *idev, __u32 speed)
* 3. clear DTR to SPACE state, wait at least 50 us for further
* operation
*/
-void tekram_reset(struct irda_device *idev)
+int tekram_reset(struct irda_task *task)
{
- ASSERT(idev != NULL, return;);
- ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;);
+ dongle_t *self = (dongle_t *) task->instance;
+ int ret = 0;
+
+ IRDA_DEBUG(2, __FUNCTION__ "()\n");
+
+ ASSERT(task != NULL, return -1;);
/* Power off dongle */
- irda_device_set_dtr_rts(idev, FALSE, FALSE);
-
- /* Sleep 50 ms */
- current->state = TASK_INTERRUPTIBLE;
- schedule_timeout(MSECS_TO_JIFFIES(50));
+ self->set_dtr_rts(self->dev, FALSE, FALSE);
- /* Clear DTR, Set RTS */
- irda_device_set_dtr_rts(idev, FALSE, TRUE);
+ switch (task->state) {
+ case IRDA_TASK_INIT:
+ irda_task_next_state(task, IRDA_TASK_WAIT1);
- /* Should sleep 1 ms, but 10-20 should not do any harm */
- current->state = TASK_INTERRUPTIBLE;
- schedule_timeout(MSECS_TO_JIFFIES(20));
+ /* Sleep 50 ms */
+ ret = MSECS_TO_JIFFIES(50);
+ break;
+ case IRDA_TASK_WAIT1:
+ /* Clear DTR, Set RTS */
+ self->set_dtr_rts(self->dev, FALSE, TRUE);
- /* Set DTR, Set RTS */
- irda_device_set_dtr_rts(idev, TRUE, TRUE);
-
- udelay(50);
+ irda_task_next_state(task, IRDA_TASK_WAIT2);
+
+ /* Should sleep 1 ms, but 10 should not do any harm */
+ ret = MSECS_TO_JIFFIES(10);
+ break;
+ case IRDA_TASK_WAIT2:
+ /* Set DTR, Set RTS */
+ self->set_dtr_rts(self->dev, TRUE, TRUE);
- /* Make sure the IrDA chip also goes to defalt speed */
- if (idev->change_speed)
- idev->change_speed(idev, 9600);
-}
+ udelay(50);
-/*
- * Function tekram_init_qos (qos)
- *
- * Initialize QoS capabilities
- *
- */
-static void tekram_init_qos(struct irda_device *idev, struct qos_info *qos)
-{
- qos->baud_rate.bits &= IR_9600|IR_19200|IR_38400|IR_57600|IR_115200;
- qos->min_turn_time.bits &= 0x01; /* Needs at least 10 ms */
- irda_qos_bits_to_value(qos);
+ irda_task_next_state(task, IRDA_TASK_DONE);
+ break;
+ default:
+ ERROR(__FUNCTION__ "(), unknown state %d\n", task->state);
+ irda_task_next_state(task, IRDA_TASK_DONE);
+
+ ret = -1;
+ }
+ return ret;
}
#ifdef MODULE
-
MODULE_AUTHOR("Dag Brattli <dagb@cs.uit.no>");
MODULE_DESCRIPTION("Tekram IrMate IR-210B dongle driver");
@@ -229,5 +276,4 @@ void cleanup_module(void)
{
tekram_cleanup();
}
-
#endif /* MODULE */
diff --git a/drivers/net/irda/toshoboe.c b/drivers/net/irda/toshoboe.c
index d0dbaa4f7..55e0e5b84 100644
--- a/drivers/net/irda/toshoboe.c
+++ b/drivers/net/irda/toshoboe.c
@@ -95,6 +95,7 @@ static char *rcsid = "$Id: toshoboe.c,v 1.9 1999/06/29 14:21:06 root Exp $";
#include <linux/malloc.h>
#include <linux/init.h>
#include <linux/pci.h>
+#include <linux/rtnetlink.h>
#include <asm/system.h>
#include <asm/io.h>
@@ -122,7 +123,7 @@ static int max_baud = 4000000;
static void
toshoboe_stopchip (struct toshoboe_cb *self)
{
- DEBUG (4, __FUNCTION__ "()\n");
+ IRDA_DEBUG (4, __FUNCTION__ "()\n");
outb_p (0x0e, OBOE_REG_11);
@@ -143,7 +144,7 @@ static void
toshoboe_setbaud (struct toshoboe_cb *self, int baud)
{
unsigned long flags;
- DEBUG (4, __FUNCTION__ "()\n");
+ IRDA_DEBUG (4, __FUNCTION__ "()\n");
printk (KERN_WARNING "ToshOboe: seting baud to %d\n", baud);
@@ -212,7 +213,7 @@ toshoboe_startchip (struct toshoboe_cb *self)
{
__u32 physaddr;
- DEBUG (4, __FUNCTION__ "()\n");
+ IRDA_DEBUG (4, __FUNCTION__ "()\n");
outb_p (0, OBOE_LOCK);
@@ -241,7 +242,7 @@ toshoboe_startchip (struct toshoboe_cb *self)
static void
toshoboe_enablebm (struct toshoboe_cb *self)
{
- DEBUG (4, __FUNCTION__ "()\n");
+ IRDA_DEBUG (4, __FUNCTION__ "()\n");
pci_set_master (self->pdev);
}
@@ -250,7 +251,7 @@ static void
toshoboe_disablebm (struct toshoboe_cb *self)
{
__u8 command;
- DEBUG (4, __FUNCTION__ "()\n");
+ IRDA_DEBUG (4, __FUNCTION__ "()\n");
pci_read_config_byte (self->pdev, PCI_COMMAND, &command);
command &= ~PCI_COMMAND_MASTER;
@@ -265,7 +266,7 @@ toshoboe_initbuffs (struct toshoboe_cb *self)
int i;
unsigned long flags;
- DEBUG (4, __FUNCTION__ "()\n");
+ IRDA_DEBUG (4, __FUNCTION__ "()\n");
save_flags (flags);
cli ();
@@ -287,29 +288,27 @@ toshoboe_initbuffs (struct toshoboe_cb *self)
restore_flags (flags);
}
-
-
-
/*Transmit something */
static int
toshoboe_hard_xmit (struct sk_buff *skb, struct net_device *dev)
{
- struct irda_device *idev;
struct toshoboe_cb *self;
+ __u32 speed;
int mtt, len;
- idev = (struct irda_device *) dev->priv;
- ASSERT (idev != NULL, return 0;
- );
- ASSERT (idev->magic == IRDA_DEVICE_MAGIC, return 0;
- );
+ self = (struct toshoboe_cb *) dev->priv;
- self = idev->priv;
ASSERT (self != NULL, return 0;
);
- if (self->stopped)
+ /* Check if we need to change the speed */
+ if ((speed = irda_get_speed(skb)) != self->io.speed)
+ toshoboe_setbaud (self, speed);
+
+ if (self->stopped) {
+ dev_kfree_skb(skb);
return 0;
+ }
#ifdef ONETASK
if (self->txpending)
@@ -376,24 +375,18 @@ toshoboe_hard_xmit (struct sk_buff *skb, struct net_device *dev)
static void
toshoboe_interrupt (int irq, void *dev_id, struct pt_regs *regs)
{
- struct irda_device *idev = (struct irda_device *) dev_id;
- struct toshoboe_cb *self;
+ struct toshoboe_cb *self = (struct toshoboe_cb *) dev_id;
__u8 irqstat;
struct sk_buff *skb;
- if (idev == NULL)
+ if (self == NULL)
{
printk (KERN_WARNING "%s: irq %d for unknown device.\n",
driver_name, irq);
return;
}
- self = idev->priv;
-
- if (!self)
- return;
-
- DEBUG (4, __FUNCTION__ "()\n");
+ IRDA_DEBUG (4, __FUNCTION__ "()\n");
irqstat = inb_p (OBOE_ISR);
@@ -409,10 +402,10 @@ toshoboe_interrupt (int irq, void *dev_id, struct pt_regs *regs)
{
self->txpending--;
- idev->stats.tx_packets++;
+ self->stats.tx_packets++;
- idev->media_busy = FALSE;
- idev->netdev.tbusy = 0;
+ /* idev->media_busy = FALSE; */
+ self->netdev->tbusy = 0;
mark_bh (NET_BH);
}
@@ -441,8 +434,8 @@ toshoboe_interrupt (int irq, void *dev_id, struct pt_regs *regs)
skb_put (skb, len);
memcpy (skb->data, self->recv_bufs[self->rxs], len);
- idev->stats.rx_packets++;
- skb->dev = &idev->netdev;
+ self->stats.rx_packets++;
+ skb->dev = self->netdev;
skb->mac.raw = skb->data;
skb->protocol = htons (ETH_P_IRDA);
}
@@ -479,79 +472,18 @@ toshoboe_interrupt (int irq, void *dev_id, struct pt_regs *regs)
{
/*FIXME: I think this is a TX or RX error of some sort */
- idev->stats.tx_errors++;
- idev->stats.rx_errors++;
+ self->stats.tx_errors++;
+ self->stats.rx_errors++;
}
}
-
-
-/* Change the baud rate */
-static void
-toshoboe_change_speed (struct irda_device *idev, __u32 speed)
-{
- struct toshoboe_cb *self;
- DEBUG (4, __FUNCTION__ "()\n");
-
- ASSERT (idev != NULL, return;
- );
- ASSERT (idev->magic == IRDA_DEVICE_MAGIC, return;
- );
-
- self = idev->priv;
- ASSERT (self != NULL, return;
- );
-
-
- idev->io.baudrate = speed;
-
- if (self->stopped)
- return;
-
- toshoboe_setbaud (self, speed);
-
-}
-
-
-/* Check all xmit_tasks finished */
-static void
-toshoboe_wait_until_sent (struct irda_device *idev)
-{
- struct toshoboe_cb *self;
- int i;
-
- DEBUG (4, __FUNCTION__ "()\n");
-
- ASSERT (idev != NULL, return;
- );
- ASSERT (idev->magic == IRDA_DEVICE_MAGIC, return;
- );
-
- self = idev->priv;
- ASSERT (self != NULL, return;
- );
-
- if (self->stopped)
- return;
-
- for (i = 0; i < TX_SLOTS; ++i)
- {
- while (self->taskfile->xmit[i].control)
- {
- current->state = TASK_INTERRUPTIBLE;
- schedule_timeout (MSECS_TO_JIFFIES(60));
- }
- }
-
-}
-
static int
-toshoboe_is_receiving (struct irda_device *idev)
+toshoboe_is_receiving (struct toshoboe_cb *self)
{
- DEBUG (4, __FUNCTION__ "()\n");
+ IRDA_DEBUG (4, __FUNCTION__ "()\n");
/*FIXME Can't tell! */
return (FALSE);
@@ -561,7 +493,7 @@ toshoboe_is_receiving (struct irda_device *idev)
static int
toshoboe_net_init (struct net_device *dev)
{
- DEBUG (4, __FUNCTION__ "()\n");
+ IRDA_DEBUG (4, __FUNCTION__ "()\n");
/* Setup to be a normal IrDA network device driver */
irda_device_setup (dev);
@@ -607,30 +539,22 @@ toshoboe_initptrs (struct toshoboe_cb *self)
static int
toshoboe_net_open (struct net_device *dev)
{
- struct irda_device *idev;
struct toshoboe_cb *self;
- DEBUG (4, __FUNCTION__ "()\n");
+ IRDA_DEBUG (4, __FUNCTION__ "()\n");
ASSERT (dev != NULL, return -1;
);
- idev = (struct irda_device *) dev->priv;
-
- ASSERT (idev != NULL, return 0;
- );
- ASSERT (idev->magic == IRDA_DEVICE_MAGIC, return 0;
- );
+ self = (struct toshoboe_cb *) dev->priv;
- self = idev->priv;
ASSERT (self != NULL, return 0;
);
if (self->stopped)
return 0;
-
- if (request_irq (idev->io.irq, toshoboe_interrupt,
- SA_SHIRQ | SA_INTERRUPT, idev->name, (void *) idev))
+ if (request_irq (self->io.irq, toshoboe_interrupt,
+ SA_SHIRQ | SA_INTERRUPT, dev->name, (void *) self))
{
return -EAGAIN;
@@ -641,8 +565,17 @@ toshoboe_net_open (struct net_device *dev)
toshoboe_startchip (self);
toshoboe_initptrs (self);
- irda_device_net_open(dev);
-
+ /* Ready to play! */
+ dev->tbusy = 0;
+ dev->interrupt = 0;
+ dev->start = 1;
+
+ /*
+ * Open new IrLAP layer instance, now that everything should be
+ * initialized properly
+ */
+ self->irlap = irlap_open(dev, &self->qos);
+
self->open = 1;
MOD_INC_USE_COUNT;
@@ -654,30 +587,26 @@ toshoboe_net_open (struct net_device *dev)
static int
toshoboe_net_close (struct net_device *dev)
{
- struct irda_device *idev;
struct toshoboe_cb *self;
- DEBUG (4, __FUNCTION__ "()\n");
+ IRDA_DEBUG (4, __FUNCTION__ "()\n");
ASSERT (dev != NULL, return -1;
);
- idev = (struct irda_device *) dev->priv;
+ self = (struct toshoboe_cb *) dev->priv;
- ASSERT (idev != NULL, return 0;
- );
- ASSERT (idev->magic == IRDA_DEVICE_MAGIC, return 0;
- );
-
- irda_device_net_close(dev);
-
- self = idev->priv;
-
- ASSERT (self != NULL, return 0;
- );
+ /* Stop device */
+ dev->tbusy = 1;
+ dev->start = 0;
+
+ /* Stop and remove instance of IrLAP */
+ if (self->irlap)
+ irlap_close(self->irlap);
+ self->irlap = NULL;
self->open = 0;
- free_irq (idev->io.irq, (void *) idev);
+ free_irq (self->io.irq, (void *) self);
if (!self->stopped)
{
@@ -698,19 +627,11 @@ toshoboe_net_close (struct net_device *dev)
MODULE_PARM (max_baud, "i");
static int
-toshoboe_close (struct irda_device *idev)
+toshoboe_close (struct toshoboe_cb *self)
{
- struct toshoboe_cb *self;
int i;
- DEBUG (4, __FUNCTION__ "()\n");
-
- ASSERT (idev != NULL, return -1;
- );
- ASSERT (idev->magic == IRDA_DEVICE_MAGIC, return -1;
- );
-
- self = idev->priv;
+ IRDA_DEBUG (4, __FUNCTION__ "()\n");
ASSERT (self != NULL, return -1;
);
@@ -721,7 +642,7 @@ toshoboe_close (struct irda_device *idev)
toshoboe_disablebm (self);
}
- release_region (idev->io.iobase, idev->io.io_ext);
+ release_region (self->io.iobase, self->io.io_ext);
for (i = 0; i < TX_SLOTS; ++i)
@@ -736,14 +657,17 @@ toshoboe_close (struct irda_device *idev)
self->recv_bufs[i] = NULL;
}
+ if (self->netdev) {
+ /* Remove netdevice */
+ rtnl_lock();
+ unregister_netdevice(self->netdev);
+ rtnl_unlock();
+ }
kfree (self->taskfilebuf);
self->taskfilebuf = NULL;
self->taskfile = NULL;
-
- irda_device_close (idev);
-
return (0);
}
@@ -756,12 +680,12 @@ static int
toshoboe_open (struct pci_dev *pci_dev)
{
struct toshoboe_cb *self;
- struct irda_device *idev;
+ struct net_device *dev;
int i = 0;
int ok = 0;
+ int err;
-
- DEBUG (4, __FUNCTION__ "()\n");
+ IRDA_DEBUG (4, __FUNCTION__ "()\n");
while (dev_self[i])
i++;
@@ -790,21 +714,17 @@ toshoboe_open (struct pci_dev *pci_dev)
self->pdev = pci_dev;
self->base = pci_dev->resource[0].start;
- idev = &self->idev;
-
- /*Setup idev */
-
- idev->io.iobase = self->base;
- idev->io.irq = pci_dev->irq;
- idev->io.io_ext = CHIP_IO_EXTENT;
- idev->io.baudrate = 9600;
+ self->io.iobase = self->base;
+ self->io.irq = pci_dev->irq;
+ self->io.io_ext = CHIP_IO_EXTENT;
+ self->io.speed = 9600;
/* Lock the port that we need */
- i = check_region (idev->io.iobase, idev->io.io_ext);
+ i = check_region (self->io.iobase, self->io.io_ext);
if (i < 0)
{
- DEBUG (0, __FUNCTION__ "(), can't get iobase of 0x%03x\n",
- idev->io.iobase);
+ IRDA_DEBUG (0, __FUNCTION__ "(), can't get iobase of 0x%03x\n",
+ self->io.iobase);
dev_self[i] = NULL;
kfree (self);
@@ -813,57 +733,39 @@ toshoboe_open (struct pci_dev *pci_dev)
}
- irda_init_max_qos_capabilies (&idev->qos);
- idev->qos.baud_rate.bits = 0;
+ irda_init_max_qos_capabilies (&self->qos);
+ self->qos.baud_rate.bits = 0;
if (max_baud >= 2400)
- idev->qos.baud_rate.bits |= IR_2400;
+ self->qos.baud_rate.bits |= IR_2400;
/*if (max_baud>=4800) idev->qos.baud_rate.bits|=IR_4800; */
if (max_baud >= 9600)
- idev->qos.baud_rate.bits |= IR_9600;
+ self->qos.baud_rate.bits |= IR_9600;
if (max_baud >= 19200)
- idev->qos.baud_rate.bits |= IR_19200;
+ self->qos.baud_rate.bits |= IR_19200;
if (max_baud >= 115200)
- idev->qos.baud_rate.bits |= IR_115200;
+ self->qos.baud_rate.bits |= IR_115200;
#ifdef ENABLE_FAST
if (max_baud >= 576000)
- idev->qos.baud_rate.bits |= IR_576000;
+ self->qos.baud_rate.bits |= IR_576000;
if (max_baud >= 1152000)
- idev->qos.baud_rate.bits |= IR_1152000;
+ self->qos.baud_rate.bits |= IR_1152000;
if (max_baud >= 4000000)
- idev->qos.baud_rate.bits |= (IR_4000000 << 8);
+ self->qos.baud_rate.bits |= (IR_4000000 << 8);
#endif
- idev->qos.min_turn_time.bits = 0xff; /*FIXME: what does this do? */
+ self->qos.min_turn_time.bits = 0xff; /*FIXME: what does this do? */
- irda_qos_bits_to_value (&idev->qos);
+ irda_qos_bits_to_value (&self->qos);
- idev->flags = IFF_SIR | IFF_DMA | IFF_PIO;
+ self->flags = IFF_SIR | IFF_DMA | IFF_PIO;
#ifdef ENABLE_FAST
if (max_baud >= 576000)
- idev->flags |= IFF_FIR;
+ self->flags |= IFF_FIR;
#endif
- /* These aren't much use as we need to have a whole panoply of
- * buffers running */
-
- idev->rx_buff.flags = 0;
- idev->tx_buff.flags = 0;
- idev->rx_buff.truesize = 0;
- idev->rx_buff.truesize = 0;
-
- idev->change_speed = toshoboe_change_speed;
- idev->wait_until_sent = toshoboe_wait_until_sent;
- idev->is_receiving = toshoboe_is_receiving;
-
- idev->netdev.init = toshoboe_net_init;
- idev->netdev.hard_start_xmit = toshoboe_hard_xmit;
- idev->netdev.open = toshoboe_net_open;
- idev->netdev.stop = toshoboe_net_close;
-
-
/* Now setup the endless buffers we need */
self->txs = 0;
@@ -922,9 +824,32 @@ toshoboe_open (struct pci_dev *pci_dev)
}
- request_region (idev->io.iobase, idev->io.io_ext, driver_name);
+ request_region (self->io.iobase, self->io.io_ext, driver_name);
- irda_device_open (idev, driver_name, self);
+ if (!(dev = dev_alloc("irda%d", &err))) {
+ ERROR(__FUNCTION__ "(), dev_alloc() failed!\n");
+ return -ENOMEM;
+ }
+ /* dev_alloc doesn't clear the struct, so lets do a little hack */
+ memset(((__u8*)dev)+sizeof(char*),0,sizeof(struct net_device)-sizeof(char*));
+
+ dev->priv = (void *) self;
+ self->netdev = dev;
+
+ MESSAGE("IrDA: Registered device %s\n", dev->name);
+
+ dev->init = toshoboe_net_init;
+ dev->hard_start_xmit = toshoboe_hard_xmit;
+ dev->open = toshoboe_net_open;
+ dev->stop = toshoboe_net_close;
+
+ rtnl_lock();
+ err = register_netdevice(dev);
+ rtnl_unlock();
+ if (err) {
+ ERROR(__FUNCTION__ "(), register_netdev() failed!\n");
+ return -1;
+ }
printk (KERN_WARNING "ToshOboe: Using ");
#ifdef ONETASK
@@ -969,8 +894,7 @@ toshoboe_gotosleep (struct toshoboe_cb *self)
static void
toshoboe_wakeup (struct toshoboe_cb *self)
{
- struct irda_device *idev = &self->idev;
- struct net_device *dev = &idev->netdev;
+ struct net_device *dev = self->netdev;
unsigned long flags;
if (!self->stopped)
@@ -989,12 +913,10 @@ toshoboe_wakeup (struct toshoboe_cb *self)
toshoboe_enablebm (self);
toshoboe_startchip (self);
- toshoboe_setbaud (self, idev->io.baudrate);
+ toshoboe_setbaud (self, self->io.speed);
toshoboe_initptrs (self);
-
-
dev->tbusy = 0;
dev->interrupt = 0;
dev->start = 1;
@@ -1093,12 +1015,12 @@ toshoboe_cleanup (void)
{
int i;
- DEBUG (4, __FUNCTION__ "()\n");
+ IRDA_DEBUG (4, __FUNCTION__ "()\n");
for (i = 0; i < 4; i++)
{
if (dev_self[i])
- toshoboe_close (&(dev_self[i]->idev));
+ toshoboe_close (dev_self[i]);
}
#ifdef CONFIG_APM
diff --git a/drivers/net/irda/uircc.c b/drivers/net/irda/uircc.c
index 869ccd5d6..2726700bb 100644
--- a/drivers/net/irda/uircc.c
+++ b/drivers/net/irda/uircc.c
@@ -113,7 +113,7 @@ static void uircc_cleanup(void)
{
int i;
- DEBUG(4, __FUNCTION__ "()\n");
+ IRDA_DEBUG(4, __FUNCTION__ "()\n");
for (i=0; i < 4; i++) {
if (dev_self[i])
@@ -135,7 +135,7 @@ static int uircc_open(int i, unsigned int iobase, unsigned int iobase2,
struct irda_device *idev;
int ret;
- DEBUG(4, __FUNCTION__ "()\n");
+ IRDA_DEBUG(4, __FUNCTION__ "()\n");
if ((uircc_probe(iobase, iobase2, irq, dma)) == -1)
return -1;
@@ -168,14 +168,14 @@ static int uircc_open(int i, unsigned int iobase, unsigned int iobase2,
/* Lock the port that we need */
ret = check_region(idev->io.iobase, idev->io.io_ext);
if (ret < 0) {
- DEBUG(0, __FUNCTION__ "(), can't get iobase of 0x%03x\n",
+ IRDA_DEBUG(0, __FUNCTION__ "(), can't get iobase of 0x%03x\n",
idev->io.iobase);
/* uircc_cleanup( self->idev); */
return -ENODEV;
}
ret = check_region(idev->io.iobase2, idev->io.io_ext2);
if (ret < 0) {
- DEBUG(0, __FUNCTION__ "(), can't get iobase of 0x%03x\n",
+ IRDA_DEBUG(0, __FUNCTION__ "(), can't get iobase of 0x%03x\n",
idev->io.iobase2);
/* uircc_cleanup( self->idev); */
return -ENODEV;
@@ -235,7 +235,7 @@ static int uircc_close(struct irda_device *idev)
int iobase;
int status;
- DEBUG(4, __FUNCTION__ "()\n");
+ IRDA_DEBUG(4, __FUNCTION__ "()\n");
ASSERT(idev != NULL, return -1;);
ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return -1;);
@@ -252,11 +252,11 @@ static int uircc_close(struct irda_device *idev)
irport_stop(idev, idev->io.iobase2);
/* Release the PORT that this driver is using */
- DEBUG(4, __FUNCTION__ "(), Releasing Region %03x\n", idev->io.iobase);
+ IRDA_DEBUG(4, __FUNCTION__ "(), Releasing Region %03x\n", idev->io.iobase);
release_region(idev->io.iobase, idev->io.io_ext);
if (idev->io.iobase2) {
- DEBUG(4, __FUNCTION__ "(), Releasing Region %03x\n",
+ IRDA_DEBUG(4, __FUNCTION__ "(), Releasing Region %03x\n",
idev->io.iobase2);
release_region(idev->io.iobase2, idev->io.io_ext2);
}
@@ -278,13 +278,13 @@ static int uircc_probe(int iobase, int iobase2, int irq, int dma)
{
int version;
- DEBUG(4, __FUNCTION__ "()\n");
+ IRDA_DEBUG(4, __FUNCTION__ "()\n");
/* read the chip version, should be 0x03 */
version = inb(iobase+UIRCC_SR8);
if (version != 0x03) {
- DEBUG(0, __FUNCTION__ "(), Wrong chip version");
+ IRDA_DEBUG(0, __FUNCTION__ "(), Wrong chip version");
return -1;
}
printk(KERN_INFO "Sharp UIRCC IrDA driver loaded. Version: 0x%02x\n",
@@ -298,7 +298,7 @@ static int uircc_probe(int iobase, int iobase2, int irq, int dma)
outb(0, iobase+UIRCC_CR11);
outb(0, iobase+UIRCC_CR9);
- DEBUG(0, __FUNCTION__ "(), sr15=%#x\n", inb(iobase+UIRCC_SR15));
+ IRDA_DEBUG(0, __FUNCTION__ "(), sr15=%#x\n", inb(iobase+UIRCC_SR15));
/* Enable DMA single mode */
outb(UIRCC_CR1_RX_DMA|UIRCC_CR1_TX_DMA|UIRCC_CR1_MUST_SET,
@@ -325,7 +325,7 @@ static void uircc_change_speed(struct irda_device *idev, __u32 speed)
int modem = UIRCC_CR10_SIR;
int status;
- DEBUG(0, __FUNCTION__ "()\n");
+ IRDA_DEBUG(0, __FUNCTION__ "()\n");
/* Just test the high speed stuff */
/*speed = 4000000;*/
@@ -358,11 +358,11 @@ static void uircc_change_speed(struct irda_device *idev, __u32 speed)
break;
case 576000:
- DEBUG(0, __FUNCTION__ "(), handling baud of 576000\n");
+ IRDA_DEBUG(0, __FUNCTION__ "(), handling baud of 576000\n");
break;
case 1152000:
- DEBUG(0, __FUNCTION__ "(), handling baud of 1152000\n");
+ IRDA_DEBUG(0, __FUNCTION__ "(), handling baud of 1152000\n");
break;
case 4000000:
irport_stop(idev, idev->io.iobase2);
@@ -371,7 +371,7 @@ static void uircc_change_speed(struct irda_device *idev, __u32 speed)
uircc_toshiba_cmd(&status, 0xffff, 0x001b, 0x0001);
modem = UIRCC_CR10_FIR;
- DEBUG(0, __FUNCTION__ "(), handling baud of 4000000\n");
+ IRDA_DEBUG(0, __FUNCTION__ "(), handling baud of 4000000\n");
/* Set self pole address */
//outb(0xfe, iobase+UIRCC_CR8);
@@ -379,7 +379,7 @@ static void uircc_change_speed(struct irda_device *idev, __u32 speed)
/* outb(0x10, iobase+UIRCC_CR11); */
break;
default:
- DEBUG( 0, __FUNCTION__ "(), unknown baud rate of %d\n", speed);
+ IRDA_DEBUG( 0, __FUNCTION__ "(), unknown baud rate of %d\n", speed);
break;
}
@@ -419,7 +419,7 @@ static int uircc_hard_xmit(struct sk_buff *skb, struct net_device *dev)
iobase = idev->io.iobase;
- DEBUG(4, __FUNCTION__ "(%ld), skb->len=%d\n", jiffies, (int) skb->len);
+ IRDA_DEBUG(4, __FUNCTION__ "(%ld), skb->len=%d\n", jiffies, (int) skb->len);
/* Reset carrier latch */
/*outb(0x02, iobase+UIRCC_CR0);*/
@@ -429,7 +429,7 @@ static int uircc_hard_xmit(struct sk_buff *skb, struct net_device *dev)
return irport_hard_xmit(skb, dev);
}
- DEBUG(0, __FUNCTION__ "(), sr0=%#x, sr1=%#x, sr2=%#x, sr3=%#x, sr10=%#x, sr11=%#x\n",
+ IRDA_DEBUG(0, __FUNCTION__ "(), sr0=%#x, sr1=%#x, sr2=%#x, sr3=%#x, sr10=%#x, sr11=%#x\n",
inb(iobase+UIRCC_SR0), inb(iobase+UIRCC_SR3),
inb(iobase+UIRCC_SR2), inb(iobase+UIRCC_SR3),
inb(iobase+UIRCC_SR10), inb(iobase+UIRCC_SR11));
@@ -473,7 +473,7 @@ static void uircc_dma_write(struct irda_device *idev, int iobase)
{
struct uircc_cb *self;
- DEBUG(4, __FUNCTION__ "()\n");
+ IRDA_DEBUG(4, __FUNCTION__ "()\n");
ASSERT(idev != NULL, return;);
ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;);
@@ -519,7 +519,7 @@ static void uircc_dma_xmit_complete( struct irda_device *idev, int underrun)
int iobase;
int len;
- DEBUG(4, __FUNCTION__ "()\n");
+ IRDA_DEBUG(4, __FUNCTION__ "()\n");
ASSERT(idev != NULL, return;);
ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;);
@@ -535,7 +535,7 @@ static void uircc_dma_xmit_complete( struct irda_device *idev, int underrun)
len = inb(iobase+UIRCC_SR4); /* Low byte */
len |= inb(iobase+UIRCC_SR5) << 8; /* High byte */
- DEBUG(4, __FUNCTION__ "(), sent %d bytes\n", len);
+ IRDA_DEBUG(4, __FUNCTION__ "(), sent %d bytes\n", len);
/* Disable transmit */
self->cr3 &= ~UIRCC_CR3_XMIT_EN;
@@ -576,7 +576,7 @@ static int uircc_dma_receive(struct irda_device *idev)
ASSERT(idev != NULL, return -1;);
ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return -1;);
- DEBUG(4, __FUNCTION__ "\n");
+ IRDA_DEBUG(4, __FUNCTION__ "\n");
self = idev->priv;
iobase= idev->io.iobase;
@@ -614,7 +614,7 @@ static int uircc_dma_receive(struct irda_device *idev)
self->cr3 = (UIRCC_CR3_RECV_EN|UIRCC_CR3_RX_CRC_EN);
outb(self->cr3, iobase+UIRCC_CR3);
#endif
- DEBUG(4, __FUNCTION__ "(), cr3=%#x\n", self->cr3);
+ IRDA_DEBUG(4, __FUNCTION__ "(), cr3=%#x\n", self->cr3);
/* Address check? */
@@ -636,11 +636,11 @@ static int uircc_dma_receive_complete(struct irda_device *idev, int iobase)
self = idev->priv;
- DEBUG(0, __FUNCTION__ "()\n");
+ IRDA_DEBUG(0, __FUNCTION__ "()\n");
/* Check for CRC or framing error */
if (inb(iobase+UIRCC_SR0) & UIRCC_SR0_RX_CRCFRM) {
- DEBUG(0, __FUNCTION__ "(), CRC or FRAME error\n");
+ IRDA_DEBUG(0, __FUNCTION__ "(), CRC or FRAME error\n");
return -1;
}
@@ -651,7 +651,7 @@ static int uircc_dma_receive_complete(struct irda_device *idev, int iobase)
len = inb(iobase+UIRCC_SR4); /* Low byte */
len |= inb(iobase+UIRCC_SR5) << 8; /* High byte */
- DEBUG(0, __FUNCTION__ "(), len=%d\n", len);
+ IRDA_DEBUG(0, __FUNCTION__ "(), len=%d\n", len);
/* Receiving disable */
self->cr3 &= ~UIRCC_CR3_RECV_EN;
@@ -716,12 +716,12 @@ static void uircc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
/* Read interrupt status */
sr3 = inb( iobase+UIRCC_SR3);
if (!sr3) {
- DEBUG(4,"**\n");
+ IRDA_DEBUG(4,"**\n");
return;
}
idev->netdev.interrupt = 1;
- DEBUG(4, __FUNCTION__ "(), sr3=%#x, sr2=%#x, sr10=%#x\n",
+ IRDA_DEBUG(4, __FUNCTION__ "(), sr3=%#x, sr2=%#x, sr10=%#x\n",
inb( iobase+UIRCC_SR3), inb( iobase+UIRCC_SR2),
inb( iobase+UIRCC_SR10));
@@ -750,7 +750,7 @@ static void uircc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
iobase+UIRCC_CR11);
break;
default:
- DEBUG(0, __FUNCTION__ "(), unknown interrupt status=%#x\n",
+ IRDA_DEBUG(0, __FUNCTION__ "(), unknown interrupt status=%#x\n",
sr3);
break;
}
@@ -800,7 +800,7 @@ static int uircc_is_receiving( struct irda_device *idev)
*/
static int uircc_net_init( struct net_device *dev)
{
- DEBUG( 4, __FUNCTION__ "()\n");
+ IRDA_DEBUG( 4, __FUNCTION__ "()\n");
/* Setup to be a normal IrDA network device driver */
irda_device_setup(dev);
@@ -822,7 +822,7 @@ static int uircc_net_open(struct net_device *dev)
struct irda_device *idev;
int iobase;
- DEBUG( 4, __FUNCTION__ "()\n");
+ IRDA_DEBUG( 4, __FUNCTION__ "()\n");
ASSERT(dev != NULL, return -1;);
idev = (struct irda_device *) dev->priv;
@@ -866,7 +866,7 @@ static int uircc_net_close(struct net_device *dev)
struct irda_device *idev;
int iobase;
- DEBUG(4, __FUNCTION__ "()\n");
+ IRDA_DEBUG(4, __FUNCTION__ "()\n");
ASSERT(dev != NULL, return -1;);
idev = (struct irda_device *) dev->priv;
diff --git a/drivers/net/irda/w83977af_ir.c b/drivers/net/irda/w83977af_ir.c
index 32e965275..422f691ab 100644
--- a/drivers/net/irda/w83977af_ir.c
+++ b/drivers/net/irda/w83977af_ir.c
@@ -6,7 +6,7 @@
* Status: Experimental.
* Author: Paul VanderSpek
* Created at: Wed Nov 4 11:46:16 1998
- * Modified at: Wed Aug 11 09:27:54 1999
+ * Modified at: Wed Oct 20 00:08:30 1999
* Modified by: Dag Brattli <dagb@cs.uit.no>
*
* Copyright (c) 1998-1999 Dag Brattli <dagb@cs.uit.no>
@@ -49,6 +49,7 @@
#include <linux/delay.h>
#include <linux/malloc.h>
#include <linux/init.h>
+#include <linux/rtnetlink.h>
#include <asm/io.h>
#include <asm/dma.h>
@@ -83,17 +84,16 @@ static struct w83977af_ir *dev_self[] = { NULL, NULL, NULL, NULL};
/* Some prototypes */
static int w83977af_open(int i, unsigned int iobase, unsigned int irq,
unsigned int dma);
-static int w83977af_close(struct irda_device *idev);
+static int w83977af_close(struct w83977af_ir *self);
static int w83977af_probe(int iobase, int irq, int dma);
-static int w83977af_dma_receive(struct irda_device *idev);
-static int w83977af_dma_receive_complete(struct irda_device *idev);
+static int w83977af_dma_receive(struct w83977af_ir *self);
+static int w83977af_dma_receive_complete(struct w83977af_ir *self);
static int w83977af_hard_xmit(struct sk_buff *skb, struct net_device *dev);
static int w83977af_pio_write(int iobase, __u8 *buf, int len, int fifo_size);
-static void w83977af_dma_write(struct irda_device *idev, int iobase);
-static void w83977af_change_speed(struct irda_device *idev, __u32 speed);
+static void w83977af_dma_write(struct w83977af_ir *self, int iobase);
+static void w83977af_change_speed(struct w83977af_ir *self, __u32 speed);
static void w83977af_interrupt(int irq, void *dev_id, struct pt_regs *regs);
-static void w83977af_wait_until_sent(struct irda_device *idev);
-static int w83977af_is_receiving(struct irda_device *idev);
+static int w83977af_is_receiving(struct w83977af_ir *self);
static int w83977af_net_init(struct net_device *dev);
static int w83977af_net_open(struct net_device *dev);
@@ -109,13 +109,13 @@ int __init w83977af_init(void)
{
int i;
- DEBUG(0, __FUNCTION__ "()\n");
+ IRDA_DEBUG(0, __FUNCTION__ "()\n");
for (i=0; (io[i] < 2000) && (i < 4); i++) {
int ioaddr = io[i];
if (check_region(ioaddr, CHIP_IO_EXTENT) < 0)
continue;
- if (w83977af_open( i, io[i], irq[i], dma[i]) == 0)
+ if (w83977af_open(i, io[i], irq[i], dma[i]) == 0)
return 0;
}
return -ENODEV;
@@ -132,11 +132,11 @@ void w83977af_cleanup(void)
{
int i;
- DEBUG(4, __FUNCTION__ "()\n");
+ IRDA_DEBUG(4, __FUNCTION__ "()\n");
for (i=0; i < 4; i++) {
if (dev_self[i])
- w83977af_close(&(dev_self[i]->idev));
+ w83977af_close(dev_self[i]);
}
}
#endif /* MODULE */
@@ -147,14 +147,15 @@ void w83977af_cleanup(void)
* Open driver instance
*
*/
-int w83977af_open( int i, unsigned int iobase, unsigned int irq,
- unsigned int dma)
+int w83977af_open(int i, unsigned int iobase, unsigned int irq,
+ unsigned int dma)
{
- struct irda_device *idev;
+ struct net_device *dev;
struct w83977af_ir *self;
int ret;
+ int err;
- DEBUG( 0, __FUNCTION__ "()\n");
+ IRDA_DEBUG(0, __FUNCTION__ "()\n");
if (w83977af_probe(iobase, irq, dma) == -1)
return -1;
@@ -173,83 +174,107 @@ int w83977af_open( int i, unsigned int iobase, unsigned int irq,
/* Need to store self somewhere */
dev_self[i] = self;
- idev = &self->idev;
-
/* Initialize IO */
- idev->io.iobase = iobase;
- idev->io.irq = irq;
- idev->io.io_ext = CHIP_IO_EXTENT;
- idev->io.dma = dma;
- idev->io.fifo_size = 32;
+ self->io.iobase = iobase;
+ self->io.irq = irq;
+ self->io.io_ext = CHIP_IO_EXTENT;
+ self->io.dma = dma;
+ self->io.fifo_size = 32;
/* Lock the port that we need */
- ret = check_region(idev->io.iobase, idev->io.io_ext);
+ ret = check_region(self->io.iobase, self->io.io_ext);
if (ret < 0) {
- DEBUG( 0, __FUNCTION__ "(), can't get iobase of 0x%03x\n",
- idev->io.iobase);
- /* w83977af_cleanup( self->idev); */
+ IRDA_DEBUG(0, __FUNCTION__ "(), can't get iobase of 0x%03x\n",
+ self->io.iobase);
+ /* w83977af_cleanup( self); */
return -ENODEV;
}
- request_region(idev->io.iobase, idev->io.io_ext, idev->name);
+ request_region(self->io.iobase, self->io.io_ext, driver_name);
/* Initialize QoS for this device */
- irda_init_max_qos_capabilies(&idev->qos);
+ irda_init_max_qos_capabilies(&self->qos);
/* The only value we must override it the baudrate */
/* FIXME: The HP HDLS-1100 does not support 1152000! */
- idev->qos.baud_rate.bits = IR_9600|IR_19200|IR_38400|IR_57600|
+ self->qos.baud_rate.bits = IR_9600|IR_19200|IR_38400|IR_57600|
IR_115200|IR_576000|IR_1152000|(IR_4000000 << 8);
/* The HP HDLS-1100 needs 1 ms according to the specs */
- idev->qos.min_turn_time.bits = qos_mtt_bits;
- irda_qos_bits_to_value(&idev->qos);
+ self->qos.min_turn_time.bits = qos_mtt_bits;
+ irda_qos_bits_to_value(&self->qos);
- idev->flags = IFF_FIR|IFF_MIR|IFF_SIR|IFF_DMA|IFF_PIO;
-
- /* Specify which buffer allocation policy we need */
- idev->rx_buff.flags = GFP_KERNEL | GFP_DMA;
- idev->tx_buff.flags = GFP_KERNEL | GFP_DMA;
+ self->flags = IFF_FIR|IFF_MIR|IFF_SIR|IFF_DMA|IFF_PIO;
/* Max DMA buffer size needed = (data_size + 6) * (window_size) + 6; */
- idev->rx_buff.truesize = 14384;
- idev->tx_buff.truesize = 4000;
+ self->rx_buff.truesize = 14384;
+ self->tx_buff.truesize = 4000;
- /* Initialize callbacks */
- idev->change_speed = w83977af_change_speed;
- idev->wait_until_sent = w83977af_wait_until_sent;
- idev->is_receiving = w83977af_is_receiving;
+ /* Allocate memory if needed */
+ if (self->rx_buff.truesize > 0) {
+ self->rx_buff.head = (__u8 *) kmalloc(self->rx_buff.truesize,
+ GFP_KERNEL|GFP_DMA);
+ if (self->rx_buff.head == NULL)
+ return -ENOMEM;
+ memset(self->rx_buff.head, 0, self->rx_buff.truesize);
+ }
+ if (self->tx_buff.truesize > 0) {
+ self->tx_buff.head = (__u8 *) kmalloc(self->tx_buff.truesize,
+ GFP_KERNEL|GFP_DMA);
+ if (self->tx_buff.head == NULL) {
+ kfree(self->rx_buff.head);
+ return -ENOMEM;
+ }
+ memset(self->tx_buff.head, 0, self->tx_buff.truesize);
+ }
+
+ self->rx_buff.in_frame = FALSE;
+ self->rx_buff.state = OUTSIDE_FRAME;
+ self->tx_buff.data = self->tx_buff.head;
+ self->rx_buff.data = self->rx_buff.head;
+
+ if (!(dev = dev_alloc("irda%d", &err))) {
+ ERROR(__FUNCTION__ "(), dev_alloc() failed!\n");
+ return -ENOMEM;
+ }
+ /* dev_alloc doesn't clear the struct, so lets do a little hack */
+ memset(((__u8*)dev)+sizeof(char*),0,sizeof(struct net_device)-sizeof(char*));
+
+ dev->priv = (void *) self;
+ self->netdev = dev;
/* Override the network functions we need to use */
- idev->netdev.init = w83977af_net_init;
- idev->netdev.hard_start_xmit = w83977af_hard_xmit;
- idev->netdev.open = w83977af_net_open;
- idev->netdev.stop = w83977af_net_close;
+ dev->init = w83977af_net_init;
+ dev->hard_start_xmit = w83977af_hard_xmit;
+ dev->open = w83977af_net_open;
+ dev->stop = w83977af_net_close;
+
+ rtnl_lock();
+ err = register_netdev(dev);
+ rtnl_unlock();
+ if (err) {
+ ERROR(__FUNCTION__ "(), register_netdev() failed!\n");
+ return -1;
+ }
- /* Open the IrDA device */
- irda_device_open(idev, driver_name, self);
+ MESSAGE("IrDA: Registered device %s\n", dev->name);
return 0;
}
/*
- * Function w83977af_close (idev)
+ * Function w83977af_close (self)
*
* Close driver instance
*
*/
-static int w83977af_close( struct irda_device *idev)
+static int w83977af_close(struct w83977af_ir *self)
{
- struct w83977af_ir *self;
int iobase;
- DEBUG(0, __FUNCTION__ "()\n");
-
- ASSERT(idev != NULL, return -1;);
- ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return -1;);
+ IRDA_DEBUG(0, __FUNCTION__ "()\n");
- iobase = idev->io.iobase;
- self = (struct w83977af_ir *) idev->priv;
+ iobase = self->io.iobase;
#ifdef CONFIG_USE_W977_PNP
/* enter PnP configuration mode */
@@ -262,12 +287,24 @@ static int w83977af_close( struct irda_device *idev)
w977_efm_exit();
#endif /* CONFIG_USE_W977_PNP */
+
+ /* Remove netdevice */
+ if (self->netdev) {
+ rtnl_lock();
+ unregister_netdev(self->netdev);
+ rtnl_unlock();
+ }
+
/* Release the PORT that this driver is using */
- DEBUG(0 , __FUNCTION__ "(), Releasing Region %03x\n",
- idev->io.iobase);
- release_region(idev->io.iobase, idev->io.io_ext);
+ IRDA_DEBUG(0 , __FUNCTION__ "(), Releasing Region %03x\n",
+ self->io.iobase);
+ release_region(self->io.iobase, self->io.io_ext);
- irda_device_close(idev);
+ if (self->tx_buff.head)
+ kfree(self->tx_buff.head);
+
+ if (self->rx_buff.head)
+ kfree(self->rx_buff.head);
kfree(self);
@@ -284,7 +321,7 @@ int w83977af_probe( int iobase, int irq, int dma)
{
int version;
- DEBUG( 0, __FUNCTION__ "()\n");
+ IRDA_DEBUG( 0, __FUNCTION__ "()\n");
#ifdef CONFIG_USE_W977_PNP
/* Enter PnP configuration mode */
w977_efm_enter();
@@ -333,7 +370,7 @@ int w83977af_probe( int iobase, int irq, int dma)
/* Should be 0x1? */
if (0x10 != (version & 0xf0)) {
- DEBUG( 0, __FUNCTION__ "(), Wrong chip version");
+ IRDA_DEBUG( 0, __FUNCTION__ "(), Wrong chip version");
return -1;
}
@@ -365,30 +402,21 @@ int w83977af_probe( int iobase, int irq, int dma)
switch_bank(iobase, SET7);
outb(0x40, iobase+7);
- DEBUG(0, "W83977AF (IR) driver loaded. Version: 0x%02x\n", version);
+ IRDA_DEBUG(0, "W83977AF (IR) driver loaded. Version: 0x%02x\n", version);
return 0;
}
-/*
- * Function w83977af_change_speed (idev, baud)
- *
- * Change the speed of the device
- *
- */
-void w83977af_change_speed(struct irda_device *idev, __u32 speed)
+void w83977af_change_speed(struct w83977af_ir *self, __u32 speed)
{
int ir_mode = HCR_SIR;
int iobase;
__u8 set;
- ASSERT(idev != NULL, return;);
- ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;);
-
- iobase = idev->io.iobase;
+ iobase = self->io.iobase;
/* Update accounting for new speed */
- idev->io.baudrate = speed;
+ self->io.speed = speed;
/* Save current bank */
set = inb(iobase+SSR);
@@ -409,19 +437,19 @@ void w83977af_change_speed(struct irda_device *idev, __u32 speed)
case 115200: outb(0x01, iobase+ABLL); break;
case 576000:
ir_mode = HCR_MIR_576;
- DEBUG(0, __FUNCTION__ "(), handling baud of 576000\n");
+ IRDA_DEBUG(0, __FUNCTION__ "(), handling baud of 576000\n");
break;
case 1152000:
ir_mode = HCR_MIR_1152;
- DEBUG(0, __FUNCTION__ "(), handling baud of 1152000\n");
+ IRDA_DEBUG(0, __FUNCTION__ "(), handling baud of 1152000\n");
break;
case 4000000:
ir_mode = HCR_FIR;
- DEBUG(0, __FUNCTION__ "(), handling baud of 4000000\n");
+ IRDA_DEBUG(0, __FUNCTION__ "(), handling baud of 4000000\n");
break;
default:
ir_mode = HCR_FIR;
- DEBUG(0, __FUNCTION__ "(), unknown baud rate of %d\n", speed);
+ IRDA_DEBUG(0, __FUNCTION__ "(), unknown baud rate of %d\n", speed);
break;
}
@@ -440,13 +468,13 @@ void w83977af_change_speed(struct irda_device *idev, __u32 speed)
outb(UFR_EN_FIFO, iobase+UFR); /* First we must enable FIFO */
outb(0xa7, iobase+UFR);
- idev->netdev.tbusy = 0;
+ self->netdev->tbusy = 0;
/* Enable some interrupts so we can receive frames */
switch_bank(iobase, SET0);
if (speed > PIO_MAX_SPEED) {
outb(ICR_EFSFI, iobase+ICR);
- w83977af_dma_receive(idev);
+ w83977af_dma_receive(self);
} else
outb(ICR_ERBRI, iobase+ICR);
@@ -462,32 +490,34 @@ void w83977af_change_speed(struct irda_device *idev, __u32 speed)
*/
int w83977af_hard_xmit(struct sk_buff *skb, struct net_device *dev)
{
- struct irda_device *idev;
+ struct w83977af_ir *self;
+ __u32 speed;
int iobase;
__u8 set;
int mtt;
- idev = (struct irda_device *) dev->priv;
+ self = (struct w83977af_ir *) dev->priv;
- ASSERT(idev != NULL, return 0;);
- ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return 0;);
+ iobase = self->io.iobase;
- iobase = idev->io.iobase;
-
- DEBUG(4, __FUNCTION__ "(%ld), skb->len=%d\n", jiffies, (int) skb->len);
+ IRDA_DEBUG(4, __FUNCTION__ "(%ld), skb->len=%d\n", jiffies, (int) skb->len);
/* Lock transmit buffer */
if (irda_lock((void *) &dev->tbusy) == FALSE)
return -EBUSY;
+ /* Check if we need to change the speed */
+ if ((speed = irda_get_speed(skb)) != self->io.speed)
+ w83977af_change_speed(self, speed);
+
/* Save current set */
set = inb(iobase+SSR);
/* Decide if we should use PIO or DMA transfer */
- if (idev->io.baudrate > PIO_MAX_SPEED) {
- idev->tx_buff.data = idev->tx_buff.head;
- memcpy(idev->tx_buff.data, skb->data, skb->len);
- idev->tx_buff.len = skb->len;
+ if (self->io.speed > PIO_MAX_SPEED) {
+ self->tx_buff.data = self->tx_buff.head;
+ memcpy(self->tx_buff.data, skb->data, skb->len);
+ self->tx_buff.len = skb->len;
mtt = irda_get_mtt(skb);
#ifdef CONFIG_USE_INTERNAL_TIMER
@@ -502,28 +532,28 @@ int w83977af_hard_xmit(struct sk_buff *skb, struct net_device *dev)
/* Start timer */
outb(IR_MSL_EN_TMR, iobase+IR_MSL);
- idev->io.direction = IO_XMIT;
+ self->io.direction = IO_XMIT;
/* Enable timer interrupt */
switch_bank(iobase, SET0);
outb(ICR_ETMRI, iobase+ICR);
} else {
#endif
- DEBUG(4,__FUNCTION__ "(%ld), mtt=%d\n", jiffies, mtt);
+ IRDA_DEBUG(4,__FUNCTION__ "(%ld), mtt=%d\n", jiffies, mtt);
if (mtt)
udelay(mtt);
/* Enable DMA interrupt */
switch_bank(iobase, SET0);
outb(ICR_EDMAI, iobase+ICR);
- w83977af_dma_write(idev, iobase);
+ w83977af_dma_write(self, iobase);
#ifdef CONFIG_USE_INTERNAL_TIMER
}
#endif
} else {
- idev->tx_buff.data = idev->tx_buff.head;
- idev->tx_buff.len = async_wrap_skb(skb, idev->tx_buff.data,
- idev->tx_buff.truesize);
+ self->tx_buff.data = self->tx_buff.head;
+ self->tx_buff.len = async_wrap_skb(skb, self->tx_buff.data,
+ self->tx_buff.truesize);
/* Add interrupt on tx low level (will fire immediately) */
switch_bank(iobase, SET0);
@@ -538,19 +568,19 @@ int w83977af_hard_xmit(struct sk_buff *skb, struct net_device *dev)
}
/*
- * Function w83977af_dma_write (idev, iobase)
+ * Function w83977af_dma_write (self, iobase)
*
* Send frame using DMA
*
*/
-static void w83977af_dma_write(struct irda_device *idev, int iobase)
+static void w83977af_dma_write(struct w83977af_ir *self, int iobase)
{
__u8 set;
#ifdef CONFIG_NETWINDER_TX_DMA_PROBLEMS
unsigned long flags;
__u8 hcr;
#endif
- DEBUG(4, __FUNCTION__ "(), len=%d\n", idev->tx_buff.len);
+ IRDA_DEBUG(4, __FUNCTION__ "(), len=%d\n", self->tx_buff.len);
/* Save current set */
set = inb(iobase+SSR);
@@ -566,23 +596,23 @@ static void w83977af_dma_write(struct irda_device *idev, int iobase)
save_flags(flags);
cli();
- disable_dma(idev->io.dma);
- clear_dma_ff(idev->io.dma);
- set_dma_mode(idev->io.dma, DMA_MODE_READ);
- set_dma_addr(idev->io.dma, virt_to_bus(idev->tx_buff.data));
- set_dma_count(idev->io.dma, idev->tx_buff.len);
+ disable_dma(self->io.dma);
+ clear_dma_ff(self->io.dma);
+ set_dma_mode(self->io.dma, DMA_MODE_READ);
+ set_dma_addr(self->io.dma, virt_to_bus(self->tx_buff.data));
+ set_dma_count(self->io.dma, self->tx_buff.len);
#else
- setup_dma(idev->io.dma, idev->tx_buff.data, idev->tx_buff.len,
+ setup_dma(self->io.dma, self->tx_buff.data, self->tx_buff.len,
DMA_MODE_WRITE);
#endif
- idev->io.direction = IO_XMIT;
+ self->io.direction = IO_XMIT;
/* Enable DMA */
switch_bank(iobase, SET0);
#ifdef CONFIG_NETWINDER_TX_DMA_PROBLEMS
hcr = inb(iobase+HCR);
outb(hcr | HCR_EN_DMA, iobase+HCR);
- enable_dma(idev->io.dma);
+ enable_dma(self->io.dma);
restore_flags(flags);
#else
outb(inb(iobase+HCR) | HCR_EN_DMA | HCR_TX_WT, iobase+HCR);
@@ -603,17 +633,17 @@ static int w83977af_pio_write(int iobase, __u8 *buf, int len, int fifo_size)
int actual = 0;
__u8 set;
- DEBUG(4, __FUNCTION__ "()\n");
+ IRDA_DEBUG(4, __FUNCTION__ "()\n");
/* Save current bank */
set = inb(iobase+SSR);
switch_bank(iobase, SET0);
if (!(inb_p(iobase+USR) & USR_TSRE)) {
- DEBUG(4, __FUNCTION__ "(), warning, FIFO not empty yet!\n");
+ IRDA_DEBUG(4, __FUNCTION__ "(), warning, FIFO not empty yet!\n");
fifo_size -= 17;
- DEBUG(4, __FUNCTION__ "%d bytes left in tx fifo\n", fifo_size);
+ IRDA_DEBUG(4, __FUNCTION__ "%d bytes left in tx fifo\n", fifo_size);
}
/* Fill FIFO with current frame */
@@ -622,7 +652,7 @@ static int w83977af_pio_write(int iobase, __u8 *buf, int len, int fifo_size)
outb(buf[actual++], iobase+TBR);
}
- DEBUG(4, __FUNCTION__ "(), fifo_size %d ; %d sent of %d\n",
+ IRDA_DEBUG(4, __FUNCTION__ "(), fifo_size %d ; %d sent of %d\n",
fifo_size, actual, len);
/* Restore bank */
@@ -632,23 +662,22 @@ static int w83977af_pio_write(int iobase, __u8 *buf, int len, int fifo_size)
}
/*
- * Function w83977af_dma_xmit_complete (idev)
+ * Function w83977af_dma_xmit_complete (self)
*
* The transfer of a frame in finished. So do the necessary things
*
*
*/
-void w83977af_dma_xmit_complete(struct irda_device *idev)
+void w83977af_dma_xmit_complete(struct w83977af_ir *self)
{
int iobase;
__u8 set;
- DEBUG(4, __FUNCTION__ "(%ld)\n", jiffies);
+ IRDA_DEBUG(4, __FUNCTION__ "(%ld)\n", jiffies);
- ASSERT(idev != NULL, return;);
- ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;);
+ ASSERT(self != NULL, return;);
- iobase = idev->io.iobase;
+ iobase = self->io.iobase;
/* Save current set */
set = inb(iobase+SSR);
@@ -659,19 +688,18 @@ void w83977af_dma_xmit_complete(struct irda_device *idev)
/* Check for underrrun! */
if (inb(iobase+AUDR) & AUDR_UNDR) {
- DEBUG(0, __FUNCTION__ "(), Transmit underrun!\n");
+ IRDA_DEBUG(0, __FUNCTION__ "(), Transmit underrun!\n");
- idev->stats.tx_errors++;
- idev->stats.tx_fifo_errors++;
+ self->stats.tx_errors++;
+ self->stats.tx_fifo_errors++;
/* Clear bit, by writing 1 to it */
outb(AUDR_UNDR, iobase+AUDR);
} else
- idev->stats.tx_packets++;
+ self->stats.tx_packets++;
/* Unlock tx_buff and request another frame */
- idev->netdev.tbusy = 0; /* Unlock */
- idev->media_busy = FALSE;
+ self->netdev->tbusy = 0; /* Unlock */
/* Tell the network layer, that we want more frames */
mark_bh(NET_BH);
@@ -681,15 +709,14 @@ void w83977af_dma_xmit_complete(struct irda_device *idev)
}
/*
- * Function w83977af_dma_receive (idev)
+ * Function w83977af_dma_receive (self)
*
* Get ready for receiving a frame. The device will initiate a DMA
* if it starts to receive a frame.
*
*/
-int w83977af_dma_receive(struct irda_device *idev)
+int w83977af_dma_receive(struct w83977af_ir *self)
{
- struct w83977af_ir *self;
int iobase;
__u8 set;
#ifdef CONFIG_NETWINDER_RX_DMA_PROBLEMS
@@ -697,13 +724,11 @@ int w83977af_dma_receive(struct irda_device *idev)
__u8 hcr;
#endif
- ASSERT(idev != NULL, return -1;);
- ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return -1;);
+ ASSERT(self != NULL, return -1;);
- DEBUG(4, __FUNCTION__ "\n");
+ IRDA_DEBUG(4, __FUNCTION__ "\n");
- self = idev->priv;
- iobase= idev->io.iobase;
+ iobase= self->io.iobase;
/* Save current set */
set = inb(iobase+SSR);
@@ -717,20 +742,20 @@ int w83977af_dma_receive(struct irda_device *idev)
outb((inb(iobase+ADCR1) & ~ADCR1_D_CHSW)/*|ADCR1_DMA_F*/|ADCR1_ADV_SL,
iobase+ADCR1);
- idev->io.direction = IO_RECV;
- idev->rx_buff.data = idev->rx_buff.head;
+ self->io.direction = IO_RECV;
+ self->rx_buff.data = self->rx_buff.head;
#ifdef CONFIG_NETWINDER_RX_DMA_PROBLEMS
save_flags(flags);
cli();
- disable_dma(idev->io.dma);
- clear_dma_ff(idev->io.dma);
- set_dma_mode(idev->io.dma, DMA_MODE_READ);
- set_dma_addr(idev->io.dma, virt_to_bus(idev->rx_buff.data));
- set_dma_count(idev->io.dma, idev->rx_buff.truesize);
+ disable_dma(self->io.dma);
+ clear_dma_ff(self->io.dma);
+ set_dma_mode(self->io.dma, DMA_MODE_READ);
+ set_dma_addr(self->io.dma, virt_to_bus(self->rx_buff.data));
+ set_dma_count(self->io.dma, self->rx_buff.truesize);
#else
- setup_dma(idev->io.dma, idev->rx_buff.data, idev->rx_buff.truesize,
+ setup_dma(self->io.dma, self->rx_buff.data, self->rx_buff.truesize,
DMA_MODE_READ);
#endif
/*
@@ -747,7 +772,7 @@ int w83977af_dma_receive(struct irda_device *idev)
#ifdef CONFIG_NETWINDER_RX_DMA_PROBLEMS
hcr = inb(iobase+HCR);
outb(hcr | HCR_EN_DMA, iobase+HCR);
- enable_dma(idev->io.dma);
+ enable_dma(self->io.dma);
restore_flags(flags);
#else
outb(inb(iobase+HCR) | HCR_EN_DMA, iobase+HCR);
@@ -759,32 +784,30 @@ int w83977af_dma_receive(struct irda_device *idev)
}
/*
- * Function w83977af_receive_complete (idev)
+ * Function w83977af_receive_complete (self)
*
* Finished with receiving a frame
*
*/
-int w83977af_dma_receive_complete(struct irda_device *idev)
+int w83977af_dma_receive_complete(struct w83977af_ir *self)
{
struct sk_buff *skb;
- struct w83977af_ir *self;
struct st_fifo *st_fifo;
int len;
int iobase;
__u8 set;
__u8 status;
- DEBUG(4, __FUNCTION__ "\n");
+ IRDA_DEBUG(4, __FUNCTION__ "\n");
- self = idev->priv;
st_fifo = &self->st_fifo;
- iobase = idev->io.iobase;
+ iobase = self->io.iobase;
/* Save current set */
set = inb(iobase+SSR);
- iobase = idev->io.iobase;
+ iobase = self->io.iobase;
/* Read status FIFO */
switch_bank(iobase, SET5);
@@ -809,28 +832,28 @@ int w83977af_dma_receive_complete(struct irda_device *idev)
if (status & FS_FO_ERR_MSK) {
if (status & FS_FO_LST_FR) {
/* Add number of lost frames to stats */
- idev->stats.rx_errors += len;
+ self->stats.rx_errors += len;
} else {
/* Skip frame */
- idev->stats.rx_errors++;
+ self->stats.rx_errors++;
- idev->rx_buff.data += len;
+ self->rx_buff.data += len;
if (status & FS_FO_MX_LEX)
- idev->stats.rx_length_errors++;
+ self->stats.rx_length_errors++;
if (status & FS_FO_PHY_ERR)
- idev->stats.rx_frame_errors++;
+ self->stats.rx_frame_errors++;
if (status & FS_FO_CRC_ERR)
- idev->stats.rx_crc_errors++;
+ self->stats.rx_crc_errors++;
}
/* The errors below can be reported in both cases */
if (status & FS_FO_RX_OV)
- idev->stats.rx_fifo_errors++;
+ self->stats.rx_fifo_errors++;
if (status & FS_FO_FSF_OV)
- idev->stats.rx_fifo_errors++;
+ self->stats.rx_fifo_errors++;
} else {
/* Check if we have transfered all data to memory */
@@ -866,19 +889,19 @@ int w83977af_dma_receive_complete(struct irda_device *idev)
skb_reserve(skb, 1);
/* Copy frame without CRC */
- if (idev->io.baudrate < 4000000) {
+ if (self->io.speed < 4000000) {
skb_put(skb, len-2);
- memcpy(skb->data, idev->rx_buff.data, len-2);
+ memcpy(skb->data, self->rx_buff.data, len-2);
} else {
skb_put(skb, len-4);
- memcpy(skb->data, idev->rx_buff.data, len-4);
+ memcpy(skb->data, self->rx_buff.data, len-4);
}
/* Move to next frame */
- idev->rx_buff.data += len;
- idev->stats.rx_packets++;
+ self->rx_buff.data += len;
+ self->stats.rx_packets++;
- skb->dev = &idev->netdev;
+ skb->dev = self->netdev;
skb->mac.raw = skb->data;
skb->protocol = htons(ETH_P_IRDA);
netif_rx(skb);
@@ -891,61 +914,60 @@ int w83977af_dma_receive_complete(struct irda_device *idev)
}
/*
- * Function pc87108_pio_receive (idev)
+ * Function pc87108_pio_receive (self)
*
* Receive all data in receiver FIFO
*
*/
-static void w83977af_pio_receive(struct irda_device *idev)
+static void w83977af_pio_receive(struct w83977af_ir *self)
{
__u8 byte = 0x00;
int iobase;
- DEBUG(4, __FUNCTION__ "()\n");
+ IRDA_DEBUG(4, __FUNCTION__ "()\n");
- ASSERT(idev != NULL, return;);
- ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return;);
+ ASSERT(self != NULL, return;);
- iobase = idev->io.iobase;
+ iobase = self->io.iobase;
/* Receive all characters in Rx FIFO */
do {
byte = inb(iobase+RBR);
- async_unwrap_char(idev, byte);
+ async_unwrap_char(self->netdev, &self->rx_buff, byte);
} while (inb(iobase+USR) & USR_RDR); /* Data available */
}
/*
- * Function w83977af_sir_interrupt (idev, eir)
+ * Function w83977af_sir_interrupt (self, eir)
*
* Handle SIR interrupt
*
*/
-static __u8 w83977af_sir_interrupt(struct irda_device *idev, int isr)
+static __u8 w83977af_sir_interrupt(struct w83977af_ir *self, int isr)
{
int actual;
__u8 new_icr = 0;
__u8 set;
int iobase;
- DEBUG(4, __FUNCTION__ "(), isr=%#x\n", isr);
+ IRDA_DEBUG(4, __FUNCTION__ "(), isr=%#x\n", isr);
- iobase = idev->io.iobase;
+ iobase = self->io.iobase;
/* Transmit FIFO low on data */
if (isr & ISR_TXTH_I) {
/* Write data left in transmit buffer */
- actual = w83977af_pio_write(idev->io.iobase,
- idev->tx_buff.data,
- idev->tx_buff.len,
- idev->io.fifo_size);
+ actual = w83977af_pio_write(self->io.iobase,
+ self->tx_buff.data,
+ self->tx_buff.len,
+ self->io.fifo_size);
- idev->tx_buff.data += actual;
- idev->tx_buff.len -= actual;
+ self->tx_buff.data += actual;
+ self->tx_buff.len -= actual;
- idev->io.direction = IO_XMIT;
+ self->io.direction = IO_XMIT;
/* Check if finished */
- if (idev->tx_buff.len > 0) {
+ if (self->tx_buff.len > 0) {
new_icr |= ICR_ETXTHI;
} else {
set = inb(iobase+SSR);
@@ -953,8 +975,8 @@ static __u8 w83977af_sir_interrupt(struct irda_device *idev, int isr)
outb(AUDR_SFEND, iobase+AUDR);
outb(set, iobase+SSR);
- idev->netdev.tbusy = 0; /* Unlock */
- idev->stats.tx_packets++;
+ self->netdev->tbusy = 0; /* Unlock */
+ self->stats.tx_packets++;
/* Schedule network layer */
mark_bh(NET_BH);
@@ -966,13 +988,13 @@ static __u8 w83977af_sir_interrupt(struct irda_device *idev, int isr)
if (isr & ISR_TXEMP_I) {
/* Turn around and get ready to receive some data */
- idev->io.direction = IO_RECV;
+ self->io.direction = IO_RECV;
new_icr |= ICR_ERBRI;
}
/* Rx FIFO threshold or timeout */
if (isr & ISR_RXTH_I) {
- w83977af_pio_receive(idev);
+ w83977af_pio_receive(self);
/* Keep receiving */
new_icr |= ICR_ERBRI;
@@ -981,23 +1003,23 @@ static __u8 w83977af_sir_interrupt(struct irda_device *idev, int isr)
}
/*
- * Function pc87108_fir_interrupt (idev, eir)
+ * Function pc87108_fir_interrupt (self, eir)
*
* Handle MIR/FIR interrupt
*
*/
-static __u8 w83977af_fir_interrupt(struct irda_device *idev, int isr)
+static __u8 w83977af_fir_interrupt(struct w83977af_ir *self, int isr)
{
__u8 new_icr = 0;
__u8 set;
int iobase;
- iobase = idev->io.iobase;
+ iobase = self->io.iobase;
set = inb(iobase+SSR);
/* End of frame detected in FIFO */
if (isr & (ISR_FEND_I|ISR_FSF_I)) {
- if (w83977af_dma_receive_complete(idev)) {
+ if (w83977af_dma_receive_complete(self)) {
/* Wait for next status FIFO interrupt */
new_icr |= ICR_EFSFI;
@@ -1026,29 +1048,29 @@ static __u8 w83977af_fir_interrupt(struct irda_device *idev, int isr)
/* outb(ASCR_CTE, iobase+ASCR); */
/* Check if this is a TX timer interrupt */
- if (idev->io.direction == IO_XMIT) {
- w83977af_dma_write(idev, iobase);
+ if (self->io.direction == IO_XMIT) {
+ w83977af_dma_write(self, iobase);
new_icr |= ICR_EDMAI;
} else {
/* Check if DMA has now finished */
- w83977af_dma_receive_complete(idev);
+ w83977af_dma_receive_complete(self);
new_icr |= ICR_EFSFI;
}
}
/* Finished with DMA */
if (isr & ISR_DMA_I) {
- w83977af_dma_xmit_complete(idev);
+ w83977af_dma_xmit_complete(self);
/* Check if there are more frames to be transmitted */
- /* if (irda_device_txqueue_empty(idev)) { */
+ /* if (irda_device_txqueue_empty(self)) { */
/* Prepare for receive
*
* ** Netwinder Tx DMA likes that we do this anyway **
*/
- w83977af_dma_receive(idev);
+ w83977af_dma_receive(self);
new_icr = ICR_EFSFI;
/* } */
}
@@ -1067,20 +1089,21 @@ static __u8 w83977af_fir_interrupt(struct irda_device *idev, int isr)
*/
static void w83977af_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
+ struct net_device *dev = (struct net_device *) dev_id;
+ struct w83977af_ir *self;
__u8 set, icr, isr;
int iobase;
- struct irda_device *idev = (struct irda_device *) dev_id;
-
- if (idev == NULL) {
+ if (!dev) {
printk(KERN_WARNING "%s: irq %d for unknown device.\n",
driver_name, irq);
return;
}
+ self = (struct w83977af_ir *) dev->priv;
- idev->netdev.interrupt = 1;
+ dev->interrupt = 1;
- iobase = idev->io.iobase;
+ iobase = self->io.iobase;
/* Save current bank */
set = inb(iobase+SSR);
@@ -1093,47 +1116,34 @@ static void w83977af_interrupt(int irq, void *dev_id, struct pt_regs *regs)
if (isr) {
/* Dispatch interrupt handler for the current speed */
- if (idev->io.baudrate > PIO_MAX_SPEED )
- icr = w83977af_fir_interrupt(idev, isr);
+ if (self->io.speed > PIO_MAX_SPEED )
+ icr = w83977af_fir_interrupt(self, isr);
else
- icr = w83977af_sir_interrupt(idev, isr);
+ icr = w83977af_sir_interrupt(self, isr);
}
outb(icr, iobase+ICR); /* Restore (new) interrupts */
outb(set, iobase+SSR); /* Restore bank register */
- idev->netdev.interrupt = 0;
+ self->netdev->interrupt = 0;
}
/*
- * Function w83977af_wait_until_sent (idev)
- *
- * This function should put the current thread to sleep until all data
- * have been sent, so it is safe to f.eks. change the speed.
- */
-static void w83977af_wait_until_sent(struct irda_device *idev)
-{
- current->state = TASK_INTERRUPTIBLE;
- schedule_timeout(60*HZ/1000);
-}
-
-/*
- * Function w83977af_is_receiving (idev)
+ * Function w83977af_is_receiving (self)
*
* Return TRUE is we are currently receiving a frame
*
*/
-static int w83977af_is_receiving(struct irda_device *idev)
+static int w83977af_is_receiving(struct w83977af_ir *self)
{
int status = FALSE;
int iobase;
__u8 set;
- ASSERT(idev != NULL, return FALSE;);
- ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return FALSE;);
+ ASSERT(self != NULL, return FALSE;);
- if (idev->io.baudrate > 115200) {
- iobase = idev->io.iobase;
+ if (self->io.speed > 115200) {
+ iobase = self->io.iobase;
/* Check if rx FIFO is not empty */
set = inb(iobase+SSR);
@@ -1144,7 +1154,7 @@ static int w83977af_is_receiving(struct irda_device *idev)
}
outb(set, iobase+SSR);
} else
- status = (idev->rx_buff.state != OUTSIDE_FRAME);
+ status = (self->rx_buff.state != OUTSIDE_FRAME);
return status;
}
@@ -1157,7 +1167,7 @@ static int w83977af_is_receiving(struct irda_device *idev)
*/
static int w83977af_net_init(struct net_device *dev)
{
- DEBUG(0, __FUNCTION__ "()\n");
+ IRDA_DEBUG(0, __FUNCTION__ "()\n");
/* Set up to be a normal IrDA network device driver */
irda_device_setup(dev);
@@ -1176,30 +1186,29 @@ static int w83977af_net_init(struct net_device *dev)
*/
static int w83977af_net_open(struct net_device *dev)
{
- struct irda_device *idev;
+ struct w83977af_ir *self;
int iobase;
__u8 set;
- DEBUG(0, __FUNCTION__ "()\n");
+ IRDA_DEBUG(0, __FUNCTION__ "()\n");
ASSERT(dev != NULL, return -1;);
- idev = (struct irda_device *) dev->priv;
+ self = (struct w83977af_ir *) dev->priv;
- ASSERT(idev != NULL, return 0;);
- ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return 0;);
+ ASSERT(self != NULL, return 0;);
- iobase = idev->io.iobase;
+ iobase = self->io.iobase;
- if (request_irq(idev->io.irq, w83977af_interrupt, 0, idev->name,
- (void *) idev)) {
+ if (request_irq(self->io.irq, w83977af_interrupt, 0, dev->name,
+ (void *) dev)) {
return -EAGAIN;
}
/*
* Always allocate the DMA channel after the IRQ,
* and clean up on failure.
*/
- if (request_dma(idev->io.dma, idev->name)) {
- free_irq(idev->io.irq, idev);
+ if (request_dma(self->io.dma, dev->name)) {
+ free_irq(self->io.irq, self);
return -EAGAIN;
}
@@ -1208,9 +1217,9 @@ static int w83977af_net_open(struct net_device *dev)
/* Enable some interrupts so we can receive frames again */
switch_bank(iobase, SET0);
- if (idev->io.baudrate > 115200) {
+ if (self->io.speed > 115200) {
outb(ICR_EFSFI, iobase+ICR);
- w83977af_dma_receive(idev);
+ w83977af_dma_receive(self);
} else
outb(ICR_ERBRI, iobase+ICR);
@@ -1218,7 +1227,15 @@ static int w83977af_net_open(struct net_device *dev)
outb(set, iobase+SSR);
/* Ready to play! */
- irda_device_net_open(dev);
+ dev->tbusy = 0;
+ dev->interrupt = 0;
+ dev->start = 1;
+
+ /*
+ * Open new IrLAP layer instance, now that everything should be
+ * initialized properly
+ */
+ self->irlap = irlap_open(dev, &self->qos);
MOD_INC_USE_COUNT;
@@ -1233,25 +1250,30 @@ static int w83977af_net_open(struct net_device *dev)
*/
static int w83977af_net_close(struct net_device *dev)
{
- struct irda_device *idev;
+ struct w83977af_ir *self;
int iobase;
__u8 set;
- DEBUG(0, __FUNCTION__ "()\n");
+ IRDA_DEBUG(0, __FUNCTION__ "()\n");
ASSERT(dev != NULL, return -1;);
- idev = (struct irda_device *) dev->priv;
+ self = (struct w83977af_ir *) dev->priv;
- ASSERT(idev != NULL, return 0;);
- ASSERT(idev->magic == IRDA_DEVICE_MAGIC, return 0;);
+ ASSERT(self != NULL, return 0;);
- iobase = idev->io.iobase;
+ iobase = self->io.iobase;
/* Stop device */
- irda_device_net_close(dev);
+ dev->tbusy = 1;
+ dev->start = 0;
+
+ /* Stop and remove instance of IrLAP */
+ if (self->irlap)
+ irlap_close(self->irlap);
+ self->irlap = NULL;
- disable_dma(idev->io.dma);
+ disable_dma(self->io.dma);
/* Save current set */
set = inb(iobase+SSR);
@@ -1260,8 +1282,8 @@ static int w83977af_net_close(struct net_device *dev)
switch_bank(iobase, SET0);
outb(0, iobase+ICR);
- free_irq(idev->io.irq, idev);
- free_dma(idev->io.dma);
+ free_irq(self->io.irq, self);
+ free_dma(self->io.dma);
/* Restore bank register */
outb(set, iobase+SSR);
diff --git a/drivers/net/pcmcia/ray_cs.c b/drivers/net/pcmcia/ray_cs.c
index 81bba9e60..5594f51d1 100644
--- a/drivers/net/pcmcia/ray_cs.c
+++ b/drivers/net/pcmcia/ray_cs.c
@@ -38,6 +38,7 @@
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
+#include <linux/if_arp.h>
#include <linux/ioport.h>
#include <linux/skbuff.h>
@@ -49,6 +50,19 @@
#include <pcmcia/ds.h>
#include <pcmcia/mem_op.h>
+#ifdef HAS_WIRELESS_EXTENSIONS
+#include <linux/wireless.h>
+#if WIRELESS_EXT < 8
+#warning "Wireless extension v8 or newer required"
+#endif /* WIRELESS_EXT < 8 */
+/* Warning : these stuff will slow down the driver... */
+#define WIRELESS_SPY /* Enable spying addresses */
+/* Definitions we need for spy */
+typedef struct iw_statistics iw_stats;
+typedef struct iw_quality iw_qual;
+typedef u_char mac_addr[ETH_ALEN]; /* Hardware address */
+#endif /* HAS_WIRELESS_EXTENSIONS */
+
#include "rayctl.h"
#include "ray_cs.h"
@@ -72,67 +86,68 @@ MODULE_PARM(pc_debug, "i");
#define DEBUG(n, args...)
#endif
/** Prototypes based on PCMCIA skeleton driver *******************************/
-void ray_config(dev_link_t *link);
-void ray_release(u_long arg);
-int ray_event(event_t event, int priority, event_callback_args_t *args);
-dev_link_t *ray_attach(void);
-void ray_detach(dev_link_t *);
+static void ray_config(dev_link_t *link);
+static void ray_release(u_long arg);
+static int ray_event(event_t event, int priority, event_callback_args_t *args);
+static dev_link_t *ray_attach(void);
+static void ray_detach(dev_link_t *);
/***** Prototypes indicated by device structure ******************************/
-int ray_dev_close(struct net_device *dev);
-int ray_dev_config(struct net_device *dev, struct ifmap *map);
-struct enet_statistics *ray_get_stats(struct net_device *dev);
-int ray_dev_init(struct net_device *dev);
-int ray_dev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd);
-int ray_open(struct net_device *dev);
-int ray_dev_start_xmit(struct sk_buff *skb, struct net_device *dev);
+static int ray_dev_close(struct net_device *dev);
+static int ray_dev_config(struct net_device *dev, struct ifmap *map);
+static struct enet_statistics *ray_get_stats(struct net_device *dev);
+static int ray_dev_init(struct net_device *dev);
+static int ray_dev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd);
+static int ray_open(struct net_device *dev);
+static int ray_dev_start_xmit(struct sk_buff *skb, struct net_device *dev);
static void set_multicast_list(struct net_device *dev);
static void ray_update_multi_list(struct net_device *dev, int all);
-int encapsulate_frame(ray_dev_t *local, struct tx_msg *ptx, UCHAR msg_type,
- unsigned char *data, int len);
-int translate_frame(ray_dev_t *local, struct tx_msg *ptx,
+static int translate_frame(ray_dev_t *local, struct tx_msg *ptx,
unsigned char *data, int len);
-void ray_build_header(ray_dev_t *local, struct tx_msg *ptx, UCHAR msg_type,
+static void ray_build_header(ray_dev_t *local, struct tx_msg *ptx, UCHAR msg_type,
unsigned char *data);
-void untranslate(ray_dev_t *local, struct sk_buff *skb, int len);
+static void untranslate(ray_dev_t *local, struct sk_buff *skb, int len);
+#if WIRELESS_EXT > 7 /* If wireless extension exist in the kernel */
+static iw_stats * ray_get_wireless_stats(struct device * dev);
+#endif /* WIRELESS_EXT > 7 */
/***** Prototypes for raylink functions **************************************/
-int asc_to_int(char a);
-void authenticate(ray_dev_t *local);
-int build_auth_frame(ray_dev_t *local, UCHAR *dest, int auth_type);
-void authenticate_timeout(u_long);
-int get_free_ccs(ray_dev_t *local);
-int get_free_tx_ccs(ray_dev_t *local);
-void init_startup_params(ray_dev_t *local);
-int parse_addr(char *in_str, UCHAR *out);
-int ray_hw_xmit(unsigned char* data, int len, struct net_device* dev, UCHAR type);
-int ray_init(struct net_device *dev);
-int interrupt_ecf(ray_dev_t *local, int ccs);
-void ray_reset(struct net_device *dev);
-void ray_update_parm(struct net_device *dev, UCHAR objid, UCHAR *value, int len);
-void verify_dl_startup(u_long);
+static int asc_to_int(char a);
+static void authenticate(ray_dev_t *local);
+static int build_auth_frame(ray_dev_t *local, UCHAR *dest, int auth_type);
+static void authenticate_timeout(u_long);
+static int get_free_ccs(ray_dev_t *local);
+static int get_free_tx_ccs(ray_dev_t *local);
+static void init_startup_params(ray_dev_t *local);
+static int parse_addr(char *in_str, UCHAR *out);
+static int ray_hw_xmit(unsigned char* data, int len, struct net_device* dev, UCHAR type);
+static int ray_init(struct net_device *dev);
+static int interrupt_ecf(ray_dev_t *local, int ccs);
+static void ray_reset(struct net_device *dev);
+static void ray_update_parm(struct net_device *dev, UCHAR objid, UCHAR *value, int len);
+static void verify_dl_startup(u_long);
/* Prototypes for interrpt time functions **********************************/
-void ray_interrupt(int reg, void *dev_id, struct pt_regs *regs);
-void clear_interrupt(ray_dev_t *local);
-void rx_deauthenticate(ray_dev_t *local, struct rcs *prcs,
+static void ray_interrupt (int reg, void *dev_id, struct pt_regs *regs);
+static void clear_interrupt(ray_dev_t *local);
+static void rx_deauthenticate(ray_dev_t *local, struct rcs *prcs,
unsigned int pkt_addr, int rx_len);
-int copy_from_rx_buff(ray_dev_t *local, UCHAR *dest, int pkt_addr, int len);
-void ray_rx(struct net_device *dev, ray_dev_t *local, struct rcs *prcs);
-void release_frag_chain(ray_dev_t *local, struct rcs *prcs);
-void rx_authenticate(ray_dev_t *local, struct rcs *prcs,
+static int copy_from_rx_buff(ray_dev_t *local, UCHAR *dest, int pkt_addr, int len);
+static void ray_rx(struct net_device *dev, ray_dev_t *local, struct rcs *prcs);
+static void release_frag_chain(ray_dev_t *local, struct rcs *prcs);
+static void rx_authenticate(ray_dev_t *local, struct rcs *prcs,
unsigned int pkt_addr, int rx_len);
-void rx_data(struct net_device *dev, struct rcs *prcs, unsigned int pkt_addr,
+static void rx_data(struct net_device *dev, struct rcs *prcs, unsigned int pkt_addr,
int rx_len);
-void associate(ray_dev_t *local);
+static void associate(ray_dev_t *local);
/* Card command functions */
-int dl_startup_params(struct net_device *dev);
-void join_net(u_long local);
-void start_net(u_long local);
+static int dl_startup_params(struct net_device *dev);
+static void join_net(u_long local);
+static void start_net(u_long local);
/* void start_net(ray_dev_t *local); */
-int ray_cs_proc_read(char *buf, char **start, off_t off, int len, int spare);
+static int ray_cs_proc_read(char *buf, char **start, off_t off, int len, int spare);
/* Create symbol table for registering with kernel in init_module */
EXPORT_SYMBOL(ray_dev_ioctl);
EXPORT_SYMBOL(ray_rx);
@@ -283,6 +298,14 @@ static UCHAR b4_default_startup_parms[] = {
/*===========================================================================*/
static unsigned char eth2_llc[] = {0xaa, 0xaa, 3, 0, 0, 0};
+static char hop_pattern_length[] = { 1,
+ USA_HOP_MOD, EUROPE_HOP_MOD,
+ JAPAN_HOP_MOD, KOREA_HOP_MOD,
+ SPAIN_HOP_MOD, FRANCE_HOP_MOD,
+ ISRAEL_HOP_MOD, AUSTRALIA_HOP_MOD,
+ JAPAN_TEST_HOP_MOD
+};
+
static char rcsid[] = "Raylink/WebGear wireless LAN - Corey <Thomas corey@world.std.com>";
#ifdef CONFIG_PROC_FS
@@ -298,7 +321,7 @@ struct proc_dir_entry ray_cs_proc_entry = {
};
#endif
/*===========================================================================*/
-void cs_error(client_handle_t handle, int func, int ret)
+static void cs_error(client_handle_t handle, int func, int ret)
{
error_info_t err = { func, ret };
CardServices(ReportError, handle, &err);
@@ -311,7 +334,7 @@ void cs_error(client_handle_t handle, int func, int ret)
configure the card at this point -- we wait until we receive a
card insertion event.
=============================================================================*/
-dev_link_t *ray_attach(void)
+static dev_link_t *ray_attach(void)
{
client_reg_t client_reg;
dev_link_t *link;
@@ -367,6 +390,9 @@ dev_link_t *ray_attach(void)
dev->set_config = &ray_dev_config;
dev->get_stats = &ray_get_stats;
dev->do_ioctl = &ray_dev_ioctl;
+#if WIRELESS_EXT > 7 /* If wireless extension exist in the kernel */
+ dev->get_wireless_stats = ray_get_wireless_stats;
+#endif
dev->set_multicast_list = &set_multicast_list;
@@ -411,7 +437,7 @@ dev_link_t *ray_attach(void)
structures are freed. Otherwise, the structures will be freed
when the device is released.
=============================================================================*/
-void ray_detach(dev_link_t *link)
+static void ray_detach(dev_link_t *link)
{
dev_link_t **linkp;
struct net_device *dev;
@@ -470,7 +496,7 @@ void ray_detach(dev_link_t *link)
#define CS_CHECK(fn, args...) \
while ((last_ret=CardServices(last_fn=(fn),args))!=0) goto cs_failed
#define MAX_TUPLE_SIZE 128
-void ray_config(dev_link_t *link)
+static void ray_config(dev_link_t *link)
{
client_handle_t handle = link->handle;
tuple_t tuple;
@@ -585,7 +611,7 @@ cs_failed:
ray_release((u_long)link);
} /* ray_config */
/*===========================================================================*/
-int ray_init(struct net_device *dev)
+static int ray_init(struct net_device *dev)
{
int i;
UCHAR *p;
@@ -648,7 +674,7 @@ int ray_init(struct net_device *dev)
} /* ray_init */
/*===========================================================================*/
/* Download startup parameters to the card and command it to read them */
-int dl_startup_params(struct net_device *dev)
+static int dl_startup_params(struct net_device *dev)
{
int ccsindex;
ray_dev_t *local = (ray_dev_t *)dev->priv;
@@ -694,16 +720,9 @@ int dl_startup_params(struct net_device *dev)
return 0;
} /* dl_startup_params */
/*===========================================================================*/
-void init_startup_params(ray_dev_t *local)
+static void init_startup_params(ray_dev_t *local)
{
int i;
- static char hop_pattern_length[] = { 1,
- USA_HOP_MOD, EUROPE_HOP_MOD,
- JAPAN_HOP_MOD, KOREA_HOP_MOD,
- SPAIN_HOP_MOD, FRANCE_HOP_MOD,
- ISRAEL_HOP_MOD, AUSTRALIA_HOP_MOD,
- JAPAN_TEST_HOP_MOD
- };
if (country > JAPAN_TEST) country = USA;
else
@@ -762,7 +781,7 @@ void init_startup_params(ray_dev_t *local)
strncpy(local->sparm.b4.a_current_ess_id, essid, ESSID_SIZE);
} /* init_startup_params */
/*===========================================================================*/
-void verify_dl_startup(u_long data)
+static void verify_dl_startup(u_long data)
{
ray_dev_t *local = (ray_dev_t *)data;
struct ccs *pccs = ((struct ccs *)(local->sram + CCS_BASE)) + local->dl_param_ccs;
@@ -779,7 +798,7 @@ void verify_dl_startup(u_long data)
printk(KERN_DEBUG "verify_dl_startup parameters sent via ccs %d:\n",
local->dl_param_ccs);
for (i=0; i<sizeof(struct b5_startup_params); i++) {
- printk(" %2x", readb(local->sram + HOST_TO_ECF_BASE + i));
+ printk(" %2x", (unsigned int) readb(local->sram + HOST_TO_ECF_BASE + i));
}
printk("\n");
}
@@ -802,7 +821,7 @@ void verify_dl_startup(u_long data)
} /* end verify_dl_startup */
/*===========================================================================*/
/* Command card to start a network */
-void start_net(u_long data)
+static void start_net(u_long data)
{
ray_dev_t *local = (ray_dev_t *)data;
struct ccs *pccs;
@@ -828,7 +847,7 @@ void start_net(u_long data)
} /* end start_net */
/*===========================================================================*/
/* Command card to join a network */
-void join_net(u_long data)
+static void join_net(u_long data)
{
ray_dev_t *local = (ray_dev_t *)data;
@@ -860,7 +879,7 @@ void join_net(u_long data)
device, and release the PCMCIA configuration. If the device is
still open, this will be postponed until it is closed.
=============================================================================*/
-void ray_release(u_long arg)
+static void ray_release(u_long arg)
{
dev_link_t *link = (dev_link_t *)arg;
struct net_device *dev = link->priv;
@@ -912,7 +931,7 @@ void ray_release(u_long arg)
actually access the device should check this flag to make sure
the card is still present.
=============================================================================*/
-int ray_event(event_t event, int priority,
+static int ray_event(event_t event, int priority,
event_callback_args_t *args)
{
dev_link_t *link = args->client_data;
@@ -991,7 +1010,7 @@ int ray_dev_init(struct net_device *dev)
return 0;
}
/*===========================================================================*/
-int ray_dev_config(struct net_device *dev, struct ifmap *map)
+static int ray_dev_config(struct net_device *dev, struct ifmap *map)
{
ray_dev_t *local = dev->priv;
dev_link_t *link = local->finder;
@@ -1005,7 +1024,7 @@ int ray_dev_config(struct net_device *dev, struct ifmap *map)
return 0;
}
/*===========================================================================*/
-int ray_dev_start_xmit(struct sk_buff *skb, struct net_device *dev)
+static int ray_dev_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
ray_dev_t *local = dev->priv;
dev_link_t *link = local->finder;
@@ -1047,7 +1066,7 @@ int ray_dev_start_xmit(struct sk_buff *skb, struct net_device *dev)
return 0;
} /* ray_dev_start_xmit */
/*===========================================================================*/
-int ray_hw_xmit(unsigned char* data, int len, struct net_device* dev,
+static int ray_hw_xmit(unsigned char* data, int len, struct net_device* dev,
UCHAR msg_type)
{
ray_dev_t *local = (ray_dev_t *)dev->priv;
@@ -1089,7 +1108,7 @@ int ray_hw_xmit(unsigned char* data, int len, struct net_device* dev,
}
else { /* Encapsulate frame */
/* TBD TIB length will move address of ptx->var */
- memcpy( (UCHAR *)&ptx->var, data, len);
+ memcpy_toio(&ptx->var, data, len);
offset = 0;
}
@@ -1121,7 +1140,7 @@ int ray_hw_xmit(unsigned char* data, int len, struct net_device* dev,
return XMIT_OK;
} /* end ray_hw_xmit */
/*===========================================================================*/
-int translate_frame(ray_dev_t *local, struct tx_msg *ptx, unsigned char *data,
+static int translate_frame(ray_dev_t *local, struct tx_msg *ptx, unsigned char *data,
int len)
{
unsigned short int proto = ((struct ethhdr *)data)->h_proto;
@@ -1137,7 +1156,7 @@ int translate_frame(ray_dev_t *local, struct tx_msg *ptx, unsigned char *data,
/* Copy body of ethernet packet without ethernet header */
memcpy_toio((UCHAR *)&ptx->var + sizeof(struct snaphdr_t), \
data + ETH_HLEN, len - ETH_HLEN);
- return sizeof(struct snaphdr_t) - ETH_HLEN;
+ return (int) sizeof(struct snaphdr_t) - ETH_HLEN;
}
else { /* already 802 type, and proto is length */
DEBUG(3,"ray_cs translate_frame 802\n");
@@ -1152,15 +1171,16 @@ int translate_frame(ray_dev_t *local, struct tx_msg *ptx, unsigned char *data,
/* TBD do other frame types */
} /* end translate_frame */
/*===========================================================================*/
-void ray_build_header(ray_dev_t *local, struct tx_msg *ptx, UCHAR msg_type,
+static void ray_build_header(ray_dev_t *local, struct tx_msg *ptx, UCHAR msg_type,
unsigned char *data)
{
writeb(PROTOCOL_VER | msg_type, &ptx->mac.frame_ctl_1);
/*** IEEE 802.11 Address field assignments *************
- addr_1 addr_2 addr_3
- AP destination AP(BSSID) source
- Infra Terminal AP terminal destination
- Adhoc destination terminal BSSID
+ TODS FROMDS addr_1 addr_2 addr_3 addr_4
+Adhoc 0 0 dest src (terminal) BSSID N/A
+AP to Terminal 0 1 dest AP(BSSID) source N/A
+Terminal to AP 1 0 AP(BSSID) src (terminal) dest N/A
+AP to AP 1 1 dest AP src AP dest source
*******************************************************/
if (local->net_type == ADHOC) {
writeb(0, &ptx->mac.frame_ctl_2);
@@ -1186,11 +1206,14 @@ void ray_build_header(ray_dev_t *local, struct tx_msg *ptx, UCHAR msg_type,
}
} /* end encapsulate_frame */
/*===========================================================================*/
-int ray_dev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
+static int ray_dev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
{
ray_dev_t *local = (ray_dev_t *)dev->priv;
dev_link_t *link = local->finder;
int err = 0;
+#if WIRELESS_EXT > 7
+ struct iwreq *wrq = (struct iwreq *) ifr;
+#endif /* WIRELESS_EXT > 7 */
if (!(link->state & DEV_PRESENT)) {
DEBUG(2,"ray_dev_ioctl - device not present\n");
@@ -1200,6 +1223,257 @@ int ray_dev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
/* Validate the command */
switch (cmd)
{
+#if WIRELESS_EXT > 7
+ /* --------------- WIRELESS EXTENSIONS --------------- */
+ /* Get name */
+ case SIOCGIWNAME:
+ strcpy(wrq->u.name, "IEEE 802.11-FH");
+ break;
+
+ /* Get frequency/channel */
+ case SIOCGIWFREQ:
+ wrq->u.freq.m = local->sparm.b5.a_hop_pattern;
+ wrq->u.freq.e = 0;
+ break;
+
+ /* Get current network name (ESSID) */
+ case SIOCGIWESSID:
+ if (wrq->u.data.pointer)
+ {
+ char essid[IW_ESSID_MAX_SIZE + 1];
+ /* Get the essid that was set */
+ memcpy(essid, local->sparm.b5.a_current_ess_id,
+ IW_ESSID_MAX_SIZE);
+ essid[IW_ESSID_MAX_SIZE] = '\0';
+
+ /* Push it out ! */
+ wrq->u.data.length = strlen(essid) + 1;
+ wrq->u.data.flags = 1; /* active */
+ copy_to_user(wrq->u.data.pointer, essid, sizeof(essid));
+ }
+ break;
+
+ /* Get current Access Point (BSSID in our case) */
+ case SIOCGIWAP:
+ memcpy(wrq->u.ap_addr.sa_data, local->bss_id, ETH_ALEN);
+ wrq->u.ap_addr.sa_family = ARPHRD_ETHER;
+ break;
+
+ /* Get the current bit-rate */
+ case SIOCGIWRATE:
+ if(local->net_default_tx_rate == 3)
+ wrq->u.bitrate.value = 2000000; /* Hum... */
+ else
+ wrq->u.bitrate.value = local->net_default_tx_rate * 500000;
+ wrq->u.bitrate.fixed = 0; /* We are in auto mode */
+ break;
+
+ /* Set the desired bit-rate */
+ case SIOCSIWRATE:
+ /* Check if rate is in range */
+ if((wrq->u.bitrate.value != 1000000) &&
+ (wrq->u.bitrate.value != 2000000))
+ {
+ err = -EINVAL;
+ break;
+ }
+ /* Hack for 1.5 Mb/s instead of 2 Mb/s */
+ if((local->fw_ver == 0x55) && /* Please check */
+ (wrq->u.bitrate.value == 2000000))
+ local->net_default_tx_rate = 3;
+ else
+ local->net_default_tx_rate = wrq->u.bitrate.value/500000;
+ break;
+
+ /* Get the current RTS threshold */
+ case SIOCGIWRTS:
+ wrq->u.rts.value = (local->sparm.b5.a_rts_threshold[0] << 8)
+ + local->sparm.b5.a_rts_threshold[1];
+#if WIRELESS_EXT > 8
+ wrq->u.rts.disabled = (wrq->u.rts.value == 32767);
+#endif /* WIRELESS_EXT > 8 */
+ wrq->u.rts.fixed = 1;
+ break;
+
+ /* Get the current fragmentation threshold */
+ case SIOCGIWFRAG:
+ wrq->u.frag.value = (local->sparm.b5.a_frag_threshold[0] << 8)
+ + local->sparm.b5.a_frag_threshold[1];
+#if WIRELESS_EXT > 8
+ wrq->u.frag.disabled = (wrq->u.frag.value == 32767);
+#endif /* WIRELESS_EXT > 8 */
+ wrq->u.frag.fixed = 1;
+ break;
+#endif /* WIRELESS_EXT > 7 */
+#if WIRELESS_EXT > 8
+
+ /* Get the current mode of operation */
+ case SIOCGIWMODE:
+ if(local->sparm.b5.a_network_type)
+ wrq->u.mode = IW_MODE_INFRA;
+ else
+ wrq->u.mode = IW_MODE_ADHOC;
+ break;
+#endif /* WIRELESS_EXT > 8 */
+#if WIRELESS_EXT > 7
+ /* ------------------ IWSPY SUPPORT ------------------ */
+ /* Define the range (variations) of above parameters */
+ case SIOCGIWRANGE:
+ /* Basic checking... */
+ if(wrq->u.data.pointer != (caddr_t) 0)
+ {
+ struct iw_range range;
+ memset((char *) &range, 0, sizeof(struct iw_range));
+
+ /* Set the length (useless : its constant...) */
+ wrq->u.data.length = sizeof(struct iw_range);
+
+ /* Set information in the range struct */
+ range.throughput = 1.1 * 1000 * 1000; /* Put the right number here */
+ range.num_channels = hop_pattern_length[(int)country];
+ range.num_frequency = 0;
+ range.max_qual.qual = 0;
+ range.max_qual.level = 255; /* What's the correct value ? */
+ range.max_qual.noise = 255; /* Idem */
+ range.num_bitrates = 2;
+ range.bitrate[0] = 1000000; /* 1 Mb/s */
+ range.bitrate[1] = 2000000; /* 2 Mb/s */
+
+ /* Copy structure to the user buffer */
+ if(copy_to_user(wrq->u.data.pointer, &range,
+ sizeof(struct iw_range)))
+ err = -EFAULT;
+ }
+ break;
+
+#ifdef WIRELESS_SPY
+ /* Set addresses to spy */
+ case SIOCSIWSPY:
+ /* Check the number of addresses */
+ if(wrq->u.data.length > IW_MAX_SPY)
+ {
+ err = -E2BIG;
+ break;
+ }
+ local->spy_number = wrq->u.data.length;
+
+ /* If there is some addresses to copy */
+ if(local->spy_number > 0)
+ {
+ struct sockaddr address[IW_MAX_SPY];
+ int i;
+
+ /* Copy addresses to the driver */
+ if(copy_from_user(address, wrq->u.data.pointer,
+ sizeof(struct sockaddr) * local->spy_number))
+ {
+ err = -EFAULT;
+ break;
+ }
+
+ /* Copy addresses to the lp structure */
+ for(i = 0; i < local->spy_number; i++)
+ memcpy(local->spy_address[i], address[i].sa_data, ETH_ALEN);
+
+ /* Reset structure... */
+ memset(local->spy_stat, 0x00, sizeof(iw_qual) * IW_MAX_SPY);
+
+#ifdef DEBUG_IOCTL_INFO
+ printk(KERN_DEBUG "SetSpy - Set of new addresses is :\n");
+ for(i = 0; i < local->spy_number; i++)
+ printk(KERN_DEBUG "%02X:%02X:%02X:%02X:%02X:%02X\n",
+ local->spy_address[i][0],
+ local->spy_address[i][1],
+ local->spy_address[i][2],
+ local->spy_address[i][3],
+ local->spy_address[i][4],
+ local->spy_address[i][5]);
+#endif /* DEBUG_IOCTL_INFO */
+ }
+ break;
+
+ /* Get the spy list and spy stats */
+ case SIOCGIWSPY:
+ /* Set the number of addresses */
+ wrq->u.data.length = local->spy_number;
+
+ /* If the user want to have the addresses back... */
+ if((local->spy_number > 0) && (wrq->u.data.pointer != (caddr_t) 0))
+ {
+ struct sockaddr address[IW_MAX_SPY];
+ int i;
+
+ /* Copy addresses from the lp structure */
+ for(i = 0; i < local->spy_number; i++)
+ {
+ memcpy(address[i].sa_data, local->spy_address[i], ETH_ALEN);
+ address[i].sa_family = ARPHRD_ETHER;
+ }
+
+ /* Copy addresses to the user buffer */
+ if(copy_to_user(wrq->u.data.pointer, address,
+ sizeof(struct sockaddr) * local->spy_number))
+ {
+ err = -EFAULT;
+ break;
+ }
+
+ /* Copy stats to the user buffer (just after) */
+ if(copy_to_user(wrq->u.data.pointer +
+ (sizeof(struct sockaddr) * local->spy_number),
+ local->spy_stat, sizeof(iw_qual) * local->spy_number))
+ {
+ err = -EFAULT;
+ break;
+ }
+
+ /* Reset updated flags */
+ for(i = 0; i < local->spy_number; i++)
+ local->spy_stat[i].updated = 0x0;
+ } /* if(pointer != NULL) */
+
+ break;
+#endif /* WIRELESS_SPY */
+
+ /* ------------------ PRIVATE IOCTL ------------------ */
+#define SIOCSIPFRAMING SIOCDEVPRIVATE /* Set framing mode */
+#define SIOCGIPFRAMING SIOCDEVPRIVATE + 1 /* Get framing mode */
+#define SIOCGIPCOUNTRY SIOCDEVPRIVATE + 3 /* Get country code */
+ case SIOCSIPFRAMING:
+ if(!suser()) /* For private IOCTLs, we need to check permissions */
+ {
+ err = -EPERM;
+ break;
+ }
+ translate = *(wrq->u.name); /* Set framing mode */
+ break;
+ case SIOCGIPFRAMING:
+ *(wrq->u.name) = translate;
+ break;
+ case SIOCGIPCOUNTRY:
+ *(wrq->u.name) = country;
+ break;
+ case SIOCGIWPRIV:
+ /* Export our "private" intercace */
+ if(wrq->u.data.pointer != (caddr_t) 0)
+ {
+ struct iw_priv_args priv[] =
+ { /* cmd, set_args, get_args, name */
+ { SIOCSIPFRAMING, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1, 0, "set_framing" },
+ { SIOCGIPFRAMING, 0, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1, "get_framing" },
+ { SIOCGIPCOUNTRY, 0, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1, "get_country" },
+ };
+ /* Set the number of ioctl available */
+ wrq->u.data.length = 3;
+ /* Copy structure to the user buffer */
+ if(copy_to_user(wrq->u.data.pointer, (u_char *) priv,
+ sizeof(priv)))
+ err = -EFAULT;
+ }
+ break;
+#endif /* WIRELESS_EXT > 7 */
+
+
default:
DEBUG(0,"ray_dev_ioctl cmd = 0x%x\n", cmd);
err = -EOPNOTSUPP;
@@ -1207,7 +1481,38 @@ int ray_dev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
return err;
} /* end ray_dev_ioctl */
/*===========================================================================*/
-int ray_open(struct net_device *dev)
+#if WIRELESS_EXT > 7 /* If wireless extension exist in the kernel */
+static iw_stats * ray_get_wireless_stats(struct device * dev)
+{
+ ray_dev_t * local = (ray_dev_t *) dev->priv;
+ dev_link_t *link = local->finder;
+ struct status *p = (struct status *)(local->sram + STATUS_BASE);
+
+ if(local == (ray_dev_t *) NULL)
+ return (iw_stats *) NULL;
+
+ local->wstats.status = local->card_status;
+#ifdef WIRELESS_SPY
+ if((local->spy_number > 0) && (local->sparm.b5.a_network_type == 0))
+ {
+ /* Get it from the first node in spy list */
+ local->wstats.qual.qual = local->spy_stat[0].qual;
+ local->wstats.qual.level = local->spy_stat[0].level;
+ local->wstats.qual.noise = local->spy_stat[0].noise;
+ local->wstats.qual.updated = local->spy_stat[0].updated;
+ }
+#endif /* WIRELESS_SPY */
+
+ if((link->state & DEV_PRESENT)) {
+ local->wstats.qual.noise = readb(&p->rxnoise);
+ local->wstats.qual.updated |= 4;
+ }
+
+ return &local->wstats;
+} /* end ray_get_wireless_stats */
+#endif /* WIRELESS_EXT > 7 */
+/*===========================================================================*/
+static int ray_open(struct net_device *dev)
{
dev_link_t *link;
ray_dev_t *local = (ray_dev_t *)dev->priv;
@@ -1232,7 +1537,7 @@ int ray_open(struct net_device *dev)
return 0;
} /* end ray_open */
/*===========================================================================*/
-int ray_dev_close(struct net_device *dev)
+static int ray_dev_close(struct net_device *dev)
{
dev_link_t *link;
@@ -1255,14 +1560,14 @@ int ray_dev_close(struct net_device *dev)
return 0;
} /* end ray_dev_close */
/*===========================================================================*/
-void ray_reset(struct net_device *dev) {
+static void ray_reset(struct net_device *dev) {
DEBUG(1,"ray_reset entered\n");
return;
}
/*===========================================================================*/
/* Cause a firmware interrupt if it is ready for one */
/* Return nonzero if not ready */
-int interrupt_ecf(ray_dev_t *local, int ccs)
+static int interrupt_ecf(ray_dev_t *local, int ccs)
{
int i = 50;
dev_link_t *link = local->finder;
@@ -1288,7 +1593,7 @@ int interrupt_ecf(ray_dev_t *local, int ccs)
/*===========================================================================*/
/* Get next free transmit CCS */
/* Return - index of current tx ccs */
-int get_free_tx_ccs(ray_dev_t *local)
+static int get_free_tx_ccs(ray_dev_t *local)
{
int i;
struct ccs *pccs = (struct ccs *)(local->sram + CCS_BASE);
@@ -1319,7 +1624,7 @@ int get_free_tx_ccs(ray_dev_t *local)
/*===========================================================================*/
/* Get next free CCS */
/* Return - index of current ccs */
-int get_free_ccs(ray_dev_t *local)
+static int get_free_ccs(ray_dev_t *local)
{
int i;
struct ccs *pccs = (struct ccs *)(local->sram + CCS_BASE);
@@ -1347,7 +1652,7 @@ int get_free_ccs(ray_dev_t *local)
return ECCSFULL;
} /* get_free_ccs */
/*===========================================================================*/
-void authenticate_timeout(u_long data)
+static void authenticate_timeout(u_long data)
{
ray_dev_t *local = (ray_dev_t *)data;
del_timer(&local->timer);
@@ -1356,7 +1661,7 @@ void authenticate_timeout(u_long data)
join_net((u_long)local);
}
/*===========================================================================*/
-int asc_to_int(char a)
+static int asc_to_int(char a)
{
if (a < '0') return -1;
if (a <= '9') return (a - '0');
@@ -1367,7 +1672,7 @@ int asc_to_int(char a)
return -1;
}
/*===========================================================================*/
-int parse_addr(char *in_str, UCHAR *out)
+static int parse_addr(char *in_str, UCHAR *out)
{
int len;
int i,j,k;
@@ -1395,7 +1700,7 @@ int parse_addr(char *in_str, UCHAR *out)
return status;
}
/*===========================================================================*/
-struct enet_statistics *ray_get_stats(struct net_device *dev)
+static struct enet_statistics *ray_get_stats(struct net_device *dev)
{
ray_dev_t *local = (ray_dev_t *)dev->priv;
dev_link_t *link = local->finder;
@@ -1425,7 +1730,7 @@ struct enet_statistics *ray_get_stats(struct net_device *dev)
return &local->stats;
}
/*===========================================================================*/
-void ray_update_parm(struct net_device *dev, UCHAR objid, UCHAR *value, int len)
+static void ray_update_parm(struct net_device *dev, UCHAR objid, UCHAR *value, int len)
{
ray_dev_t *local = (ray_dev_t *)dev->priv;
dev_link_t *link = local->finder;
@@ -1542,7 +1847,7 @@ static void set_multicast_list(struct net_device *dev)
/*=============================================================================
* All routines below here are run at interrupt time.
=============================================================================*/
-void ray_interrupt(int irq, void *dev_id, struct pt_regs * regs)
+static void ray_interrupt(int irq, void *dev_id, struct pt_regs * regs)
{
struct net_device *dev = (struct net_device *)dev_id;
dev_link_t *link;
@@ -1727,7 +2032,7 @@ void ray_interrupt(int irq, void *dev_id, struct pt_regs * regs)
break;
default:
DEBUG(1,"ray_cs Unexpected interrupt for RCS 0x%x cmd = 0x%x\n",\
- rcsindex, readb(&prcs->interrupt_id));
+ rcsindex, (unsigned int) readb(&prcs->interrupt_id));
break;
}
writeb(CCS_BUFFER_FREE, &prcs->buffer_status);
@@ -1736,7 +2041,7 @@ void ray_interrupt(int irq, void *dev_id, struct pt_regs * regs)
dev->interrupt = 0;
} /* ray_interrupt */
/*===========================================================================*/
-void ray_rx(struct net_device *dev, ray_dev_t *local, struct rcs *prcs)
+static void ray_rx(struct net_device *dev, ray_dev_t *local, struct rcs *prcs)
{
int rx_len;
unsigned int pkt_addr;
@@ -1750,6 +2055,7 @@ void ray_rx(struct net_device *dev, ray_dev_t *local, struct rcs *prcs)
rx_len = (readb(&prcs->var.rx_packet.rx_data_length[0]) << 8)
+ readb(&prcs->var.rx_packet.rx_data_length[1]);
+ local->last_rsl = readb(&prcs->var.rx_packet.rx_sig_lev);
pmsg = local->rmem + pkt_addr;
switch(readb(pmsg))
{
@@ -1778,17 +2084,18 @@ void ray_rx(struct net_device *dev, ray_dev_t *local, struct rcs *prcs)
rx_len < sizeof(struct beacon_rx) ?
rx_len : sizeof(struct beacon_rx));
+ local->beacon_rxed = 1;
/* Get the statistics so the card counters never overflow */
ray_get_stats(dev);
break;
default:
- DEBUG(0,"ray_cs unknown pkt type %2x\n", readb(pmsg));
+ DEBUG(0,"ray_cs unknown pkt type %2x\n", (unsigned int) readb(pmsg));
break;
}
} /* end ray_rx */
/*===========================================================================*/
-void rx_data(struct net_device *dev, struct rcs *prcs, unsigned int pkt_addr,
+static void rx_data(struct net_device *dev, struct rcs *prcs, unsigned int pkt_addr,
int rx_len)
{
struct sk_buff *skb = NULL;
@@ -1797,6 +2104,10 @@ void rx_data(struct net_device *dev, struct rcs *prcs, unsigned int pkt_addr,
UCHAR *rx_ptr;
int total_len;
int tmp;
+#ifdef WIRELESS_SPY
+ int siglev = prcs->var.rx_packet.rx_sig_lev;
+ u_char linksrcaddr[ETH_ALEN]; /* Other end of the wireless link */
+#endif
if (!sniffer) {
if (translate) {
@@ -1819,7 +2130,7 @@ void rx_data(struct net_device *dev, struct rcs *prcs, unsigned int pkt_addr,
}
DEBUG(4,"ray_cs rx_data packet\n");
/* If fragmented packet, verify sizes of fragments add up */
- if (prcs->var.rx_packet.next_frag_rcs_index != 0xFF) {
+ if (readb(&prcs->var.rx_packet.next_frag_rcs_index) != 0xFF) {
DEBUG(1,"ray_cs rx'ed fragment\n");
tmp = (readb(&prcs->var.rx_packet.totalpacketlength[0]) << 8)
+ readb(&prcs->var.rx_packet.totalpacketlength[1]);
@@ -1865,7 +2176,10 @@ void rx_data(struct net_device *dev, struct rcs *prcs, unsigned int pkt_addr,
rx_ptr = skb_put( skb, total_len);
/* Copy the whole packet to sk_buff */
rx_ptr += copy_from_rx_buff(local, rx_ptr, pkt_addr & RX_BUFF_END, rx_len);
-
+ /* Get source address */
+#ifdef WIRELESS_SPY
+ memcpy(linksrcaddr, ((struct mac_header *)skb->data)->addr_2, ETH_ALEN);
+#endif
/* Now, deal with encapsulation/translation/sniffer */
if (!sniffer) {
if (!translate) {
@@ -1909,9 +2223,39 @@ void rx_data(struct net_device *dev, struct rcs *prcs, unsigned int pkt_addr,
local->stats.rx_packets++;
local->stats.rx_bytes += skb->len;
+
+ /* Gather signal strength per address */
+#ifdef WIRELESS_SPY
+ /* For the Access Point or the node having started the ad-hoc net
+ * note : ad-hoc work only in some specific configurations, but we
+ * kludge in ray_get_wireless_stats... */
+ if(!memcmp(linksrcaddr, local->bss_id, ETH_ALEN))
+ {
+ /* Update statistics */
+ /*local->wstats.qual.qual = none ? */
+ local->wstats.qual.level = siglev;
+ /*local->wstats.qual.noise = none ? */
+ local->wstats.qual.updated = 0x2;
+ }
+ /* Now, for the addresses in the spy list */
+ {
+ int i;
+ /* Look all addresses */
+ for(i = 0; i < local->spy_number; i++)
+ /* If match */
+ if(!memcmp(linksrcaddr, local->spy_address[i], ETH_ALEN))
+ {
+ /* Update statistics */
+ /*local->spy_stat[i].qual = none ? */
+ local->spy_stat[i].level = siglev;
+ /*local->spy_stat[i].noise = none ? */
+ local->spy_stat[i].updated = 0x2;
+ }
+ }
+#endif /* WIRELESS_SPY */
} /* end rx_data */
/*===========================================================================*/
-void untranslate(ray_dev_t *local, struct sk_buff *skb, int len)
+static void untranslate(ray_dev_t *local, struct sk_buff *skb, int len)
{
snaphdr_t *psnap = (snaphdr_t *)(skb->data + RX_MAC_HEADER_LENGTH);
struct mac_header *pmac = (struct mac_header *)skb->data;
@@ -1923,11 +2267,23 @@ void untranslate(ray_dev_t *local, struct sk_buff *skb, int len)
UCHAR srcaddr[ADDRLEN];
UCHAR destaddr[ADDRLEN];
- if (local->sparm.b5.a_acting_as_ap_status != TYPE_STA)
- memcpy(destaddr, pmac->addr_3, ADDRLEN);
- else
- memcpy(destaddr, pmac->addr_1, ADDRLEN);
- memcpy(srcaddr, pmac->addr_2, ADDRLEN);
+ if (pmac->frame_ctl_2 & FC2_FROM_DS) {
+ if (pmac->frame_ctl_2 & FC2_TO_DS) { /* AP to AP */
+ memcpy(destaddr, pmac->addr_3, ADDRLEN);
+ memcpy(srcaddr, ((unsigned char *)pmac->addr_3) + ADDRLEN, ADDRLEN);
+ } else { /* AP to terminal */
+ memcpy(destaddr, pmac->addr_1, ADDRLEN);
+ memcpy(srcaddr, pmac->addr_3, ADDRLEN);
+ }
+ } else { /* Terminal to AP */
+ if (pmac->frame_ctl_2 & FC2_TO_DS) {
+ memcpy(destaddr, pmac->addr_3, ADDRLEN);
+ memcpy(srcaddr, pmac->addr_2, ADDRLEN);
+ } else { /* Adhoc */
+ memcpy(destaddr, pmac->addr_1, ADDRLEN);
+ memcpy(srcaddr, pmac->addr_2, ADDRLEN);
+ }
+ }
#ifdef PCMCIA_DEBUG
if (pc_debug > 3) {
@@ -2005,7 +2361,7 @@ void untranslate(ray_dev_t *local, struct sk_buff *skb, int len)
* pkt_addr = source address in receive buffer
* len = length of packet to copy
*/
-int copy_from_rx_buff(ray_dev_t *local, UCHAR *dest, int pkt_addr, int length)
+static int copy_from_rx_buff(ray_dev_t *local, UCHAR *dest, int pkt_addr, int length)
{
int wrap_bytes = (pkt_addr + length) - (RX_BUFF_END + 1);
if (wrap_bytes <= 0)
@@ -2020,7 +2376,7 @@ int copy_from_rx_buff(ray_dev_t *local, UCHAR *dest, int pkt_addr, int length)
return length;
}
/*===========================================================================*/
-void release_frag_chain(ray_dev_t *local, struct rcs* prcs)
+static void release_frag_chain(ray_dev_t *local, struct rcs* prcs)
{
struct rcs *prcslink = prcs;
int tmp = 17;
@@ -2038,7 +2394,7 @@ void release_frag_chain(ray_dev_t *local, struct rcs* prcs)
writeb(CCS_BUFFER_FREE, &prcslink->buffer_status);
}
/*===========================================================================*/
-void authenticate(ray_dev_t *local)
+static void authenticate(ray_dev_t *local)
{
dev_link_t *link = local->finder;
DEBUG(0,"ray_cs Starting authentication.\n");
@@ -2060,7 +2416,7 @@ void authenticate(ray_dev_t *local)
local->authentication_state = AWAITING_RESPONSE;
} /* end authenticate */
/*===========================================================================*/
-void rx_authenticate(ray_dev_t *local, struct rcs *prcs,
+static void rx_authenticate(ray_dev_t *local, struct rcs *prcs,
unsigned int pkt_addr, int rx_len)
{
UCHAR buff[256];
@@ -2103,7 +2459,7 @@ void rx_authenticate(ray_dev_t *local, struct rcs *prcs,
} /* end rx_authenticate */
/*===========================================================================*/
-void associate(ray_dev_t *local)
+static void associate(ray_dev_t *local)
{
struct ccs *pccs;
dev_link_t *link = local->finder;
@@ -2141,7 +2497,7 @@ void associate(ray_dev_t *local)
} /* end associate */
/*===========================================================================*/
-void rx_deauthenticate(ray_dev_t *local, struct rcs *prcs,
+static void rx_deauthenticate(ray_dev_t *local, struct rcs *prcs,
unsigned int pkt_addr, int rx_len)
{
/* UCHAR buff[256];
@@ -2154,7 +2510,7 @@ void rx_deauthenticate(ray_dev_t *local, struct rcs *prcs,
*/
}
/*===========================================================================*/
-void clear_interrupt(ray_dev_t *local)
+static void clear_interrupt(ray_dev_t *local)
{
writeb(0, local->amem + CIS_OFFSET + HCS_INTR_OFFSET);
}
@@ -2183,7 +2539,7 @@ static char *nettype[] = {"Adhoc", "Infra "};
static char *framing[] = {"Encapsulation", "Translation"}
;
/*===========================================================================*/
-int ray_cs_proc_read(char *buf, char **start, off_t offset,
+static int ray_cs_proc_read(char *buf, char **start, off_t offset,
int len, int unused)
{
/* Print current values which are not available via other means
@@ -2229,10 +2585,13 @@ int ray_cs_proc_read(char *buf, char **start, off_t offset,
len += sprintf(buf + len, "Framing mode = %s\n",framing[translate]);
- /* Pull some fields out of last beacon received */
- len += sprintf(buf + len, "Beacon Interval = %d Kus\n",
- local->last_bcn.beacon_intvl[0]
- + 256 * local->last_bcn.beacon_intvl[1]);
+ len += sprintf(buf + len, "Last pkt signal lvl = %d\n", local->last_rsl);
+
+ if (local->beacon_rxed) {
+ /* Pull some fields out of last beacon received */
+ len += sprintf(buf + len, "Beacon Interval = %d Kus\n",
+ local->last_bcn.beacon_intvl[0]
+ + 256 * local->last_bcn.beacon_intvl[1]);
p = local->last_bcn.elements;
if (p[0] == C_ESSID_ELEMENT_ID) p += p[1] + 2;
@@ -2253,25 +2612,28 @@ int ray_cs_proc_read(char *buf, char **start, off_t offset,
return len;
}
- if (p[0] == C_FH_PARAM_SET_ELEMENT_ID) {
- pfh = (struct freq_hop_element *)p;
- len += sprintf(buf + len, "Hop dwell = %d Kus\n",
- pfh->dwell_time[0] + 256 * pfh->dwell_time[1]);
- len += sprintf(buf + len, "Hop set = %d \n", pfh->hop_set);
- len += sprintf(buf + len, "Hop pattern = %d \n", pfh->hop_pattern);
- len += sprintf(buf + len, "Hop index = %d \n", pfh->hop_index);
- p += p[1] + 2;
- }
- else {
- len += sprintf(buf + len, "Parse beacon failed at FH param element\n");
- return len;
+ if (p[0] == C_FH_PARAM_SET_ELEMENT_ID) {
+ pfh = (struct freq_hop_element *)p;
+ len += sprintf(buf + len, "Hop dwell = %d Kus\n",
+ pfh->dwell_time[0] + 256 * pfh->dwell_time[1]);
+ len += sprintf(buf + len, "Hop set = %d \n", pfh->hop_set);
+ len += sprintf(buf + len, "Hop pattern = %d \n", pfh->hop_pattern);
+ len += sprintf(buf + len, "Hop index = %d \n", pfh->hop_index);
+ p += p[1] + 2;
+ }
+ else {
+ len += sprintf(buf + len, "Parse beacon failed at FH param element\n");
+ return len;
+ }
+ } else {
+ len += sprintf(buf + len, "No beacons received\n");
}
return len;
}
#endif
/*===========================================================================*/
-int build_auth_frame(ray_dev_t *local, UCHAR *dest, int auth_type)
+static int build_auth_frame(ray_dev_t *local, UCHAR *dest, int auth_type)
{
int addr;
struct ccs *pccs;
diff --git a/drivers/net/pcmcia/ray_cs.h b/drivers/net/pcmcia/ray_cs.h
index ae28bc71a..6f6f8e6ca 100644
--- a/drivers/net/pcmcia/ray_cs.h
+++ b/drivers/net/pcmcia/ray_cs.h
@@ -60,7 +60,18 @@ typedef struct ray_dev_t {
UCHAR ASIC_version;
UCHAR assoc_id[2];
UCHAR tib_length;
+ UCHAR last_rsl;
+ int beacon_rxed;
struct beacon_rx last_bcn;
+#ifdef WIRELESS_EXT
+ iw_stats wstats; /* Wireless specific stats */
+#endif
+#ifdef WIRELESS_SPY
+ int spy_number; /* Number of addresses to spy */
+ mac_addr spy_address[IW_MAX_SPY + 1]; /* The addresses to spy */
+ iw_qual spy_stat[IW_MAX_SPY + 1]; /* Statistics gathered */
+#endif /* WIRELESS_SPY */
+
} ray_dev_t;
/*****************************************************************************/
diff --git a/drivers/net/ppp_generic.c b/drivers/net/ppp_generic.c
index 19b0c5819..bfe494177 100644
--- a/drivers/net/ppp_generic.c
+++ b/drivers/net/ppp_generic.c
@@ -561,6 +561,7 @@ ppp_init(struct net_device *dev)
#ifndef MODULE
extern struct compressor ppp_deflate, ppp_deflate_draft;
extern int ppp_async_init(void);
+ extern int ppp_sync_init(void);
#endif
printk(KERN_INFO "PPP generic driver version " PPP_VERSION "\n");
@@ -571,6 +572,9 @@ ppp_init(struct net_device *dev)
#ifdef CONFIG_PPP_ASYNC
ppp_async_init();
#endif
+#ifdef CONFIG_PPP_SYNC_TTY
+ ppp_sync_init();
+#endif
#ifdef CONFIG_PPP_DEFLATE
if (ppp_register_compressor(&ppp_deflate) == 0)
printk(KERN_INFO "PPP Deflate compression module registered\n");
diff --git a/drivers/net/ppp_synctty.c b/drivers/net/ppp_synctty.c
new file mode 100644
index 000000000..5a1755b4e
--- /dev/null
+++ b/drivers/net/ppp_synctty.c
@@ -0,0 +1,768 @@
+/*
+ * PPP synchronous tty channel driver for Linux.
+ *
+ * This is a ppp channel driver that can be used with tty device drivers
+ * that are frame oriented, such as synchronous HDLC devices.
+ *
+ * Complete PPP frames without encoding/decoding are exchanged between
+ * the channel driver and the device driver.
+ *
+ * The async map IOCTL codes are implemented to keep the user mode
+ * applications happy if they call them. Synchronous PPP does not use
+ * the async maps.
+ *
+ * Copyright 1999 Paul Mackerras.
+ *
+ * Also touched by the grubby hands of Paul Fulghum paulkf@microgate.com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ * This driver provides the encapsulation and framing for sending
+ * and receiving PPP frames over sync serial lines. It relies on
+ * the generic PPP layer to give it frames to send and to process
+ * received frames. It implements the PPP line discipline.
+ *
+ * Part of the code in this driver was inspired by the old sync-only
+ * PPP driver, written by Michael Callahan and Al Longyear, and
+ * subsequently hacked by Paul Mackerras.
+ *
+ * ==FILEVERSION 991014==
+ */
+
+/* $Id: ppp_synctty.c,v 1.3 1999/09/02 05:30:10 paulus Exp $ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/skbuff.h>
+#include <linux/tty.h>
+#include <linux/netdevice.h>
+#include <linux/poll.h>
+#include <linux/ppp_defs.h>
+#include <linux/if_ppp.h>
+#include <linux/ppp_channel.h>
+#include <asm/uaccess.h>
+
+#define PPP_VERSION "2.4.0"
+
+/* Structure for storing local state. */
+struct syncppp {
+ struct tty_struct *tty;
+ unsigned int flags;
+ unsigned int rbits;
+ int mru;
+ unsigned long busy;
+ u32 xaccm[8];
+ u32 raccm;
+ unsigned int bytes_sent;
+ unsigned int bytes_rcvd;
+
+ struct sk_buff *tpkt;
+ struct sk_buff_head xq;
+ unsigned long last_xmit;
+
+ struct sk_buff *rpkt;
+ struct sk_buff_head rq;
+ wait_queue_head_t rwait;
+
+ struct ppp_channel chan; /* interface to generic ppp layer */
+ int connected;
+};
+
+/* Bit numbers in busy */
+#define XMIT_BUSY 0
+#define RECV_BUSY 1
+#define XMIT_WAKEUP 2
+#define XMIT_FULL 3
+
+/* Bits in rbits */
+#define SC_RCV_BITS (SC_RCV_B7_1|SC_RCV_B7_0|SC_RCV_ODDP|SC_RCV_EVNP)
+
+#define PPPSYNC_MAX_RQLEN 32 /* arbitrary */
+
+/*
+ * Prototypes.
+ */
+static struct sk_buff* ppp_sync_txdequeue(struct syncppp *ap);
+static int ppp_sync_send(struct ppp_channel *chan, struct sk_buff *skb);
+static int ppp_sync_push(struct syncppp *ap);
+static void ppp_sync_flush_output(struct syncppp *ap);
+static void ppp_sync_input(struct syncppp *ap, const unsigned char *buf,
+ char *flags, int count);
+
+struct ppp_channel_ops sync_ops = {
+ ppp_sync_send
+};
+
+/*
+ * Routines for locking and unlocking the transmit and receive paths.
+ */
+static inline void
+lock_path(struct syncppp *ap, int bit)
+{
+ do {
+ while (test_bit(bit, &ap->busy))
+ mb();
+ } while (test_and_set_bit(bit, &ap->busy));
+ mb();
+}
+
+static inline int
+trylock_path(struct syncppp *ap, int bit)
+{
+ if (test_and_set_bit(bit, &ap->busy))
+ return 0;
+ mb();
+ return 1;
+}
+
+static inline void
+unlock_path(struct syncppp *ap, int bit)
+{
+ mb();
+ clear_bit(bit, &ap->busy);
+}
+
+#define lock_xmit_path(ap) lock_path(ap, XMIT_BUSY)
+#define trylock_xmit_path(ap) trylock_path(ap, XMIT_BUSY)
+#define unlock_xmit_path(ap) unlock_path(ap, XMIT_BUSY)
+#define lock_recv_path(ap) lock_path(ap, RECV_BUSY)
+#define trylock_recv_path(ap) trylock_path(ap, RECV_BUSY)
+#define unlock_recv_path(ap) unlock_path(ap, RECV_BUSY)
+
+static inline void
+flush_skb_queue(struct sk_buff_head *q)
+{
+ struct sk_buff *skb;
+
+ while ((skb = skb_dequeue(q)) != 0)
+ kfree_skb(skb);
+}
+
+/*
+ * Routines implementing the synchronous PPP line discipline.
+ */
+
+/*
+ * Called when a tty is put into line discipline.
+ */
+static int
+ppp_sync_open(struct tty_struct *tty)
+{
+ struct syncppp *ap;
+
+ ap = kmalloc(sizeof(*ap), GFP_KERNEL);
+ if (ap == 0)
+ return -ENOMEM;
+
+ MOD_INC_USE_COUNT;
+
+ /* initialize the syncppp structure */
+ memset(ap, 0, sizeof(*ap));
+ ap->tty = tty;
+ ap->mru = PPP_MRU;
+ ap->xaccm[0] = ~0U;
+ ap->xaccm[3] = 0x60000000U;
+ ap->raccm = ~0U;
+ skb_queue_head_init(&ap->xq);
+ skb_queue_head_init(&ap->rq);
+ init_waitqueue_head(&ap->rwait);
+
+ tty->disc_data = ap;
+
+ return 0;
+}
+
+/*
+ * Called when the tty is put into another line discipline
+ * (or it hangs up).
+ */
+static void
+ppp_sync_close(struct tty_struct *tty)
+{
+ struct syncppp *ap = tty->disc_data;
+
+ if (ap == 0)
+ return;
+ tty->disc_data = 0;
+ lock_xmit_path(ap);
+ lock_recv_path(ap);
+ if (ap->rpkt != 0)
+ kfree_skb(ap->rpkt);
+ flush_skb_queue(&ap->rq);
+ if (ap->tpkt != 0)
+ kfree_skb(ap->tpkt);
+ flush_skb_queue(&ap->xq);
+ if (ap->connected)
+ ppp_unregister_channel(&ap->chan);
+ kfree(ap);
+ MOD_DEC_USE_COUNT;
+}
+
+/*
+ * Read a PPP frame. pppd can use this to negotiate over the
+ * channel before it joins it to a bundle.
+ */
+static ssize_t
+ppp_sync_read(struct tty_struct *tty, struct file *file,
+ unsigned char *buf, size_t count)
+{
+ struct syncppp *ap = tty->disc_data;
+ DECLARE_WAITQUEUE(wait, current);
+ ssize_t ret;
+ struct sk_buff *skb = 0;
+
+ ret = -ENXIO;
+ if (ap == 0)
+ goto out; /* should never happen */
+
+ add_wait_queue(&ap->rwait, &wait);
+ current->state = TASK_INTERRUPTIBLE;
+ for (;;) {
+ ret = -EAGAIN;
+ skb = skb_dequeue(&ap->rq);
+ if (skb)
+ break;
+ if (file->f_flags & O_NONBLOCK)
+ break;
+ ret = -ERESTARTSYS;
+ if (signal_pending(current))
+ break;
+ schedule();
+ }
+ current->state = TASK_RUNNING;
+ remove_wait_queue(&ap->rwait, &wait);
+
+ if (skb == 0)
+ goto out;
+
+ ret = -EOVERFLOW;
+ if (skb->len > count)
+ goto outf;
+ ret = -EFAULT;
+ if (copy_to_user(buf, skb->data, skb->len))
+ goto outf;
+ ret = skb->len;
+
+ outf:
+ kfree_skb(skb);
+ out:
+ return ret;
+}
+
+/*
+ * Write a ppp frame. pppd can use this to send frames over
+ * this particular channel.
+ */
+static ssize_t
+ppp_sync_write(struct tty_struct *tty, struct file *file,
+ const unsigned char *buf, size_t count)
+{
+ struct syncppp *ap = tty->disc_data;
+ struct sk_buff *skb;
+ ssize_t ret;
+
+ ret = -ENXIO;
+ if (ap == 0)
+ goto out; /* should never happen */
+
+ ret = -ENOMEM;
+ skb = alloc_skb(count + 2, GFP_KERNEL);
+ if (skb == 0)
+ goto out;
+ skb_reserve(skb, 2);
+ ret = -EFAULT;
+ if (copy_from_user(skb_put(skb, count), buf, count)) {
+ kfree_skb(skb);
+ goto out;
+ }
+
+ skb_queue_tail(&ap->xq, skb);
+ ppp_sync_push(ap);
+
+ ret = count;
+
+ out:
+ return ret;
+}
+
+static int
+ppp_sync_ioctl(struct tty_struct *tty, struct file *file,
+ unsigned int cmd, unsigned long arg)
+{
+ struct syncppp *ap = tty->disc_data;
+ int err, val;
+ u32 accm[8];
+ struct sk_buff *skb;
+
+ err = -ENXIO;
+ if (ap == 0)
+ goto out; /* should never happen */
+ err = -EPERM;
+ if (!capable(CAP_NET_ADMIN))
+ goto out;
+
+ err = -EFAULT;
+ switch (cmd) {
+ case PPPIOCGFLAGS:
+ val = ap->flags | ap->rbits;
+ if (put_user(val, (int *) arg))
+ break;
+ err = 0;
+ break;
+ case PPPIOCSFLAGS:
+ if (get_user(val, (int *) arg))
+ break;
+ ap->flags = val & ~SC_RCV_BITS;
+ ap->rbits = val & SC_RCV_BITS;
+ err = 0;
+ break;
+
+ case PPPIOCGASYNCMAP:
+ if (put_user(ap->xaccm[0], (u32 *) arg))
+ break;
+ err = 0;
+ break;
+ case PPPIOCSASYNCMAP:
+ if (get_user(ap->xaccm[0], (u32 *) arg))
+ break;
+ err = 0;
+ break;
+
+ case PPPIOCGRASYNCMAP:
+ if (put_user(ap->raccm, (u32 *) arg))
+ break;
+ err = 0;
+ break;
+ case PPPIOCSRASYNCMAP:
+ if (get_user(ap->raccm, (u32 *) arg))
+ break;
+ err = 0;
+ break;
+
+ case PPPIOCGXASYNCMAP:
+ if (copy_to_user((void *) arg, ap->xaccm, sizeof(ap->xaccm)))
+ break;
+ err = 0;
+ break;
+ case PPPIOCSXASYNCMAP:
+ if (copy_from_user(accm, (void *) arg, sizeof(accm)))
+ break;
+ accm[2] &= ~0x40000000U; /* can't escape 0x5e */
+ accm[3] |= 0x60000000U; /* must escape 0x7d, 0x7e */
+ memcpy(ap->xaccm, accm, sizeof(ap->xaccm));
+ err = 0;
+ break;
+
+ case PPPIOCGMRU:
+ if (put_user(ap->mru, (int *) arg))
+ break;
+ err = 0;
+ break;
+ case PPPIOCSMRU:
+ if (get_user(val, (int *) arg))
+ break;
+ if (val < PPP_MRU)
+ val = PPP_MRU;
+ ap->mru = val;
+ err = 0;
+ break;
+
+ case PPPIOCATTACH:
+ if (get_user(val, (int *) arg))
+ break;
+ err = -EALREADY;
+ if (ap->connected)
+ break;
+ ap->chan.private = ap;
+ ap->chan.ops = &sync_ops;
+ err = ppp_register_channel(&ap->chan, val);
+ if (err != 0)
+ break;
+ ap->connected = 1;
+ break;
+ case PPPIOCDETACH:
+ err = -ENXIO;
+ if (!ap->connected)
+ break;
+ ppp_unregister_channel(&ap->chan);
+ ap->connected = 0;
+ err = 0;
+ break;
+
+ case TCGETS:
+ case TCGETA:
+ err = n_tty_ioctl(tty, file, cmd, arg);
+ break;
+
+ case TCFLSH:
+ /* flush our buffers and the serial port's buffer */
+ if (arg == TCIFLUSH || arg == TCIOFLUSH)
+ flush_skb_queue(&ap->rq);
+ if (arg == TCIOFLUSH || arg == TCOFLUSH)
+ ppp_sync_flush_output(ap);
+ err = n_tty_ioctl(tty, file, cmd, arg);
+ break;
+
+ case FIONREAD:
+ val = 0;
+ if ((skb = skb_peek(&ap->rq)) != 0)
+ val = skb->len;
+ if (put_user(val, (int *) arg))
+ break;
+ err = 0;
+ break;
+
+ default:
+ err = -ENOIOCTLCMD;
+ }
+ out:
+ return err;
+}
+
+static unsigned int
+ppp_sync_poll(struct tty_struct *tty, struct file *file, poll_table *wait)
+{
+ struct syncppp *ap = tty->disc_data;
+ unsigned int mask;
+
+ if (ap == 0)
+ return 0; /* should never happen */
+ poll_wait(file, &ap->rwait, wait);
+ mask = POLLOUT | POLLWRNORM;
+ if (skb_peek(&ap->rq))
+ mask |= POLLIN | POLLRDNORM;
+ if (test_bit(TTY_OTHER_CLOSED, &tty->flags) || tty_hung_up_p(file))
+ mask |= POLLHUP;
+ return mask;
+}
+
+static int
+ppp_sync_room(struct tty_struct *tty)
+{
+ return 65535;
+}
+
+static void
+ppp_sync_receive(struct tty_struct *tty, const unsigned char *buf,
+ char *flags, int count)
+{
+ struct syncppp *ap = tty->disc_data;
+
+ if (ap == 0)
+ return;
+ trylock_recv_path(ap);
+ ppp_sync_input(ap, buf, flags, count);
+ unlock_recv_path(ap);
+ if (test_and_clear_bit(TTY_THROTTLED, &tty->flags)
+ && tty->driver.unthrottle)
+ tty->driver.unthrottle(tty);
+}
+
+static void
+ppp_sync_wakeup(struct tty_struct *tty)
+{
+ struct syncppp *ap = tty->disc_data;
+
+ clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
+ if (ap == 0)
+ return;
+ if (ppp_sync_push(ap) && ap->connected)
+ ppp_output_wakeup(&ap->chan);
+}
+
+
+static struct tty_ldisc ppp_sync_ldisc = {
+ magic: TTY_LDISC_MAGIC,
+ name: "pppsync",
+ open: ppp_sync_open,
+ close: ppp_sync_close,
+ read: ppp_sync_read,
+ write: ppp_sync_write,
+ ioctl: ppp_sync_ioctl,
+ poll: ppp_sync_poll,
+ receive_room: ppp_sync_room,
+ receive_buf: ppp_sync_receive,
+ write_wakeup: ppp_sync_wakeup,
+};
+
+int
+ppp_sync_init(void)
+{
+ int err;
+
+ err = tty_register_ldisc(N_SYNC_PPP, &ppp_sync_ldisc);
+ if (err != 0)
+ printk(KERN_ERR "PPP_sync: error %d registering line disc.\n",
+ err);
+ return err;
+}
+
+/*
+ * Procedures for encapsulation and framing.
+ */
+
+struct sk_buff*
+ppp_sync_txdequeue(struct syncppp *ap)
+{
+ int proto;
+ unsigned char *data;
+ int islcp;
+ struct sk_buff *skb;
+
+ while ((skb = skb_dequeue(&ap->xq)) != NULL) {
+
+ data = skb->data;
+ proto = (data[0] << 8) + data[1];
+
+ /* LCP packets with codes between 1 (configure-request)
+ * and 7 (code-reject) must be sent as though no options
+ * have been negotiated.
+ */
+ islcp = proto == PPP_LCP && 1 <= data[2] && data[2] <= 7;
+
+ /* prepend address/control fields if necessary */
+ if ((ap->flags & SC_COMP_AC) == 0 || islcp) {
+ if (skb_headroom(skb) < 2) {
+ struct sk_buff *npkt = dev_alloc_skb(skb->len + 2);
+ if (npkt == NULL) {
+ kfree_skb(skb);
+ continue;
+ }
+ skb_reserve(npkt,2);
+ memcpy(skb_put(npkt,skb->len), skb->data, skb->len);
+ kfree_skb(skb);
+ skb = npkt;
+ }
+ skb_pull(skb,2);
+ skb->data[0] = PPP_ALLSTATIONS;
+ skb->data[1] = PPP_UI;
+ }
+
+ ap->last_xmit = jiffies;
+ break;
+ }
+
+ return skb;
+}
+
+/*
+ * Transmit-side routines.
+ */
+
+/*
+ * Send a packet to the peer over an sync tty line.
+ * Returns 1 iff the packet was accepted.
+ * If the packet was not accepted, we will call ppp_output_wakeup
+ * at some later time.
+ */
+static int
+ppp_sync_send(struct ppp_channel *chan, struct sk_buff *skb)
+{
+ struct syncppp *ap = chan->private;
+
+ ppp_sync_push(ap);
+
+ if (test_and_set_bit(XMIT_FULL, &ap->busy))
+ return 0; /* already full */
+ ap->tpkt = skb;
+
+ ppp_sync_push(ap);
+ return 1;
+}
+
+/*
+ * Push as much data as possible out to the tty.
+ */
+static int
+ppp_sync_push(struct syncppp *ap)
+{
+ int sent, done = 0;
+ struct tty_struct *tty = ap->tty;
+ int tty_stuffed = 0;
+
+ if (!trylock_xmit_path(ap)) {
+ set_bit(XMIT_WAKEUP, &ap->busy);
+ return 0;
+ }
+ for (;;) {
+ if (test_and_clear_bit(XMIT_WAKEUP, &ap->busy))
+ tty_stuffed = 0;
+ if (ap->tpkt == 0) {
+ if ((ap->tpkt = ppp_sync_txdequeue(ap)) == 0) {
+ clear_bit(XMIT_FULL, &ap->busy);
+ done = 1;
+ }
+ }
+ if (!tty_stuffed && ap->tpkt != NULL) {
+ set_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
+ sent = tty->driver.write(tty, 0, ap->tpkt->data, ap->tpkt->len);
+ if (sent < 0)
+ goto flush; /* error, e.g. loss of CD */
+ if (sent < ap->tpkt->len) {
+ tty_stuffed = 1;
+ } else {
+ kfree_skb(ap->tpkt);
+ ap->tpkt = 0;
+ }
+ continue;
+ }
+ /* haven't made any progress */
+ unlock_xmit_path(ap);
+ if (!(test_bit(XMIT_WAKEUP, &ap->busy)
+ || (!tty_stuffed && ap->tpkt != 0)))
+ break;
+ if (!trylock_xmit_path(ap))
+ break;
+ }
+ return done;
+
+flush:
+ if (ap->tpkt != 0) {
+ kfree_skb(ap->tpkt);
+ ap->tpkt = 0;
+ clear_bit(XMIT_FULL, &ap->busy);
+ done = 1;
+ }
+ unlock_xmit_path(ap);
+ return done;
+}
+
+/*
+ * Flush output from our internal buffers.
+ * Called for the TCFLSH ioctl.
+ */
+static void
+ppp_sync_flush_output(struct syncppp *ap)
+{
+ int done = 0;
+
+ flush_skb_queue(&ap->xq);
+ lock_xmit_path(ap);
+ if (ap->tpkt != NULL) {
+ kfree_skb(ap->tpkt);
+ ap->tpkt = 0;
+ clear_bit(XMIT_FULL, &ap->busy);
+ done = 1;
+ }
+ unlock_xmit_path(ap);
+ if (done && ap->connected)
+ ppp_output_wakeup(&ap->chan);
+}
+
+/*
+ * Receive-side routines.
+ */
+
+static inline void
+process_input_packet(struct syncppp *ap)
+{
+ struct sk_buff *skb;
+ unsigned char *p;
+ int code = 0;
+
+ skb = ap->rpkt;
+ ap->rpkt = 0;
+
+ /* strip address/control field if present */
+ p = skb->data;
+ if (p[0] == PPP_ALLSTATIONS && p[1] == PPP_UI) {
+ /* chop off address/control */
+ if (skb->len < 3)
+ goto err;
+ p = skb_pull(skb, 2);
+ }
+
+ /* decompress protocol field if compressed */
+ if (p[0] & 1) {
+ /* protocol is compressed */
+ skb_push(skb, 1)[0] = 0;
+ } else if (skb->len < 2)
+ goto err;
+
+ /* pass to generic layer or queue it */
+ if (ap->connected) {
+ ppp_input(&ap->chan, skb);
+ } else {
+ skb_queue_tail(&ap->rq, skb);
+ /* drop old frames if queue too long */
+ while (ap->rq.qlen > PPPSYNC_MAX_RQLEN
+ && (skb = skb_dequeue(&ap->rq)) != 0)
+ kfree(skb);
+ wake_up_interruptible(&ap->rwait);
+ }
+ return;
+
+ err:
+ kfree_skb(skb);
+ if (ap->connected)
+ ppp_input_error(&ap->chan, code);
+}
+
+static inline void
+input_error(struct syncppp *ap, int code)
+{
+ if (ap->connected)
+ ppp_input_error(&ap->chan, code);
+}
+
+/* called when the tty driver has data for us.
+ *
+ * Data is frame oriented: each call to ppp_sync_input is considered
+ * a whole frame. If the 1st flag byte is non-zero then the whole
+ * frame is considered to be in error and is tossed.
+ */
+static void
+ppp_sync_input(struct syncppp *ap, const unsigned char *buf,
+ char *flags, int count)
+{
+ struct sk_buff *skb;
+ unsigned char *sp;
+
+ if (count == 0)
+ return;
+
+ /* if flag set, then error, ignore frame */
+ if (flags != 0 && *flags) {
+ input_error(ap, *flags);
+ return;
+ }
+
+ /* stuff the chars in the skb */
+ if ((skb = ap->rpkt) == 0) {
+ if ((skb = dev_alloc_skb(ap->mru + PPP_HDRLEN + 2)) == 0) {
+ printk(KERN_ERR "PPPsync: no memory (input pkt)\n");
+ input_error(ap, 0);
+ return;
+ }
+ /* Try to get the payload 4-byte aligned */
+ if (buf[0] != PPP_ALLSTATIONS)
+ skb_reserve(skb, 2 + (buf[0] & 1));
+ ap->rpkt = skb;
+ }
+ if (count > skb_tailroom(skb)) {
+ /* packet overflowed MRU */
+ input_error(ap, 1);
+ } else {
+ sp = skb_put(skb, count);
+ memcpy(sp, buf, count);
+ process_input_packet(ap);
+ }
+}
+
+#ifdef MODULE
+int
+init_module(void)
+{
+ return ppp_sync_init();
+}
+
+void
+cleanup_module(void)
+{
+ if (tty_register_ldisc(N_SYNC_PPP, NULL) != 0)
+ printk(KERN_ERR "failed to unregister Sync PPP line discipline\n");
+}
+#endif /* MODULE */
diff --git a/drivers/net/strip.c b/drivers/net/strip.c
index 9acb7f031..b9131cb73 100644
--- a/drivers/net/strip.c
+++ b/drivers/net/strip.c
@@ -118,6 +118,7 @@ static const char StripVersion[] = "1.3-STUART.CHESHIRE";
#include <linux/if_arp.h>
#include <linux/if_strip.h>
#include <linux/proc_fs.h>
+#include <linux/serialP.h>
#include <linux/serial.h>
#include <net/arp.h>
diff --git a/drivers/pci/pcisyms.c b/drivers/pci/pcisyms.c
index 030e36f3d..44d272776 100644
--- a/drivers/pci/pcisyms.c
+++ b/drivers/pci/pcisyms.c
@@ -19,6 +19,7 @@ EXPORT_SYMBOL(pci_write_config_word);
EXPORT_SYMBOL(pci_write_config_dword);
EXPORT_SYMBOL(pci_devices);
EXPORT_SYMBOL(pci_root);
+EXPORT_SYMBOL(pci_enable_device);
EXPORT_SYMBOL(pci_find_class);
EXPORT_SYMBOL(pci_find_device);
EXPORT_SYMBOL(pci_find_slot);
diff --git a/drivers/pcmcia/rsrc_mgr.c b/drivers/pcmcia/rsrc_mgr.c
index fa6eba768..736ac0c05 100644
--- a/drivers/pcmcia/rsrc_mgr.c
+++ b/drivers/pcmcia/rsrc_mgr.c
@@ -100,16 +100,6 @@ static irq_info_t irq_table[NR_IRQS] = { { 0, 0, 0 }, /* etc */ };
/*======================================================================
- Linux resource management extensions
-
-======================================================================*/
-
-static spinlock_t rsrc_lock = SPIN_LOCK_UNLOCKED;
-
-#define check_io_region(b,n) (0)
-
-/*======================================================================
-
These manage the internal databases of available resources.
======================================================================*/
@@ -190,7 +180,7 @@ static void do_io_probe(ioaddr_t base, ioaddr_t num)
b = kmalloc(256, GFP_KERNEL);
memset(b, 0, 256);
for (i = base, most = 0; i < base+num; i += 8) {
- if (check_region(i, 8) || check_io_region(i, 8))
+ if (check_region(i, 8))
continue;
hole = inb(i);
for (j = 1; j < 8; j++)
@@ -203,7 +193,7 @@ static void do_io_probe(ioaddr_t base, ioaddr_t num)
bad = any = 0;
for (i = base; i < base+num; i += 8) {
- if (check_region(i, 8) || check_io_region(i, 8))
+ if (check_region(i, 8))
continue;
for (j = 0; j < 8; j++)
if (inb(i+j) != most) break;
@@ -365,8 +355,7 @@ int find_io_region(ioaddr_t *base, ioaddr_t num, char *name)
if (*base != 0) {
for (m = io_db.next; m != &io_db; m = m->next) {
if ((*base >= m->base) && (*base+num <= m->base+m->num)) {
- if (check_region(*base, num) ||
- check_io_region(*base, num)) {
+ if (check_region(*base, num)) {
return -1;
} else {
request_region(*base, num, name);
@@ -382,8 +371,7 @@ int find_io_region(ioaddr_t *base, ioaddr_t num, char *name)
for (*base = (m->base + align - 1) & (~(align-1));
*base+align <= m->base + m->num;
*base += align)
- if ((check_region(*base, num) == 0) &&
- (check_io_region(*base, num) == 0)) {
+ if (check_region(*base, num) == 0) {
request_region(*base, num, name);
return 0;
}
diff --git a/drivers/scsi/script_asm.pl b/drivers/scsi/script_asm.pl
index d99fcc950..a25a7271a 100644
--- a/drivers/scsi/script_asm.pl
+++ b/drivers/scsi/script_asm.pl
@@ -896,7 +896,7 @@ foreach $label (@label) {
open (OUTPUT, ">$output") || die "$0 : can't open $output for writing\n";
open (OUTPUTU, ">$outputu") || die "$0 : can't open $outputu for writing\n";
-print OUTPUT "u32 ".$prefix."SCRIPT[] = {\n";
+print OUTPUT "static u32 ".$prefix."SCRIPT[] = {\n";
$instructions = 0;
for ($i = 0; $i < $#code; ) {
if ($list_in_array) {
@@ -935,7 +935,7 @@ foreach $i (@absolute) {
}
printf OUTPUTU "#undef A_$i\n";
- printf OUTPUT "u32 A_".$i."_used\[\] = {\n";
+ printf OUTPUT "static u32 A_".$i."_used\[\] __attribute((unused)) = {\n";
printf STDERR "$i is used $symbol_references{$i}\n" if ($debug);
foreach $j (split (/\s+/,$symbol_references{$i})) {
$j =~ /(ABS|REL),(.*),(.*)/;
@@ -957,15 +957,15 @@ foreach $i (sort @entry) {
# NCR assembler outputs label patches in the form of indices into
# the code.
#
-printf OUTPUT "u32 ".$prefix."LABELPATCHES[] = {\n";
+printf OUTPUT "static u32 ".$prefix."LABELPATCHES[] __attribute((unused)) = {\n";
for $patch (sort {$a <=> $b} @label_patches) {
printf OUTPUT "\t0x%08x,\n", $patch;
}
printf OUTPUT "};\n\n";
$num_external_patches = 0;
-printf OUTPUT "struct {\n\tu32\toffset;\n\tvoid\t\t*address;\n".
- "} ".$prefix."EXTERNAL_PATCHES[] = {\n";
+printf OUTPUT "static struct {\n\tu32\toffset;\n\tvoid\t\t*address;\n".
+ "} ".$prefix."EXTERNAL_PATCHES[] __attribute((unused)) = {\n";
while ($ident = pop(@external_patches)) {
$off = pop(@external_patches);
printf OUTPUT "\t{0x%08x, &%s},\n", $off, $ident;
@@ -973,11 +973,11 @@ while ($ident = pop(@external_patches)) {
}
printf OUTPUT "};\n\n";
-printf OUTPUT "u32 ".$prefix."INSTRUCTIONS\t= %d;\n",
+printf OUTPUT "static u32 ".$prefix."INSTRUCTIONS __attribute((unused))\t= %d;\n",
$instructions;
-printf OUTPUT "u32 ".$prefix."PATCHES\t= %d;\n",
+printf OUTPUT "static u32 ".$prefix."PATCHES __attribute((unused))\t= %d;\n",
$#label_patches+1;
-printf OUTPUT "u32 ".$prefix."EXTERNAL_PATCHES_LEN\t= %d;\n",
+printf OUTPUT "static u32 ".$prefix."EXTERNAL_PATCHES_LEN __attribute((unused))\t= %d;\n",
$num_external_patches;
close OUTPUT;
close OUTPUTU;
diff --git a/drivers/sound/ac97.c b/drivers/sound/ac97.c
index bc313134f..b54e62f76 100644
--- a/drivers/sound/ac97.c
+++ b/drivers/sound/ac97.c
@@ -5,6 +5,10 @@
/* And for stereo. */
#define ST 1
+/* Whether or not the bits in the channel are inverted. */
+#define INV 1
+#define NINV 0
+
static struct ac97_chn_desc {
int ac97_regnum;
int oss_channel;
@@ -13,21 +17,22 @@ static struct ac97_chn_desc {
int oss_mask;
int recordNum;
u16 regmask;
+ int is_inverted;
} mixerRegs[] = {
- { AC97_MASTER_VOL_STEREO, SOUND_MIXER_VOLUME, 0x3f, ST, SOUND_MASK_VOLUME, 5, 0x0000 },
- { AC97_MASTER_VOL_MONO, SOUND_MIXER_PHONEOUT, 0x3f, MO, SOUND_MASK_PHONEOUT, 6, 0x0000 },
- { AC97_MASTER_TONE, SOUND_MIXER_TREBLE, 0x0f, MO, SOUND_MASK_TREBLE, -1, 0x00ff },
- { AC97_MASTER_TONE, SOUND_MIXER_BASS, 0x0f, MO, SOUND_MASK_BASS, -1, 0xff00 },
- { AC97_PCBEEP_VOL, SOUND_MIXER_SPEAKER, 0x0f, MO, SOUND_MASK_SPEAKER, -1, 0x001e },
- { AC97_PHONE_VOL, SOUND_MIXER_PHONEIN, 0x1f, MO, SOUND_MASK_PHONEIN, 7, 0x0000 },
- { AC97_MIC_VOL, SOUND_MIXER_MIC, 0x1f, MO, SOUND_MASK_MIC, 0, 0x0000 },
- { AC97_LINEIN_VOL, SOUND_MIXER_LINE, 0x1f, ST, SOUND_MASK_LINE, 4, 0x0000 },
- { AC97_CD_VOL, SOUND_MIXER_CD, 0x1f, ST, SOUND_MASK_CD, 1, 0x0000 },
- { AC97_VIDEO_VOL, SOUND_MIXER_VIDEO, 0x1f, ST, SOUND_MASK_VIDEO, 2, 0x0000 },
- { AC97_AUX_VOL, SOUND_MIXER_LINE1, 0x1f, ST, SOUND_MASK_LINE1, 3, 0x0000 },
- { AC97_PCMOUT_VOL, SOUND_MIXER_PCM, 0x1f, ST, SOUND_MASK_PCM, -1, 0x0000 },
- { AC97_RECORD_GAIN, SOUND_MIXER_IGAIN, 0x0f, ST, SOUND_MASK_IGAIN, -1, 0x0000 },
- { -1, -1, 0xff, 0, 0, -1, 0x0000 },
+ { AC97_MASTER_VOL_STEREO, SOUND_MIXER_VOLUME, 0x3f, ST, SOUND_MASK_VOLUME, 5, 0x0000, INV },
+ { AC97_MASTER_VOL_MONO, SOUND_MIXER_PHONEOUT, 0x3f, MO, SOUND_MASK_PHONEOUT, 6, 0x0000, INV },
+ { AC97_MASTER_TONE, SOUND_MIXER_TREBLE, 0x0f, MO, SOUND_MASK_TREBLE, -1, 0x00ff, INV },
+ { AC97_MASTER_TONE, SOUND_MIXER_BASS, 0x0f, MO, SOUND_MASK_BASS, -1, 0xff00, INV },
+ { AC97_PCBEEP_VOL, SOUND_MIXER_SPEAKER, 0x0f, MO, SOUND_MASK_SPEAKER, -1, 0x001e, INV },
+ { AC97_PHONE_VOL, SOUND_MIXER_PHONEIN, 0x1f, MO, SOUND_MASK_PHONEIN, 7, 0x0000, INV },
+ { AC97_MIC_VOL, SOUND_MIXER_MIC, 0x1f, MO, SOUND_MASK_MIC, 0, 0x0000, INV },
+ { AC97_LINEIN_VOL, SOUND_MIXER_LINE, 0x1f, ST, SOUND_MASK_LINE, 4, 0x0000, INV },
+ { AC97_CD_VOL, SOUND_MIXER_CD, 0x1f, ST, SOUND_MASK_CD, 1, 0x0000, INV },
+ { AC97_VIDEO_VOL, SOUND_MIXER_VIDEO, 0x1f, ST, SOUND_MASK_VIDEO, 2, 0x0000, INV },
+ { AC97_AUX_VOL, SOUND_MIXER_LINE1, 0x1f, ST, SOUND_MASK_LINE1, 3, 0x0000, INV },
+ { AC97_PCMOUT_VOL, SOUND_MIXER_PCM, 0x1f, ST, SOUND_MASK_PCM, -1, 0x0000, INV },
+ { AC97_RECORD_GAIN, SOUND_MIXER_IGAIN, 0x0f, ST, SOUND_MASK_IGAIN, -1, 0x0000, NINV },
+ { -1, -1, 0xff, 0, 0, -1, 0x0000, 0 },
};
static struct ac97_chn_desc *
@@ -104,6 +109,25 @@ ac97_init (struct ac97_hwint *dev)
return 0;
}
+/* Reset the mixer to the currently saved settings. */
+int
+ac97_reset (struct ac97_hwint *dev)
+{
+ int x;
+
+ if (dev->reset_device (dev))
+ return -1;
+
+ /* Now set the registers back to their last-written values. */
+ for (x = 0; mixerRegs[x].ac97_regnum != -1; x++) {
+ int regnum = mixerRegs[x].ac97_regnum;
+ int value = dev->last_written_mixer_values [regnum / 2];
+ if (value >= 0)
+ ac97_put_register (dev, regnum, value);
+ }
+ return 0;
+}
+
/* Return the contents of register REG; use the cache if the value in it
is valid. Returns a negative error code on failure. */
int
@@ -156,38 +180,45 @@ ac97_put_register (struct ac97_hwint *dev, u8 reg, u16 value)
scaled value on success. */
static int
-ac97_scale_to_oss_val (int value, int maxval, int is_stereo)
+ac97_scale_to_oss_val (int value, int maxval, int is_stereo, int inv)
{
/* Muted? */
if (value & AC97_MUTE)
return 0;
if (is_stereo)
- return (ac97_scale_to_oss_val (value & 255, maxval, 0) << 8)
- | (ac97_scale_to_oss_val ((value >> 8) & 255, maxval, 0) << 0);
+ return (ac97_scale_to_oss_val (value & 255, maxval, 0, inv) << 8)
+ | (ac97_scale_to_oss_val ((value >> 8) & 255, maxval, 0, inv) << 0);
else {
int i;
/* Inverted. */
- value = maxval - value;
+ if (inv)
+ value = maxval - value;
i = (value * 100 + (maxval / 2)) / maxval;
if (i > 100)
i = 100;
+ if (i < 0)
+ i = 0;
return i;
}
}
static int
-ac97_scale_from_oss_val (int value, int maxval, int is_stereo)
+ac97_scale_from_oss_val (int value, int maxval, int is_stereo, int inv)
{
if (is_stereo)
- return (ac97_scale_from_oss_val (value & 255, maxval, 0) << 8)
- | (ac97_scale_from_oss_val ((value >> 8) & 255, maxval, 0) << 0);
+ return (ac97_scale_from_oss_val (value & 255, maxval, 0, inv) << 8)
+ | (ac97_scale_from_oss_val ((value >> 8) & 255, maxval, 0, inv) << 0);
else {
- int i = maxval - ((value & 255) * maxval + 50) / 100;
+ int i = ((value & 255) * maxval + 50) / 100;
+ if (inv)
+ i = maxval - i;
if (i < 0)
i = 0;
+ if (i > maxval)
+ i = maxval;
return i;
}
}
@@ -204,7 +235,8 @@ ac97_set_mixer (struct ac97_hwint *dev, int oss_channel, u16 oss_value)
if (! ac97_is_valid_channel (dev, channel))
return -ENODEV;
scaled_value = ac97_scale_from_oss_val (oss_value, channel->maxval,
- channel->is_stereo);
+ channel->is_stereo,
+ channel->is_inverted);
if (scaled_value < 0)
return scaled_value;
@@ -253,7 +285,8 @@ ac97_get_mixer_scaled (struct ac97_hwint *dev, int oss_channel)
regval >>= 1;
}
return ac97_scale_to_oss_val (regval, channel->maxval,
- channel->is_stereo);
+ channel->is_stereo,
+ channel->is_inverted);
}
int
@@ -383,8 +416,9 @@ ac97_mixer_ioctl (struct ac97_hwint *dev, unsigned int cmd, caddr_t arg)
else
ret = -EFAULT;
}
- if (ret >= 0) {
- if (dev->last_written_OSS_values[channel] == AC97_REGVAL_UNKNOWN)
+ if (ret >= 0 && (dir & _IOC_READ)) {
+ if (dev->last_written_OSS_values[channel]
+ == AC97_REGVAL_UNKNOWN)
dev->last_written_OSS_values[channel]
= ac97_get_mixer_scaled (dev, channel);
ret = dev->last_written_OSS_values[channel];
diff --git a/drivers/sound/ac97.h b/drivers/sound/ac97.h
index 490d69f88..294000f6d 100644
--- a/drivers/sound/ac97.h
+++ b/drivers/sound/ac97.h
@@ -10,7 +10,7 @@
#include "sound_config.h"
#include "sound_calls.h"
-#define AC97_RESET 0x0000 // */
+#define AC97_RESET 0x0000 //
#define AC97_MASTER_VOL_STEREO 0x0002 // Line Out
#define AC97_HEADPHONE_VOL 0x0004 //
#define AC97_MASTER_VOL_MONO 0x0006 // TAD Output
@@ -207,6 +207,10 @@ extern int ac97_get_mixer_scaled (struct ac97_hwint *dev, int oss_channel);
/* Default ioctl. */
extern int ac97_mixer_ioctl (struct ac97_hwint *dev, unsigned int cmd,
caddr_t arg);
+
+/* Do a complete reset on the AC97 mixer, restoring all mixer registers to
+ the current values. Normally used after an APM resume event. */
+extern int ac97_reset (struct ac97_hwint *dev);
#endif
/*
diff --git a/drivers/sound/nm256.h b/drivers/sound/nm256.h
index 4cc720ab9..c640b88ce 100644
--- a/drivers/sound/nm256.h
+++ b/drivers/sound/nm256.h
@@ -3,10 +3,12 @@
#include "ac97.h"
+/* The revisions that we currently handle. */
enum nm256rev {
REV_NM256AV, REV_NM256ZX
};
+/* Per-card structure. */
struct nm256_info
{
/* Magic number used to verify that this struct is valid. */
@@ -34,10 +36,12 @@ struct nm256_info
/* The mixer device. */
int mixer_oss_dev;
- /* Can only be opened once for each operation. These aren't set
- until an actual I/O operation is performed; this allows one
- device to be open for read/write without inhibiting I/O to
- the other device. */
+ /*
+ * Can only be opened once for each operation. These aren't set
+ * until an actual I/O operation is performed; this allows one
+ * device to be open for read/write without inhibiting I/O to
+ * the other device.
+ */
int is_open_play;
int is_open_record;
@@ -46,25 +50,40 @@ struct nm256_info
/* Ditto for recording a sample. */
int recording;
- /* The two memory ports. */
- char *ports[2];
-
- /* Starting offset of the port1 area mapped into memory. */
- u32 port1_start;
- /* Ending offset. */
- u32 port1_end;
- /* The offset of the end of the actual buffer area. */
- u32 bufend;
+ /* The two memory ports. */
+ struct nm256_ports {
+ /* Physical address of the port. */
+ u32 physaddr;
+ /* Our mapped-in pointer. */
+ char *ptr;
+ /* PTR's offset within the physical port. */
+ u32 start_offset;
+ /* And the offset of the end of the buffer. */
+ u32 end_offset;
+ } port[2];
/* The following are offsets within memory port 1. */
u32 coeffBuf;
u32 allCoeffBuf;
+
/* Record and playback buffers. */
u32 abuf1, abuf2;
/* Offset of the AC97 mixer in memory port 2. */
u32 mixer;
+ /* Offset of the mixer status register in memory port 2. */
+ u32 mixer_status_offset;
+
+ /* Non-zero if we have written initial values to the mixer. */
+ u8 mixer_values_init;
+
+ /*
+ * Status mask bit; (*mixer_status_loc & mixer_status_mask) == 0 means
+ * it's ready.
+ */
+ u16 mixer_status_mask;
+
/* The sizes of the playback and record ring buffers. */
u32 playbackBufferSize;
u32 recordBufferSize;
@@ -77,7 +96,7 @@ struct nm256_info
/* The start of the block currently playing. */
u32 curPlayPos;
- /* The amount of data we requested to record. */
+ /* The amount of data we were requested to record. */
u32 requestedRecAmt;
/* The offset of the currently-recording block. */
u32 curRecPos;
@@ -107,10 +126,17 @@ struct nm256_info
/* Debug flag--bigger numbers mean more output. */
extern int nm256_debug;
-/* Size of the second memory port. */
+/* The BIOS signature. */
+#define NM_SIGNATURE 0x4e4d0000
+/* Signature mask. */
+#define NM_SIG_MASK 0xffff0000
+
+/* Size of the second memory area. */
#define NM_PORT2_SIZE 4096
-/* The location of the mixer. */
-#define NM_MIXER_BASE 0x600
+
+/* The base offset of the mixer in the second memory area. */
+#define NM_MIXER_OFFSET 0x600
+
/* The maximum size of a coefficient entry. */
#define NM_MAX_COEFFICIENT 0x5000
@@ -123,21 +149,33 @@ extern int nm256_debug;
#define NM_MISC_INT_2 0x1
#define NM_ACK_INT(CARD, X) nm256_writePort16((CARD), 2, NM_INT_REG, (X) << 1)
-/* For the second revision. It uses the same interrupt register, but it
- holds 32 bits instead of 16. */
+/* The AV's "mixer ready" status bit and location. */
+#define NM_MIXER_STATUS_OFFSET 0xa04
+#define NM_MIXER_READY_MASK 0x0800
+#define NM_MIXER_PRESENCE 0xa06
+#define NM_PRESENCE_MASK 0x0050
+#define NM_PRESENCE_VALUE 0x0040
+
+/*
+ * For the ZX. It uses the same interrupt register, but it holds 32
+ * bits instead of 16.
+ */
#define NM2_PLAYBACK_INT 0x10000
#define NM2_RECORD_INT 0x80000
#define NM2_MISC_INT_1 0x8
#define NM2_MISC_INT_2 0x2
#define NM2_ACK_INT(CARD, X) nm256_writePort32((CARD), 2, NM_INT_REG, (X))
+/* The ZX's "mixer ready" status bit and location. */
+#define NM2_MIXER_STATUS_OFFSET 0xa06
+#define NM2_MIXER_READY_MASK 0x0800
+
/* The playback registers start from here. */
#define NM_PLAYBACK_REG_OFFSET 0x0
/* The record registers start from here. */
#define NM_RECORD_REG_OFFSET 0x200
-/* The rate register is located 2 bytes from the start of the register
- area. */
+/* The rate register is located 2 bytes from the start of the register area. */
#define NM_RATE_REG_OFFSET 2
/* Mono/stereo flag, number of bits on playback, and rate mask. */
@@ -156,7 +194,7 @@ extern int nm256_debug;
#define NM_AUDIO_MUTE_LEFT 0x8000
#define NM_AUDIO_MUTE_RIGHT 0x0080
-/* Recording enable register */
+/* Recording enable register. */
#define NM_RECORD_ENABLE_REG (NM_RECORD_REG_OFFSET + 0)
#define NM_RECORD_ENABLE_FLAG 1
#define NM_RECORD_FREERUN 2
@@ -179,26 +217,25 @@ extern int nm256_debug;
if (port < 1 || port > 2 || card == NULL) \
return -1; \
\
- if (port == 1) { \
- if (offset < card->port1_start || offset >= card->port1_end) { \
- printk (KERN_ERR "Bad port request port 1:0x%x\n", offset); \
- return -1; \
- } \
- offset -= card->port1_start; \
- } else if (offset < 0 || offset > 4096) { \
- printk (KERN_ERR "Bad port request port 2: 0x%x\n", offset); \
- return -1; \
- }
+ if (offset < card->port[port - 1].start_offset \
+ || offset >= card->port[port - 1].end_offset) { \
+ printk (KERN_ERR "Bad access: port %d, offset 0x%x\n", port, offset); \
+ return -1; \
+ } \
+ offset -= card->port[port - 1].start_offset;
#define DEFwritePortX(X, func) \
static inline int nm256_writePort##X (struct nm256_info *card,\
- int port, int offset, int value)\
+ int port, int offset, int value)\
{\
u##X *addr;\
\
+ if (nm256_debug > 1)\
+ printk (KERN_DEBUG "Writing 0x%x to %d:0x%x\n", value, port, offset);\
+\
NM_FIX_PORT;\
\
- addr = (u##X *)(card->ports[port - 1] + offset);\
+ addr = (u##X *)(card->port[port - 1].ptr + offset);\
func (value, addr);\
return 0;\
}
@@ -207,29 +244,28 @@ DEFwritePortX (8, writeb)
DEFwritePortX (16, writew)
DEFwritePortX (32, writel)
-#define DEFreadPortX(X) \
+#define DEFreadPortX(X, func) \
static inline u##X nm256_readPort##X (struct nm256_info *card,\
int port, int offset)\
{\
- u##X *addr, res;\
+ u##X *addr;\
\
NM_FIX_PORT\
\
- addr = (u##X *)(card->ports[port - 1] + offset);\
- memcpy_fromio (&res, addr, sizeof (res));\
- return res;\
+ addr = (u##X *)(card->port[port - 1].ptr + offset);\
+ return func(addr);\
}
-DEFreadPortX (8)
-DEFreadPortX (16)
-DEFreadPortX (32)
+DEFreadPortX (8, readb)
+DEFreadPortX (16, readw)
+DEFreadPortX (32, readl)
static inline int
nm256_writeBuffer8 (struct nm256_info *card, u8 *src, int port, int offset,
int amt)
{
NM_FIX_PORT;
- memcpy_toio (card->ports[port - 1] + offset, src, amt);
+ memcpy_toio (card->port[port - 1].ptr + offset, src, amt);
return 0;
}
@@ -238,7 +274,7 @@ nm256_readBuffer8 (struct nm256_info *card, u8 *dst, int port, int offset,
int amt)
{
NM_FIX_PORT;
- memcpy_fromio (dst, card->ports[port - 1] + offset, amt);
+ memcpy_fromio (dst, card->port[port - 1].ptr + offset, amt);
return 0;
}
diff --git a/drivers/sound/nm256_audio.c b/drivers/sound/nm256_audio.c
index 0c3ee7b37..a066c65b9 100644
--- a/drivers/sound/nm256_audio.c
+++ b/drivers/sound/nm256_audio.c
@@ -1,27 +1,37 @@
-/* Audio driver for the NeoMagic 256AV and 256ZX chipsets in native
- mode, with AC97 mixer support.
-
- Overall design and parts of this code stolen from vidc_*.c and
- skeleton.c.
-
- Yeah, there are a lot of magic constants in here. You tell ME what
- they are. I just get this stuff psychically, remember?
-
- This driver was written by someone who wishes to remain anonymous.
- It is in the public domain, so share and enjoy. Try to make a profit
- off of it; go on, I dare you. */
+/*
+ * Audio driver for the NeoMagic 256AV and 256ZX chipsets in native
+ * mode, with AC97 mixer support.
+ *
+ * Overall design and parts of this code stolen from vidc_*.c and
+ * skeleton.c.
+ *
+ * Yeah, there are a lot of magic constants in here. You tell ME what
+ * they are. I just get this stuff psychically, remember?
+ *
+ * This driver was written by someone who wishes to remain anonymous.
+ * It is in the public domain, so share and enjoy. Try to make a profit
+ * off of it; go on, I dare you.
+ */
#include <linux/config.h>
#include <linux/pci.h>
#include <linux/module.h>
+#ifdef CONFIG_APM
+#include <linux/apm_bios.h>
+#endif
#include "sound_config.h"
#include "soundmodule.h"
#include "nm256.h"
#include "nm256_coeff.h"
int nm256_debug = 0;
+static int force_load = 0;
-/* The size of the playback reserve. */
+/*
+ * The size of the playback reserve. When the playback buffer has less
+ * than NM256_PLAY_WMARK_SIZE bytes to output, we request a new
+ * buffer.
+ */
#define NM256_PLAY_WMARK_SIZE 512
static struct audio_driver nm256_audio_driver;
@@ -29,16 +39,74 @@ static struct audio_driver nm256_audio_driver;
static int nm256_grabInterrupt (struct nm256_info *card);
static int nm256_releaseInterrupt (struct nm256_info *card);
static void nm256_interrupt (int irq, void *dev_id, struct pt_regs *dummy);
-static void nm256_interrupt_zx (int irq, void *dev_id,
- struct pt_regs *dummy);
+static void nm256_interrupt_zx (int irq, void *dev_id, struct pt_regs *dummy);
/* These belong in linux/pci.h. */
#define PCI_DEVICE_ID_NEOMAGIC_NM256AV_AUDIO 0x8005
#define PCI_DEVICE_ID_NEOMAGIC_NM256ZX_AUDIO 0x8006
+/* eeeew. */
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,0)
+#define RSRCADDRESS(dev,num) ((dev)->resource[(num)].start)
+#else
+#define RSRCADDRESS(dev,num) ((dev)->base_address[(num)] \
+ & PCI_BASE_ADDRESS_MEM_MASK)
+
+#endif
+
/* List of cards. */
static struct nm256_info *nmcard_list;
+/* Release the mapped-in memory for CARD. */
+static void
+nm256_release_ports (struct nm256_info *card)
+{
+ int x;
+
+ for (x = 0; x < 2; x++) {
+ if (card->port[x].ptr != NULL) {
+ u32 size =
+ card->port[x].end_offset - card->port[x].start_offset;
+ release_region ((unsigned long) card->port[x].ptr, size);
+ card->port[x].ptr = NULL;
+ }
+ }
+}
+
+/*
+ * Map in the memory ports for CARD, if they aren't already mapped in
+ * and have been configured. If successful, a zero value is returned;
+ * otherwise any previously mapped-in areas are released and a non-zero
+ * value is returned.
+ *
+ * This is invoked twice, once for each port. Ideally it would only be
+ * called once, but we now need to map in the second port in order to
+ * check how much memory the card has on the 256ZX.
+ */
+static int
+nm256_remap_ports (struct nm256_info *card)
+{
+ int x;
+
+ for (x = 0; x < 2; x++) {
+ if (card->port[x].ptr == NULL && card->port[x].end_offset > 0) {
+ u32 physaddr
+ = card->port[x].physaddr + card->port[x].start_offset;
+ u32 size
+ = card->port[x].end_offset - card->port[x].start_offset;
+
+ card->port[x].ptr = ioremap_nocache (physaddr, size);
+
+ if (card->port[x].ptr == NULL) {
+ printk (KERN_ERR "NM256: Unable to remap port %d\n", x + 1);
+ nm256_release_ports (card);
+ return -1;
+ }
+ }
+ }
+ return 0;
+}
+
/* Locate the card in our list. */
static struct nm256_info *
nm256_find_card (int dev)
@@ -52,8 +120,10 @@ nm256_find_card (int dev)
return NULL;
}
-/* Ditto, but find the card struct corresponding to the mixer device DEV
- instead. */
+/*
+ * Ditto, but find the card struct corresponding to the mixer device DEV
+ * instead.
+ */
static struct nm256_info *
nm256_find_card_for_mixer (int dev)
{
@@ -81,11 +151,13 @@ static int samplerates[9] = {
8000, 11025, 16000, 22050, 24000, 32000, 44100, 48000, 99999999
};
-/* Set the card samplerate, word size and stereo mode to correspond to
- the settings in the CARD struct for the specified device in DEV.
- We keep two separate sets of information, one for each device; the
- hardware is not actually configured until a read or write is
- attempted. */
+/*
+ * Set the card samplerate, word size and stereo mode to correspond to
+ * the settings in the CARD struct for the specified device in DEV.
+ * We keep two separate sets of information, one for each device; the
+ * hardware is not actually configured until a read or write is
+ * attempted.
+ */
int
nm256_setInfo (int dev, struct nm256_info *card)
@@ -113,24 +185,33 @@ nm256_setInfo (int dev, struct nm256_info *card)
break;
if (x < 8) {
- u8 speedbits = ((x << 4) & NM_RATE_MASK)
- | (card->sinfo[w].bits == 16 ? NM_RATE_BITS_16: 0)
- | (card->sinfo[w].stereo ? NM_RATE_STEREO : 0);
+ u8 ratebits = ((x << 4) & NM_RATE_MASK);
+ if (card->sinfo[w].bits == 16)
+ ratebits |= NM_RATE_BITS_16;
+ if (card->sinfo[w].stereo)
+ ratebits |= NM_RATE_STEREO;
card->sinfo[w].samplerate = samplerates[x];
+
if (card->dev_for_play == dev && card->playing) {
+ if (nm256_debug)
+ printk (KERN_DEBUG "Setting play ratebits to 0x%x\n",
+ ratebits);
nm256_loadCoefficient (card, 0, x);
nm256_writePort8 (card, 2,
- NM_PLAYBACK_REG_OFFSET + NM_RATE_REG_OFFSET,
- speedbits);
+ NM_PLAYBACK_REG_OFFSET + NM_RATE_REG_OFFSET,
+ ratebits);
}
if (card->dev_for_record == dev && card->recording) {
+ if (nm256_debug)
+ printk (KERN_DEBUG "Setting record ratebits to 0x%x\n",
+ ratebits);
nm256_loadCoefficient (card, 1, x);
- nm256_writePort8 (card, 2,
- NM_RECORD_REG_OFFSET + NM_RATE_REG_OFFSET,
- speedbits);
+ nm256_writePort8 (card, 2,
+ NM_RECORD_REG_OFFSET + NM_RATE_REG_OFFSET,
+ ratebits);
}
return 0;
}
@@ -149,7 +230,7 @@ startPlay (struct nm256_info *card)
/* Enable playback engine and interrupts. */
nm256_writePort8 (card, 2, NM_PLAYBACK_ENABLE_REG,
- NM_PLAYBACK_ENABLE_FLAG | NM_PLAYBACK_FREERUN);
+ NM_PLAYBACK_ENABLE_FLAG | NM_PLAYBACK_FREERUN);
/* Enable both channels. */
nm256_writePort16 (card, 2, NM_AUDIO_MUTE_REG, 0x0);
@@ -157,9 +238,11 @@ startPlay (struct nm256_info *card)
}
}
-/* Request one chunk of AMT bytes from the recording device. When the
- operation is complete, the data will be copied into BUFFER and the
- function DMAbuf_inputintr will be invoked. */
+/*
+ * Request one chunk of AMT bytes from the recording device. When the
+ * operation is complete, the data will be copied into BUFFER and the
+ * function DMAbuf_inputintr will be invoked.
+ */
static void
nm256_startRecording (struct nm256_info *card, char *buffer, u32 amt)
@@ -167,11 +250,14 @@ nm256_startRecording (struct nm256_info *card, char *buffer, u32 amt)
u32 endpos;
int enableEngine = 0;
u32 ringsize = card->recordBufferSize;
+ unsigned long flags;
if (amt > (ringsize / 2)) {
- /* Of course this won't actually work right, because the
- caller is going to assume we will give what we got asked
- for. */
+ /*
+ * Of course this won't actually work right, because the
+ * caller is going to assume we will give what we got asked
+ * for.
+ */
printk (KERN_ERR "NM256: Read request too large: %d\n", amt);
amt = ringsize / 2;
}
@@ -181,8 +267,12 @@ nm256_startRecording (struct nm256_info *card, char *buffer, u32 amt)
return;
}
- /* If we're not currently recording, set up the start and end registers
- for the recording engine. */
+ save_flags (flags);
+ cli ();
+ /*
+ * If we're not currently recording, set up the start and end registers
+ * for the recording engine.
+ */
if (! card->recording) {
card->recording = 1;
if (nm256_grabInterrupt (card) == 0) {
@@ -198,10 +288,16 @@ nm256_startRecording (struct nm256_info *card, char *buffer, u32 amt)
}
else {
/* Not sure what else to do here. */
+ restore_flags (flags);
return;
}
}
+ /*
+ * If we happen to go past the end of the buffer a bit (due to a
+ * delayed interrupt) it's OK. So might as well set the watermark
+ * right at the end of the data we want.
+ */
endpos = card->abuf2 + ((card->curRecPos + amt) % ringsize);
card->recBuf = buffer;
@@ -211,6 +307,8 @@ nm256_startRecording (struct nm256_info *card, char *buffer, u32 amt)
if (enableEngine)
nm256_writePort8 (card, 2, NM_RECORD_ENABLE_REG,
NM_RECORD_ENABLE_FLAG | NM_RECORD_FREERUN);
+
+ restore_flags (flags);
}
/* Stop the play engine. */
@@ -219,7 +317,7 @@ stopPlay (struct nm256_info *card)
{
/* Shut off sound from both channels. */
nm256_writePort16 (card, 2, NM_AUDIO_MUTE_REG,
- NM_AUDIO_MUTE_LEFT | NM_AUDIO_MUTE_RIGHT);
+ NM_AUDIO_MUTE_LEFT | NM_AUDIO_MUTE_RIGHT);
/* Disable play engine. */
nm256_writePort8 (card, 2, NM_PLAYBACK_ENABLE_REG, 0);
if (card->playing) {
@@ -246,18 +344,22 @@ stopRecord (struct nm256_info *card)
}
}
-/* Ring buffers, man. That's where the hip-hop, wild-n-wooly action's at.
- 1972?
-
- Write AMT bytes of BUFFER to the playback ring buffer, and start the
- playback engine running. It will only accept up to 1/2 of the total
- size of the ring buffer. */
+/*
+ * Ring buffers, man. That's where the hip-hop, wild-n-wooly action's at.
+ * 1972? (Well, I suppose it was cheep-n-easy to implement.)
+ *
+ * Write AMT bytes of BUFFER to the playback ring buffer, and start the
+ * playback engine running. It will only accept up to 1/2 of the total
+ * size of the ring buffer. No check is made that we're about to overwrite
+ * the currently-playing sample.
+ */
static void
nm256_write_block (struct nm256_info *card, char *buffer, u32 amt)
{
u32 ringsize = card->playbackBufferSize;
u32 endstop;
+ unsigned long flags;
if (amt > (ringsize / 2)) {
printk (KERN_ERR "NM256: Write request too large: %d\n", amt);
@@ -273,6 +375,9 @@ nm256_write_block (struct nm256_info *card, char *buffer, u32 amt)
card->requested_amt = amt;
+ save_flags (flags);
+ cli ();
+
if ((card->curPlayPos + amt) >= ringsize) {
u32 rem = ringsize - card->curPlayPos;
@@ -288,33 +393,40 @@ nm256_write_block (struct nm256_info *card, char *buffer, u32 amt)
card->abuf1 + card->curPlayPos,
amt);
- /* Setup the start-n-stop-n-limit registers, and start that engine
- goin'.
-
- Normally we just let it wrap around to avoid the click-click
- action scene. */
+ /*
+ * Setup the start-n-stop-n-limit registers, and start that engine
+ * goin'.
+ *
+ * Normally we just let it wrap around to avoid the click-click
+ * action scene.
+ */
if (! card->playing) {
- /* The PBUFFER_END register in this case points to one "word"
+ /* The PBUFFER_END register in this case points to one sample
before the end of the buffer. */
int w = (card->dev_for_play == card->dev[0] ? 0 : 1);
- int wordsize = (card->sinfo[w].bits == 16 ? 2 : 1)
- * (card->sinfo[w].stereo ? 2 : 1);
+ int sampsize = (card->sinfo[w].bits == 16 ? 2 : 1);
+
+ if (card->sinfo[w].stereo)
+ sampsize *= 2;
/* Need to set the not-normally-changing-registers up. */
nm256_writePort32 (card, 2, NM_PBUFFER_START,
card->abuf1 + card->curPlayPos);
nm256_writePort32 (card, 2, NM_PBUFFER_END,
- card->abuf1 + ringsize - wordsize);
+ card->abuf1 + ringsize - sampsize);
nm256_writePort32 (card, 2, NM_PBUFFER_CURRP,
card->abuf1 + card->curPlayPos);
}
endstop = (card->curPlayPos + amt - NM256_PLAY_WMARK_SIZE) % ringsize;
nm256_writePort32 (card, 2, NM_PBUFFER_WMARK, card->abuf1 + endstop);
+
if (! card->playing)
startPlay (card);
+
+ restore_flags (flags);
}
-/* We just got a card playback interrupt; process it. */
+/* We just got a card playback interrupt; process it. */
static void
nm256_get_new_block (struct nm256_info *card)
{
@@ -332,13 +444,14 @@ nm256_get_new_block (struct nm256_info *card)
amt -= card->curPlayPos;
if (card->requested_amt > (amt + NM256_PLAY_WMARK_SIZE)) {
- u32 endstop =
+ u32 endstop =
card->curPlayPos + card->requested_amt - NM256_PLAY_WMARK_SIZE;
nm256_writePort32 (card, 2, NM_PBUFFER_WMARK, card->abuf1 + endstop);
- } else {
+ }
+ else {
card->curPlayPos += card->requested_amt;
/* Get a new block to write. This will eventually invoke
- nm256_write_block (). */
+ nm256_write_block () or stopPlay (). */
DMAbuf_outputintr (card->dev_for_play, 1);
}
}
@@ -346,9 +459,11 @@ nm256_get_new_block (struct nm256_info *card)
/* Ultra cheez-whiz. But I'm too lazy to grep headers. */
#define MIN(X,Y) ((X) < (Y) ? (X) : (Y))
-/* Read the last-recorded block from the ring buffer, copy it into the
- saved buffer pointer, and invoke DMAuf_inputintr() with the recording
- device. */
+/*
+ * Read the last-recorded block from the ring buffer, copy it into the
+ * saved buffer pointer, and invoke DMAuf_inputintr() with the recording
+ * device.
+ */
static void
nm256_read_block (struct nm256_info *card)
@@ -363,8 +478,10 @@ nm256_read_block (struct nm256_info *card)
currptr = 0;
}
- /* This test is probably redundant; we shouldn't be here unless
- it's true. */
+ /*
+ * This test is probably redundant; we shouldn't be here unless
+ * it's true.
+ */
if (card->recording) {
/* If we wrapped around, copy everything from the start of our
recording buffer to the end of the buffer. */
@@ -394,52 +511,28 @@ nm256_read_block (struct nm256_info *card)
}
#undef MIN
-/* Initialize the hardware and various other card data we'll need
- later. */
+/*
+ * Initialize the hardware.
+ */
static void
nm256_initHw (struct nm256_info *card)
{
- int x;
-
- card->playbackBufferSize = 16384;
- card->recordBufferSize = 16384;
-
- card->coeffBuf = card->bufend - NM_MAX_COEFFICIENT;
- card->abuf2 = card->coeffBuf - card->recordBufferSize;
- card->abuf1 = card->abuf2 - card->playbackBufferSize;
- card->allCoeffBuf = card->abuf2 - (NM_TOTAL_COEFF_COUNT * 4);
-
- /* Fixed setting. */
- card->mixer = NM_MIXER_BASE;
-
- card->playing = 0;
- card->is_open_play = 0;
- card->curPlayPos = 0;
-
- card->recording = 0;
- card->is_open_record = 0;
- card->curRecPos = 0;
-
- card->coeffsCurrent = 0;
-
- card->opencnt[0] = 0; card->opencnt[1] = 0;
-
/* Reset everything. */
- nm256_writePort8 (card, 2, 0, 0x11);
-
- /* Disable recording. */
- nm256_writePort8 (card, 2, NM_RECORD_ENABLE_REG, 0);
+ nm256_writePort8 (card, 2, 0x0, 0x11);
nm256_writePort16 (card, 2, 0x214, 0);
- /* Reasonable default settings, but largely unnecessary. */
- for (x = 0; x < 2; x++) {
- card->sinfo[x].bits = 8;
- card->sinfo[x].stereo = 0;
- card->sinfo[x].samplerate = 8000;
- }
+ stopRecord (card);
+ stopPlay (card);
}
-/* Handle a potential interrupt for the device referred to by DEV_ID. */
+/*
+ * Handle a potential interrupt for the device referred to by DEV_ID.
+ *
+ * I don't like the cut-n-paste job here either between the two routines,
+ * but there are sufficient differences between the two interrupt handlers
+ * that parameterizing it isn't all that great either. (Could use a macro,
+ * I suppose...yucky bleah.)
+ */
static void
nm256_interrupt (int irq, void *dev_id, struct pt_regs *dummy)
@@ -458,14 +551,32 @@ nm256_interrupt (int irq, void *dev_id, struct pt_regs *dummy)
/* Not ours. */
if (status == 0) {
if (badintrcount++ > 1000) {
- printk (KERN_ERR "NM256: Releasing interrupt, over 1000 invalid interrupts\n");
- nm256_releaseInterrupt (card);
+ /*
+ * I'm not sure if the best thing is to stop the card from
+ * playing or just release the interrupt (after all, we're in
+ * a bad situation, so doing fancy stuff may not be such a good
+ * idea).
+ *
+ * I worry about the card engine continuing to play noise
+ * over and over, however--that could become a very
+ * obnoxious problem. And we know that when this usually
+ * happens things are fairly safe, it just means the user's
+ * inserted a PCMCIA card and someone's spamming us with IRQ 9s.
+ */
+
+ if (card->playing)
+ stopPlay (card);
+ if (card->recording)
+ stopRecord (card);
+ badintrcount = 0;
}
return;
}
badintrcount = 0;
+ /* Rather boring; check for individual interrupts and process them. */
+
if (status & NM_PLAYBACK_INT) {
status &= ~NM_PLAYBACK_INT;
NM_ACK_INT (card, NM_PLAYBACK_INT);
@@ -503,6 +614,7 @@ nm256_interrupt (int irq, void *dev_id, struct pt_regs *dummy)
nm256_writePort8 (card, 2, 0x400, cbyte & ~2);
}
+ /* Unknown interrupt. */
if (status) {
printk (KERN_ERR "NM256: Fire in the hole! Unknown status 0x%x\n",
status);
@@ -511,8 +623,11 @@ nm256_interrupt (int irq, void *dev_id, struct pt_regs *dummy)
}
}
-/* Handle a potential interrupt for the device referred to by DEV_ID.
- This handler is for the 256ZX. */
+/*
+ * Handle a potential interrupt for the device referred to by DEV_ID.
+ * This handler is for the 256ZX, and is very similar to the non-ZX
+ * routine.
+ */
static void
nm256_interrupt_zx (int irq, void *dev_id, struct pt_regs *dummy)
@@ -532,13 +647,33 @@ nm256_interrupt_zx (int irq, void *dev_id, struct pt_regs *dummy)
if (status == 0) {
if (badintrcount++ > 1000) {
printk (KERN_ERR "NM256: Releasing interrupt, over 1000 invalid interrupts\n");
- nm256_releaseInterrupt (card);
+ /*
+ * I'm not sure if the best thing is to stop the card from
+ * playing or just release the interrupt (after all, we're in
+ * a bad situation, so doing fancy stuff may not be such a good
+ * idea).
+ *
+ * I worry about the card engine continuing to play noise
+ * over and over, however--that could become a very
+ * obnoxious problem. And we know that when this usually
+ * happens things are fairly safe, it just means the user's
+ * inserted a PCMCIA card and someone's spamming us with
+ * IRQ 9s.
+ */
+
+ if (card->playing)
+ stopPlay (card);
+ if (card->recording)
+ stopRecord (card);
+ badintrcount = 0;
}
return;
}
badintrcount = 0;
+ /* Rather boring; check for individual interrupts and process them. */
+
if (status & NM2_PLAYBACK_INT) {
status &= ~NM2_PLAYBACK_INT;
NM2_ACK_INT (card, NM2_PLAYBACK_INT);
@@ -575,6 +710,7 @@ nm256_interrupt_zx (int irq, void *dev_id, struct pt_regs *dummy)
nm256_writePort8 (card, 2, 0x400, cbyte & ~2);
}
+ /* Unknown interrupt. */
if (status) {
printk (KERN_ERR "NM256: Fire in the hole! Unknown status 0x%x\n",
status);
@@ -583,7 +719,9 @@ nm256_interrupt_zx (int irq, void *dev_id, struct pt_regs *dummy)
}
}
-/* Request our interrupt. */
+/*
+ * Request our interrupt.
+ */
static int
nm256_grabInterrupt (struct nm256_info *card)
{
@@ -597,7 +735,9 @@ nm256_grabInterrupt (struct nm256_info *card)
return 0;
}
-/* Release our interrupt. */
+/*
+ * Release our interrupt.
+ */
static int
nm256_releaseInterrupt (struct nm256_info *card)
{
@@ -612,6 +752,11 @@ nm256_releaseInterrupt (struct nm256_info *card)
return 0;
}
+/*
+ * Waits for the mixer to become ready to be written; returns a zero value
+ * if it timed out.
+ */
+
static int
nm256_isReady (struct ac97_hwint *dev)
{
@@ -626,26 +771,25 @@ nm256_isReady (struct ac97_hwint *dev)
return 0;
}
- if (card->rev == REV_NM256AV) {
- testaddr = 0xa06;
- testb = 0x0100;
- } else if (card->rev == REV_NM256ZX) {
- testaddr = 0xa08;
- testb = 0x0800;
- } else {
- return -1;
- }
+ testaddr = card->mixer_status_offset;
+ testb = card->mixer_status_mask;
- while (t2-- > 0) {
- if ((nm256_readPort16 (card, 2, testaddr) & testb) == 0) {
+ /*
+ * Loop around waiting for the mixer to become ready.
+ */
+ while (! done && t2-- > 0) {
+ if ((nm256_readPort16 (card, 2, testaddr) & testb) == 0)
done = 1;
- break;
- }
- udelay (100);
+ else
+ udelay (100);
}
return done;
}
+/*
+ * Return the contents of the AC97 mixer register REG. Returns a positive
+ * value if successful, or a negative error code.
+ */
static int
nm256_readAC97Reg (struct ac97_hwint *dev, u8 reg)
{
@@ -661,6 +805,7 @@ nm256_readAC97Reg (struct ac97_hwint *dev, u8 reg)
nm256_isReady (dev);
res = nm256_readPort16 (card, 2, card->mixer + reg);
+ /* Magic delay. Bleah yucky. */
udelay (1000);
return res;
}
@@ -668,6 +813,10 @@ nm256_readAC97Reg (struct ac97_hwint *dev, u8 reg)
return -EINVAL;
}
+/*
+ * Writes VALUE to AC97 mixer register REG. Returns 0 if successful, or
+ * a negative error code.
+ */
static int
nm256_writeAC97Reg (struct ac97_hwint *dev, u8 reg, u16 value)
{
@@ -706,6 +855,13 @@ nm256_writeAC97Reg (struct ac97_hwint *dev, u8 reg, u16 value)
return ! done;
}
+/*
+ * Initial register values to be written to the AC97 mixer.
+ * While most of these are identical to the reset values, we do this
+ * so that we have most of the register contents cached--this avoids
+ * reading from the mixer directly (which seems to be problematic,
+ * probably due to ignorance).
+ */
struct initialValues
{
unsigned short port;
@@ -714,23 +870,24 @@ struct initialValues
static struct initialValues nm256_ac97_initial_values[] =
{
- { 0x0002, 0x8000 },
- { 0x0004, 0x0000 },
- { 0x0006, 0x0000 },
- { 0x000A, 0x0000 },
- { 0x000C, 0x0008 },
- { 0x000E, 0x8008 },
- { 0x0010, 0x8808 },
- { 0x0012, 0x8808 },
- { 0x0014, 0x8808 },
- { 0x0016, 0x8808 },
- { 0x0018, 0x0808 },
- { 0x001A, 0x0000 },
- { 0x001C, 0x0B0B },
- { 0x0020, 0x0000 },
+ { AC97_MASTER_VOL_STEREO, 0x8000 },
+ { AC97_HEADPHONE_VOL, 0x8000 },
+ { AC97_MASTER_VOL_MONO, 0x0000 },
+ { AC97_PCBEEP_VOL, 0x0000 },
+ { AC97_PHONE_VOL, 0x0008 },
+ { AC97_MIC_VOL, 0x8000 },
+ { AC97_LINEIN_VOL, 0x8808 },
+ { AC97_CD_VOL, 0x8808 },
+ { AC97_VIDEO_VOL, 0x8808 },
+ { AC97_AUX_VOL, 0x8808 },
+ { AC97_PCMOUT_VOL, 0x0808 },
+ { AC97_RECORD_SELECT, 0x0000 },
+ { AC97_RECORD_GAIN, 0x0B0B },
+ { AC97_GENERAL_PURPOSE, 0x0000 },
{ 0xffff, 0xffff }
};
+/* Initialize the AC97 into a known state. */
static int
nm256_resetAC97 (struct ac97_hwint *dev)
{
@@ -742,22 +899,28 @@ nm256_resetAC97 (struct ac97_hwint *dev)
return -EINVAL;
}
- /* Reset the card. 'Tis magic! */
+ /* Reset the mixer. 'Tis magic! */
nm256_writePort8 (card, 2, 0x6c0, 1);
nm256_writePort8 (card, 2, 0x6cc, 0x87);
nm256_writePort8 (card, 2, 0x6cc, 0x80);
nm256_writePort8 (card, 2, 0x6cc, 0x0);
- for (x = 0; nm256_ac97_initial_values[x].port != 0xffff; x++) {
- ac97_put_register (dev,
- nm256_ac97_initial_values[x].port,
- nm256_ac97_initial_values[x].value);
+ if (! card->mixer_values_init) {
+ for (x = 0; nm256_ac97_initial_values[x].port != 0xffff; x++) {
+ ac97_put_register (dev,
+ nm256_ac97_initial_values[x].port,
+ nm256_ac97_initial_values[x].value);
+ card->mixer_values_init = 1;
+ }
}
return 0;
}
-/* We don't do anything special here. */
+/*
+ * We don't do anything particularly special here; it just passes the
+ * mixer ioctl to the AC97 driver.
+ */
static int
nm256_default_mixer_ioctl (int dev, unsigned int cmd, caddr_t arg)
{
@@ -774,7 +937,12 @@ static struct mixer_operations nm256_mixer_operations = {
nm256_default_mixer_ioctl
};
-/* I "love" C sometimes. Got braces? */
+/*
+ * Default settings for the OSS mixer. These are set last, after the
+ * mixer is initialized.
+ *
+ * I "love" C sometimes. Got braces?
+ */
static struct ac97_mixer_value_list mixer_defaults[] = {
{ SOUND_MIXER_VOLUME, { { 85, 85 } } },
{ SOUND_MIXER_SPEAKER, { { 100 } } },
@@ -783,6 +951,8 @@ static struct ac97_mixer_value_list mixer_defaults[] = {
{ -1, { { 0, 0 } } }
};
+
+/* Installs the AC97 mixer into CARD. */
static int
nm256_install_mixer (struct nm256_info *card)
{
@@ -812,36 +982,67 @@ nm256_install_mixer (struct nm256_info *card)
return 0;
}
-/* See if the signature left by the NM256 BIOS is intact; if so, we use
- the associated address as the end of our buffer. */
+/* Perform a full reset on the hardware; this is invoked when an APM
+ resume event occurs. */
static void
-nm256_peek_for_sig (struct nm256_info *card, u32 port1addr)
+nm256_full_reset (struct nm256_info *card)
{
- char *temp = ioremap_nocache (port1addr + card->port1_end - 0x0400, 16);
+ nm256_initHw (card);
+ ac97_reset (&(card->mdev));
+}
+
+/*
+ * See if the signature left by the NM256 BIOS is intact; if so, we use
+ * the associated address as the end of our audio buffer in the video
+ * RAM.
+ */
+
+static void
+nm256_peek_for_sig (struct nm256_info *card)
+{
+ u32 port1offset
+ = card->port[0].physaddr + card->port[0].end_offset - 0x0400;
+ /* The signature is located 1K below the end of video RAM. */
+ char *temp = ioremap_nocache (port1offset, 16);
+ /* Default buffer end is 5120 bytes below the top of RAM. */
+ u32 default_value = card->port[0].end_offset - 0x1400;
u32 sig;
+ /* Install the default value first, so we don't have to repeatedly
+ do it if there is a problem. */
+ card->port[0].end_offset = default_value;
+
if (temp == NULL) {
printk (KERN_ERR "NM256: Unable to scan for card signature in video RAM\n");
return;
}
- memcpy_fromio (&sig, temp, sizeof (u32));
- if ((sig & 0xffff0000) == 0x4e4d0000) {
- memcpy_fromio (&(card->bufend), temp + 4, sizeof (u32));
+ sig = readl (temp);
+ if ((sig & NM_SIG_MASK) == NM_SIGNATURE) {
+ u32 pointer = readl (temp + 4);
+
+ /*
+ * If it's obviously invalid, don't use it (the port already has a
+ * suitable default value set).
+ */
+ if (pointer != 0xffffffff)
+ card->port[0].end_offset = pointer;
+
printk (KERN_INFO "NM256: Found card signature in video RAM: 0x%x\n",
- card->bufend);
+ pointer);
}
release_region ((unsigned long) temp, 16);
}
-/* Install a driver for the soundcard referenced by PCIDEV. */
+/*
+ * Install a driver for the PCI device referenced by PCIDEV.
+ * VERSTR is a human-readable version string.
+ */
static int
nm256_install(struct pci_dev *pcidev, enum nm256rev rev, char *verstr)
{
struct nm256_info *card;
- u32 port1addr = pcidev->resource[0].start;
- u32 port2addr = pcidev->resource[1].start;
int x;
card = kmalloc (sizeof (struct nm256_info), GFP_KERNEL);
@@ -855,52 +1056,85 @@ nm256_install(struct pci_dev *pcidev, enum nm256rev rev, char *verstr)
card->recording = 0;
card->rev = rev;
- /* The NM256 has two memory ports. The first port is nothing
- more than a chunk of video RAM, which is used as the I/O ring
- buffer. The second port has the actual juicy stuff (like the
- mixer and the playback engine control registers). */
+ /* Init the memory port info. */
+ for (x = 0; x < 2; x++) {
+ card->port[x].physaddr = RSRCADDRESS (pcidev, x);
+ card->port[x].ptr = NULL;
+ card->port[x].start_offset = 0;
+ card->port[x].end_offset = 0;
+ }
- card->ports[1] = ioremap_nocache (port2addr, NM_PORT2_SIZE);
+ /* Port 2 is easy. */
+ card->port[1].start_offset = 0;
+ card->port[1].end_offset = NM_PORT2_SIZE;
- if (card->ports[1] == NULL) {
- printk (KERN_ERR "NM256: Unable to remap port 2\n");
+ /* Yuck. But we have to map in port 2 so we can check how much RAM the
+ card has. */
+ if (nm256_remap_ports (card)) {
kfree_s (card, sizeof (struct nm256_info));
return 0;
}
+ /*
+ * The NM256 has two memory ports. The first port is nothing
+ * more than a chunk of video RAM, which is used as the I/O ring
+ * buffer. The second port has the actual juicy stuff (like the
+ * mixer and the playback engine control registers).
+ */
+
if (card->rev == REV_NM256AV) {
- card->port1_end = 2560 * 1024;
+ /* Ok, try to see if this is a non-AC97 version of the hardware. */
+ int pval = nm256_readPort16 (card, 2, NM_MIXER_PRESENCE);
+ if ((pval & NM_PRESENCE_MASK) != NM_PRESENCE_VALUE) {
+ if (! force_load) {
+ printk (KERN_ERR "NM256: This doesn't look to me like the AC97-compatible version.\n");
+ printk (KERN_ERR " You can force the driver to load by passing in the module\n");
+ printk (KERN_ERR " parameter:\n");
+ printk (KERN_ERR " force_ac97 = 1\n");
+ printk (KERN_ERR "\n");
+ printk (KERN_ERR " More likely, you should be using the appropriate SB-16 or\n");
+ printk (KERN_ERR " CS4232 driver instead. (If your BIOS has settings for\n");
+ printk (KERN_ERR " IRQ and/or DMA for the sound card, this is *not* the correct\n");
+ printk (KERN_ERR " driver to use.)\n");
+ nm256_release_ports (card);
+ kfree_s (card, sizeof (struct nm256_info));
+ return 0;
+ }
+ else {
+ printk (KERN_INFO "NM256: Forcing driver load as per user request.\n");
+ }
+ }
+ else {
+ /* printk (KERN_INFO "NM256: Congratulations. You're not running Eunice.\n")*/;
+ }
+ card->port[0].end_offset = 2560 * 1024;
card->introutine = nm256_interrupt;
+ card->mixer_status_offset = NM_MIXER_STATUS_OFFSET;
+ card->mixer_status_mask = NM_MIXER_READY_MASK;
}
else {
+ /* Not sure if there is any relevant detect for the ZX or not. */
if (nm256_readPort8 (card, 2, 0xa0b) != 0)
- card->port1_end = 6144 * 1024;
+ card->port[0].end_offset = 6144 * 1024;
else
- card->port1_end = 4096 * 1024;
+ card->port[0].end_offset = 4096 * 1024;
card->introutine = nm256_interrupt_zx;
+ card->mixer_status_offset = NM2_MIXER_STATUS_OFFSET;
+ card->mixer_status_mask = NM2_MIXER_READY_MASK;
}
- /* Default value. */
- card->bufend = card->port1_end - 0x1400;
-
- if (buffertop >= 98304 && buffertop < card->port1_end)
- card->bufend = buffertop;
+ if (buffertop >= 98304 && buffertop < card->port[0].end_offset)
+ card->port[0].end_offset = buffertop;
else
- nm256_peek_for_sig (card, port1addr);
+ nm256_peek_for_sig (card);
- card->port1_start = card->bufend - 98304;
+ card->port[0].start_offset = card->port[0].end_offset - 98304;
printk (KERN_INFO "NM256: Mapping port 1 from 0x%x - 0x%x\n",
- card->port1_start, card->port1_end);
-
- card->ports[0] =
- ioremap_nocache (port1addr + card->port1_start,
- card->port1_end - card->port1_start);
+ card->port[0].start_offset, card->port[0].end_offset);
- if (card->ports[0] == NULL) {
- printk (KERN_ERR "NM256: Unable to remap port 1\n");
- release_region ((unsigned long) card->ports[1], NM_PORT2_SIZE);
+ if (nm256_remap_ports (card)) {
kfree_s (card, sizeof (struct nm256_info));
return 0;
}
@@ -911,9 +1145,7 @@ nm256_install(struct pci_dev *pcidev, enum nm256rev rev, char *verstr)
card->has_irq = 0;
if (nm256_grabInterrupt (card) != 0) {
- release_region ((unsigned long) card->ports[0],
- card->port1_end - card->port1_start);
- release_region ((unsigned long) card->ports[1], NM_PORT2_SIZE);
+ nm256_release_ports (card);
kfree_s (card, sizeof (struct nm256_info));
return 0;
}
@@ -924,10 +1156,36 @@ nm256_install(struct pci_dev *pcidev, enum nm256rev rev, char *verstr)
* Init the board.
*/
+ card->playbackBufferSize = 16384;
+ card->recordBufferSize = 16384;
+
+ card->coeffBuf = card->port[0].end_offset - NM_MAX_COEFFICIENT;
+ card->abuf2 = card->coeffBuf - card->recordBufferSize;
+ card->abuf1 = card->abuf2 - card->playbackBufferSize;
+ card->allCoeffBuf = card->abuf2 - (NM_TOTAL_COEFF_COUNT * 4);
+
+ /* Fixed setting. */
+ card->mixer = NM_MIXER_OFFSET;
+ card->mixer_values_init = 0;
+
+ card->is_open_play = 0;
+ card->is_open_record = 0;
+
+ card->coeffsCurrent = 0;
+
+ card->opencnt[0] = 0; card->opencnt[1] = 0;
+
+ /* Reasonable default settings, but largely unnecessary. */
+ for (x = 0; x < 2; x++) {
+ card->sinfo[x].bits = 8;
+ card->sinfo[x].stereo = 0;
+ card->sinfo[x].samplerate = 8000;
+ }
+
nm256_initHw (card);
for (x = 0; x < 2; x++) {
- if ((card->dev[x] =
+ if ((card->dev[x] =
sound_install_audiodrv(AUDIO_DRIVER_VERSION,
"NM256", &nm256_audio_driver,
sizeof(struct audio_driver),
@@ -940,9 +1198,7 @@ nm256_install(struct pci_dev *pcidev, enum nm256rev rev, char *verstr)
}
else {
printk(KERN_ERR "NM256: Too many PCM devices available\n");
- release_region ((unsigned long) card->ports[0],
- card->port1_end - card->port1_start);
- release_region ((unsigned long) card->ports[1], NM_PORT2_SIZE);
+ nm256_release_ports (card);
kfree_s (card, sizeof (struct nm256_info));
return 0;
}
@@ -964,6 +1220,48 @@ nm256_install(struct pci_dev *pcidev, enum nm256rev rev, char *verstr)
return 1;
}
+
+#ifdef CONFIG_APM
+/*
+ * APM event handler, so the card is properly reinitialized after a power
+ * event.
+ */
+static int
+handle_apm_event (apm_event_t event)
+{
+ static int down = 0;
+
+ switch (event)
+ {
+ case APM_SYS_SUSPEND:
+ case APM_USER_SUSPEND:
+ down++;
+ break;
+ case APM_NORMAL_RESUME:
+ case APM_CRITICAL_RESUME:
+ if (down)
+ {
+ struct nm256_info *crd;
+
+ down = 0;
+ for (crd = nmcard_list; crd != NULL; crd = crd->next_card)
+ {
+ int playing = crd->playing;
+ nm256_full_reset (crd);
+ /*
+ * A little ugly, but that's ok; pretend the
+ * block we were playing is done.
+ */
+ if (playing)
+ DMAbuf_outputintr (crd->dev_for_play, 1);
+ }
+ }
+ break;
+ }
+ return 0;
+}
+#endif
+
/*
* This loop walks the PCI configuration database and finds where
* the sound cards are.
@@ -993,6 +1291,10 @@ init_nm256(void)
if (count == 0)
return -ENODEV;
+#ifdef CONFIG_APM
+ apm_register_callback (&handle_apm_event);
+#endif
+
printk (KERN_INFO "Done installing NM256 audio driver.\n");
return 0;
}
@@ -1028,10 +1330,13 @@ nm256_audio_open(int dev, int mode)
if (! ((mode & OPEN_READ) || (mode & OPEN_WRITE)))
return -EIO;
- /* If it's open for both read and write, and the card's currently
- being read or written to, then do the opposite of what has
- already been done. Otherwise, don't specify any mode until the
- user actually tries to do I/O. */
+ /*
+ * If it's open for both read and write, and the card's currently
+ * being read or written to, then do the opposite of what has
+ * already been done. Otherwise, don't specify any mode until the
+ * user actually tries to do I/O. (Some programs open the device
+ * for both read and write, but only actually do reading or writing.)
+ */
if ((mode & OPEN_WRITE) && (mode & OPEN_READ)) {
if (card->is_open_play)
@@ -1105,6 +1410,7 @@ nm256_audio_close(int dev)
}
}
+/* Standard ioctl handler. */
static int
nm256_audio_ioctl(int dev, unsigned int cmd, caddr_t arg)
{
@@ -1122,6 +1428,11 @@ nm256_audio_ioctl(int dev, unsigned int cmd, caddr_t arg)
else
w = 1;
+ /*
+ * The code here is messy. There are probably better ways to do
+ * it. (It should be possible to handle it the same way the AC97 mixer
+ * is done.)
+ */
switch (cmd)
{
case SOUND_PCM_WRITE_RATE:
@@ -1193,8 +1504,12 @@ nm256_audio_ioctl(int dev, unsigned int cmd, caddr_t arg)
return put_user(ret, (int *) arg);
}
-/* Given the dev DEV and an associated physical buffer PHYSBUF, return
- a pointer to the actual buffer in kernel space. */
+/*
+ * Given the sound device DEV and an associated physical buffer PHYSBUF,
+ * return a pointer to the actual buffer in kernel space.
+ *
+ * This routine should exist as part of the soundcore routines.
+ */
static char *
nm256_getDMAbuffer (int dev, unsigned long physbuf)
@@ -1238,9 +1553,10 @@ nm256_audio_output_block(int dev, unsigned long physbuf,
}
}
+/* Ditto, but do recording instead. */
static void
nm256_audio_start_input(int dev, unsigned long physbuf, int count,
- int intrflag)
+ int intrflag)
{
struct nm256_info *card = nm256_find_card (dev);
@@ -1252,6 +1568,12 @@ nm256_audio_start_input(int dev, unsigned long physbuf, int count,
}
}
+/*
+ * Prepare for inputting samples to DEV.
+ * Each requested buffer will be BSIZE byes long, with a total of
+ * BCOUNT buffers.
+ */
+
static int
nm256_audio_prepare_for_input(int dev, int bsize, int bcount)
{
@@ -1278,6 +1600,7 @@ nm256_audio_prepare_for_input(int dev, int bsize, int bcount)
* 2. We get a write buffer without dma_mode setup (dmabuf.c:1152)
* 3. We restart a transfer (dmabuf.c:1324)
*/
+
static int
nm256_audio_prepare_for_output(int dev, int bsize, int bcount)
{
@@ -1342,12 +1665,13 @@ static int loaded = 0;
MODULE_PARM (usecache, "i");
MODULE_PARM (buffertop, "i");
MODULE_PARM (nm256_debug, "i");
+MODULE_PARM (force_load, "i");
int
init_module (void)
{
nmcard_list = NULL;
- printk (KERN_INFO "NeoMagic 256AV/256ZX audio driver, version 1.0\n");
+ printk (KERN_INFO "NeoMagic 256AV/256ZX audio driver, version 1.1\n");
if (init_nm256 () == 0) {
SOUND_LOCK;
@@ -1372,9 +1696,7 @@ cleanup_module (void)
stopRecord (card);
if (card->has_irq)
free_irq (card->irq, card);
- release_region ((unsigned long) card->ports[0],
- card->port1_end - card->port1_start);
- release_region ((unsigned long) card->ports[1], NM_PORT2_SIZE);
+ nm256_release_ports (card);
sound_unload_mixerdev (card->mixer_oss_dev);
sound_unload_audiodev (card->dev[0]);
sound_unload_audiodev (card->dev[1]);
@@ -1383,6 +1705,9 @@ cleanup_module (void)
}
nmcard_list = NULL;
}
+#ifdef CONFIG_APM
+ apm_unregister_callback (&handle_apm_event);
+#endif
}
#endif
diff --git a/drivers/sound/nm256_coeff.h b/drivers/sound/nm256_coeff.h
index c8fc7ecbe..0ceecc200 100644
--- a/drivers/sound/nm256_coeff.h
+++ b/drivers/sound/nm256_coeff.h
@@ -4622,7 +4622,8 @@ nm256_getStartOffset (u8 which)
}
static void
-nm256_loadOneCoefficient (struct nm256_info *card, u32 port, u16 which)
+nm256_loadOneCoefficient (struct nm256_info *card, int devnum, u32 port,
+ u16 which)
{
u32 coeffBuf = (which < 8) ? card->coeffBuf : card->allCoeffBuf;
u16 offset = nm256_getStartOffset (which);
@@ -4631,11 +4632,14 @@ nm256_loadOneCoefficient (struct nm256_info *card, u32 port, u16 which)
card->coeffsCurrent = 0;
if (nm256_debug)
- printk (KERN_INFO "NM256: Loading coefficient buffer 0x%x-0x%x with coefficient %d\n",
- coeffBuf, coeffBuf + size - 1, which);
+ printk (KERN_INFO "NM256: Loading coefficient buffer 0x%x-0x%x with coefficient %d, size %d, port 0x%x\n",
+ coeffBuf, coeffBuf + size - 1, which, size, port);
nm256_writeBuffer8 (card, coefficients + offset, 1, coeffBuf, size);
nm256_writePort32 (card, 2, port + 0, coeffBuf);
- nm256_writePort32 (card, 2, port + 4, coeffBuf + size - 1);
+ /* ??? Record seems to behave differently than playback. */
+ if (devnum == 0)
+ size--;
+ nm256_writePort32 (card, 2, port + 4, coeffBuf + size);
}
static void
@@ -4663,7 +4667,7 @@ nm256_loadCoefficient (struct nm256_info *card, int which, int number)
number += 8;
if (! nm256_cachedCoefficients (card))
- nm256_loadOneCoefficient (card, addrs[which], number);
+ nm256_loadOneCoefficient (card, which, addrs[which], number);
else {
u32 base = card->allCoeffBuf;
u32 offset = nm256_getStartOffset (number);
diff --git a/drivers/usb/acm.c b/drivers/usb/acm.c
index 3ecea982e..a47920d00 100644
--- a/drivers/usb/acm.c
+++ b/drivers/usb/acm.c
@@ -486,8 +486,8 @@ static void acm_disconnect(struct usb_device *dev)
if (!acm->present)
return;
- printk("disconnecting\n");
-
+ acm->active=0;
+ acm->present=0;
if (acm->writing){
usb_terminate_bulk(acm->dev, acm->writetransfer);
acm->writing=0;
@@ -498,8 +498,6 @@ static void acm_disconnect(struct usb_device *dev)
}
usb_release_irq(acm->dev,acm->ctrltransfer, acm->ctrlpipe);
//BUG: What to do if a device is open?? Notify process or not allow cleanup?
- acm->active=0;
- acm->present=0;
kfree(acm->writebuffer);
kfree(acm->readbuffer);
diff --git a/drivers/usb/cpia.c b/drivers/usb/cpia.c
index 976ab02da..e6515c710 100644
--- a/drivers/usb/cpia.c
+++ b/drivers/usb/cpia.c
@@ -52,7 +52,7 @@ static inline unsigned long uvirt_to_kva(pgd_t *pgd, unsigned long adr)
ptep = pte_offset(pmd, adr);
pte = *ptep;
if (pte_present(pte))
- ret = (pte_page(pte) | (adr & (PAGE_SIZE-1)));
+ ret = page_address(pte_page(pte)) | (adr & (PAGE_SIZE-1));
}
}
MDEBUG(printk("uv2kva(%lx-->%lx)", adr, ret));
diff --git a/drivers/usb/ezusb.c b/drivers/usb/ezusb.c
index 8aabddd17..c64335699 100644
--- a/drivers/usb/ezusb.c
+++ b/drivers/usb/ezusb.c
@@ -1073,11 +1073,8 @@ void ezusb_cleanup(void)
#ifdef MODULE
-int minor = 192;
-
int init_module(void)
{
- ezusb_misc.minor = minor;
return ezusb_init();
}
diff --git a/drivers/usb/hub.c b/drivers/usb/hub.c
index 59a539867..98c1c540c 100644
--- a/drivers/usb/hub.c
+++ b/drivers/usb/hub.c
@@ -15,6 +15,7 @@
#include <linux/spinlock.h>
#include <asm/uaccess.h>
+#include <asm/byteorder.h>
#include "usb.h"
#include "hub.h"
@@ -51,16 +52,16 @@ static int usb_set_port_feature(struct usb_device *dev, int port, int feature)
static int usb_get_hub_status(struct usb_device *dev, void *data)
{
- /* FIXME: Don't hardcode 4 */
return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
- USB_REQ_GET_STATUS, USB_DIR_IN | USB_RT_HUB, 0, 0, data, 4, HZ);
+ USB_REQ_GET_STATUS, USB_DIR_IN | USB_RT_HUB, 0, 0,
+ data, sizeof(struct usb_hub_status), HZ);
}
static int usb_get_port_status(struct usb_device *dev, int port, void *data)
{
- /* FIXME: Don't hardcode 4 */
return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
- USB_REQ_GET_STATUS, USB_DIR_IN | USB_RT_PORT, 0, port, data, 4, HZ);
+ USB_REQ_GET_STATUS, USB_DIR_IN | USB_RT_PORT, 0, port,
+ data, sizeof(struct usb_hub_status), HZ);
}
/*
@@ -101,6 +102,7 @@ static int usb_hub_configure(struct usb_hub *hub)
unsigned char buffer[4], *bitmap;
struct usb_hub_descriptor *descriptor;
struct usb_descriptor_header *header;
+ struct usb_hub_status *hubsts;
int i;
/* Set it to the first configuration */
@@ -121,7 +123,7 @@ static int usb_hub_configure(struct usb_hub *hub)
descriptor = (struct usb_hub_descriptor *)bitmap;
hub->nports = dev->maxchild = descriptor->bNbrPorts;
- printk(KERN_INFO "hub: %d-port%s detected\n", hub->nports,
+ printk(KERN_INFO "hub: %d port%s detected\n", hub->nports,
(hub->nports == 1) ? "" : "s");
switch (descriptor->wHubCharacteristics & HUB_CHAR_LPSM) {
@@ -144,14 +146,14 @@ static int usb_hub_configure(struct usb_hub *hub)
switch (descriptor->wHubCharacteristics & HUB_CHAR_OCPM) {
case 0x00:
- printk(KERN_INFO "hub: global over current protection\n");
+ printk(KERN_INFO "hub: global over-current protection\n");
break;
case 0x08:
- printk(KERN_INFO "hub: individual port over current protection\n");
+ printk(KERN_INFO "hub: individual port over-current protection\n");
break;
case 0x10:
case 0x18:
- printk(KERN_INFO "hub: no over current protection\n");
+ printk(KERN_INFO "hub: no over-current protection\n");
break;
}
@@ -171,11 +173,12 @@ static int usb_hub_configure(struct usb_hub *hub)
if (usb_get_hub_status(dev, buffer))
return -1;
+ hubsts = (struct usb_hub_status *)buffer;
printk(KERN_INFO "hub: local power source is %s\n",
- (buffer[0] & 1) ? "lost (inactive)" : "good");
+ (le16_to_cpu(hubsts->wHubStatus) & HUB_STATUS_LOCAL_POWER) ? "lost (inactive)" : "good");
- printk(KERN_INFO "hub: %sover current condition exists\n",
- (buffer[0] & 2) ? "" : "no ");
+ printk(KERN_INFO "hub: %sover-current condition exists\n",
+ (le16_to_cpu(hubsts->wHubStatus) & HUB_STATUS_OVERCURRENT) ? "" : "no ");
/* Enable power to the ports */
printk(KERN_INFO "hub: enabling power on all ports\n");
@@ -292,7 +295,7 @@ static void hub_disconnect(struct usb_device *dev)
static void usb_hub_port_connect_change(struct usb_device *hub, int port)
{
struct usb_device *usb;
- unsigned char buf[4];
+ struct usb_port_status portsts;
unsigned short portstatus, portchange;
/* Disconnect anything that may have been there */
@@ -304,13 +307,13 @@ static void usb_hub_port_connect_change(struct usb_device *hub, int port)
wait_ms(50); /* FIXME: This is from the *BSD stack, thanks! :) */
/* Check status */
- if (usb_get_port_status(hub, port + 1, buf)) {
+ if (usb_get_port_status(hub, port + 1, &portsts)) {
printk(KERN_ERR "get_port_status failed\n");
return;
}
- portstatus = le16_to_cpup((unsigned short *)buf + 0);
- portchange = le16_to_cpup((unsigned short *)buf + 1);
+ portstatus = le16_to_cpu(portsts.wPortStatus);
+ portchange = le16_to_cpu(portsts.wPortChange);
/* If it's not in CONNECT and ENABLE state, we're done */
if ((!(portstatus & USB_PORT_STAT_CONNECTION)) &&
@@ -373,16 +376,16 @@ static void usb_hub_events(void)
spin_unlock_irqrestore(&hub_event_lock, flags);
for (i = 0; i < hub->nports; i++) {
- unsigned char buf[4];
+ struct usb_port_status portsts;
unsigned short portstatus, portchange;
- if (usb_get_port_status(dev, i + 1, buf)) {
+ if (usb_get_port_status(dev, i + 1, &portsts)) {
printk(KERN_ERR "get_port_status failed\n");
continue;
}
- portstatus = le16_to_cpup((unsigned short *)buf + 0);
- portchange = le16_to_cpup((unsigned short *)buf + 1);
+ portstatus = le16_to_cpu(portsts.wPortStatus);
+ portchange = le16_to_cpu(portsts.wPortChange);
if (portchange & USB_PORT_STAT_C_CONNECTION) {
printk(KERN_INFO "hub: port %d connection change\n",
@@ -415,9 +418,8 @@ static void usb_hub_events(void)
usb_clear_port_feature(dev, i + 1,
USB_PORT_FEAT_C_RESET);
}
-
- }
- }
+ } /* end for i */
+ } /* end while (1) */
he_unlock:
spin_unlock_irqrestore(&hub_event_lock, flags);
diff --git a/drivers/usb/hub.h b/drivers/usb/hub.h
index 49c531d30..c95a07d74 100644
--- a/drivers/usb/hub.h
+++ b/drivers/usb/hub.h
@@ -4,7 +4,7 @@
#include <linux/list.h>
/*
- * Hub feature numbers
+ * Hub Class feature numbers
*/
#define C_HUB_LOCAL_POWER 0
#define C_HUB_OVER_CURRENT 1
@@ -25,7 +25,12 @@
#define USB_PORT_FEAT_C_OVER_CURRENT 19
#define USB_PORT_FEAT_C_RESET 20
-/* wPortStatus */
+struct usb_port_status {
+ __u16 wPortStatus;
+ __u16 wPortChange;
+} __attribute__ ((packed));
+
+/* wPortStatus bits */
#define USB_PORT_STAT_CONNECTION 0x0001
#define USB_PORT_STAT_ENABLE 0x0002
#define USB_PORT_STAT_SUSPEND 0x0004
@@ -34,7 +39,7 @@
#define USB_PORT_STAT_POWER 0x0100
#define USB_PORT_STAT_LOW_SPEED 0x0200
-/* wPortChange */
+/* wPortChange bits */
#define USB_PORT_STAT_C_CONNECTION 0x0001
#define USB_PORT_STAT_C_ENABLE 0x0002
#define USB_PORT_STAT_C_SUSPEND 0x0004
@@ -46,6 +51,20 @@
#define HUB_CHAR_COMPOUND 0x0004
#define HUB_CHAR_OCPM 0x0018
+struct usb_hub_status {
+ __u16 wHubStatus;
+ __u16 wHubChange;
+} __attribute__ ((packed));
+
+/*
+ *Hub Status & Hub Change bit masks
+ */
+#define HUB_STATUS_LOCAL_POWER 0x0001
+#define HUB_STATUS_OVERCURRENT 0x0002
+
+#define HUB_CHANGE_LOCAL_POWER 0x0001
+#define HUB_CHANGE_OVERCURRENT 0x0002
+
/* Hub descriptor */
struct usb_hub_descriptor {
__u8 bLength;
@@ -103,4 +122,3 @@ struct usb_hub {
};
#endif
-
diff --git a/drivers/usb/ohci-hcd.c b/drivers/usb/ohci-hcd.c
index 3dc6d74ca..3345e12be 100644
--- a/drivers/usb/ohci-hcd.c
+++ b/drivers/usb/ohci-hcd.c
@@ -14,9 +14,8 @@
* [ Open Host Controller Interface driver for USB. ]
* [ (C) Copyright 1999 Linus Torvalds (uhci.c) ]
* [ (C) Copyright 1999 Gregory P. Smith <greg@electricrain.com> ]
- * [ _Log: ohci-hcd.c,v _
- * [ Revision 1.1 1999/04/05 08:32:30 greg ]
*
+ * v4.3 1999/10/27 multiple HCs, bulk_request
* v4.2 1999/09/05 ISO API alpha, new dev alloc, neg Error-codes
* v4.1 1999/08/27 Randy Dunlap's - ISO API first impl.
* v4.0 1999/08/18
@@ -48,6 +47,7 @@
#include <linux/errno.h>
#include <linux/timer.h>
#include <linux/spinlock.h>
+#include <linux/list.h>
#include <asm/io.h>
#include <asm/irq.h>
@@ -61,6 +61,7 @@
static int handle_apm_event(apm_event_t event);
static int apm_resume = 0;
#endif
+static LIST_HEAD(ohci_hcd_list);
static int ohci_link_ed(struct ohci * ohci, struct usb_ohci_ed *ed);
static int sohci_kill_isoc (struct usb_isoc_desc *id);
@@ -85,10 +86,11 @@ OHCI_DEBUG(printk("******* dev: devnum: %4x, slow: %4x, maxpacketsize: %4x\n",us
**** Interface functions
***********************************************/
-static int sohci_blocking_handler(void * ohci_in, struct usb_ohci_ed *ed, void * data, int data_len, int status, __OHCI_BAG lw0, __OHCI_BAG lw1)
+static int sohci_blocking_handler(void * ohci_in, struct usb_ohci_td *td, void * data, int data_len, int dlen, int status, __OHCI_BAG lw0, __OHCI_BAG lw1)
{
+ struct usb_ohci_ed *ed = td->ed;
if(lw0 != NULL) {
- if(USB_ST_CRC < 0 && (status == USB_ST_DATAUNDERRUN || status == USB_ST_NOERROR))
+ if(0 < 0 && (status == USB_ST_DATAUNDERRUN || status == USB_ST_NOERROR))
((struct ohci_state * )lw0)->status = data_len;
else
((struct ohci_state * )lw0)->status = status;
@@ -107,9 +109,9 @@ static int sohci_blocking_handler(void * ohci_in, struct usb_ohci_ed *ed, void *
return 0;
}
-static int sohci_int_handler(void * ohci_in, struct usb_ohci_ed *ed, void * data, int data_len, int status, __OHCI_BAG lw0, __OHCI_BAG lw1)
+static int sohci_int_handler(void * ohci_in, struct usb_ohci_td *td, void * data, int data_len, int dlen, int status, __OHCI_BAG lw0, __OHCI_BAG lw1)
{
-
+ struct usb_ohci_ed *ed = td->ed;
struct ohci * ohci = ohci_in;
usb_device_irq handler=(void *) lw0;
void *dev_id = (void *) lw1;
@@ -127,9 +129,30 @@ static int sohci_int_handler(void * ohci_in, struct usb_ohci_ed *ed, void * data
return 0;
}
-static int sohci_iso_handler(void * ohci_in, struct usb_ohci_ed *ed, void * data, int data_len, int status, __OHCI_BAG lw0, __OHCI_BAG lw1) {
+static int sohci_ret_handler(void * ohci_in, struct usb_ohci_td *td, void * data, int data_len, int dlen, int status, __OHCI_BAG lw0, __OHCI_BAG lw1)
+{
+ struct usb_ohci_ed *ed = td->ed;
+ struct ohci * ohci = ohci_in;
+ usb_device_irq handler=(void *) lw0;
+ void *dev_id = (void *) lw1;
+ int ret;
+
+ OHCI_DEBUG({ int i; printk("USB HC RET <<<: %x: data(%d):", ed->hwINFO, data_len);)
+ OHCI_DEBUG( for(i=0; i < data_len; i++ ) printk(" %02x", ((__u8 *) data)[i]);)
+ OHCI_DEBUG( printk(" ret_status: %x\n", status); })
+
+ ret = handler(status, data, data_len, dev_id);
+ if(ret == 0) return 0; /* 0 .. do not requeue */
+ if(status > 0) return -1; /* error occured do not requeue ? */
+ ohci_trans_req(ohci, ed, 0, NULL, data, dlen, (__OHCI_BAG) handler, (__OHCI_BAG) dev_id, td->type & 0x7, sohci_ret_handler); /* requeue int request */
+
+ return 0;
+}
+
+static int sohci_iso_handler(void * ohci_in, struct usb_ohci_td *td, void * data, int data_len, int dlen, int status, __OHCI_BAG lw0, __OHCI_BAG lw1) {
// struct ohci * ohci = ohci_in;
+ struct usb_ohci_ed *ed = td->ed;
unsigned int ix = (unsigned int) lw0;
struct usb_isoc_desc * id = (struct usb_isoc_desc *) lw1;
struct usb_ohci_td **tdp = id->td;
@@ -311,7 +334,7 @@ static void * sohci_request_bulk(struct usb_device *usb_dev, unsigned int pipe,
OHCI_DEBUG( printk("USB HC BULK_RQ>>>: %x \n", ed->hwINFO);)
- ohci_trans_req(ohci, ed, 0, NULL, data, len, (__OHCI_BAG) handler, (__OHCI_BAG) dev_id, (usb_pipeout(pipe))?BULK_OUT:BULK_IN, sohci_int_handler);
+ ohci_trans_req(ohci, ed, 0, NULL, data, len, (__OHCI_BAG) handler, (__OHCI_BAG) dev_id, (usb_pipeout(pipe))?BULK_OUT:BULK_IN, sohci_ret_handler);
if (ED_STATE(ed) != ED_OPER) ohci_link_ed(ohci, ed);
return ed;
@@ -482,7 +505,7 @@ static int sohci_kill_isoc(struct usb_isoc_desc *id) {
struct usb_ohci_ed *ed = NULL;
struct usb_ohci_td **td = id->td;
int i;
-printk("KILL_ISOC***:\n");
+
for (i = 0; i < id->frame_count; i++) {
if(td[i]) {
td[i]->type |= DEL;
@@ -490,22 +513,17 @@ printk("KILL_ISOC***:\n");
}
}
if(ed) usb_ohci_rm_ep(id->usb_dev, ed, NULL, NULL, NULL, TD_RM);
-printk(": end KILL_ISOC***: %p\n", ed);
+
id->start_frame = -1;
return 0;
}
static void sohci_free_isoc(struct usb_isoc_desc *id) {
-printk("FREE_ISOC***\n");
-wait_ms(2000);
+
if(id->start_frame >= 0) sohci_kill_isoc(id);
-printk("FREE_ISOC2***\n");
-wait_ms(2000);
kfree(id->td);
kfree(id);
-printk("FREE_ISOC3***\n");
-wait_ms(2000);
}
struct usb_operations sohci_device_operations = {
@@ -772,17 +790,14 @@ struct usb_ohci_ed *usb_ohci_add_ep(struct usb_device * usb_dev, struct usb_hcd_
// struct ohci * ohci = usb_dev->bus->hcpriv;
struct usb_ohci_td * td;
- struct usb_ohci_ed * ed, *ed1;
+ struct usb_ohci_ed * ed;
- int ed_state, ed_state1;
+ int ed_state;
spin_lock(&usb_ed_lock);
ed = ohci_find_ep(usb_dev, hcd_ed);
-
- ed1 = ((void *) ed) + 0x40; ed_state1 = ED_STATE(ed1);
-OHCI_DEBUG(printk("++++ USB HC add 60 ed1 %x: %x :state: %x\n", ed1->hwINFO, (unsigned int ) ed1, ed_state1); )
ed_state = ED_STATE(ed); /* store state of ed */
OHCI_DEBUG(printk("USB HC add ed %x: %x :state: %x\n", ed->hwINFO, (unsigned int ) ed, ed_state); )
if (ed_state == ED_NEW) {
@@ -1139,7 +1154,8 @@ static int usb_ohci_done_list(struct ohci * ohci, struct usb_ohci_td * td_list)
struct usb_ohci_td * td_list_next = NULL;
int cc;
- int i;
+ int i;
+ int dlen = 0;
while(td_list) {
td_list_next = td_list->next_dl_td;
@@ -1156,8 +1172,9 @@ static int usb_ohci_done_list(struct ohci * ohci, struct usb_ohci_td * td_list)
}
else {
if(td_list->hwBE != 0) {
+ dlen = (bus_to_virt(td_list->hwBE) - td_list->buffer_start + 1);
if(td_list->hwCBP == 0)
- td_list->ed->len += (bus_to_virt(td_list->hwBE) - td_list->buffer_start + 1);
+ td_list->ed->len += dlen;
else
td_list->ed->len += (bus_to_virt(td_list->hwCBP) - td_list->buffer_start);
}
@@ -1170,9 +1187,10 @@ static int usb_ohci_done_list(struct ohci * ohci, struct usb_ohci_td * td_list)
if((td_list->type & SEND) && (ED_STATE(td_list->ed) != ED_STOP) && (td_list->handler)) { /* send the reply */
td_list->handler((void *) ohci,
- td_list->ed,
+ td_list,
td_list->ed->buffer_start,
td_list->ed->len,
+ dlen,
cc,
td_list->lw0,
td_list->lw1);
@@ -1227,7 +1245,7 @@ void reset_hc(struct ohci *ohci) {
udelay(1);
}
}
-static struct ohci *__ohci;
+
/*
* Start an OHCI controller, set the BUS operational
@@ -1353,7 +1371,7 @@ static struct ohci *alloc_ohci(void* mem_base)
ohci->irq = -1;
ohci->regs = mem_base;
ohci->hc_area = hc_area;
- __ohci = ohci;
+
/*
* for load ballancing of the interrupt branches
*/
@@ -1395,7 +1413,7 @@ static void release_ohci(struct ohci *ohci)
/* disconnect all devices */
if(ohci->bus->root_hub) usb_disconnect(&ohci->bus->root_hub);
- reset_hc(__ohci);
+ reset_hc(ohci);
writel(OHCI_USB_RESET, &ohci->regs->control);
wait_ms(10);
@@ -1428,6 +1446,9 @@ static int found_ohci(int irq, void* mem_base)
return -ENOMEM;
}
+ INIT_LIST_HEAD(&ohci->ohci_hcd_list);
+ list_add(&ohci->ohci_hcd_list, &ohci_hcd_list);
+
reset_hc(ohci);
writel(OHCI_USB_RESET, &ohci->regs->control);
wait_ms(10);
@@ -1438,6 +1459,7 @@ static int found_ohci(int irq, void* mem_base)
start_hc(ohci);
return 0;
}
+ printk(KERN_ERR "USB HC (ohci-hcd): request interrupt %d failed\n", irq);
release_ohci(ohci);
return -EBUSY;
}
@@ -1445,7 +1467,8 @@ static int found_ohci(int irq, void* mem_base)
static int start_ohci(struct pci_dev *dev)
{
unsigned int mem_base = dev->resource[0].start;
-
+
+ pci_set_master(dev);
mem_base = (unsigned int) ioremap_nocache(mem_base, 4096);
if (!mem_base) {
@@ -1488,17 +1511,18 @@ static int handle_apm_event(apm_event_t event)
int ohci_hcd_init(void)
{
+ int ret = -ENODEV;
struct pci_dev *dev = NULL;
while((dev = pci_find_class(PCI_CLASS_SERIAL_USB_OHCI, dev))) {
- if (start_ohci(dev) < 0) return -ENODEV;
+ if (start_ohci(dev) >= 0) ret = 0;
}
#ifdef CONFIG_APM
apm_register_callback(&handle_apm_event);
#endif
- return 0;
+ return ret;
}
#ifdef MODULE
@@ -1509,10 +1533,17 @@ int init_module(void)
void cleanup_module(void)
{
+ struct ohci *ohci;
+
# ifdef CONFIG_APM
apm_unregister_callback(&handle_apm_event);
# endif
- release_ohci(__ohci);
+ while(!list_empty(&ohci_hcd_list)) {
+ ohci = list_entry(ohci_hcd_list.next, struct ohci, ohci_hcd_list);
+ list_del(ohci->ohci_hcd_list);
+ INIT_LIST_HEAD(ohci->ohci_hcd_list);
+ release_ohci(ohci);
+ }
}
#endif //MODULE
diff --git a/drivers/usb/ohci-hcd.h b/drivers/usb/ohci-hcd.h
index 3ff3ae91d..722bbeaea 100644
--- a/drivers/usb/ohci-hcd.h
+++ b/drivers/usb/ohci-hcd.h
@@ -48,10 +48,11 @@
#include <linux/list.h>
#include <asm/io.h>
struct usb_ohci_ed;
+struct usb_ohci_td;
/* for ED and TD structures */
typedef void * __OHCI_BAG;
-typedef int (*f_handler )(void * ohci, struct usb_ohci_ed *ed, void *data, int data_len, int status, __OHCI_BAG lw0, __OHCI_BAG lw1);
+typedef int (*f_handler )(void * ohci, struct usb_ohci_td *td, void *data, int data_len, int dlen, int status, __OHCI_BAG lw0, __OHCI_BAG lw1);
@@ -309,7 +310,9 @@ struct ohci {
int irq;
struct ohci_regs *regs; /* OHCI controller's memory */
struct ohci_hc_area *hc_area; /* hcca, int ed-tree, ohci itself .. */
-
+
+ struct list_head ohci_hcd_list; /* list of all ohci_hcd */
+
int ohci_int_load[32]; /* load of the 32 Interrupt Chains (for load ballancing)*/
struct usb_ohci_ed * ed_rm_list; /* list of all endpoints to be removed */
struct usb_ohci_ed * ed_bulktail; /* last endpoint of bulk list */
diff --git a/drivers/usb/uhci.c b/drivers/usb/uhci.c
index 20be3faab..25b2b303c 100644
--- a/drivers/usb/uhci.c
+++ b/drivers/usb/uhci.c
@@ -154,7 +154,10 @@ static int uhci_td_result(struct uhci_device *dev, struct uhci_td *td, unsigned
actlength = uhci_actual_length(tmp->status);
if (rval)
*rval += actlength;
- if (explength != actlength) {
+ /* This check is bogus, at least for acm. It
+ always expects 64, but gets as many bytes
+ as available (typically 1) -- pavel */
+ if (0 && (explength != actlength)) {
/* Reset the data toggle on error. */
if (debug || uhci_debug)
printk(KERN_DEBUG "Set toggle from %p rval %ld%c for status=%x to %d, exp=%d, act=%d\n",
diff --git a/drivers/usb/usb-serial.c b/drivers/usb/usb-serial.c
index b85f2b5c6..6eb2d6455 100644
--- a/drivers/usb/usb-serial.c
+++ b/drivers/usb/usb-serial.c
@@ -11,6 +11,9 @@
* vendor and device ids for that device.
*
*
+ * version 0.1.2 (10/25/99) gkh
+ * Fixed bug in detecting device.
+ *
* version 0.1.1 (10/05/99) gkh
* Changed the major number to not conflict with anything else.
*
@@ -528,7 +531,7 @@ static int usb_serial_probe(struct usb_device *dev)
serial->interrupt_in_interval = endpoint->bInterval;
/* serial->interrupt_in_pipe = usb_rcvbulkpipe (dev, serial->bulk_in_endpoint); */
serial->interrupt_in_buffer = kmalloc (serial->bulk_in_size, GFP_KERNEL);
- if (!serial->bulk_in_buffer) {
+ if (!serial->interrupt_in_buffer) {
printk("USB Serial: Couldn't allocate interrupt_in_buffer\n");
goto probe_error;
}