Staging: Merge staging-next into Linus's tree

Conflicts:
	drivers/staging/Kconfig
	drivers/staging/batman-adv/bat_sysfs.c
	drivers/staging/batman-adv/device.c
	drivers/staging/batman-adv/hard-interface.c
	drivers/staging/cx25821/cx25821-audups11.c

Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
This commit is contained in:
Greg Kroah-Hartman 2010-08-05 14:18:03 -07:00
commit e9563355ac
812 changed files with 106098 additions and 33576 deletions

View File

@ -18,6 +18,7 @@
#include <asm/mshyperv.h> #include <asm/mshyperv.h>
struct ms_hyperv_info ms_hyperv; struct ms_hyperv_info ms_hyperv;
EXPORT_SYMBOL_GPL(ms_hyperv);
static bool __init ms_hyperv_platform(void) static bool __init ms_hyperv_platform(void)
{ {

View File

@ -97,6 +97,8 @@ source "drivers/staging/octeon/Kconfig"
source "drivers/staging/serqt_usb2/Kconfig" source "drivers/staging/serqt_usb2/Kconfig"
source "drivers/staging/spectra/Kconfig"
source "drivers/staging/quatech_usb2/Kconfig" source "drivers/staging/quatech_usb2/Kconfig"
source "drivers/staging/vt6655/Kconfig" source "drivers/staging/vt6655/Kconfig"
@ -115,7 +117,7 @@ source "drivers/staging/sep/Kconfig"
source "drivers/staging/iio/Kconfig" source "drivers/staging/iio/Kconfig"
source "drivers/staging/ramzswap/Kconfig" source "drivers/staging/zram/Kconfig"
source "drivers/staging/wlags49_h2/Kconfig" source "drivers/staging/wlags49_h2/Kconfig"
@ -127,8 +129,6 @@ source "drivers/staging/samsung-laptop/Kconfig"
source "drivers/staging/sm7xx/Kconfig" source "drivers/staging/sm7xx/Kconfig"
source "drivers/staging/dt3155/Kconfig"
source "drivers/staging/dt3155v4l/Kconfig" source "drivers/staging/dt3155v4l/Kconfig"
source "drivers/staging/crystalhd/Kconfig" source "drivers/staging/crystalhd/Kconfig"
@ -147,5 +147,13 @@ source "drivers/staging/msm/Kconfig"
source "drivers/staging/lirc/Kconfig" source "drivers/staging/lirc/Kconfig"
source "drivers/staging/easycap/Kconfig"
source "drivers/staging/solo6x10/Kconfig"
source "drivers/staging/tidspbridge/Kconfig"
source "drivers/staging/quickstart/Kconfig"
endif # !STAGING_EXCLUDE_BUILD endif # !STAGING_EXCLUDE_BUILD
endif # STAGING endif # STAGING

View File

@ -23,6 +23,7 @@ obj-$(CONFIG_R8187SE) += rtl8187se/
obj-$(CONFIG_RTL8192SU) += rtl8192su/ obj-$(CONFIG_RTL8192SU) += rtl8192su/
obj-$(CONFIG_RTL8192U) += rtl8192u/ obj-$(CONFIG_RTL8192U) += rtl8192u/
obj-$(CONFIG_RTL8192E) += rtl8192e/ obj-$(CONFIG_RTL8192E) += rtl8192e/
obj-$(CONFIG_SPECTRA) += spectra/
obj-$(CONFIG_TRANZPORT) += frontier/ obj-$(CONFIG_TRANZPORT) += frontier/
obj-$(CONFIG_DREAM) += dream/ obj-$(CONFIG_DREAM) += dream/
obj-$(CONFIG_POHMELFS) += pohmelfs/ obj-$(CONFIG_POHMELFS) += pohmelfs/
@ -39,13 +40,12 @@ obj-$(CONFIG_VME_BUS) += vme/
obj-$(CONFIG_MRST_RAR_HANDLER) += memrar/ obj-$(CONFIG_MRST_RAR_HANDLER) += memrar/
obj-$(CONFIG_DX_SEP) += sep/ obj-$(CONFIG_DX_SEP) += sep/
obj-$(CONFIG_IIO) += iio/ obj-$(CONFIG_IIO) += iio/
obj-$(CONFIG_RAMZSWAP) += ramzswap/ obj-$(CONFIG_ZRAM) += zram/
obj-$(CONFIG_WLAGS49_H2) += wlags49_h2/ obj-$(CONFIG_WLAGS49_H2) += wlags49_h2/
obj-$(CONFIG_WLAGS49_H25) += wlags49_h25/ obj-$(CONFIG_WLAGS49_H25) += wlags49_h25/
obj-$(CONFIG_BATMAN_ADV) += batman-adv/ obj-$(CONFIG_BATMAN_ADV) += batman-adv/
obj-$(CONFIG_SAMSUNG_LAPTOP) += samsung-laptop/ obj-$(CONFIG_SAMSUNG_LAPTOP) += samsung-laptop/
obj-$(CONFIG_FB_SM7XX) += sm7xx/ obj-$(CONFIG_FB_SM7XX) += sm7xx/
obj-$(CONFIG_DT3155) += dt3155/
obj-$(CONFIG_VIDEO_DT3155) += dt3155v4l/ obj-$(CONFIG_VIDEO_DT3155) += dt3155v4l/
obj-$(CONFIG_CRYSTALHD) += crystalhd/ obj-$(CONFIG_CRYSTALHD) += crystalhd/
obj-$(CONFIG_CXT1E1) += cxt1e1/ obj-$(CONFIG_CXT1E1) += cxt1e1/
@ -54,3 +54,7 @@ obj-$(CONFIG_ADIS16255) += adis16255/
obj-$(CONFIG_FB_XGI) += xgifb/ obj-$(CONFIG_FB_XGI) += xgifb/
obj-$(CONFIG_TOUCHSCREEN_MRSTOUCH) += mrst-touchscreen/ obj-$(CONFIG_TOUCHSCREEN_MRSTOUCH) += mrst-touchscreen/
obj-$(CONFIG_MSM_STAGING) += msm/ obj-$(CONFIG_MSM_STAGING) += msm/
obj-$(CONFIG_EASYCAP) += easycap/
obj-$(CONFIG_SOLO6X10) += solo6x10/
obj-$(CONFIG_TIDSPBRIDGE) += tidspbridge/
obj-$(CONFIG_ACPI_QUICKSTART) += quickstart/

View File

@ -303,7 +303,7 @@ static int spi_adis16255_bringup(struct spi_adis16255_data *spiadis)
if (status != 0) if (status != 0)
goto err; goto err;
if (value != 0x0800) { if (value != 0x0800) {
dev_warn(&spiadis->spi->dev, "Scale factor is none default" dev_warn(&spiadis->spi->dev, "Scale factor is none default "
"value (%.4x)\n", value); "value (%.4x)\n", value);
} }
@ -338,7 +338,7 @@ static int spi_adis16255_bringup(struct spi_adis16255_data *spiadis)
status = -ENODEV; status = -ENODEV;
goto err; goto err;
} else if (value & 0x3) { } else if (value & 0x3) {
dev_warn(&spiadis->spi->dev, "Sensor voltage" dev_warn(&spiadis->spi->dev, "Sensor voltage "
"out of range.\n"); "out of range.\n");
status = -ENODEV; status = -ENODEV;
goto err; goto err;

View File

@ -1,3 +1,15 @@
batman-adv 2010.0.0:
* support latest kernels (2.6.21 - 2.6.35)
* further code refactoring and cleaning for coding style
* move from procfs based configuration to sysfs
* reorganized sequence number handling
* limit queue lengths for batman and broadcast packets
* many bugs (endless loop and rogue packets on shutdown, wrong tcpdump output,
missing frees in error situations, sleeps in atomic contexts) squashed
-- Fri, 18 Jun 2010 21:34:26 +0200
batman-adv 0.2.1: batman-adv 0.2.1:
* support latest kernels (2.6.20 - 2.6.33) * support latest kernels (2.6.20 - 2.6.33)

View File

@ -4,7 +4,7 @@
config BATMAN_ADV config BATMAN_ADV
tristate "B.A.T.M.A.N. Advanced Meshing Protocol" tristate "B.A.T.M.A.N. Advanced Meshing Protocol"
depends on PROC_FS && NET depends on NET
default n default n
---help--- ---help---

View File

@ -18,5 +18,5 @@
# 02110-1301, USA # 02110-1301, USA
# #
obj-m += batman-adv.o obj-$(CONFIG_BATMAN_ADV) += batman-adv.o
batman-adv-objs := main.o send.o routing.o soft-interface.o device.o translation-table.o bitarray.o hash.o ring_buffer.o vis.o hard-interface.o aggregation.o originator.o bat_sysfs.o batman-adv-objs := main.o bat_debugfs.o bat_sysfs.o send.o routing.o soft-interface.o icmp_socket.o translation-table.o bitarray.o hash.o ring_buffer.o vis.o hard-interface.o aggregation.o originator.o

View File

@ -1,4 +1,4 @@
[state: 03-05-2010] [state: 12-06-2010]
BATMAN-ADV BATMAN-ADV
---------- ----------

View File

@ -1,6 +1,9 @@
Request a review. * Use hweight* for hamming weight calculation
Process the comments from the review. * Save/cache packets direktly as skb instead of using a normal memory region
Move into mainline proper. and copying it in a skb using send_raw_packet and similar functions
* Request a new review
* Process the comments from the review
* Move into mainline proper
Please send all patches to: Please send all patches to:
Marek Lindner <lindner_marek@yahoo.de> Marek Lindner <lindner_marek@yahoo.de>

View File

@ -106,11 +106,14 @@ static void new_aggregated_packet(unsigned char *packet_buff,
{ {
struct forw_packet *forw_packet_aggr; struct forw_packet *forw_packet_aggr;
unsigned long flags; unsigned long flags;
/* FIXME: each batman_if will be attached to a softif */
struct bat_priv *bat_priv = netdev_priv(soft_device);
/* own packet should always be scheduled */ /* own packet should always be scheduled */
if (!own_packet) { if (!own_packet) {
if (!atomic_dec_not_zero(&batman_queue_left)) { if (!atomic_dec_not_zero(&batman_queue_left)) {
bat_dbg(DBG_BATMAN, "batman packet queue full\n"); bat_dbg(DBG_BATMAN, bat_priv,
"batman packet queue full\n");
return; return;
} }
} }
@ -252,9 +255,9 @@ void receive_aggr_bat_packet(struct ethhdr *ethhdr, unsigned char *packet_buff,
while (aggregated_packet(buff_pos, packet_len, while (aggregated_packet(buff_pos, packet_len,
batman_packet->num_hna)) { batman_packet->num_hna)) {
/* network to host order for our 16bit seqno, and the /* network to host order for our 32bit seqno, and the
orig_interval. */ orig_interval. */
batman_packet->seqno = ntohs(batman_packet->seqno); batman_packet->seqno = ntohl(batman_packet->seqno);
hna_buff = packet_buff + buff_pos + BAT_PACKET_LEN; hna_buff = packet_buff + buff_pos + BAT_PACKET_LEN;
receive_bat_packet(ethhdr, batman_packet, receive_bat_packet(ethhdr, batman_packet,

View File

@ -19,6 +19,9 @@
* *
*/ */
#ifndef _NET_BATMAN_ADV_AGGREGATION_H_
#define _NET_BATMAN_ADV_AGGREGATION_H_
#include "main.h" #include "main.h"
/* is there another aggregated packet here? */ /* is there another aggregated packet here? */
@ -36,3 +39,5 @@ void add_bat_packet_to_list(struct bat_priv *bat_priv,
unsigned long send_time); unsigned long send_time);
void receive_aggr_bat_packet(struct ethhdr *ethhdr, unsigned char *packet_buff, void receive_aggr_bat_packet(struct ethhdr *ethhdr, unsigned char *packet_buff,
int packet_len, struct batman_if *if_incoming); int packet_len, struct batman_if *if_incoming);
#endif /* _NET_BATMAN_ADV_AGGREGATION_H_ */

View File

@ -0,0 +1,341 @@
/*
* Copyright (C) 2010 B.A.T.M.A.N. contributors:
*
* Marek Lindner
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of version 2 of the GNU General Public
* License as published by the Free Software Foundation.
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA
*
*/
#include "main.h"
#include <linux/debugfs.h>
#include "bat_debugfs.h"
#include "translation-table.h"
#include "originator.h"
#include "hard-interface.h"
#include "vis.h"
#include "icmp_socket.h"
static struct dentry *bat_debugfs;
#ifdef CONFIG_BATMAN_ADV_DEBUG
#define LOG_BUFF_MASK (log_buff_len-1)
#define LOG_BUFF(idx) (debug_log->log_buff[(idx) & LOG_BUFF_MASK])
static int log_buff_len = LOG_BUF_LEN;
static void emit_log_char(struct debug_log *debug_log, char c)
{
LOG_BUFF(debug_log->log_end) = c;
debug_log->log_end++;
if (debug_log->log_end - debug_log->log_start > log_buff_len)
debug_log->log_start = debug_log->log_end - log_buff_len;
}
static int fdebug_log(struct debug_log *debug_log, char *fmt, ...)
{
int printed_len;
va_list args;
static char debug_log_buf[256];
char *p;
unsigned long flags;
if (!debug_log)
return 0;
spin_lock_irqsave(&debug_log->lock, flags);
va_start(args, fmt);
printed_len = vscnprintf(debug_log_buf, sizeof(debug_log_buf),
fmt, args);
va_end(args);
for (p = debug_log_buf; *p != 0; p++)
emit_log_char(debug_log, *p);
spin_unlock_irqrestore(&debug_log->lock, flags);
wake_up(&debug_log->queue_wait);
return 0;
}
int debug_log(struct bat_priv *bat_priv, char *fmt, ...)
{
va_list args;
char tmp_log_buf[256];
va_start(args, fmt);
vscnprintf(tmp_log_buf, sizeof(tmp_log_buf), fmt, args);
fdebug_log(bat_priv->debug_log, "[%10u] %s",
(jiffies / HZ), tmp_log_buf);
va_end(args);
return 0;
}
static int log_open(struct inode *inode, struct file *file)
{
file->private_data = inode->i_private;
inc_module_count();
return 0;
}
static int log_release(struct inode *inode, struct file *file)
{
dec_module_count();
return 0;
}
static ssize_t log_read(struct file *file, char __user *buf,
size_t count, loff_t *ppos)
{
struct bat_priv *bat_priv = file->private_data;
struct debug_log *debug_log = bat_priv->debug_log;
int error, i = 0;
char c;
unsigned long flags;
if ((file->f_flags & O_NONBLOCK) &&
!(debug_log->log_end - debug_log->log_start))
return -EAGAIN;
if ((!buf) || (count < 0))
return -EINVAL;
if (count == 0)
return 0;
if (!access_ok(VERIFY_WRITE, buf, count))
return -EFAULT;
error = wait_event_interruptible(debug_log->queue_wait,
(debug_log->log_start - debug_log->log_end));
if (error)
return error;
spin_lock_irqsave(&debug_log->lock, flags);
while ((!error) && (i < count) &&
(debug_log->log_start != debug_log->log_end)) {
c = LOG_BUFF(debug_log->log_start);
debug_log->log_start++;
spin_unlock_irqrestore(&debug_log->lock, flags);
error = __put_user(c, buf);
spin_lock_irqsave(&debug_log->lock, flags);
buf++;
i++;
}
spin_unlock_irqrestore(&debug_log->lock, flags);
if (!error)
return i;
return error;
}
static unsigned int log_poll(struct file *file, poll_table *wait)
{
struct bat_priv *bat_priv = file->private_data;
struct debug_log *debug_log = bat_priv->debug_log;
poll_wait(file, &debug_log->queue_wait, wait);
if (debug_log->log_end - debug_log->log_start)
return POLLIN | POLLRDNORM;
return 0;
}
static const struct file_operations log_fops = {
.open = log_open,
.release = log_release,
.read = log_read,
.poll = log_poll,
};
static int debug_log_setup(struct bat_priv *bat_priv)
{
struct dentry *d;
if (!bat_priv->debug_dir)
goto err;
bat_priv->debug_log = kzalloc(sizeof(struct debug_log), GFP_ATOMIC);
if (!bat_priv->debug_log)
goto err;
spin_lock_init(&bat_priv->debug_log->lock);
init_waitqueue_head(&bat_priv->debug_log->queue_wait);
d = debugfs_create_file("log", S_IFREG | S_IRUSR,
bat_priv->debug_dir, bat_priv, &log_fops);
if (d)
goto err;
return 0;
err:
return 1;
}
static void debug_log_cleanup(struct bat_priv *bat_priv)
{
kfree(bat_priv->debug_log);
bat_priv->debug_log = NULL;
}
#else /* CONFIG_BATMAN_ADV_DEBUG */
static int debug_log_setup(struct bat_priv *bat_priv)
{
bat_priv->debug_log = NULL;
return 0;
}
static void debug_log_cleanup(struct bat_priv *bat_priv)
{
return;
}
#endif
static int originators_open(struct inode *inode, struct file *file)
{
struct net_device *net_dev = (struct net_device *)inode->i_private;
return single_open(file, orig_seq_print_text, net_dev);
}
static int transtable_global_open(struct inode *inode, struct file *file)
{
struct net_device *net_dev = (struct net_device *)inode->i_private;
return single_open(file, hna_global_seq_print_text, net_dev);
}
static int transtable_local_open(struct inode *inode, struct file *file)
{
struct net_device *net_dev = (struct net_device *)inode->i_private;
return single_open(file, hna_local_seq_print_text, net_dev);
}
static int vis_data_open(struct inode *inode, struct file *file)
{
struct net_device *net_dev = (struct net_device *)inode->i_private;
return single_open(file, vis_seq_print_text, net_dev);
}
struct bat_debuginfo {
struct attribute attr;
const struct file_operations fops;
};
#define BAT_DEBUGINFO(_name, _mode, _open) \
struct bat_debuginfo bat_debuginfo_##_name = { \
.attr = { .name = __stringify(_name), \
.mode = _mode, }, \
.fops = { .owner = THIS_MODULE, \
.open = _open, \
.read = seq_read, \
.llseek = seq_lseek, \
.release = single_release, \
} \
};
static BAT_DEBUGINFO(originators, S_IRUGO, originators_open);
static BAT_DEBUGINFO(transtable_global, S_IRUGO, transtable_global_open);
static BAT_DEBUGINFO(transtable_local, S_IRUGO, transtable_local_open);
static BAT_DEBUGINFO(vis_data, S_IRUGO, vis_data_open);
static struct bat_debuginfo *mesh_debuginfos[] = {
&bat_debuginfo_originators,
&bat_debuginfo_transtable_global,
&bat_debuginfo_transtable_local,
&bat_debuginfo_vis_data,
NULL,
};
void debugfs_init(void)
{
bat_debugfs = debugfs_create_dir(DEBUGFS_BAT_SUBDIR, NULL);
if (bat_debugfs == ERR_PTR(-ENODEV))
bat_debugfs = NULL;
}
void debugfs_destroy(void)
{
if (bat_debugfs) {
debugfs_remove_recursive(bat_debugfs);
bat_debugfs = NULL;
}
}
int debugfs_add_meshif(struct net_device *dev)
{
struct bat_priv *bat_priv = netdev_priv(dev);
struct bat_debuginfo **bat_debug;
struct dentry *file;
if (!bat_debugfs)
goto out;
bat_priv->debug_dir = debugfs_create_dir(dev->name, bat_debugfs);
if (!bat_priv->debug_dir)
goto out;
bat_socket_setup(bat_priv);
debug_log_setup(bat_priv);
for (bat_debug = mesh_debuginfos; *bat_debug; ++bat_debug) {
file = debugfs_create_file(((*bat_debug)->attr).name,
S_IFREG | ((*bat_debug)->attr).mode,
bat_priv->debug_dir,
dev, &(*bat_debug)->fops);
if (!file) {
bat_err(dev, "Can't add debugfs file: %s/%s\n",
dev->name, ((*bat_debug)->attr).name);
goto rem_attr;
}
}
return 0;
rem_attr:
debugfs_remove_recursive(bat_priv->debug_dir);
bat_priv->debug_dir = NULL;
out:
#ifdef CONFIG_DEBUG_FS
return -ENOMEM;
#else
return 0;
#endif /* CONFIG_DEBUG_FS */
}
void debugfs_del_meshif(struct net_device *dev)
{
struct bat_priv *bat_priv = netdev_priv(dev);
debug_log_cleanup(bat_priv);
if (bat_debugfs) {
debugfs_remove_recursive(bat_priv->debug_dir);
bat_priv->debug_dir = NULL;
}
}

View File

@ -0,0 +1,33 @@
/*
* Copyright (C) 2010 B.A.T.M.A.N. contributors:
*
* Marek Lindner
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of version 2 of the GNU General Public
* License as published by the Free Software Foundation.
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA
*
*/
#ifndef _NET_BATMAN_ADV_DEBUGFS_H_
#define _NET_BATMAN_ADV_DEBUGFS_H_
#define DEBUGFS_BAT_SUBDIR "batman_adv"
void debugfs_init(void);
void debugfs_destroy(void);
int debugfs_add_meshif(struct net_device *dev);
void debugfs_del_meshif(struct net_device *dev);
#endif /* _NET_BATMAN_ADV_DEBUGFS_H_ */

View File

@ -28,22 +28,6 @@
#define to_dev(obj) container_of(obj, struct device, kobj) #define to_dev(obj) container_of(obj, struct device, kobj)
struct bat_attribute {
struct attribute attr;
ssize_t (*show)(struct kobject *kobj, struct attribute *attr,
char *buf);
ssize_t (*store)(struct kobject *kobj, struct attribute *attr,
char *buf, size_t count);
};
struct hardif_attribute {
struct attribute attr;
ssize_t (*show)(struct kobject *kobj, struct attribute *attr,
char *buf);
ssize_t (*store)(struct kobject *kobj, struct attribute *attr,
char *buf, size_t count);
};
#define BAT_ATTR(_name, _mode, _show, _store) \ #define BAT_ATTR(_name, _mode, _show, _store) \
struct bat_attribute bat_attr_##_name = { \ struct bat_attribute bat_attr_##_name = { \
.attr = {.name = __stringify(_name), \ .attr = {.name = __stringify(_name), \
@ -52,34 +36,18 @@ struct bat_attribute bat_attr_##_name = { \
.store = _store, \ .store = _store, \
}; };
#define BAT_BIN_ATTR(_name, _mode, _read, _write) \ static ssize_t show_aggr_ogms(struct kobject *kobj, struct attribute *attr,
struct bin_attribute bat_attr_##_name = { \
.attr = { .name = __stringify(_name), \
.mode = _mode, }, \
.read = _read, \
.write = _write, \
};
#define HARDIF_ATTR(_name, _mode, _show, _store) \
struct hardif_attribute hardif_attr_##_name = { \
.attr = {.name = __stringify(_name), \
.mode = _mode }, \
.show = _show, \
.store = _store, \
};
static ssize_t show_aggr_ogm(struct kobject *kobj, struct attribute *attr,
char *buff) char *buff)
{ {
struct device *dev = to_dev(kobj->parent); struct device *dev = to_dev(kobj->parent);
struct bat_priv *bat_priv = netdev_priv(to_net_dev(dev)); struct bat_priv *bat_priv = netdev_priv(to_net_dev(dev));
int aggr_status = atomic_read(&bat_priv->aggregation_enabled); int aggr_status = atomic_read(&bat_priv->aggregation_enabled);
return sprintf(buff, "status: %s\ncommands: enable, disable, 0, 1\n", return sprintf(buff, "%s\n",
aggr_status == 0 ? "disabled" : "enabled"); aggr_status == 0 ? "disabled" : "enabled");
} }
static ssize_t store_aggr_ogm(struct kobject *kobj, struct attribute *attr, static ssize_t store_aggr_ogms(struct kobject *kobj, struct attribute *attr,
char *buff, size_t count) char *buff, size_t count)
{ {
struct device *dev = to_dev(kobj->parent); struct device *dev = to_dev(kobj->parent);
@ -99,23 +67,73 @@ static ssize_t store_aggr_ogm(struct kobject *kobj, struct attribute *attr,
if (buff[count - 1] == '\n') if (buff[count - 1] == '\n')
buff[count - 1] = '\0'; buff[count - 1] = '\0';
printk(KERN_INFO "batman-adv:Invalid parameter for 'aggregate OGM' setting on mesh %s received: %s\n", bat_info(net_dev,
net_dev->name, buff); "Invalid parameter for 'aggregate OGM' setting"
"received: %s\n", buff);
return -EINVAL; return -EINVAL;
} }
if (atomic_read(&bat_priv->aggregation_enabled) == aggr_tmp) if (atomic_read(&bat_priv->aggregation_enabled) == aggr_tmp)
return count; return count;
printk(KERN_INFO "batman-adv:Changing aggregation from: %s to: %s on mesh: %s\n", bat_info(net_dev, "Changing aggregation from: %s to: %s\n",
atomic_read(&bat_priv->aggregation_enabled) == 1 ? atomic_read(&bat_priv->aggregation_enabled) == 1 ?
"enabled" : "disabled", aggr_tmp == 1 ? "enabled" : "disabled", "enabled" : "disabled", aggr_tmp == 1 ? "enabled" :
net_dev->name); "disabled");
atomic_set(&bat_priv->aggregation_enabled, (unsigned)aggr_tmp); atomic_set(&bat_priv->aggregation_enabled, (unsigned)aggr_tmp);
return count; return count;
} }
static ssize_t show_bond(struct kobject *kobj, struct attribute *attr,
char *buff)
{
struct device *dev = to_dev(kobj->parent);
struct bat_priv *bat_priv = netdev_priv(to_net_dev(dev));
int bond_status = atomic_read(&bat_priv->bonding_enabled);
return sprintf(buff, "%s\n",
bond_status == 0 ? "disabled" : "enabled");
}
static ssize_t store_bond(struct kobject *kobj, struct attribute *attr,
char *buff, size_t count)
{
struct device *dev = to_dev(kobj->parent);
struct net_device *net_dev = to_net_dev(dev);
struct bat_priv *bat_priv = netdev_priv(net_dev);
int bonding_enabled_tmp = -1;
if (((count == 2) && (buff[0] == '1')) ||
(strncmp(buff, "enable", 6) == 0))
bonding_enabled_tmp = 1;
if (((count == 2) && (buff[0] == '0')) ||
(strncmp(buff, "disable", 7) == 0))
bonding_enabled_tmp = 0;
if (bonding_enabled_tmp < 0) {
if (buff[count - 1] == '\n')
buff[count - 1] = '\0';
bat_err(net_dev,
"Invalid parameter for 'bonding' setting received: "
"%s\n", buff);
return -EINVAL;
}
if (atomic_read(&bat_priv->bonding_enabled) == bonding_enabled_tmp)
return count;
bat_info(net_dev, "Changing bonding from: %s to: %s\n",
atomic_read(&bat_priv->bonding_enabled) == 1 ?
"enabled" : "disabled",
bonding_enabled_tmp == 1 ? "enabled" : "disabled");
atomic_set(&bat_priv->bonding_enabled, (unsigned)bonding_enabled_tmp);
return count;
}
static ssize_t show_vis_mode(struct kobject *kobj, struct attribute *attr, static ssize_t show_vis_mode(struct kobject *kobj, struct attribute *attr,
char *buff) char *buff)
{ {
@ -123,10 +141,9 @@ static ssize_t show_vis_mode(struct kobject *kobj, struct attribute *attr,
struct bat_priv *bat_priv = netdev_priv(to_net_dev(dev)); struct bat_priv *bat_priv = netdev_priv(to_net_dev(dev));
int vis_mode = atomic_read(&bat_priv->vis_mode); int vis_mode = atomic_read(&bat_priv->vis_mode);
return sprintf(buff, "status: %s\ncommands: client, server, %d, %d\n", return sprintf(buff, "%s\n",
vis_mode == VIS_TYPE_CLIENT_UPDATE ? vis_mode == VIS_TYPE_CLIENT_UPDATE ?
"client" : "server", "client" : "server");
VIS_TYPE_SERVER_SYNC, VIS_TYPE_CLIENT_UPDATE);
} }
static ssize_t store_vis_mode(struct kobject *kobj, struct attribute *attr, static ssize_t store_vis_mode(struct kobject *kobj, struct attribute *attr,
@ -141,7 +158,8 @@ static ssize_t store_vis_mode(struct kobject *kobj, struct attribute *attr,
ret = strict_strtoul(buff, 10, &val); ret = strict_strtoul(buff, 10, &val);
if (((count == 2) && (!ret) && (val == VIS_TYPE_CLIENT_UPDATE)) || if (((count == 2) && (!ret) && (val == VIS_TYPE_CLIENT_UPDATE)) ||
(strncmp(buff, "client", 6) == 0)) (strncmp(buff, "client", 6) == 0) ||
(strncmp(buff, "off", 3) == 0))
vis_mode_tmp = VIS_TYPE_CLIENT_UPDATE; vis_mode_tmp = VIS_TYPE_CLIENT_UPDATE;
if (((count == 2) && (!ret) && (val == VIS_TYPE_SERVER_SYNC)) || if (((count == 2) && (!ret) && (val == VIS_TYPE_SERVER_SYNC)) ||
@ -152,18 +170,19 @@ static ssize_t store_vis_mode(struct kobject *kobj, struct attribute *attr,
if (buff[count - 1] == '\n') if (buff[count - 1] == '\n')
buff[count - 1] = '\0'; buff[count - 1] = '\0';
printk(KERN_INFO "batman-adv:Invalid parameter for 'vis mode' setting on mesh %s received: %s\n", bat_info(net_dev,
net_dev->name, buff); "Invalid parameter for 'vis mode' setting received: "
"%s\n", buff);
return -EINVAL; return -EINVAL;
} }
if (atomic_read(&bat_priv->vis_mode) == vis_mode_tmp) if (atomic_read(&bat_priv->vis_mode) == vis_mode_tmp)
return count; return count;
printk(KERN_INFO "batman-adv:Changing vis mode from: %s to: %s on mesh: %s\n", bat_info(net_dev, "Changing vis mode from: %s to: %s\n",
atomic_read(&bat_priv->vis_mode) == VIS_TYPE_CLIENT_UPDATE ? atomic_read(&bat_priv->vis_mode) == VIS_TYPE_CLIENT_UPDATE ?
"client" : "server", vis_mode_tmp == VIS_TYPE_CLIENT_UPDATE ? "client" : "server", vis_mode_tmp == VIS_TYPE_CLIENT_UPDATE ?
"client" : "server", net_dev->name); "client" : "server");
atomic_set(&bat_priv->vis_mode, (unsigned)vis_mode_tmp); atomic_set(&bat_priv->vis_mode, (unsigned)vis_mode_tmp);
return count; return count;
@ -175,7 +194,7 @@ static ssize_t show_orig_interval(struct kobject *kobj, struct attribute *attr,
struct device *dev = to_dev(kobj->parent); struct device *dev = to_dev(kobj->parent);
struct bat_priv *bat_priv = netdev_priv(to_net_dev(dev)); struct bat_priv *bat_priv = netdev_priv(to_net_dev(dev));
return sprintf(buff, "status: %i\n", return sprintf(buff, "%i\n",
atomic_read(&bat_priv->orig_interval)); atomic_read(&bat_priv->orig_interval));
} }
@ -190,91 +209,87 @@ static ssize_t store_orig_interval(struct kobject *kobj, struct attribute *attr,
ret = strict_strtoul(buff, 10, &orig_interval_tmp); ret = strict_strtoul(buff, 10, &orig_interval_tmp);
if (ret) { if (ret) {
printk(KERN_INFO "batman-adv:Invalid parameter for 'orig_interval' setting on mesh %s received: %s\n", bat_info(net_dev, "Invalid parameter for 'orig_interval' "
net_dev->name, buff); "setting received: %s\n", buff);
return -EINVAL; return -EINVAL;
} }
if (orig_interval_tmp <= JITTER * 2) { if (orig_interval_tmp < JITTER * 2) {
printk(KERN_INFO "batman-adv:New originator interval too small: %li (min: %i)\n", bat_info(net_dev, "New originator interval too small: %li "
orig_interval_tmp, JITTER * 2); "(min: %i)\n", orig_interval_tmp, JITTER * 2);
return -EINVAL; return -EINVAL;
} }
if (atomic_read(&bat_priv->orig_interval) == orig_interval_tmp) if (atomic_read(&bat_priv->orig_interval) == orig_interval_tmp)
return count; return count;
printk(KERN_INFO "batman-adv:Changing originator interval from: %i to: %li on mesh: %s\n", bat_info(net_dev, "Changing originator interval from: %i to: %li\n",
atomic_read(&bat_priv->orig_interval), atomic_read(&bat_priv->orig_interval),
orig_interval_tmp, net_dev->name); orig_interval_tmp);
atomic_set(&bat_priv->orig_interval, orig_interval_tmp); atomic_set(&bat_priv->orig_interval, orig_interval_tmp);
return count; return count;
} }
static BAT_ATTR(aggregate_ogm, S_IRUGO | S_IWUSR, #ifdef CONFIG_BATMAN_ADV_DEBUG
show_aggr_ogm, store_aggr_ogm); static ssize_t show_log_level(struct kobject *kobj, struct attribute *attr,
char *buff)
{
struct device *dev = to_dev(kobj->parent);
struct bat_priv *bat_priv = netdev_priv(to_net_dev(dev));
int log_level = atomic_read(&bat_priv->log_level);
return sprintf(buff, "%d\n", log_level);
}
static ssize_t store_log_level(struct kobject *kobj, struct attribute *attr,
char *buff, size_t count)
{
struct device *dev = to_dev(kobj->parent);
struct net_device *net_dev = to_net_dev(dev);
struct bat_priv *bat_priv = netdev_priv(net_dev);
unsigned long log_level_tmp;
int ret;
ret = strict_strtoul(buff, 10, &log_level_tmp);
if (ret) {
bat_info(net_dev, "Invalid parameter for 'log_level' "
"setting received: %s\n", buff);
return -EINVAL;
}
if (log_level_tmp > 3) {
bat_info(net_dev, "New log level too big: %li "
"(max: %i)\n", log_level_tmp, 3);
return -EINVAL;
}
if (atomic_read(&bat_priv->log_level) == log_level_tmp)
return count;
atomic_set(&bat_priv->log_level, (unsigned)log_level_tmp);
return count;
}
#endif
static BAT_ATTR(aggregated_ogms, S_IRUGO | S_IWUSR,
show_aggr_ogms, store_aggr_ogms);
static BAT_ATTR(bonding, S_IRUGO | S_IWUSR, show_bond, store_bond);
static BAT_ATTR(vis_mode, S_IRUGO | S_IWUSR, show_vis_mode, store_vis_mode); static BAT_ATTR(vis_mode, S_IRUGO | S_IWUSR, show_vis_mode, store_vis_mode);
static BAT_ATTR(orig_interval, S_IRUGO | S_IWUSR, static BAT_ATTR(orig_interval, S_IRUGO | S_IWUSR,
show_orig_interval, store_orig_interval); show_orig_interval, store_orig_interval);
#ifdef CONFIG_BATMAN_ADV_DEBUG
static BAT_ATTR(log_level, S_IRUGO | S_IWUSR, show_log_level, store_log_level);
#endif
static struct bat_attribute *mesh_attrs[] = { static struct bat_attribute *mesh_attrs[] = {
&bat_attr_aggregate_ogm, &bat_attr_aggregated_ogms,
&bat_attr_bonding,
&bat_attr_vis_mode, &bat_attr_vis_mode,
&bat_attr_orig_interval, &bat_attr_orig_interval,
NULL, #ifdef CONFIG_BATMAN_ADV_DEBUG
}; &bat_attr_log_level,
#endif
static ssize_t transtable_local_read(struct file *filp, struct kobject *kobj,
struct bin_attribute *bin_attr,
char *buff, loff_t off, size_t count)
{
struct device *dev = to_dev(kobj->parent);
struct net_device *net_dev = to_net_dev(dev);
return hna_local_fill_buffer_text(net_dev, buff, count, off);
}
static ssize_t transtable_global_read(struct file *filp, struct kobject *kobj,
struct bin_attribute *bin_attr,
char *buff, loff_t off, size_t count)
{
struct device *dev = to_dev(kobj->parent);
struct net_device *net_dev = to_net_dev(dev);
return hna_global_fill_buffer_text(net_dev, buff, count, off);
}
static ssize_t originators_read(struct file *filp, struct kobject *kobj,
struct bin_attribute *bin_attr,
char *buff, loff_t off, size_t count)
{
struct device *dev = to_dev(kobj->parent);
struct net_device *net_dev = to_net_dev(dev);
return orig_fill_buffer_text(net_dev, buff, count, off);
}
static ssize_t vis_data_read(struct file *filp, struct kobject *kobj,
struct bin_attribute *bin_attr,
char *buff, loff_t off, size_t count)
{
struct device *dev = to_dev(kobj->parent);
struct net_device *net_dev = to_net_dev(dev);
return vis_fill_buffer_text(net_dev, buff, count, off);
}
static BAT_BIN_ATTR(transtable_local, S_IRUGO, transtable_local_read, NULL);
static BAT_BIN_ATTR(transtable_global, S_IRUGO, transtable_global_read, NULL);
static BAT_BIN_ATTR(originators, S_IRUGO, originators_read, NULL);
static BAT_BIN_ATTR(vis_data, S_IRUGO, vis_data_read, NULL);
static struct bin_attribute *mesh_bin_attrs[] = {
&bat_attr_transtable_local,
&bat_attr_transtable_global,
&bat_attr_originators,
&bat_attr_vis_data,
NULL, NULL,
}; };
@ -283,22 +298,24 @@ int sysfs_add_meshif(struct net_device *dev)
struct kobject *batif_kobject = &dev->dev.kobj; struct kobject *batif_kobject = &dev->dev.kobj;
struct bat_priv *bat_priv = netdev_priv(dev); struct bat_priv *bat_priv = netdev_priv(dev);
struct bat_attribute **bat_attr; struct bat_attribute **bat_attr;
struct bin_attribute **bin_attr;
int err; int err;
/* FIXME: should be done in the general mesh setup /* FIXME: should be done in the general mesh setup
routine as soon as we have it */ routine as soon as we have it */
atomic_set(&bat_priv->aggregation_enabled, 1); atomic_set(&bat_priv->aggregation_enabled, 1);
atomic_set(&bat_priv->bonding_enabled, 0);
atomic_set(&bat_priv->vis_mode, VIS_TYPE_CLIENT_UPDATE); atomic_set(&bat_priv->vis_mode, VIS_TYPE_CLIENT_UPDATE);
atomic_set(&bat_priv->orig_interval, 1000); atomic_set(&bat_priv->orig_interval, 1000);
atomic_set(&bat_priv->log_level, 0);
bat_priv->primary_if = NULL; bat_priv->primary_if = NULL;
bat_priv->num_ifaces = 0; bat_priv->num_ifaces = 0;
bat_priv->mesh_obj = kobject_create_and_add(SYSFS_IF_MESH_SUBDIR, bat_priv->mesh_obj = kobject_create_and_add(SYSFS_IF_MESH_SUBDIR,
batif_kobject); batif_kobject);
if (!bat_priv->mesh_obj) { if (!bat_priv->mesh_obj) {
printk(KERN_ERR "batman-adv:Can't add sysfs directory: %s/%s\n", bat_err(dev, "Can't add sysfs directory: %s/%s\n", dev->name,
dev->name, SYSFS_IF_MESH_SUBDIR); SYSFS_IF_MESH_SUBDIR);
goto out; goto out;
} }
@ -306,28 +323,15 @@ int sysfs_add_meshif(struct net_device *dev)
err = sysfs_create_file(bat_priv->mesh_obj, err = sysfs_create_file(bat_priv->mesh_obj,
&((*bat_attr)->attr)); &((*bat_attr)->attr));
if (err) { if (err) {
printk(KERN_ERR "batman-adv:Can't add sysfs file: %s/%s/%s\n", bat_err(dev, "Can't add sysfs file: %s/%s/%s\n",
dev->name, SYSFS_IF_MESH_SUBDIR, dev->name, SYSFS_IF_MESH_SUBDIR,
((*bat_attr)->attr).name); ((*bat_attr)->attr).name);
goto rem_attr; goto rem_attr;
} }
} }
for (bin_attr = mesh_bin_attrs; *bin_attr; ++bin_attr) {
err = sysfs_create_bin_file(bat_priv->mesh_obj, (*bin_attr));
if (err) {
printk(KERN_ERR "batman-adv:Can't add sysfs file: %s/%s/%s\n",
dev->name, SYSFS_IF_MESH_SUBDIR,
((*bin_attr)->attr).name);
goto rem_bin_attr;
}
}
return 0; return 0;
rem_bin_attr:
for (bin_attr = mesh_bin_attrs; *bin_attr; ++bin_attr)
sysfs_remove_bin_file(bat_priv->mesh_obj, (*bin_attr));
rem_attr: rem_attr:
for (bat_attr = mesh_attrs; *bat_attr; ++bat_attr) for (bat_attr = mesh_attrs; *bat_attr; ++bat_attr)
sysfs_remove_file(bat_priv->mesh_obj, &((*bat_attr)->attr)); sysfs_remove_file(bat_priv->mesh_obj, &((*bat_attr)->attr));
@ -342,10 +346,6 @@ void sysfs_del_meshif(struct net_device *dev)
{ {
struct bat_priv *bat_priv = netdev_priv(dev); struct bat_priv *bat_priv = netdev_priv(dev);
struct bat_attribute **bat_attr; struct bat_attribute **bat_attr;
struct bin_attribute **bin_attr;
for (bin_attr = mesh_bin_attrs; *bin_attr; ++bin_attr)
sysfs_remove_bin_file(bat_priv->mesh_obj, (*bin_attr));
for (bat_attr = mesh_attrs; *bat_attr; ++bat_attr) for (bat_attr = mesh_attrs; *bat_attr; ++bat_attr)
sysfs_remove_file(bat_priv->mesh_obj, &((*bat_attr)->attr)); sysfs_remove_file(bat_priv->mesh_obj, &((*bat_attr)->attr));
@ -364,7 +364,7 @@ static ssize_t show_mesh_iface(struct kobject *kobj, struct attribute *attr,
if (!batman_if) if (!batman_if)
return 0; return 0;
return sprintf(buff, "status: %s\ncommands: none, bat0\n", return sprintf(buff, "%s\n",
batman_if->if_status == IF_NOT_IN_USE ? batman_if->if_status == IF_NOT_IN_USE ?
"none" : "bat0"); "none" : "bat0");
} }
@ -390,8 +390,8 @@ static ssize_t store_mesh_iface(struct kobject *kobj, struct attribute *attr,
if (buff[count - 1] == '\n') if (buff[count - 1] == '\n')
buff[count - 1] = '\0'; buff[count - 1] = '\0';
printk(KERN_ERR "batman-adv:Invalid parameter for 'mesh_iface' setting received: %s\n", pr_err("Invalid parameter for 'mesh_iface' setting received: "
buff); "%s\n", buff);
return -EINVAL; return -EINVAL;
} }
@ -433,37 +433,37 @@ static ssize_t show_iface_status(struct kobject *kobj, struct attribute *attr,
} }
} }
static HARDIF_ATTR(mesh_iface, S_IRUGO | S_IWUSR, static BAT_ATTR(mesh_iface, S_IRUGO | S_IWUSR,
show_mesh_iface, store_mesh_iface); show_mesh_iface, store_mesh_iface);
static HARDIF_ATTR(iface_status, S_IRUGO, show_iface_status, NULL); static BAT_ATTR(iface_status, S_IRUGO, show_iface_status, NULL);
static struct hardif_attribute *batman_attrs[] = { static struct bat_attribute *batman_attrs[] = {
&hardif_attr_mesh_iface, &bat_attr_mesh_iface,
&hardif_attr_iface_status, &bat_attr_iface_status,
NULL, NULL,
}; };
int sysfs_add_hardif(struct kobject **hardif_obj, struct net_device *dev) int sysfs_add_hardif(struct kobject **hardif_obj, struct net_device *dev)
{ {
struct kobject *hardif_kobject = &dev->dev.kobj; struct kobject *hardif_kobject = &dev->dev.kobj;
struct hardif_attribute **hardif_attr; struct bat_attribute **bat_attr;
int err; int err;
*hardif_obj = kobject_create_and_add(SYSFS_IF_BAT_SUBDIR, *hardif_obj = kobject_create_and_add(SYSFS_IF_BAT_SUBDIR,
hardif_kobject); hardif_kobject);
if (!*hardif_obj) { if (!*hardif_obj) {
printk(KERN_ERR "batman-adv:Can't add sysfs directory: %s/%s\n", bat_err(dev, "Can't add sysfs directory: %s/%s\n", dev->name,
dev->name, SYSFS_IF_BAT_SUBDIR); SYSFS_IF_BAT_SUBDIR);
goto out; goto out;
} }
for (hardif_attr = batman_attrs; *hardif_attr; ++hardif_attr) { for (bat_attr = batman_attrs; *bat_attr; ++bat_attr) {
err = sysfs_create_file(*hardif_obj, &((*hardif_attr)->attr)); err = sysfs_create_file(*hardif_obj, &((*bat_attr)->attr));
if (err) { if (err) {
printk(KERN_ERR "batman-adv:Can't add sysfs file: %s/%s/%s\n", bat_err(dev, "Can't add sysfs file: %s/%s/%s\n",
dev->name, SYSFS_IF_BAT_SUBDIR, dev->name, SYSFS_IF_BAT_SUBDIR,
((*hardif_attr)->attr).name); ((*bat_attr)->attr).name);
goto rem_attr; goto rem_attr;
} }
} }
@ -471,8 +471,8 @@ int sysfs_add_hardif(struct kobject **hardif_obj, struct net_device *dev)
return 0; return 0;
rem_attr: rem_attr:
for (hardif_attr = batman_attrs; *hardif_attr; ++hardif_attr) for (bat_attr = batman_attrs; *bat_attr; ++bat_attr)
sysfs_remove_file(*hardif_obj, &((*hardif_attr)->attr)); sysfs_remove_file(*hardif_obj, &((*bat_attr)->attr));
out: out:
return -ENOMEM; return -ENOMEM;
} }

View File

@ -20,10 +20,23 @@
*/ */
#ifndef _NET_BATMAN_ADV_SYSFS_H_
#define _NET_BATMAN_ADV_SYSFS_H_
#define SYSFS_IF_MESH_SUBDIR "mesh" #define SYSFS_IF_MESH_SUBDIR "mesh"
#define SYSFS_IF_BAT_SUBDIR "batman_adv" #define SYSFS_IF_BAT_SUBDIR "batman_adv"
struct bat_attribute {
struct attribute attr;
ssize_t (*show)(struct kobject *kobj, struct attribute *attr,
char *buf);
ssize_t (*store)(struct kobject *kobj, struct attribute *attr,
char *buf, size_t count);
};
int sysfs_add_meshif(struct net_device *dev); int sysfs_add_meshif(struct net_device *dev);
void sysfs_del_meshif(struct net_device *dev); void sysfs_del_meshif(struct net_device *dev);
int sysfs_add_hardif(struct kobject **hardif_obj, struct net_device *dev); int sysfs_add_hardif(struct kobject **hardif_obj, struct net_device *dev);
void sysfs_del_hardif(struct kobject **hardif_obj); void sysfs_del_hardif(struct kobject **hardif_obj);
#endif /* _NET_BATMAN_ADV_SYSFS_H_ */

View File

@ -24,10 +24,10 @@
/* returns true if the corresponding bit in the given seq_bits indicates true /* returns true if the corresponding bit in the given seq_bits indicates true
* and curr_seqno is within range of last_seqno */ * and curr_seqno is within range of last_seqno */
uint8_t get_bit_status(TYPE_OF_WORD *seq_bits, uint16_t last_seqno, uint8_t get_bit_status(TYPE_OF_WORD *seq_bits, uint32_t last_seqno,
uint16_t curr_seqno) uint32_t curr_seqno)
{ {
int16_t diff, word_offset, word_num; int32_t diff, word_offset, word_num;
diff = last_seqno - curr_seqno; diff = last_seqno - curr_seqno;
if (diff < 0 || diff >= TQ_LOCAL_WINDOW_SIZE) { if (diff < 0 || diff >= TQ_LOCAL_WINDOW_SIZE) {
@ -63,7 +63,7 @@ void bit_mark(TYPE_OF_WORD *seq_bits, int32_t n)
} }
/* shift the packet array by n places. */ /* shift the packet array by n places. */
void bit_shift(TYPE_OF_WORD *seq_bits, int32_t n) static void bit_shift(TYPE_OF_WORD *seq_bits, int32_t n)
{ {
int32_t word_offset, word_num; int32_t word_offset, word_num;
int32_t i; int32_t i;
@ -125,9 +125,12 @@ static void bit_reset_window(TYPE_OF_WORD *seq_bits)
* 1 if the window was moved (either new or very old) * 1 if the window was moved (either new or very old)
* 0 if the window was not moved/shifted. * 0 if the window was not moved/shifted.
*/ */
char bit_get_packet(TYPE_OF_WORD *seq_bits, int16_t seq_num_diff, char bit_get_packet(TYPE_OF_WORD *seq_bits, int32_t seq_num_diff,
int8_t set_mark) int8_t set_mark)
{ {
/* FIXME: each orig_node->batman_if will be attached to a softif */
struct bat_priv *bat_priv = netdev_priv(soft_device);
/* sequence number is slightly older. We already got a sequence number /* sequence number is slightly older. We already got a sequence number
* higher than this one, so we just mark it. */ * higher than this one, so we just mark it. */
@ -152,7 +155,7 @@ char bit_get_packet(TYPE_OF_WORD *seq_bits, int16_t seq_num_diff,
if ((seq_num_diff >= TQ_LOCAL_WINDOW_SIZE) if ((seq_num_diff >= TQ_LOCAL_WINDOW_SIZE)
|| (seq_num_diff < EXPECTED_SEQNO_RANGE)) { || (seq_num_diff < EXPECTED_SEQNO_RANGE)) {
bat_dbg(DBG_BATMAN, bat_dbg(DBG_BATMAN, bat_priv,
"We missed a lot of packets (%i) !\n", "We missed a lot of packets (%i) !\n",
seq_num_diff - 1); seq_num_diff - 1);
bit_reset_window(seq_bits); bit_reset_window(seq_bits);
@ -169,7 +172,7 @@ char bit_get_packet(TYPE_OF_WORD *seq_bits, int16_t seq_num_diff,
if ((seq_num_diff <= -TQ_LOCAL_WINDOW_SIZE) if ((seq_num_diff <= -TQ_LOCAL_WINDOW_SIZE)
|| (seq_num_diff >= EXPECTED_SEQNO_RANGE)) { || (seq_num_diff >= EXPECTED_SEQNO_RANGE)) {
bat_dbg(DBG_BATMAN, bat_dbg(DBG_BATMAN, bat_priv,
"Other host probably restarted!\n"); "Other host probably restarted!\n");
bit_reset_window(seq_bits); bit_reset_window(seq_bits);

View File

@ -19,6 +19,8 @@
* *
*/ */
#ifndef _NET_BATMAN_ADV_BITARRAY_H_
#define _NET_BATMAN_ADV_BITARRAY_H_
/* you should choose something big, if you don't want to waste cpu */ /* you should choose something big, if you don't want to waste cpu */
#define TYPE_OF_WORD unsigned long #define TYPE_OF_WORD unsigned long
@ -26,20 +28,19 @@
/* returns true if the corresponding bit in the given seq_bits indicates true /* returns true if the corresponding bit in the given seq_bits indicates true
* and curr_seqno is within range of last_seqno */ * and curr_seqno is within range of last_seqno */
uint8_t get_bit_status(TYPE_OF_WORD *seq_bits, uint16_t last_seqno, uint8_t get_bit_status(TYPE_OF_WORD *seq_bits, uint32_t last_seqno,
uint16_t curr_seqno); uint32_t curr_seqno);
/* turn corresponding bit on, so we can remember that we got the packet */ /* turn corresponding bit on, so we can remember that we got the packet */
void bit_mark(TYPE_OF_WORD *seq_bits, int32_t n); void bit_mark(TYPE_OF_WORD *seq_bits, int32_t n);
/* shift the packet array by n places. */
void bit_shift(TYPE_OF_WORD *seq_bits, int32_t n);
/* receive and process one packet, returns 1 if received seq_num is considered /* receive and process one packet, returns 1 if received seq_num is considered
* new, 0 if old */ * new, 0 if old */
char bit_get_packet(TYPE_OF_WORD *seq_bits, int16_t seq_num_diff, char bit_get_packet(TYPE_OF_WORD *seq_bits, int32_t seq_num_diff,
int8_t set_mark); int8_t set_mark);
/* count the hamming weight, how many good packets did we receive? */ /* count the hamming weight, how many good packets did we receive? */
int bit_packet_count(TYPE_OF_WORD *seq_bits); int bit_packet_count(TYPE_OF_WORD *seq_bits);
#endif /* _NET_BATMAN_ADV_BITARRAY_H_ */

View File

@ -1,354 +0,0 @@
/*
* Copyright (C) 2007-2010 B.A.T.M.A.N. contributors:
*
* Marek Lindner
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of version 2 of the GNU General Public
* License as published by the Free Software Foundation.
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA
*
*/
#include <linux/device.h>
#include <linux/slab.h>
#include "main.h"
#include "device.h"
#include "send.h"
#include "types.h"
#include "hash.h"
#include "hard-interface.h"
static struct class *batman_class;
static int Major; /* Major number assigned to our device driver */
static const struct file_operations fops = {
.open = bat_device_open,
.release = bat_device_release,
.read = bat_device_read,
.write = bat_device_write,
.poll = bat_device_poll,
};
static struct device_client *device_client_hash[256];
void bat_device_init(void)
{
memset(device_client_hash, 0, sizeof(device_client_hash));
}
int bat_device_setup(void)
{
int tmp_major;
if (Major)
return 1;
/* register our device - kernel assigns a free major number */
tmp_major = register_chrdev(0, DRIVER_DEVICE, &fops);
if (tmp_major < 0) {
printk(KERN_ERR "batman-adv:"
"Registering the character device failed with %d\n",
tmp_major);
return 0;
}
batman_class = class_create(THIS_MODULE, "batman-adv");
if (IS_ERR(batman_class)) {
printk(KERN_ERR "batman-adv:"
"Could not register class 'batman-adv'\n");
return 0;
}
device_create(batman_class, NULL, MKDEV(tmp_major, 0), NULL,
"batman-adv");
Major = tmp_major;
return 1;
}
void bat_device_destroy(void)
{
if (!Major)
return;
device_destroy(batman_class, MKDEV(Major, 0));
class_destroy(batman_class);
/* Unregister the device */
unregister_chrdev(Major, DRIVER_DEVICE);
Major = 0;
}
int bat_device_open(struct inode *inode, struct file *file)
{
unsigned int i;
struct device_client *device_client;
device_client = kmalloc(sizeof(struct device_client), GFP_KERNEL);
if (!device_client)
return -ENOMEM;
for (i = 0; i < ARRAY_SIZE(device_client_hash); i++) {
if (!device_client_hash[i]) {
device_client_hash[i] = device_client;
break;
}
}
if (i == ARRAY_SIZE(device_client_hash)) {
printk(KERN_ERR "batman-adv:"
"Error - can't add another packet client: "
"maximum number of clients reached\n");
kfree(device_client);
return -EXFULL;
}
INIT_LIST_HEAD(&device_client->queue_list);
device_client->queue_len = 0;
device_client->index = i;
spin_lock_init(&device_client->lock);
init_waitqueue_head(&device_client->queue_wait);
file->private_data = device_client;
inc_module_count();
return 0;
}
int bat_device_release(struct inode *inode, struct file *file)
{
struct device_client *device_client =
(struct device_client *)file->private_data;
struct device_packet *device_packet;
struct list_head *list_pos, *list_pos_tmp;
unsigned long flags;
spin_lock_irqsave(&device_client->lock, flags);
/* for all packets in the queue ... */
list_for_each_safe(list_pos, list_pos_tmp, &device_client->queue_list) {
device_packet = list_entry(list_pos,
struct device_packet, list);
list_del(list_pos);
kfree(device_packet);
}
device_client_hash[device_client->index] = NULL;
spin_unlock_irqrestore(&device_client->lock, flags);
kfree(device_client);
dec_module_count();
return 0;
}
ssize_t bat_device_read(struct file *file, char __user *buf, size_t count,
loff_t *ppos)
{
struct device_client *device_client =
(struct device_client *)file->private_data;
struct device_packet *device_packet;
int error;
unsigned long flags;
if ((file->f_flags & O_NONBLOCK) && (device_client->queue_len == 0))
return -EAGAIN;
if ((!buf) || (count < sizeof(struct icmp_packet)))
return -EINVAL;
if (!access_ok(VERIFY_WRITE, buf, count))
return -EFAULT;
error = wait_event_interruptible(device_client->queue_wait,
device_client->queue_len);
if (error)
return error;
spin_lock_irqsave(&device_client->lock, flags);
device_packet = list_first_entry(&device_client->queue_list,
struct device_packet, list);
list_del(&device_packet->list);
device_client->queue_len--;
spin_unlock_irqrestore(&device_client->lock, flags);
error = __copy_to_user(buf, &device_packet->icmp_packet,
sizeof(struct icmp_packet));
kfree(device_packet);
if (error)
return -EFAULT;
return sizeof(struct icmp_packet);
}
ssize_t bat_device_write(struct file *file, const char __user *buff,
size_t len, loff_t *off)
{
struct device_client *device_client =
(struct device_client *)file->private_data;
struct icmp_packet icmp_packet;
struct orig_node *orig_node;
struct batman_if *batman_if;
uint8_t dstaddr[ETH_ALEN];
unsigned long flags;
if (len < sizeof(struct icmp_packet)) {
bat_dbg(DBG_BATMAN, "batman-adv:"
"Error - can't send packet from char device: "
"invalid packet size\n");
return -EINVAL;
}
if (!access_ok(VERIFY_READ, buff, sizeof(struct icmp_packet)))
return -EFAULT;
if (__copy_from_user(&icmp_packet, buff, sizeof(icmp_packet)))
return -EFAULT;
if (icmp_packet.packet_type != BAT_ICMP) {
bat_dbg(DBG_BATMAN, "batman-adv:"
"Error - can't send packet from char device: "
"got bogus packet type (expected: BAT_ICMP)\n");
return -EINVAL;
}
if (icmp_packet.msg_type != ECHO_REQUEST) {
bat_dbg(DBG_BATMAN, "batman-adv:"
"Error - can't send packet from char device: "
"got bogus message type (expected: ECHO_REQUEST)\n");
return -EINVAL;
}
icmp_packet.uid = device_client->index;
if (icmp_packet.version != COMPAT_VERSION) {
icmp_packet.msg_type = PARAMETER_PROBLEM;
icmp_packet.ttl = COMPAT_VERSION;
bat_device_add_packet(device_client, &icmp_packet);
goto out;
}
if (atomic_read(&module_state) != MODULE_ACTIVE)
goto dst_unreach;
spin_lock_irqsave(&orig_hash_lock, flags);
orig_node = ((struct orig_node *)hash_find(orig_hash, icmp_packet.dst));
if (!orig_node)
goto unlock;
if (!orig_node->router)
goto unlock;
batman_if = orig_node->router->if_incoming;
memcpy(dstaddr, orig_node->router->addr, ETH_ALEN);
spin_unlock_irqrestore(&orig_hash_lock, flags);
if (!batman_if)
goto dst_unreach;
if (batman_if->if_status != IF_ACTIVE)
goto dst_unreach;
memcpy(icmp_packet.orig,
batman_if->net_dev->dev_addr,
ETH_ALEN);
send_raw_packet((unsigned char *)&icmp_packet,
sizeof(struct icmp_packet),
batman_if, dstaddr);
goto out;
unlock:
spin_unlock_irqrestore(&orig_hash_lock, flags);
dst_unreach:
icmp_packet.msg_type = DESTINATION_UNREACHABLE;
bat_device_add_packet(device_client, &icmp_packet);
out:
return len;
}
unsigned int bat_device_poll(struct file *file, poll_table *wait)
{
struct device_client *device_client =
(struct device_client *)file->private_data;
poll_wait(file, &device_client->queue_wait, wait);
if (device_client->queue_len > 0)
return POLLIN | POLLRDNORM;
return 0;
}
void bat_device_add_packet(struct device_client *device_client,
struct icmp_packet *icmp_packet)
{
struct device_packet *device_packet;
unsigned long flags;
device_packet = kmalloc(sizeof(struct device_packet), GFP_ATOMIC);
if (!device_packet)
return;
INIT_LIST_HEAD(&device_packet->list);
memcpy(&device_packet->icmp_packet, icmp_packet,
sizeof(struct icmp_packet));
spin_lock_irqsave(&device_client->lock, flags);
/* while waiting for the lock the device_client could have been
* deleted */
if (!device_client_hash[icmp_packet->uid]) {
spin_unlock_irqrestore(&device_client->lock, flags);
kfree(device_packet);
return;
}
list_add_tail(&device_packet->list, &device_client->queue_list);
device_client->queue_len++;
if (device_client->queue_len > 100) {
device_packet = list_first_entry(&device_client->queue_list,
struct device_packet, list);
list_del(&device_packet->list);
kfree(device_packet);
device_client->queue_len--;
}
spin_unlock_irqrestore(&device_client->lock, flags);
wake_up(&device_client->queue_wait);
}
void bat_device_receive_packet(struct icmp_packet *icmp_packet)
{
struct device_client *hash = device_client_hash[icmp_packet->uid];
if (hash)
bat_device_add_packet(hash, icmp_packet);
}

View File

@ -30,6 +30,7 @@
#include "hash.h" #include "hash.h"
#include <linux/if_arp.h> #include <linux/if_arp.h>
#include <linux/netfilter_bridge.h>
#define MIN(x, y) ((x) < (y) ? (x) : (y)) #define MIN(x, y) ((x) < (y) ? (x) : (y))
@ -108,7 +109,7 @@ static void set_primary_if(struct bat_priv *bat_priv,
set_main_if_addr(batman_if->net_dev->dev_addr); set_main_if_addr(batman_if->net_dev->dev_addr);
batman_packet = (struct batman_packet *)(batman_if->packet_buff); batman_packet = (struct batman_packet *)(batman_if->packet_buff);
batman_packet->flags = 0; batman_packet->flags = PRIMARIES_FIRST_HOP;
batman_packet->ttl = TTL; batman_packet->ttl = TTL;
/*** /***
@ -149,12 +150,10 @@ static void check_known_mac_addr(uint8_t *addr)
if (!compare_orig(batman_if->net_dev->dev_addr, addr)) if (!compare_orig(batman_if->net_dev->dev_addr, addr))
continue; continue;
printk(KERN_WARNING "batman-adv:" pr_warning("The newly added mac address (%pM) already exists "
"The newly added mac address (%pM) already exists on: %s\n", "on: %s\n", addr, batman_if->dev);
addr, batman_if->dev); pr_warning("It is strongly recommended to keep mac addresses "
printk(KERN_WARNING "batman-adv:" "unique to avoid problems!\n");
"It is strongly recommended to keep mac addresses unique"
"to avoid problems!\n");
} }
rcu_read_unlock(); rcu_read_unlock();
} }
@ -188,7 +187,8 @@ void update_min_mtu(void)
soft_device->mtu = min_mtu; soft_device->mtu = min_mtu;
} }
static void hardif_activate_interface(struct bat_priv *bat_priv, static void hardif_activate_interface(struct net_device *net_dev,
struct bat_priv *bat_priv,
struct batman_if *batman_if) struct batman_if *batman_if)
{ {
if (batman_if->if_status != IF_INACTIVE) if (batman_if->if_status != IF_INACTIVE)
@ -206,8 +206,7 @@ static void hardif_activate_interface(struct bat_priv *bat_priv,
if (!bat_priv->primary_if) if (!bat_priv->primary_if)
set_primary_if(bat_priv, batman_if); set_primary_if(bat_priv, batman_if);
printk(KERN_INFO "batman-adv:Interface activated: %s\n", bat_info(net_dev, "Interface activated: %s\n", batman_if->dev);
batman_if->dev);
if (atomic_read(&module_state) == MODULE_INACTIVE) if (atomic_read(&module_state) == MODULE_INACTIVE)
activate_module(); activate_module();
@ -216,7 +215,8 @@ static void hardif_activate_interface(struct bat_priv *bat_priv,
return; return;
} }
static void hardif_deactivate_interface(struct batman_if *batman_if) static void hardif_deactivate_interface(struct net_device *net_dev,
struct batman_if *batman_if)
{ {
if ((batman_if->if_status != IF_ACTIVE) && if ((batman_if->if_status != IF_ACTIVE) &&
(batman_if->if_status != IF_TO_BE_ACTIVATED)) (batman_if->if_status != IF_TO_BE_ACTIVATED))
@ -226,8 +226,7 @@ static void hardif_deactivate_interface(struct batman_if *batman_if)
batman_if->if_status = IF_INACTIVE; batman_if->if_status = IF_INACTIVE;
printk(KERN_INFO "batman-adv:Interface deactivated: %s\n", bat_info(net_dev, "Interface deactivated: %s\n", batman_if->dev);
batman_if->dev);
update_min_mtu(); update_min_mtu();
} }
@ -245,9 +244,8 @@ int hardif_enable_interface(struct batman_if *batman_if)
batman_if->packet_buff = kmalloc(batman_if->packet_len, GFP_ATOMIC); batman_if->packet_buff = kmalloc(batman_if->packet_len, GFP_ATOMIC);
if (!batman_if->packet_buff) { if (!batman_if->packet_buff) {
printk(KERN_ERR "batman-adv:" bat_err(soft_device, "Can't add interface packet (%s): "
"Can't add interface packet (%s): out of memory\n", "out of memory\n", batman_if->dev);
batman_if->dev);
goto err; goto err;
} }
@ -265,13 +263,12 @@ int hardif_enable_interface(struct batman_if *batman_if)
orig_hash_add_if(batman_if, bat_priv->num_ifaces); orig_hash_add_if(batman_if, bat_priv->num_ifaces);
atomic_set(&batman_if->seqno, 1); atomic_set(&batman_if->seqno, 1);
printk(KERN_INFO "batman-adv:Adding interface: %s\n", batman_if->dev); bat_info(soft_device, "Adding interface: %s\n", batman_if->dev);
if (hardif_is_iface_up(batman_if)) if (hardif_is_iface_up(batman_if))
hardif_activate_interface(bat_priv, batman_if); hardif_activate_interface(soft_device, bat_priv, batman_if);
else else
printk(KERN_ERR "batman-adv:" bat_err(soft_device, "Not using interface %s "
"Not using interface %s "
"(retrying later): interface not active\n", "(retrying later): interface not active\n",
batman_if->dev); batman_if->dev);
@ -291,12 +288,12 @@ void hardif_disable_interface(struct batman_if *batman_if)
struct bat_priv *bat_priv = netdev_priv(soft_device); struct bat_priv *bat_priv = netdev_priv(soft_device);
if (batman_if->if_status == IF_ACTIVE) if (batman_if->if_status == IF_ACTIVE)
hardif_deactivate_interface(batman_if); hardif_deactivate_interface(soft_device, batman_if);
if (batman_if->if_status != IF_INACTIVE) if (batman_if->if_status != IF_INACTIVE)
return; return;
printk(KERN_INFO "batman-adv:Removing interface: %s\n", batman_if->dev); bat_info(soft_device, "Removing interface: %s\n", batman_if->dev);
bat_priv->num_ifaces--; bat_priv->num_ifaces--;
orig_hash_del_if(batman_if, bat_priv->num_ifaces); orig_hash_del_if(batman_if, bat_priv->num_ifaces);
@ -323,8 +320,7 @@ static struct batman_if *hardif_add_interface(struct net_device *net_dev)
batman_if = kmalloc(sizeof(struct batman_if), GFP_ATOMIC); batman_if = kmalloc(sizeof(struct batman_if), GFP_ATOMIC);
if (!batman_if) { if (!batman_if) {
printk(KERN_ERR "batman-adv:" pr_err("Can't add interface (%s): out of memory\n",
"Can't add interface (%s): out of memory\n",
net_dev->name); net_dev->name);
goto out; goto out;
} }
@ -407,11 +403,11 @@ static int hard_if_event(struct notifier_block *this,
case NETDEV_REGISTER: case NETDEV_REGISTER:
break; break;
case NETDEV_UP: case NETDEV_UP:
hardif_activate_interface(bat_priv, batman_if); hardif_activate_interface(soft_device, bat_priv, batman_if);
break; break;
case NETDEV_GOING_DOWN: case NETDEV_GOING_DOWN:
case NETDEV_DOWN: case NETDEV_DOWN:
hardif_deactivate_interface(batman_if); hardif_deactivate_interface(soft_device, batman_if);
break; break;
case NETDEV_UNREGISTER: case NETDEV_UNREGISTER:
hardif_remove_interface(batman_if); hardif_remove_interface(batman_if);
@ -432,11 +428,18 @@ out:
return NOTIFY_DONE; return NOTIFY_DONE;
} }
static int batman_skb_recv_finish(struct sk_buff *skb)
{
return NF_ACCEPT;
}
/* receive a packet with the batman ethertype coming on a hard /* receive a packet with the batman ethertype coming on a hard
* interface */ * interface */
int batman_skb_recv(struct sk_buff *skb, struct net_device *dev, int batman_skb_recv(struct sk_buff *skb, struct net_device *dev,
struct packet_type *ptype, struct net_device *orig_dev) struct packet_type *ptype, struct net_device *orig_dev)
{ {
/* FIXME: each orig_node->batman_if will be attached to a softif */
struct bat_priv *bat_priv = netdev_priv(soft_device);
struct batman_packet *batman_packet; struct batman_packet *batman_packet;
struct batman_if *batman_if; struct batman_if *batman_if;
struct net_device_stats *stats; struct net_device_stats *stats;
@ -452,6 +455,13 @@ int batman_skb_recv(struct sk_buff *skb, struct net_device *dev,
if (atomic_read(&module_state) != MODULE_ACTIVE) if (atomic_read(&module_state) != MODULE_ACTIVE)
goto err_free; goto err_free;
/* if netfilter/ebtables wants to block incoming batman
* packets then give them a chance to do so here */
ret = NF_HOOK(PF_BRIDGE, NF_BR_LOCAL_IN, skb, dev, NULL,
batman_skb_recv_finish);
if (ret != 1)
goto err_out;
/* packet should hold at least type and version */ /* packet should hold at least type and version */
if (unlikely(skb_headlen(skb) < 2)) if (unlikely(skb_headlen(skb) < 2))
goto err_free; goto err_free;
@ -478,7 +488,7 @@ int batman_skb_recv(struct sk_buff *skb, struct net_device *dev,
batman_packet = (struct batman_packet *)skb->data; batman_packet = (struct batman_packet *)skb->data;
if (batman_packet->version != COMPAT_VERSION) { if (batman_packet->version != COMPAT_VERSION) {
bat_dbg(DBG_BATMAN, bat_dbg(DBG_BATMAN, bat_priv,
"Drop packet: incompatible batman version (%i)\n", "Drop packet: incompatible batman version (%i)\n",
batman_packet->version); batman_packet->version);
goto err_free; goto err_free;
@ -500,7 +510,7 @@ int batman_skb_recv(struct sk_buff *skb, struct net_device *dev,
/* unicast packet */ /* unicast packet */
case BAT_UNICAST: case BAT_UNICAST:
ret = recv_unicast_packet(skb); ret = recv_unicast_packet(skb, batman_if);
break; break;
/* broadcast packet */ /* broadcast packet */
@ -531,7 +541,6 @@ err_out:
return NET_RX_DROP; return NET_RX_DROP;
} }
struct notifier_block hard_if_notifier = { struct notifier_block hard_if_notifier = {
.notifier_call = hard_if_event, .notifier_call = hard_if_event,
}; };

View File

@ -19,6 +19,9 @@
* *
*/ */
#ifndef _NET_BATMAN_ADV_HARD_INTERFACE_H_
#define _NET_BATMAN_ADV_HARD_INTERFACE_H_
#define IF_NOT_IN_USE 0 #define IF_NOT_IN_USE 0
#define IF_TO_BE_REMOVED 1 #define IF_TO_BE_REMOVED 1
#define IF_INACTIVE 2 #define IF_INACTIVE 2
@ -38,3 +41,5 @@ int batman_skb_recv(struct sk_buff *skb,
struct net_device *orig_dev); struct net_device *orig_dev);
int hardif_min_mtu(void); int hardif_min_mtu(void);
void update_min_mtu(void); void update_min_mtu(void);
#endif /* _NET_BATMAN_ADV_HARD_INTERFACE_H_ */

View File

@ -23,7 +23,7 @@
#include "hash.h" #include "hash.h"
/* clears the hash */ /* clears the hash */
void hash_init(struct hashtable_t *hash) static void hash_init(struct hashtable_t *hash)
{ {
int i; int i;

View File

@ -19,8 +19,9 @@
* *
*/ */
#ifndef _BATMAN_HASH_H #ifndef _NET_BATMAN_ADV_HASH_H_
#define _BATMAN_HASH_H #define _NET_BATMAN_ADV_HASH_H_
#define HASHIT(name) struct hash_it_t name = { \ #define HASHIT(name) struct hash_it_t name = { \
.index = -1, .bucket = NULL, \ .index = -1, .bucket = NULL, \
.prev_bucket = NULL, \ .prev_bucket = NULL, \
@ -56,9 +57,6 @@ struct hashtable_t {
* argument and the size the second */ * argument and the size the second */
}; };
/* clears the hash */
void hash_init(struct hashtable_t *hash);
/* allocates and clears the hash */ /* allocates and clears the hash */
struct hashtable_t *hash_new(int size, hashdata_compare_cb compare, struct hashtable_t *hash_new(int size, hashdata_compare_cb compare,
hashdata_choose_cb choose); hashdata_choose_cb choose);
@ -99,6 +97,4 @@ struct hashtable_t *hash_resize(struct hashtable_t *hash, int size);
struct hash_it_t *hash_iterate(struct hashtable_t *hash, struct hash_it_t *hash_iterate(struct hashtable_t *hash,
struct hash_it_t *iter_in); struct hash_it_t *iter_in);
/* print the hash table for debugging */ #endif /* _NET_BATMAN_ADV_HASH_H_ */
void hash_debug(struct hashtable_t *hash);
#endif

View File

@ -0,0 +1,334 @@
/*
* Copyright (C) 2007-2010 B.A.T.M.A.N. contributors:
*
* Marek Lindner
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of version 2 of the GNU General Public
* License as published by the Free Software Foundation.
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA
*
*/
#include "main.h"
#include <linux/debugfs.h>
#include <linux/slab.h>
#include "icmp_socket.h"
#include "send.h"
#include "types.h"
#include "hash.h"
#include "hard-interface.h"
static struct socket_client *socket_client_hash[256];
static void bat_socket_add_packet(struct socket_client *socket_client,
struct icmp_packet_rr *icmp_packet,
size_t icmp_len);
void bat_socket_init(void)
{
memset(socket_client_hash, 0, sizeof(socket_client_hash));
}
static int bat_socket_open(struct inode *inode, struct file *file)
{
unsigned int i;
struct socket_client *socket_client;
socket_client = kmalloc(sizeof(struct socket_client), GFP_KERNEL);
if (!socket_client)
return -ENOMEM;
for (i = 0; i < ARRAY_SIZE(socket_client_hash); i++) {
if (!socket_client_hash[i]) {
socket_client_hash[i] = socket_client;
break;
}
}
if (i == ARRAY_SIZE(socket_client_hash)) {
pr_err("Error - can't add another packet client: "
"maximum number of clients reached\n");
kfree(socket_client);
return -EXFULL;
}
INIT_LIST_HEAD(&socket_client->queue_list);
socket_client->queue_len = 0;
socket_client->index = i;
spin_lock_init(&socket_client->lock);
init_waitqueue_head(&socket_client->queue_wait);
file->private_data = socket_client;
inc_module_count();
return 0;
}
static int bat_socket_release(struct inode *inode, struct file *file)
{
struct socket_client *socket_client = file->private_data;
struct socket_packet *socket_packet;
struct list_head *list_pos, *list_pos_tmp;
unsigned long flags;
spin_lock_irqsave(&socket_client->lock, flags);
/* for all packets in the queue ... */
list_for_each_safe(list_pos, list_pos_tmp, &socket_client->queue_list) {
socket_packet = list_entry(list_pos,
struct socket_packet, list);
list_del(list_pos);
kfree(socket_packet);
}
socket_client_hash[socket_client->index] = NULL;
spin_unlock_irqrestore(&socket_client->lock, flags);
kfree(socket_client);
dec_module_count();
return 0;
}
static ssize_t bat_socket_read(struct file *file, char __user *buf,
size_t count, loff_t *ppos)
{
struct socket_client *socket_client = file->private_data;
struct socket_packet *socket_packet;
size_t packet_len;
int error;
unsigned long flags;
if ((file->f_flags & O_NONBLOCK) && (socket_client->queue_len == 0))
return -EAGAIN;
if ((!buf) || (count < sizeof(struct icmp_packet)))
return -EINVAL;
if (!access_ok(VERIFY_WRITE, buf, count))
return -EFAULT;
error = wait_event_interruptible(socket_client->queue_wait,
socket_client->queue_len);
if (error)
return error;
spin_lock_irqsave(&socket_client->lock, flags);
socket_packet = list_first_entry(&socket_client->queue_list,
struct socket_packet, list);
list_del(&socket_packet->list);
socket_client->queue_len--;
spin_unlock_irqrestore(&socket_client->lock, flags);
error = __copy_to_user(buf, &socket_packet->icmp_packet,
socket_packet->icmp_len);
packet_len = socket_packet->icmp_len;
kfree(socket_packet);
if (error)
return -EFAULT;
return packet_len;
}
static ssize_t bat_socket_write(struct file *file, const char __user *buff,
size_t len, loff_t *off)
{
/* FIXME: each orig_node->batman_if will be attached to a softif */
struct bat_priv *bat_priv = netdev_priv(soft_device);
struct socket_client *socket_client = file->private_data;
struct icmp_packet_rr icmp_packet;
struct orig_node *orig_node;
struct batman_if *batman_if;
size_t packet_len = sizeof(struct icmp_packet);
uint8_t dstaddr[ETH_ALEN];
unsigned long flags;
if (len < sizeof(struct icmp_packet)) {
bat_dbg(DBG_BATMAN, bat_priv,
"Error - can't send packet from char device: "
"invalid packet size\n");
return -EINVAL;
}
if (len >= sizeof(struct icmp_packet_rr))
packet_len = sizeof(struct icmp_packet_rr);
if (!access_ok(VERIFY_READ, buff, packet_len))
return -EFAULT;
if (__copy_from_user(&icmp_packet, buff, packet_len))
return -EFAULT;
if (icmp_packet.packet_type != BAT_ICMP) {
bat_dbg(DBG_BATMAN, bat_priv,
"Error - can't send packet from char device: "
"got bogus packet type (expected: BAT_ICMP)\n");
return -EINVAL;
}
if (icmp_packet.msg_type != ECHO_REQUEST) {
bat_dbg(DBG_BATMAN, bat_priv,
"Error - can't send packet from char device: "
"got bogus message type (expected: ECHO_REQUEST)\n");
return -EINVAL;
}
icmp_packet.uid = socket_client->index;
if (icmp_packet.version != COMPAT_VERSION) {
icmp_packet.msg_type = PARAMETER_PROBLEM;
icmp_packet.ttl = COMPAT_VERSION;
bat_socket_add_packet(socket_client, &icmp_packet, packet_len);
goto out;
}
if (atomic_read(&module_state) != MODULE_ACTIVE)
goto dst_unreach;
spin_lock_irqsave(&orig_hash_lock, flags);
orig_node = ((struct orig_node *)hash_find(orig_hash, icmp_packet.dst));
if (!orig_node)
goto unlock;
if (!orig_node->router)
goto unlock;
batman_if = orig_node->router->if_incoming;
memcpy(dstaddr, orig_node->router->addr, ETH_ALEN);
spin_unlock_irqrestore(&orig_hash_lock, flags);
if (!batman_if)
goto dst_unreach;
if (batman_if->if_status != IF_ACTIVE)
goto dst_unreach;
memcpy(icmp_packet.orig, batman_if->net_dev->dev_addr, ETH_ALEN);
if (packet_len == sizeof(struct icmp_packet_rr))
memcpy(icmp_packet.rr, batman_if->net_dev->dev_addr, ETH_ALEN);
send_raw_packet((unsigned char *)&icmp_packet,
packet_len, batman_if, dstaddr);
goto out;
unlock:
spin_unlock_irqrestore(&orig_hash_lock, flags);
dst_unreach:
icmp_packet.msg_type = DESTINATION_UNREACHABLE;
bat_socket_add_packet(socket_client, &icmp_packet, packet_len);
out:
return len;
}
static unsigned int bat_socket_poll(struct file *file, poll_table *wait)
{
struct socket_client *socket_client = file->private_data;
poll_wait(file, &socket_client->queue_wait, wait);
if (socket_client->queue_len > 0)
return POLLIN | POLLRDNORM;
return 0;
}
static const struct file_operations fops = {
.owner = THIS_MODULE,
.open = bat_socket_open,
.release = bat_socket_release,
.read = bat_socket_read,
.write = bat_socket_write,
.poll = bat_socket_poll,
};
int bat_socket_setup(struct bat_priv *bat_priv)
{
struct dentry *d;
if (!bat_priv->debug_dir)
goto err;
d = debugfs_create_file(ICMP_SOCKET, S_IFREG | S_IWUSR | S_IRUSR,
bat_priv->debug_dir, NULL, &fops);
if (d)
goto err;
return 0;
err:
return 1;
}
static void bat_socket_add_packet(struct socket_client *socket_client,
struct icmp_packet_rr *icmp_packet,
size_t icmp_len)
{
struct socket_packet *socket_packet;
unsigned long flags;
socket_packet = kmalloc(sizeof(struct socket_packet), GFP_ATOMIC);
if (!socket_packet)
return;
INIT_LIST_HEAD(&socket_packet->list);
memcpy(&socket_packet->icmp_packet, icmp_packet, icmp_len);
socket_packet->icmp_len = icmp_len;
spin_lock_irqsave(&socket_client->lock, flags);
/* while waiting for the lock the socket_client could have been
* deleted */
if (!socket_client_hash[icmp_packet->uid]) {
spin_unlock_irqrestore(&socket_client->lock, flags);
kfree(socket_packet);
return;
}
list_add_tail(&socket_packet->list, &socket_client->queue_list);
socket_client->queue_len++;
if (socket_client->queue_len > 100) {
socket_packet = list_first_entry(&socket_client->queue_list,
struct socket_packet, list);
list_del(&socket_packet->list);
kfree(socket_packet);
socket_client->queue_len--;
}
spin_unlock_irqrestore(&socket_client->lock, flags);
wake_up(&socket_client->queue_wait);
}
void bat_socket_receive_packet(struct icmp_packet_rr *icmp_packet,
size_t icmp_len)
{
struct socket_client *hash = socket_client_hash[icmp_packet->uid];
if (hash)
bat_socket_add_packet(hash, icmp_packet, icmp_len);
}

View File

@ -19,18 +19,16 @@
* *
*/ */
#ifndef _NET_BATMAN_ADV_ICMP_SOCKET_H_
#define _NET_BATMAN_ADV_ICMP_SOCKET_H_
#include "types.h" #include "types.h"
void bat_device_init(void); #define ICMP_SOCKET "socket"
int bat_device_setup(void);
void bat_device_destroy(void); void bat_socket_init(void);
int bat_device_open(struct inode *inode, struct file *file); int bat_socket_setup(struct bat_priv *bat_priv);
int bat_device_release(struct inode *inode, struct file *file); void bat_socket_receive_packet(struct icmp_packet_rr *icmp_packet,
ssize_t bat_device_read(struct file *file, char __user *buf, size_t count, size_t icmp_len);
loff_t *ppos);
ssize_t bat_device_write(struct file *file, const char __user *buff, #endif /* _NET_BATMAN_ADV_ICMP_SOCKET_H_ */
size_t len, loff_t *off);
unsigned int bat_device_poll(struct file *file, poll_table *wait);
void bat_device_add_packet(struct device_client *device_client,
struct icmp_packet *icmp_packet);
void bat_device_receive_packet(struct icmp_packet *icmp_packet);

View File

@ -21,11 +21,12 @@
#include "main.h" #include "main.h"
#include "bat_sysfs.h" #include "bat_sysfs.h"
#include "bat_debugfs.h"
#include "routing.h" #include "routing.h"
#include "send.h" #include "send.h"
#include "originator.h" #include "originator.h"
#include "soft-interface.h" #include "soft-interface.h"
#include "device.h" #include "icmp_socket.h"
#include "translation-table.h" #include "translation-table.h"
#include "hard-interface.h" #include "hard-interface.h"
#include "types.h" #include "types.h"
@ -41,7 +42,6 @@ DEFINE_SPINLOCK(orig_hash_lock);
DEFINE_SPINLOCK(forw_bat_list_lock); DEFINE_SPINLOCK(forw_bat_list_lock);
DEFINE_SPINLOCK(forw_bcast_list_lock); DEFINE_SPINLOCK(forw_bcast_list_lock);
atomic_t vis_interval;
atomic_t bcast_queue_left; atomic_t bcast_queue_left;
atomic_t batman_queue_left; atomic_t batman_queue_left;
@ -49,7 +49,7 @@ int16_t num_hna;
struct net_device *soft_device; struct net_device *soft_device;
unsigned char broadcastAddr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; unsigned char broadcast_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
atomic_t module_state; atomic_t module_state;
static struct packet_type batman_adv_packet_type __read_mostly = { static struct packet_type batman_adv_packet_type __read_mostly = {
@ -59,18 +59,7 @@ static struct packet_type batman_adv_packet_type __read_mostly = {
struct workqueue_struct *bat_event_workqueue; struct workqueue_struct *bat_event_workqueue;
#ifdef CONFIG_BATMAN_ADV_DEBUG static int __init batman_init(void)
int debug;
module_param(debug, int, 0644);
int bat_debug_type(int type)
{
return debug & type;
}
#endif
int init_module(void)
{ {
int retval; int retval;
@ -80,8 +69,6 @@ int init_module(void)
atomic_set(&module_state, MODULE_INACTIVE); atomic_set(&module_state, MODULE_INACTIVE);
atomic_set(&vis_interval, 1000);/* TODO: raise this later, this is only
* for debugging now. */
atomic_set(&bcast_queue_left, BCAST_QUEUE_LEN); atomic_set(&bcast_queue_left, BCAST_QUEUE_LEN);
atomic_set(&batman_queue_left, BATMAN_QUEUE_LEN); atomic_set(&batman_queue_left, BATMAN_QUEUE_LEN);
@ -92,23 +79,22 @@ int init_module(void)
if (!bat_event_workqueue) if (!bat_event_workqueue)
return -ENOMEM; return -ENOMEM;
bat_device_init(); bat_socket_init();
debugfs_init();
/* initialize layer 2 interface */ /* initialize layer 2 interface */
soft_device = alloc_netdev(sizeof(struct bat_priv) , "bat%d", soft_device = alloc_netdev(sizeof(struct bat_priv) , "bat%d",
interface_setup); interface_setup);
if (!soft_device) { if (!soft_device) {
printk(KERN_ERR "batman-adv:" pr_err("Unable to allocate the batman interface\n");
"Unable to allocate the batman interface\n");
goto end; goto end;
} }
retval = register_netdev(soft_device); retval = register_netdev(soft_device);
if (retval < 0) { if (retval < 0) {
printk(KERN_ERR "batman-adv:" pr_err("Unable to register the batman interface: %i\n", retval);
"Unable to register the batman interface: %i\n", retval);
goto free_soft_device; goto free_soft_device;
} }
@ -117,15 +103,22 @@ int init_module(void)
if (retval < 0) if (retval < 0)
goto unreg_soft_device; goto unreg_soft_device;
retval = debugfs_add_meshif(soft_device);
if (retval < 0)
goto unreg_sysfs;
register_netdevice_notifier(&hard_if_notifier); register_netdevice_notifier(&hard_if_notifier);
dev_add_pack(&batman_adv_packet_type); dev_add_pack(&batman_adv_packet_type);
printk(KERN_INFO "batman-adv:" pr_info("B.A.T.M.A.N. advanced %s%s (compatibility version %i) "
"B.A.T.M.A.N. advanced %s%s (compatibility version %i) loaded\n", "loaded\n", SOURCE_VERSION, REVISION_VERSION_STR,
SOURCE_VERSION, REVISION_VERSION_STR, COMPAT_VERSION); COMPAT_VERSION);
return 0; return 0;
unreg_sysfs:
sysfs_del_meshif(soft_device);
unreg_soft_device: unreg_soft_device:
unregister_netdev(soft_device); unregister_netdev(soft_device);
soft_device = NULL; soft_device = NULL;
@ -138,14 +131,16 @@ end:
return -ENOMEM; return -ENOMEM;
} }
void cleanup_module(void) static void __exit batman_exit(void)
{ {
deactivate_module(); deactivate_module();
debugfs_destroy();
unregister_netdevice_notifier(&hard_if_notifier); unregister_netdevice_notifier(&hard_if_notifier);
hardif_remove_interfaces(); hardif_remove_interfaces();
if (soft_device) { if (soft_device) {
debugfs_del_meshif(soft_device);
sysfs_del_meshif(soft_device); sysfs_del_meshif(soft_device);
unregister_netdev(soft_device); unregister_netdev(soft_device);
soft_device = NULL; soft_device = NULL;
@ -157,7 +152,7 @@ void cleanup_module(void)
bat_event_workqueue = NULL; bat_event_workqueue = NULL;
} }
/* activates the module, creates bat device, starts timer ... */ /* activates the module, starts timer ... */
void activate_module(void) void activate_module(void)
{ {
if (originator_init() < 1) if (originator_init() < 1)
@ -171,9 +166,6 @@ void activate_module(void)
hna_local_add(soft_device->dev_addr); hna_local_add(soft_device->dev_addr);
if (bat_device_setup() < 1)
goto end;
if (vis_init() < 1) if (vis_init() < 1)
goto err; goto err;
@ -182,8 +174,7 @@ void activate_module(void)
goto end; goto end;
err: err:
printk(KERN_ERR "batman-adv:" pr_err("Unable to allocate memory for mesh information structures: "
"Unable to allocate memory for mesh information structures: "
"out of mem ?\n"); "out of mem ?\n");
deactivate_module(); deactivate_module();
end: end:
@ -208,7 +199,6 @@ void deactivate_module(void)
hna_global_free(); hna_global_free();
synchronize_net(); synchronize_net();
bat_device_destroy();
synchronize_rcu(); synchronize_rcu();
atomic_set(&module_state, MODULE_INACTIVE); atomic_set(&module_state, MODULE_INACTIVE);
@ -226,8 +216,7 @@ void dec_module_count(void)
int addr_to_string(char *buff, uint8_t *addr) int addr_to_string(char *buff, uint8_t *addr)
{ {
return sprintf(buff, MAC_FMT, return sprintf(buff, "%pM", addr);
addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]);
} }
/* returns 1 if they are the same originator */ /* returns 1 if they are the same originator */
@ -284,6 +273,9 @@ int is_mcast(uint8_t *addr)
return *addr & 0x01; return *addr & 0x01;
} }
module_init(batman_init);
module_exit(batman_exit);
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_AUTHOR(DRIVER_AUTHOR);

View File

@ -19,6 +19,9 @@
* *
*/ */
#ifndef _NET_BATMAN_ADV_MAIN_H_
#define _NET_BATMAN_ADV_MAIN_H_
/* Kernel Programming */ /* Kernel Programming */
#define LINUX #define LINUX
@ -27,7 +30,7 @@
#define DRIVER_DESC "B.A.T.M.A.N. advanced" #define DRIVER_DESC "B.A.T.M.A.N. advanced"
#define DRIVER_DEVICE "batman-adv" #define DRIVER_DEVICE "batman-adv"
#define SOURCE_VERSION "0.2.2-beta" #define SOURCE_VERSION "maint"
/* B.A.T.M.A.N. parameters */ /* B.A.T.M.A.N. parameters */
@ -36,10 +39,10 @@
#define JITTER 20 #define JITTER 20
#define TTL 50 /* Time To Live of broadcast messages */ #define TTL 50 /* Time To Live of broadcast messages */
#define PURGE_TIMEOUT 200000 /* purge originators after time in ms if no #define PURGE_TIMEOUT 200 /* purge originators after time in seconds if no
* valid packet comes in -> TODO: check * valid packet comes in -> TODO: check
* influence on TQ_LOCAL_WINDOW_SIZE */ * influence on TQ_LOCAL_WINDOW_SIZE */
#define LOCAL_HNA_TIMEOUT 3600000 #define LOCAL_HNA_TIMEOUT 3600 /* in seconds */
#define TQ_LOCAL_WINDOW_SIZE 64 /* sliding packet range of received originator #define TQ_LOCAL_WINDOW_SIZE 64 /* sliding packet range of received originator
* messages in squence numbers (should be a * messages in squence numbers (should be a
@ -57,13 +60,20 @@
#define LOG_BUF_LEN 8192 /* has to be a power of 2 */ #define LOG_BUF_LEN 8192 /* has to be a power of 2 */
#define ETH_STR_LEN 20 #define ETH_STR_LEN 20
#define VIS_INTERVAL 5000 /* 5 seconds */
/* how much worse secondary interfaces may be to
* to be considered as bonding candidates */
#define BONDING_TQ_THRESHOLD 50
#define MAX_AGGREGATION_BYTES 512 /* should not be bigger than 512 bytes or #define MAX_AGGREGATION_BYTES 512 /* should not be bigger than 512 bytes or
* change the size of * change the size of
* forw_packet->direct_link_flags */ * forw_packet->direct_link_flags */
#define MAX_AGGREGATION_MS 100 #define MAX_AGGREGATION_MS 100
#define RESET_PROTECTION_MS 30000 #define RESET_PROTECTION_MS 30000
#define EXPECTED_SEQNO_RANGE 4096 #define EXPECTED_SEQNO_RANGE 65536
/* don't reset again within 30 seconds */ /* don't reset again within 30 seconds */
#define MODULE_INACTIVE 0 #define MODULE_INACTIVE 0
@ -76,25 +86,16 @@
/* /*
* Debug Messages * Debug Messages
*/ */
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt /* Append 'batman-adv: ' before
* kernel messages */
#define DBG_BATMAN 1 /* all messages related to routing / flooding / #define DBG_BATMAN 1 /* all messages related to routing / flooding /
* broadcasting / etc */ * broadcasting / etc */
#define DBG_ROUTES 2 /* route or hna added / changed / deleted */ #define DBG_ROUTES 2 /* route or hna added / changed / deleted */
#define DBG_ALL 3
#ifdef CONFIG_BATMAN_ADV_DEBUG #define LOG_BUF_LEN 8192 /* has to be a power of 2 */
extern int debug;
extern int bat_debug_type(int type);
#define bat_dbg(type, fmt, arg...) do { \
if (bat_debug_type(type)) \
printk(KERN_DEBUG "batman-adv:" fmt, ## arg); \
} \
while (0)
#else /* !CONFIG_BATMAN_ADV_DEBUG */
#define bat_dbg(type, fmt, arg...) do { \
} \
while (0)
#endif
/* /*
* Vis * Vis
@ -117,6 +118,7 @@ extern int bat_debug_type(int type);
#include <linux/slab.h> #include <linux/slab.h>
#include <net/sock.h> /* struct sock */ #include <net/sock.h> /* struct sock */
#include <linux/jiffies.h> #include <linux/jiffies.h>
#include <linux/seq_file.h>
#include "types.h" #include "types.h"
#ifndef REVISION_VERSION #ifndef REVISION_VERSION
@ -134,14 +136,13 @@ extern spinlock_t orig_hash_lock;
extern spinlock_t forw_bat_list_lock; extern spinlock_t forw_bat_list_lock;
extern spinlock_t forw_bcast_list_lock; extern spinlock_t forw_bcast_list_lock;
extern atomic_t vis_interval;
extern atomic_t bcast_queue_left; extern atomic_t bcast_queue_left;
extern atomic_t batman_queue_left; extern atomic_t batman_queue_left;
extern int16_t num_hna; extern int16_t num_hna;
extern struct net_device *soft_device; extern struct net_device *soft_device;
extern unsigned char broadcastAddr[]; extern unsigned char broadcast_addr[];
extern atomic_t module_state; extern atomic_t module_state;
extern struct workqueue_struct *bat_event_workqueue; extern struct workqueue_struct *bat_event_workqueue;
@ -155,3 +156,44 @@ int choose_orig(void *data, int32_t size);
int is_my_mac(uint8_t *addr); int is_my_mac(uint8_t *addr);
int is_bcast(uint8_t *addr); int is_bcast(uint8_t *addr);
int is_mcast(uint8_t *addr); int is_mcast(uint8_t *addr);
#ifdef CONFIG_BATMAN_ADV_DEBUG
extern int debug_log(struct bat_priv *bat_priv, char *fmt, ...);
#define bat_dbg(type, bat_priv, fmt, arg...) \
do { \
if (atomic_read(&bat_priv->log_level) & type) \
debug_log(bat_priv, fmt, ## arg); \
} \
while (0)
#else /* !CONFIG_BATMAN_ADV_DEBUG */
static inline void bat_dbg(char type __attribute__((unused)),
struct bat_priv *bat_priv __attribute__((unused)),
char *fmt __attribute__((unused)), ...)
{
}
#endif
#define bat_warning(net_dev, fmt, arg...) \
do { \
struct net_device *_netdev = (net_dev); \
struct bat_priv *_batpriv = netdev_priv(_netdev); \
bat_dbg(DBG_ALL, _batpriv, fmt, ## arg); \
pr_warning("%s: " fmt, _netdev->name, ## arg); \
} while (0)
#define bat_info(net_dev, fmt, arg...) \
do { \
struct net_device *_netdev = (net_dev); \
struct bat_priv *_batpriv = netdev_priv(_netdev); \
bat_dbg(DBG_ALL, _batpriv, fmt, ## arg); \
pr_info("%s: " fmt, _netdev->name, ## arg); \
} while (0)
#define bat_err(net_dev, fmt, arg...) \
do { \
struct net_device *_netdev = (net_dev); \
struct bat_priv *_batpriv = netdev_priv(_netdev); \
bat_dbg(DBG_ALL, _batpriv, fmt, ## arg); \
pr_err("%s: " fmt, _netdev->name, ## arg); \
} while (0)
#endif /* _NET_BATMAN_ADV_MAIN_H_ */

View File

@ -56,28 +56,16 @@ err:
return 0; return 0;
} }
void originator_free(void)
{
unsigned long flags;
if (!orig_hash)
return;
cancel_delayed_work_sync(&purge_orig_wq);
spin_lock_irqsave(&orig_hash_lock, flags);
hash_delete(orig_hash, free_orig_node);
orig_hash = NULL;
spin_unlock_irqrestore(&orig_hash_lock, flags);
}
struct neigh_node * struct neigh_node *
create_neighbor(struct orig_node *orig_node, struct orig_node *orig_neigh_node, create_neighbor(struct orig_node *orig_node, struct orig_node *orig_neigh_node,
uint8_t *neigh, struct batman_if *if_incoming) uint8_t *neigh, struct batman_if *if_incoming)
{ {
/* FIXME: each orig_node->batman_if will be attached to a softif */
struct bat_priv *bat_priv = netdev_priv(soft_device);
struct neigh_node *neigh_node; struct neigh_node *neigh_node;
bat_dbg(DBG_BATMAN, "Creating new last-hop neighbor of originator\n"); bat_dbg(DBG_BATMAN, bat_priv,
"Creating new last-hop neighbor of originator\n");
neigh_node = kzalloc(sizeof(struct neigh_node), GFP_ATOMIC); neigh_node = kzalloc(sizeof(struct neigh_node), GFP_ATOMIC);
if (!neigh_node) if (!neigh_node)
@ -93,7 +81,7 @@ create_neighbor(struct orig_node *orig_node, struct orig_node *orig_neigh_node,
return neigh_node; return neigh_node;
} }
void free_orig_node(void *data) static void free_orig_node(void *data)
{ {
struct list_head *list_pos, *list_pos_tmp; struct list_head *list_pos, *list_pos_tmp;
struct neigh_node *neigh_node; struct neigh_node *neigh_node;
@ -114,6 +102,21 @@ void free_orig_node(void *data)
kfree(orig_node); kfree(orig_node);
} }
void originator_free(void)
{
unsigned long flags;
if (!orig_hash)
return;
cancel_delayed_work_sync(&purge_orig_wq);
spin_lock_irqsave(&orig_hash_lock, flags);
hash_delete(orig_hash, free_orig_node);
orig_hash = NULL;
spin_unlock_irqrestore(&orig_hash_lock, flags);
}
/* this function finds or creates an originator entry for the given /* this function finds or creates an originator entry for the given
* address if it does not exits */ * address if it does not exits */
struct orig_node *get_orig_node(uint8_t *addr) struct orig_node *get_orig_node(uint8_t *addr)
@ -129,7 +132,8 @@ struct orig_node *get_orig_node(uint8_t *addr)
if (orig_node != NULL) if (orig_node != NULL)
return orig_node; return orig_node;
bat_dbg(DBG_BATMAN, "Creating new originator: %pM\n", addr); bat_dbg(DBG_BATMAN, bat_priv,
"Creating new originator: %pM\n", addr);
orig_node = kzalloc(sizeof(struct orig_node), GFP_ATOMIC); orig_node = kzalloc(sizeof(struct orig_node), GFP_ATOMIC);
if (!orig_node) if (!orig_node)
@ -163,8 +167,8 @@ struct orig_node *get_orig_node(uint8_t *addr)
swaphash = hash_resize(orig_hash, orig_hash->size * 2); swaphash = hash_resize(orig_hash, orig_hash->size * 2);
if (swaphash == NULL) if (swaphash == NULL)
printk(KERN_ERR bat_err(soft_device,
"batman-adv:Couldn't resize orig hash table\n"); "Couldn't resize orig hash table\n");
else else
orig_hash = swaphash; orig_hash = swaphash;
} }
@ -182,6 +186,8 @@ free_orig_node:
static bool purge_orig_neighbors(struct orig_node *orig_node, static bool purge_orig_neighbors(struct orig_node *orig_node,
struct neigh_node **best_neigh_node) struct neigh_node **best_neigh_node)
{ {
/* FIXME: each orig_node->batman_if will be attached to a softif */
struct bat_priv *bat_priv = netdev_priv(soft_device);
struct list_head *list_pos, *list_pos_tmp; struct list_head *list_pos, *list_pos_tmp;
struct neigh_node *neigh_node; struct neigh_node *neigh_node;
bool neigh_purged = false; bool neigh_purged = false;
@ -193,20 +199,19 @@ static bool purge_orig_neighbors(struct orig_node *orig_node,
neigh_node = list_entry(list_pos, struct neigh_node, list); neigh_node = list_entry(list_pos, struct neigh_node, list);
if ((time_after(jiffies, if ((time_after(jiffies,
(neigh_node->last_valid + neigh_node->last_valid + PURGE_TIMEOUT * HZ)) ||
((PURGE_TIMEOUT * HZ) / 1000)))) ||
(neigh_node->if_incoming->if_status == (neigh_node->if_incoming->if_status ==
IF_TO_BE_REMOVED)) { IF_TO_BE_REMOVED)) {
if (neigh_node->if_incoming->if_status == if (neigh_node->if_incoming->if_status ==
IF_TO_BE_REMOVED) IF_TO_BE_REMOVED)
bat_dbg(DBG_BATMAN, bat_dbg(DBG_BATMAN, bat_priv,
"neighbor purge: originator %pM, " "neighbor purge: originator %pM, "
"neighbor: %pM, iface: %s\n", "neighbor: %pM, iface: %s\n",
orig_node->orig, neigh_node->addr, orig_node->orig, neigh_node->addr,
neigh_node->if_incoming->dev); neigh_node->if_incoming->dev);
else else
bat_dbg(DBG_BATMAN, bat_dbg(DBG_BATMAN, bat_priv,
"neighbor timeout: originator %pM, " "neighbor timeout: originator %pM, "
"neighbor: %pM, last_valid: %lu\n", "neighbor: %pM, last_valid: %lu\n",
orig_node->orig, neigh_node->addr, orig_node->orig, neigh_node->addr,
@ -226,21 +231,26 @@ static bool purge_orig_neighbors(struct orig_node *orig_node,
static bool purge_orig_node(struct orig_node *orig_node) static bool purge_orig_node(struct orig_node *orig_node)
{ {
/* FIXME: each batman_if will be attached to a softif */
struct bat_priv *bat_priv = netdev_priv(soft_device);
struct neigh_node *best_neigh_node; struct neigh_node *best_neigh_node;
if (time_after(jiffies, if (time_after(jiffies,
(orig_node->last_valid + orig_node->last_valid + 2 * PURGE_TIMEOUT * HZ)) {
((2 * PURGE_TIMEOUT * HZ) / 1000)))) {
bat_dbg(DBG_BATMAN, bat_dbg(DBG_BATMAN, bat_priv,
"Originator timeout: originator %pM, last_valid %lu\n", "Originator timeout: originator %pM, last_valid %lu\n",
orig_node->orig, (orig_node->last_valid / HZ)); orig_node->orig, (orig_node->last_valid / HZ));
return true; return true;
} else { } else {
if (purge_orig_neighbors(orig_node, &best_neigh_node)) if (purge_orig_neighbors(orig_node, &best_neigh_node)) {
update_routes(orig_node, best_neigh_node, update_routes(orig_node, best_neigh_node,
orig_node->hna_buff, orig_node->hna_buff,
orig_node->hna_buff_len); orig_node->hna_buff_len);
/* update bonding candidates, we could have lost
* some candidates. */
update_bonding_candidates(bat_priv, orig_node);
}
} }
return false; return false;
@ -271,49 +281,41 @@ void purge_orig(struct work_struct *work)
start_purge_timer(); start_purge_timer();
} }
ssize_t orig_fill_buffer_text(struct net_device *net_dev, char *buff, int orig_seq_print_text(struct seq_file *seq, void *offset)
size_t count, loff_t off)
{ {
HASHIT(hashit); HASHIT(hashit);
struct net_device *net_dev = (struct net_device *)seq->private;
struct bat_priv *bat_priv = netdev_priv(net_dev); struct bat_priv *bat_priv = netdev_priv(net_dev);
struct orig_node *orig_node; struct orig_node *orig_node;
struct neigh_node *neigh_node; struct neigh_node *neigh_node;
size_t hdr_len, tmp_len; int batman_count = 0;
int batman_count = 0, bytes_written = 0; int last_seen_secs;
int last_seen_msecs;
unsigned long flags; unsigned long flags;
char orig_str[ETH_STR_LEN], router_str[ETH_STR_LEN]; char orig_str[ETH_STR_LEN], router_str[ETH_STR_LEN];
if (!bat_priv->primary_if) { if ((!bat_priv->primary_if) ||
if (off == 0) (bat_priv->primary_if->if_status != IF_ACTIVE)) {
return sprintf(buff, if (!bat_priv->primary_if)
"BATMAN mesh %s disabled - " return seq_printf(seq, "BATMAN mesh %s disabled - "
"please specify interfaces to enable it\n", "please specify interfaces to enable it\n",
net_dev->name); net_dev->name);
return 0; return seq_printf(seq, "BATMAN mesh %s "
}
if (bat_priv->primary_if->if_status != IF_ACTIVE && off == 0)
return sprintf(buff,
"BATMAN mesh %s "
"disabled - primary interface not active\n", "disabled - primary interface not active\n",
net_dev->name); net_dev->name);
else if (bat_priv->primary_if->if_status != IF_ACTIVE) }
return 0;
rcu_read_lock(); rcu_read_lock();
hdr_len = sprintf(buff, seq_printf(seq, "[B.A.T.M.A.N. adv %s%s, MainIF/MAC: %s/%s (%s)]\n",
" %-14s (%s/%i) %17s [%10s]: %20s " SOURCE_VERSION, REVISION_VERSION_STR,
"... [B.A.T.M.A.N. adv %s%s, MainIF/MAC: %s/%s (%s)]\n",
"Originator", "#", TQ_MAX_VALUE, "Nexthop", "outgoingIF",
"Potential nexthops", SOURCE_VERSION, REVISION_VERSION_STR,
bat_priv->primary_if->dev, bat_priv->primary_if->addr_str, bat_priv->primary_if->dev, bat_priv->primary_if->addr_str,
net_dev->name); net_dev->name);
seq_printf(seq, " %-15s %s (%s/%i) %17s [%10s]: %20s ...\n",
"Originator", "last-seen", "#", TQ_MAX_VALUE, "Nexthop",
"outgoingIF", "Potential nexthops");
rcu_read_unlock(); rcu_read_unlock();
if (off < hdr_len)
bytes_written = hdr_len;
spin_lock_irqsave(&orig_hash_lock, flags); spin_lock_irqsave(&orig_hash_lock, flags);
while (hash_iterate(orig_hash, &hashit)) { while (hash_iterate(orig_hash, &hashit)) {
@ -326,44 +328,34 @@ ssize_t orig_fill_buffer_text(struct net_device *net_dev, char *buff,
if (orig_node->router->tq_avg == 0) if (orig_node->router->tq_avg == 0)
continue; continue;
/* estimated line length */
if (count < bytes_written + 200)
break;
addr_to_string(orig_str, orig_node->orig); addr_to_string(orig_str, orig_node->orig);
addr_to_string(router_str, orig_node->router->addr); addr_to_string(router_str, orig_node->router->addr);
last_seen_secs = jiffies_to_msecs(jiffies -
orig_node->last_valid) / 1000;
last_seen_msecs = jiffies_to_msecs(jiffies -
orig_node->last_valid) % 1000;
tmp_len = sprintf(buff + bytes_written, seq_printf(seq, "%-17s %4i.%03is (%3i) %17s [%10s]:",
"%-17s (%3i) %17s [%10s]:", orig_str, last_seen_secs, last_seen_msecs,
orig_str, orig_node->router->tq_avg, orig_node->router->tq_avg, router_str,
router_str,
orig_node->router->if_incoming->dev); orig_node->router->if_incoming->dev);
list_for_each_entry(neigh_node, &orig_node->neigh_list, list) { list_for_each_entry(neigh_node, &orig_node->neigh_list, list) {
addr_to_string(orig_str, neigh_node->addr); addr_to_string(orig_str, neigh_node->addr);
tmp_len += sprintf(buff + bytes_written + tmp_len, seq_printf(seq, " %17s (%3i)", orig_str,
" %17s (%3i)", orig_str,
neigh_node->tq_avg); neigh_node->tq_avg);
} }
tmp_len += sprintf(buff + bytes_written + tmp_len, "\n"); seq_printf(seq, "\n");
batman_count++; batman_count++;
hdr_len += tmp_len;
if (off >= hdr_len)
continue;
bytes_written += tmp_len;
} }
spin_unlock_irqrestore(&orig_hash_lock, flags); spin_unlock_irqrestore(&orig_hash_lock, flags);
if ((batman_count == 0) && (off == 0)) if ((batman_count == 0))
bytes_written += sprintf(buff + bytes_written, seq_printf(seq, "No batman nodes in range ...\n");
"No batman nodes in range ...\n");
return bytes_written; return 0;
} }
static int orig_node_add_if(struct orig_node *orig_node, int max_if_num) static int orig_node_add_if(struct orig_node *orig_node, int max_if_num)
@ -373,8 +365,7 @@ static int orig_node_add_if(struct orig_node *orig_node, int max_if_num)
data_ptr = kmalloc(max_if_num * sizeof(TYPE_OF_WORD) * NUM_WORDS, data_ptr = kmalloc(max_if_num * sizeof(TYPE_OF_WORD) * NUM_WORDS,
GFP_ATOMIC); GFP_ATOMIC);
if (!data_ptr) { if (!data_ptr) {
printk(KERN_ERR pr_err("Can't resize orig: out of memory\n");
"batman-adv:Can't resize orig: out of memory\n");
return -1; return -1;
} }
@ -385,8 +376,7 @@ static int orig_node_add_if(struct orig_node *orig_node, int max_if_num)
data_ptr = kmalloc(max_if_num * sizeof(uint8_t), GFP_ATOMIC); data_ptr = kmalloc(max_if_num * sizeof(uint8_t), GFP_ATOMIC);
if (!data_ptr) { if (!data_ptr) {
printk(KERN_ERR pr_err("Can't resize orig: out of memory\n");
"batman-adv:Can't resize orig: out of memory\n");
return -1; return -1;
} }
@ -435,8 +425,7 @@ static int orig_node_del_if(struct orig_node *orig_node,
chunk_size = sizeof(TYPE_OF_WORD) * NUM_WORDS; chunk_size = sizeof(TYPE_OF_WORD) * NUM_WORDS;
data_ptr = kmalloc(max_if_num * chunk_size, GFP_ATOMIC); data_ptr = kmalloc(max_if_num * chunk_size, GFP_ATOMIC);
if (!data_ptr) { if (!data_ptr) {
printk(KERN_ERR pr_err("Can't resize orig: out of memory\n");
"batman-adv:Can't resize orig: out of memory\n");
return -1; return -1;
} }
@ -457,8 +446,7 @@ free_bcast_own:
data_ptr = kmalloc(max_if_num * sizeof(uint8_t), GFP_ATOMIC); data_ptr = kmalloc(max_if_num * sizeof(uint8_t), GFP_ATOMIC);
if (!data_ptr) { if (!data_ptr) {
printk(KERN_ERR pr_err("Can't resize orig: out of memory\n");
"batman-adv:Can't resize orig: out of memory\n");
return -1; return -1;
} }

View File

@ -19,16 +19,18 @@
* *
*/ */
#ifndef _NET_BATMAN_ADV_ORIGINATOR_H_
#define _NET_BATMAN_ADV_ORIGINATOR_H_
int originator_init(void); int originator_init(void);
void free_orig_node(void *data);
void originator_free(void); void originator_free(void);
void purge_orig(struct work_struct *work); void purge_orig(struct work_struct *work);
struct orig_node *orig_find(char *mac);
struct orig_node *get_orig_node(uint8_t *addr); struct orig_node *get_orig_node(uint8_t *addr);
struct neigh_node * struct neigh_node *
create_neighbor(struct orig_node *orig_node, struct orig_node *orig_neigh_node, create_neighbor(struct orig_node *orig_node, struct orig_node *orig_neigh_node,
uint8_t *neigh, struct batman_if *if_incoming); uint8_t *neigh, struct batman_if *if_incoming);
ssize_t orig_fill_buffer_text(struct net_device *net_dev, char *buff, int orig_seq_print_text(struct seq_file *seq, void *offset);
size_t count, loff_t off);
int orig_hash_add_if(struct batman_if *batman_if, int max_if_num); int orig_hash_add_if(struct batman_if *batman_if, int max_if_num);
int orig_hash_del_if(struct batman_if *batman_if, int max_if_num); int orig_hash_del_if(struct batman_if *batman_if, int max_if_num);
#endif /* _NET_BATMAN_ADV_ORIGINATOR_H_ */

View File

@ -19,6 +19,9 @@
* *
*/ */
#ifndef _NET_BATMAN_ADV_PACKET_H_
#define _NET_BATMAN_ADV_PACKET_H_
#define ETH_P_BATMAN 0x4305 /* unofficial/not registered Ethertype */ #define ETH_P_BATMAN 0x4305 /* unofficial/not registered Ethertype */
#define BAT_PACKET 0x01 #define BAT_PACKET 0x01
@ -28,9 +31,10 @@
#define BAT_VIS 0x05 #define BAT_VIS 0x05
/* this file is included by batctl which needs these defines */ /* this file is included by batctl which needs these defines */
#define COMPAT_VERSION 8 #define COMPAT_VERSION 11
#define DIRECTLINK 0x40 #define DIRECTLINK 0x40
#define VIS_SERVER 0x20 #define VIS_SERVER 0x20
#define PRIMARIES_FIRST_HOP 0x10
/* ICMP message types */ /* ICMP message types */
#define ECHO_REPLY 0 #define ECHO_REPLY 0
@ -48,7 +52,7 @@ struct batman_packet {
uint8_t version; /* batman version field */ uint8_t version; /* batman version field */
uint8_t flags; /* 0x40: DIRECTLINK flag, 0x20 VIS_SERVER flag... */ uint8_t flags; /* 0x40: DIRECTLINK flag, 0x20 VIS_SERVER flag... */
uint8_t tq; uint8_t tq;
uint16_t seqno; uint32_t seqno;
uint8_t orig[6]; uint8_t orig[6];
uint8_t prev_sender[6]; uint8_t prev_sender[6];
uint8_t ttl; uint8_t ttl;
@ -68,6 +72,23 @@ struct icmp_packet {
uint8_t uid; uint8_t uid;
} __attribute__((packed)); } __attribute__((packed));
#define BAT_RR_LEN 16
/* icmp_packet_rr must start with all fields from imcp_packet
as this is assumed by code that handles ICMP packets */
struct icmp_packet_rr {
uint8_t packet_type;
uint8_t version; /* batman version field */
uint8_t msg_type; /* see ICMP message types above */
uint8_t ttl;
uint8_t dst[6];
uint8_t orig[6];
uint16_t seqno;
uint8_t uid;
uint8_t rr_cur;
uint8_t rr[BAT_RR_LEN][ETH_ALEN];
} __attribute__((packed));
struct unicast_packet { struct unicast_packet {
uint8_t packet_type; uint8_t packet_type;
uint8_t version; /* batman version field */ uint8_t version; /* batman version field */
@ -79,18 +100,21 @@ struct bcast_packet {
uint8_t packet_type; uint8_t packet_type;
uint8_t version; /* batman version field */ uint8_t version; /* batman version field */
uint8_t orig[6]; uint8_t orig[6];
uint16_t seqno; uint8_t ttl;
uint32_t seqno;
} __attribute__((packed)); } __attribute__((packed));
struct vis_packet { struct vis_packet {
uint8_t packet_type; uint8_t packet_type;
uint8_t version; /* batman version field */ uint8_t version; /* batman version field */
uint8_t vis_type; /* which type of vis-participant sent this? */ uint8_t vis_type; /* which type of vis-participant sent this? */
uint8_t seqno; /* sequence number */
uint8_t entries; /* number of entries behind this struct */ uint8_t entries; /* number of entries behind this struct */
uint32_t seqno; /* sequence number */
uint8_t ttl; /* TTL */ uint8_t ttl; /* TTL */
uint8_t vis_orig[6]; /* originator that informs about its uint8_t vis_orig[6]; /* originator that informs about its
* neighbors */ * neighbors */
uint8_t target_orig[6]; /* who should receive this packet */ uint8_t target_orig[6]; /* who should receive this packet */
uint8_t sender_orig[6]; /* who sent or rebroadcasted this packet */ uint8_t sender_orig[6]; /* who sent or rebroadcasted this packet */
} __attribute__((packed)); } __attribute__((packed));
#endif /* _NET_BATMAN_ADV_PACKET_H_ */

View File

@ -19,5 +19,10 @@
* *
*/ */
#ifndef _NET_BATMAN_ADV_RING_BUFFER_H_
#define _NET_BATMAN_ADV_RING_BUFFER_H_
void ring_buffer_set(uint8_t lq_recv[], uint8_t *lq_index, uint8_t value); void ring_buffer_set(uint8_t lq_recv[], uint8_t *lq_index, uint8_t value);
uint8_t ring_buffer_avg(uint8_t lq_recv[]); uint8_t ring_buffer_avg(uint8_t lq_recv[]);
#endif /* _NET_BATMAN_ADV_RING_BUFFER_H_ */

View File

@ -25,7 +25,7 @@
#include "hash.h" #include "hash.h"
#include "soft-interface.h" #include "soft-interface.h"
#include "hard-interface.h" #include "hard-interface.h"
#include "device.h" #include "icmp_socket.h"
#include "translation-table.h" #include "translation-table.h"
#include "originator.h" #include "originator.h"
#include "types.h" #include "types.h"
@ -33,7 +33,7 @@
#include "vis.h" #include "vis.h"
#include "aggregation.h" #include "aggregation.h"
DECLARE_WAIT_QUEUE_HEAD(thread_wait); static DECLARE_WAIT_QUEUE_HEAD(thread_wait);
void slide_own_bcast_window(struct batman_if *batman_if) void slide_own_bcast_window(struct batman_if *batman_if)
{ {
@ -77,24 +77,27 @@ static void update_route(struct orig_node *orig_node,
struct neigh_node *neigh_node, struct neigh_node *neigh_node,
unsigned char *hna_buff, int hna_buff_len) unsigned char *hna_buff, int hna_buff_len)
{ {
/* FIXME: each orig_node->batman_if will be attached to a softif */
struct bat_priv *bat_priv = netdev_priv(soft_device);
/* route deleted */ /* route deleted */
if ((orig_node->router != NULL) && (neigh_node == NULL)) { if ((orig_node->router != NULL) && (neigh_node == NULL)) {
bat_dbg(DBG_ROUTES, "Deleting route towards: %pM\n", bat_dbg(DBG_ROUTES, bat_priv, "Deleting route towards: %pM\n",
orig_node->orig); orig_node->orig);
hna_global_del_orig(orig_node, "originator timed out"); hna_global_del_orig(orig_node, "originator timed out");
/* route added */ /* route added */
} else if ((orig_node->router == NULL) && (neigh_node != NULL)) { } else if ((orig_node->router == NULL) && (neigh_node != NULL)) {
bat_dbg(DBG_ROUTES, bat_dbg(DBG_ROUTES, bat_priv,
"Adding route towards: %pM (via %pM)\n", "Adding route towards: %pM (via %pM)\n",
orig_node->orig, neigh_node->addr); orig_node->orig, neigh_node->addr);
hna_global_add_orig(orig_node, hna_buff, hna_buff_len); hna_global_add_orig(orig_node, hna_buff, hna_buff_len);
/* route changed */ /* route changed */
} else { } else {
bat_dbg(DBG_ROUTES, bat_dbg(DBG_ROUTES, bat_priv,
"Changing route towards: %pM " "Changing route towards: %pM "
"(now via %pM - was via %pM)\n", "(now via %pM - was via %pM)\n",
orig_node->orig, neigh_node->addr, orig_node->orig, neigh_node->addr,
@ -120,11 +123,13 @@ void update_routes(struct orig_node *orig_node,
update_HNA(orig_node, hna_buff, hna_buff_len); update_HNA(orig_node, hna_buff, hna_buff_len);
} }
static int isBidirectionalNeigh(struct orig_node *orig_node, static int is_bidirectional_neigh(struct orig_node *orig_node,
struct orig_node *orig_neigh_node, struct orig_node *orig_neigh_node,
struct batman_packet *batman_packet, struct batman_packet *batman_packet,
struct batman_if *if_incoming) struct batman_if *if_incoming)
{ {
/* FIXME: each orig_node->batman_if will be attached to a softif */
struct bat_priv *bat_priv = netdev_priv(soft_device);
struct neigh_node *neigh_node = NULL, *tmp_neigh_node = NULL; struct neigh_node *neigh_node = NULL, *tmp_neigh_node = NULL;
unsigned char total_count; unsigned char total_count;
@ -211,7 +216,7 @@ static int isBidirectionalNeigh(struct orig_node *orig_node,
orig_neigh_node->tq_asym_penalty) / orig_neigh_node->tq_asym_penalty) /
(TQ_MAX_VALUE * TQ_MAX_VALUE)); (TQ_MAX_VALUE * TQ_MAX_VALUE));
bat_dbg(DBG_BATMAN, bat_dbg(DBG_BATMAN, bat_priv,
"bidirectional: " "bidirectional: "
"orig = %-15pM neigh = %-15pM => own_bcast = %2i, " "orig = %-15pM neigh = %-15pM => own_bcast = %2i, "
"real recv = %2i, local tq: %3i, asym_penalty: %3i, " "real recv = %2i, local tq: %3i, asym_penalty: %3i, "
@ -234,10 +239,12 @@ static void update_orig(struct orig_node *orig_node, struct ethhdr *ethhdr,
unsigned char *hna_buff, int hna_buff_len, unsigned char *hna_buff, int hna_buff_len,
char is_duplicate) char is_duplicate)
{ {
/* FIXME: get bat_priv */
struct bat_priv *bat_priv = netdev_priv(soft_device);
struct neigh_node *neigh_node = NULL, *tmp_neigh_node = NULL; struct neigh_node *neigh_node = NULL, *tmp_neigh_node = NULL;
int tmp_hna_buff_len; int tmp_hna_buff_len;
bat_dbg(DBG_BATMAN, "update_originator(): " bat_dbg(DBG_BATMAN, bat_priv, "update_originator(): "
"Searching and updating originator entry of received packet\n"); "Searching and updating originator entry of received packet\n");
list_for_each_entry(tmp_neigh_node, &orig_node->neigh_list, list) { list_for_each_entry(tmp_neigh_node, &orig_node->neigh_list, list) {
@ -269,7 +276,7 @@ static void update_orig(struct orig_node *orig_node, struct ethhdr *ethhdr,
if (!neigh_node) if (!neigh_node)
return; return;
} else } else
bat_dbg(DBG_BATMAN, bat_dbg(DBG_BATMAN, bat_priv,
"Updating existing last-hop neighbor of originator\n"); "Updating existing last-hop neighbor of originator\n");
orig_node->flags = batman_packet->flags; orig_node->flags = batman_packet->flags;
@ -318,16 +325,19 @@ update_hna:
* 0 if the packet is to be accepted * 0 if the packet is to be accepted
* 1 if the packet is to be ignored. * 1 if the packet is to be ignored.
*/ */
static int window_protected(int16_t seq_num_diff, static int window_protected(int32_t seq_num_diff,
unsigned long *last_reset) unsigned long *last_reset)
{ {
/* FIXME: each orig_node->batman_if will be attached to a softif */
struct bat_priv *bat_priv = netdev_priv(soft_device);
if ((seq_num_diff <= -TQ_LOCAL_WINDOW_SIZE) if ((seq_num_diff <= -TQ_LOCAL_WINDOW_SIZE)
|| (seq_num_diff >= EXPECTED_SEQNO_RANGE)) { || (seq_num_diff >= EXPECTED_SEQNO_RANGE)) {
if (time_after(jiffies, *last_reset + if (time_after(jiffies, *last_reset +
msecs_to_jiffies(RESET_PROTECTION_MS))) { msecs_to_jiffies(RESET_PROTECTION_MS))) {
*last_reset = jiffies; *last_reset = jiffies;
bat_dbg(DBG_BATMAN, bat_dbg(DBG_BATMAN, bat_priv,
"old packet received, start protection\n"); "old packet received, start protection\n");
return 0; return 0;
@ -349,10 +359,12 @@ static char count_real_packets(struct ethhdr *ethhdr,
struct batman_packet *batman_packet, struct batman_packet *batman_packet,
struct batman_if *if_incoming) struct batman_if *if_incoming)
{ {
/* FIXME: each orig_node->batman_if will be attached to a softif */
struct bat_priv *bat_priv = netdev_priv(soft_device);
struct orig_node *orig_node; struct orig_node *orig_node;
struct neigh_node *tmp_neigh_node; struct neigh_node *tmp_neigh_node;
char is_duplicate = 0; char is_duplicate = 0;
int16_t seq_diff; int32_t seq_diff;
int need_update = 0; int need_update = 0;
int set_mark; int set_mark;
@ -387,7 +399,8 @@ static char count_real_packets(struct ethhdr *ethhdr,
} }
if (need_update) { if (need_update) {
bat_dbg(DBG_BATMAN, "updating last_seqno: old %d, new %d\n", bat_dbg(DBG_BATMAN, bat_priv,
"updating last_seqno: old %d, new %d\n",
orig_node->last_real_seqno, batman_packet->seqno); orig_node->last_real_seqno, batman_packet->seqno);
orig_node->last_real_seqno = batman_packet->seqno; orig_node->last_real_seqno = batman_packet->seqno;
} }
@ -395,18 +408,127 @@ static char count_real_packets(struct ethhdr *ethhdr,
return is_duplicate; return is_duplicate;
} }
/* copy primary address for bonding */
static void mark_bonding_address(struct bat_priv *bat_priv,
struct orig_node *orig_node,
struct orig_node *orig_neigh_node,
struct batman_packet *batman_packet)
{
if (batman_packet->flags & PRIMARIES_FIRST_HOP)
memcpy(orig_neigh_node->primary_addr,
orig_node->orig, ETH_ALEN);
return;
}
/* mark possible bond.candidates in the neighbor list */
void update_bonding_candidates(struct bat_priv *bat_priv,
struct orig_node *orig_node)
{
int candidates;
int interference_candidate;
int best_tq;
struct neigh_node *tmp_neigh_node, *tmp_neigh_node2;
struct neigh_node *first_candidate, *last_candidate;
/* update the candidates for this originator */
if (!orig_node->router) {
orig_node->bond.candidates = 0;
return;
}
best_tq = orig_node->router->tq_avg;
/* update bond.candidates */
candidates = 0;
/* mark other nodes which also received "PRIMARIES FIRST HOP" packets
* as "bonding partner" */
/* first, zero the list */
list_for_each_entry(tmp_neigh_node, &orig_node->neigh_list, list) {
tmp_neigh_node->next_bond_candidate = NULL;
}
first_candidate = NULL;
last_candidate = NULL;
list_for_each_entry(tmp_neigh_node, &orig_node->neigh_list, list) {
/* only consider if it has the same primary address ... */
if (memcmp(orig_node->orig,
tmp_neigh_node->orig_node->primary_addr,
ETH_ALEN) != 0)
continue;
/* ... and is good enough to be considered */
if (tmp_neigh_node->tq_avg < best_tq - BONDING_TQ_THRESHOLD)
continue;
/* check if we have another candidate with the same
* mac address or interface. If we do, we won't
* select this candidate because of possible interference. */
interference_candidate = 0;
list_for_each_entry(tmp_neigh_node2,
&orig_node->neigh_list, list) {
if (tmp_neigh_node2 == tmp_neigh_node)
continue;
/* we only care if the other candidate is even
* considered as candidate. */
if (tmp_neigh_node2->next_bond_candidate == NULL)
continue;
if ((tmp_neigh_node->if_incoming ==
tmp_neigh_node2->if_incoming)
|| (memcmp(tmp_neigh_node->addr,
tmp_neigh_node2->addr, ETH_ALEN) == 0)) {
interference_candidate = 1;
break;
}
}
/* don't care further if it is an interference candidate */
if (interference_candidate)
continue;
if (first_candidate == NULL) {
first_candidate = tmp_neigh_node;
tmp_neigh_node->next_bond_candidate = first_candidate;
} else
tmp_neigh_node->next_bond_candidate = last_candidate;
last_candidate = tmp_neigh_node;
candidates++;
}
if (candidates > 0) {
first_candidate->next_bond_candidate = last_candidate;
orig_node->bond.selected = first_candidate;
}
orig_node->bond.candidates = candidates;
}
void receive_bat_packet(struct ethhdr *ethhdr, void receive_bat_packet(struct ethhdr *ethhdr,
struct batman_packet *batman_packet, struct batman_packet *batman_packet,
unsigned char *hna_buff, int hna_buff_len, unsigned char *hna_buff, int hna_buff_len,
struct batman_if *if_incoming) struct batman_if *if_incoming)
{ {
/* FIXME: each orig_node->batman_if will be attached to a softif */
struct bat_priv *bat_priv = netdev_priv(soft_device);
struct batman_if *batman_if; struct batman_if *batman_if;
struct orig_node *orig_neigh_node, *orig_node; struct orig_node *orig_neigh_node, *orig_node;
char has_directlink_flag; char has_directlink_flag;
char is_my_addr = 0, is_my_orig = 0, is_my_oldorig = 0; char is_my_addr = 0, is_my_orig = 0, is_my_oldorig = 0;
char is_broadcast = 0, is_bidirectional, is_single_hop_neigh; char is_broadcast = 0, is_bidirectional, is_single_hop_neigh;
char is_duplicate; char is_duplicate;
unsigned short if_incoming_seqno; uint32_t if_incoming_seqno;
/* Silently drop when the batman packet is actually not a /* Silently drop when the batman packet is actually not a
* correct packet. * correct packet.
@ -431,7 +553,8 @@ void receive_bat_packet(struct ethhdr *ethhdr,
is_single_hop_neigh = (compare_orig(ethhdr->h_source, is_single_hop_neigh = (compare_orig(ethhdr->h_source,
batman_packet->orig) ? 1 : 0); batman_packet->orig) ? 1 : 0);
bat_dbg(DBG_BATMAN, "Received BATMAN packet via NB: %pM, IF: %s [%s] " bat_dbg(DBG_BATMAN, bat_priv,
"Received BATMAN packet via NB: %pM, IF: %s [%s] "
"(from OG: %pM, via prev OG: %pM, seqno %d, tq %d, " "(from OG: %pM, via prev OG: %pM, seqno %d, tq %d, "
"TTL %d, V %d, IDF %d)\n", "TTL %d, V %d, IDF %d)\n",
ethhdr->h_source, if_incoming->dev, if_incoming->addr_str, ethhdr->h_source, if_incoming->dev, if_incoming->addr_str,
@ -455,19 +578,19 @@ void receive_bat_packet(struct ethhdr *ethhdr,
batman_if->net_dev->dev_addr)) batman_if->net_dev->dev_addr))
is_my_oldorig = 1; is_my_oldorig = 1;
if (compare_orig(ethhdr->h_source, broadcastAddr)) if (compare_orig(ethhdr->h_source, broadcast_addr))
is_broadcast = 1; is_broadcast = 1;
} }
if (batman_packet->version != COMPAT_VERSION) { if (batman_packet->version != COMPAT_VERSION) {
bat_dbg(DBG_BATMAN, bat_dbg(DBG_BATMAN, bat_priv,
"Drop packet: incompatible batman version (%i)\n", "Drop packet: incompatible batman version (%i)\n",
batman_packet->version); batman_packet->version);
return; return;
} }
if (is_my_addr) { if (is_my_addr) {
bat_dbg(DBG_BATMAN, bat_dbg(DBG_BATMAN, bat_priv,
"Drop packet: received my own broadcast (sender: %pM" "Drop packet: received my own broadcast (sender: %pM"
")\n", ")\n",
ethhdr->h_source); ethhdr->h_source);
@ -475,7 +598,7 @@ void receive_bat_packet(struct ethhdr *ethhdr,
} }
if (is_broadcast) { if (is_broadcast) {
bat_dbg(DBG_BATMAN, "Drop packet: " bat_dbg(DBG_BATMAN, bat_priv, "Drop packet: "
"ignoring all packets with broadcast source addr (sender: %pM" "ignoring all packets with broadcast source addr (sender: %pM"
")\n", ethhdr->h_source); ")\n", ethhdr->h_source);
return; return;
@ -505,13 +628,13 @@ void receive_bat_packet(struct ethhdr *ethhdr,
bit_packet_count(word); bit_packet_count(word);
} }
bat_dbg(DBG_BATMAN, "Drop packet: " bat_dbg(DBG_BATMAN, bat_priv, "Drop packet: "
"originator packet from myself (via neighbor)\n"); "originator packet from myself (via neighbor)\n");
return; return;
} }
if (is_my_oldorig) { if (is_my_oldorig) {
bat_dbg(DBG_BATMAN, bat_dbg(DBG_BATMAN, bat_priv,
"Drop packet: ignoring all rebroadcast echos (sender: " "Drop packet: ignoring all rebroadcast echos (sender: "
"%pM)\n", ethhdr->h_source); "%pM)\n", ethhdr->h_source);
return; return;
@ -524,14 +647,14 @@ void receive_bat_packet(struct ethhdr *ethhdr,
is_duplicate = count_real_packets(ethhdr, batman_packet, if_incoming); is_duplicate = count_real_packets(ethhdr, batman_packet, if_incoming);
if (is_duplicate == -1) { if (is_duplicate == -1) {
bat_dbg(DBG_BATMAN, bat_dbg(DBG_BATMAN, bat_priv,
"Drop packet: packet within seqno protection time " "Drop packet: packet within seqno protection time "
"(sender: %pM)\n", ethhdr->h_source); "(sender: %pM)\n", ethhdr->h_source);
return; return;
} }
if (batman_packet->tq == 0) { if (batman_packet->tq == 0) {
bat_dbg(DBG_BATMAN, bat_dbg(DBG_BATMAN, bat_priv,
"Drop packet: originator packet with tq equal 0\n"); "Drop packet: originator packet with tq equal 0\n");
return; return;
} }
@ -544,7 +667,7 @@ void receive_bat_packet(struct ethhdr *ethhdr,
!(compare_orig(batman_packet->orig, batman_packet->prev_sender)) && !(compare_orig(batman_packet->orig, batman_packet->prev_sender)) &&
(compare_orig(orig_node->router->addr, (compare_orig(orig_node->router->addr,
orig_node->router->orig_node->router->addr))) { orig_node->router->orig_node->router->addr))) {
bat_dbg(DBG_BATMAN, bat_dbg(DBG_BATMAN, bat_priv,
"Drop packet: ignoring all rebroadcast packets that " "Drop packet: ignoring all rebroadcast packets that "
"may make me loop (sender: %pM)\n", ethhdr->h_source); "may make me loop (sender: %pM)\n", ethhdr->h_source);
return; return;
@ -561,11 +684,12 @@ void receive_bat_packet(struct ethhdr *ethhdr,
* don't route towards it */ * don't route towards it */
if (!is_single_hop_neigh && if (!is_single_hop_neigh &&
(orig_neigh_node->router == NULL)) { (orig_neigh_node->router == NULL)) {
bat_dbg(DBG_BATMAN, "Drop packet: OGM via unknown neighbor!\n"); bat_dbg(DBG_BATMAN, bat_priv,
"Drop packet: OGM via unknown neighbor!\n");
return; return;
} }
is_bidirectional = isBidirectionalNeigh(orig_node, orig_neigh_node, is_bidirectional = is_bidirectional_neigh(orig_node, orig_neigh_node,
batman_packet, if_incoming); batman_packet, if_incoming);
/* update ranking if it is not a duplicate or has the same /* update ranking if it is not a duplicate or has the same
@ -577,6 +701,10 @@ void receive_bat_packet(struct ethhdr *ethhdr,
update_orig(orig_node, ethhdr, batman_packet, update_orig(orig_node, ethhdr, batman_packet,
if_incoming, hna_buff, hna_buff_len, is_duplicate); if_incoming, hna_buff, hna_buff_len, is_duplicate);
mark_bonding_address(bat_priv, orig_node,
orig_neigh_node, batman_packet);
update_bonding_candidates(bat_priv, orig_node);
/* is single hop (direct) neighbor */ /* is single hop (direct) neighbor */
if (is_single_hop_neigh) { if (is_single_hop_neigh) {
@ -584,24 +712,25 @@ void receive_bat_packet(struct ethhdr *ethhdr,
schedule_forward_packet(orig_node, ethhdr, batman_packet, schedule_forward_packet(orig_node, ethhdr, batman_packet,
1, hna_buff_len, if_incoming); 1, hna_buff_len, if_incoming);
bat_dbg(DBG_BATMAN, "Forwarding packet: " bat_dbg(DBG_BATMAN, bat_priv, "Forwarding packet: "
"rebroadcast neighbor packet with direct link flag\n"); "rebroadcast neighbor packet with direct link flag\n");
return; return;
} }
/* multihop originator */ /* multihop originator */
if (!is_bidirectional) { if (!is_bidirectional) {
bat_dbg(DBG_BATMAN, bat_dbg(DBG_BATMAN, bat_priv,
"Drop packet: not received via bidirectional link\n"); "Drop packet: not received via bidirectional link\n");
return; return;
} }
if (is_duplicate) { if (is_duplicate) {
bat_dbg(DBG_BATMAN, "Drop packet: duplicate packet received\n"); bat_dbg(DBG_BATMAN, bat_priv,
"Drop packet: duplicate packet received\n");
return; return;
} }
bat_dbg(DBG_BATMAN, bat_dbg(DBG_BATMAN, bat_priv,
"Forwarding packet: rebroadcast originator packet\n"); "Forwarding packet: rebroadcast originator packet\n");
schedule_forward_packet(orig_node, ethhdr, batman_packet, schedule_forward_packet(orig_node, ethhdr, batman_packet,
0, hna_buff_len, if_incoming); 0, hna_buff_len, if_incoming);
@ -652,10 +781,10 @@ int recv_bat_packet(struct sk_buff *skb,
return NET_RX_SUCCESS; return NET_RX_SUCCESS;
} }
static int recv_my_icmp_packet(struct sk_buff *skb) static int recv_my_icmp_packet(struct sk_buff *skb, size_t icmp_len)
{ {
struct orig_node *orig_node; struct orig_node *orig_node;
struct icmp_packet *icmp_packet; struct icmp_packet_rr *icmp_packet;
struct ethhdr *ethhdr; struct ethhdr *ethhdr;
struct sk_buff *skb_old; struct sk_buff *skb_old;
struct batman_if *batman_if; struct batman_if *batman_if;
@ -663,12 +792,12 @@ static int recv_my_icmp_packet(struct sk_buff *skb)
unsigned long flags; unsigned long flags;
uint8_t dstaddr[ETH_ALEN]; uint8_t dstaddr[ETH_ALEN];
icmp_packet = (struct icmp_packet *)skb->data; icmp_packet = (struct icmp_packet_rr *)skb->data;
ethhdr = (struct ethhdr *)skb_mac_header(skb); ethhdr = (struct ethhdr *)skb_mac_header(skb);
/* add data to device queue */ /* add data to device queue */
if (icmp_packet->msg_type != ECHO_REQUEST) { if (icmp_packet->msg_type != ECHO_REQUEST) {
bat_device_receive_packet(icmp_packet); bat_socket_receive_packet(icmp_packet, icmp_len);
return NET_RX_DROP; return NET_RX_DROP;
} }
@ -690,13 +819,12 @@ static int recv_my_icmp_packet(struct sk_buff *skb)
/* create a copy of the skb, if needed, to modify it. */ /* create a copy of the skb, if needed, to modify it. */
skb_old = NULL; skb_old = NULL;
if (!skb_clone_writable(skb, sizeof(struct icmp_packet))) { if (!skb_clone_writable(skb, icmp_len)) {
skb_old = skb; skb_old = skb;
skb = skb_copy(skb, GFP_ATOMIC); skb = skb_copy(skb, GFP_ATOMIC);
if (!skb) if (!skb)
return NET_RX_DROP; return NET_RX_DROP;
icmp_packet = (struct icmp_packet_rr *)skb->data;
icmp_packet = (struct icmp_packet *)skb->data;
ethhdr = (struct ethhdr *)skb_mac_header(skb); ethhdr = (struct ethhdr *)skb_mac_header(skb);
kfree_skb(skb_old); kfree_skb(skb_old);
} }
@ -715,7 +843,7 @@ static int recv_my_icmp_packet(struct sk_buff *skb)
return ret; return ret;
} }
static int recv_icmp_ttl_exceeded(struct sk_buff *skb) static int recv_icmp_ttl_exceeded(struct sk_buff *skb, size_t icmp_len)
{ {
struct orig_node *orig_node; struct orig_node *orig_node;
struct icmp_packet *icmp_packet; struct icmp_packet *icmp_packet;
@ -731,10 +859,9 @@ static int recv_icmp_ttl_exceeded(struct sk_buff *skb)
/* send TTL exceeded if packet is an echo request (traceroute) */ /* send TTL exceeded if packet is an echo request (traceroute) */
if (icmp_packet->msg_type != ECHO_REQUEST) { if (icmp_packet->msg_type != ECHO_REQUEST) {
printk(KERN_WARNING "batman-adv:" pr_warning("Warning - can't forward icmp packet from %pM to "
"Warning - can't forward icmp packet from %pM to %pM: " "%pM: ttl exceeded\n", icmp_packet->orig,
"ttl exceeded\n", icmp_packet->dst);
icmp_packet->orig, icmp_packet->dst);
return NET_RX_DROP; return NET_RX_DROP;
} }
@ -754,7 +881,7 @@ static int recv_icmp_ttl_exceeded(struct sk_buff *skb)
spin_unlock_irqrestore(&orig_hash_lock, flags); spin_unlock_irqrestore(&orig_hash_lock, flags);
/* create a copy of the skb, if needed, to modify it. */ /* create a copy of the skb, if needed, to modify it. */
if (!skb_clone_writable(skb, sizeof(struct icmp_packet))) { if (!skb_clone_writable(skb, icmp_len)) {
skb_old = skb; skb_old = skb;
skb = skb_copy(skb, GFP_ATOMIC); skb = skb_copy(skb, GFP_ATOMIC);
if (!skb) if (!skb)
@ -781,7 +908,7 @@ static int recv_icmp_ttl_exceeded(struct sk_buff *skb)
int recv_icmp_packet(struct sk_buff *skb) int recv_icmp_packet(struct sk_buff *skb)
{ {
struct icmp_packet *icmp_packet; struct icmp_packet_rr *icmp_packet;
struct ethhdr *ethhdr; struct ethhdr *ethhdr;
struct orig_node *orig_node; struct orig_node *orig_node;
struct sk_buff *skb_old; struct sk_buff *skb_old;
@ -791,6 +918,12 @@ int recv_icmp_packet(struct sk_buff *skb)
unsigned long flags; unsigned long flags;
uint8_t dstaddr[ETH_ALEN]; uint8_t dstaddr[ETH_ALEN];
/**
* we truncate all incoming icmp packets if they don't match our size
*/
if (skb_headlen(skb) >= sizeof(struct icmp_packet_rr))
hdr_size = sizeof(struct icmp_packet_rr);
/* drop packet if it has not necessary minimum size */ /* drop packet if it has not necessary minimum size */
if (skb_headlen(skb) < hdr_size) if (skb_headlen(skb) < hdr_size)
return NET_RX_DROP; return NET_RX_DROP;
@ -809,15 +942,23 @@ int recv_icmp_packet(struct sk_buff *skb)
if (!is_my_mac(ethhdr->h_dest)) if (!is_my_mac(ethhdr->h_dest))
return NET_RX_DROP; return NET_RX_DROP;
icmp_packet = (struct icmp_packet *)skb->data; icmp_packet = (struct icmp_packet_rr *)skb->data;
/* add record route information if not full */
if ((hdr_size == sizeof(struct icmp_packet_rr)) &&
(icmp_packet->rr_cur < BAT_RR_LEN)) {
memcpy(&(icmp_packet->rr[icmp_packet->rr_cur]),
ethhdr->h_dest, ETH_ALEN);
icmp_packet->rr_cur++;
}
/* packet for me */ /* packet for me */
if (is_my_mac(icmp_packet->dst)) if (is_my_mac(icmp_packet->dst))
return recv_my_icmp_packet(skb); return recv_my_icmp_packet(skb, hdr_size);
/* TTL exceeded */ /* TTL exceeded */
if (icmp_packet->ttl < 2) if (icmp_packet->ttl < 2)
return recv_icmp_ttl_exceeded(skb); return recv_icmp_ttl_exceeded(skb, hdr_size);
ret = NET_RX_DROP; ret = NET_RX_DROP;
@ -836,12 +977,12 @@ int recv_icmp_packet(struct sk_buff *skb)
spin_unlock_irqrestore(&orig_hash_lock, flags); spin_unlock_irqrestore(&orig_hash_lock, flags);
/* create a copy of the skb, if needed, to modify it. */ /* create a copy of the skb, if needed, to modify it. */
if (!skb_clone_writable(skb, sizeof(struct icmp_packet))) { if (!skb_clone_writable(skb, hdr_size)) {
skb_old = skb; skb_old = skb;
skb = skb_copy(skb, GFP_ATOMIC); skb = skb_copy(skb, GFP_ATOMIC);
if (!skb) if (!skb)
return NET_RX_DROP; return NET_RX_DROP;
icmp_packet = (struct icmp_packet *)skb->data; icmp_packet = (struct icmp_packet_rr *)skb->data;
ethhdr = (struct ethhdr *)skb_mac_header(skb); ethhdr = (struct ethhdr *)skb_mac_header(skb);
kfree_skb(skb_old); kfree_skb(skb_old);
} }
@ -859,16 +1000,109 @@ int recv_icmp_packet(struct sk_buff *skb)
return ret; return ret;
} }
int recv_unicast_packet(struct sk_buff *skb) /* find a suitable router for this originator, and use
* bonding if possible. */
struct neigh_node *find_router(struct orig_node *orig_node,
struct batman_if *recv_if)
{
/* FIXME: each orig_node->batman_if will be attached to a softif */
struct bat_priv *bat_priv = netdev_priv(soft_device);
struct orig_node *primary_orig_node;
struct orig_node *router_orig;
struct neigh_node *router, *first_candidate, *best_router;
static uint8_t zero_mac[ETH_ALEN] = {0, 0, 0, 0, 0, 0};
int bonding_enabled;
if (!orig_node)
return NULL;
if (!orig_node->router)
return NULL;
/* without bonding, the first node should
* always choose the default router. */
bonding_enabled = atomic_read(&bat_priv->bonding_enabled);
if (!bonding_enabled && (recv_if == NULL))
return orig_node->router;
router_orig = orig_node->router->orig_node;
/* if we have something in the primary_addr, we can search
* for a potential bonding candidate. */
if (memcmp(router_orig->primary_addr, zero_mac, ETH_ALEN) == 0)
return orig_node->router;
/* find the orig_node which has the primary interface. might
* even be the same as our router_orig in many cases */
if (memcmp(router_orig->primary_addr,
router_orig->orig, ETH_ALEN) == 0) {
primary_orig_node = router_orig;
} else {
primary_orig_node = hash_find(orig_hash,
router_orig->primary_addr);
if (!primary_orig_node)
return orig_node->router;
}
/* with less than 2 candidates, we can't do any
* bonding and prefer the original router. */
if (primary_orig_node->bond.candidates < 2)
return orig_node->router;
/* all nodes between should choose a candidate which
* is is not on the interface where the packet came
* in. */
first_candidate = primary_orig_node->bond.selected;
router = first_candidate;
if (bonding_enabled) {
/* in the bonding case, send the packets in a round
* robin fashion over the remaining interfaces. */
do {
/* recv_if == NULL on the first node. */
if (router->if_incoming != recv_if)
break;
router = router->next_bond_candidate;
} while (router != first_candidate);
primary_orig_node->bond.selected = router->next_bond_candidate;
} else {
/* if bonding is disabled, use the best of the
* remaining candidates which are not using
* this interface. */
best_router = first_candidate;
do {
/* recv_if == NULL on the first node. */
if ((router->if_incoming != recv_if) &&
(router->tq_avg > best_router->tq_avg))
best_router = router;
router = router->next_bond_candidate;
} while (router != first_candidate);
router = best_router;
}
return router;
}
int recv_unicast_packet(struct sk_buff *skb, struct batman_if *recv_if)
{ {
struct unicast_packet *unicast_packet; struct unicast_packet *unicast_packet;
struct orig_node *orig_node; struct orig_node *orig_node;
struct neigh_node *router;
struct ethhdr *ethhdr; struct ethhdr *ethhdr;
struct batman_if *batman_if; struct batman_if *batman_if;
struct sk_buff *skb_old; struct sk_buff *skb_old;
uint8_t dstaddr[ETH_ALEN]; uint8_t dstaddr[ETH_ALEN];
int hdr_size = sizeof(struct unicast_packet); int hdr_size = sizeof(struct unicast_packet);
int ret;
unsigned long flags; unsigned long flags;
/* drop packet if it has not necessary minimum size */ /* drop packet if it has not necessary minimum size */
@ -899,26 +1133,30 @@ int recv_unicast_packet(struct sk_buff *skb)
/* TTL exceeded */ /* TTL exceeded */
if (unicast_packet->ttl < 2) { if (unicast_packet->ttl < 2) {
printk(KERN_WARNING "batman-adv:Warning - " pr_warning("Warning - can't forward unicast packet from %pM to "
"can't forward unicast packet from %pM to %pM: " "%pM: ttl exceeded\n", ethhdr->h_source,
"ttl exceeded\n", unicast_packet->dest);
ethhdr->h_source, unicast_packet->dest);
return NET_RX_DROP; return NET_RX_DROP;
} }
ret = NET_RX_DROP;
/* get routing information */ /* get routing information */
spin_lock_irqsave(&orig_hash_lock, flags); spin_lock_irqsave(&orig_hash_lock, flags);
orig_node = ((struct orig_node *) orig_node = ((struct orig_node *)
hash_find(orig_hash, unicast_packet->dest)); hash_find(orig_hash, unicast_packet->dest));
if ((orig_node != NULL) && router = find_router(orig_node, recv_if);
(orig_node->router != NULL)) {
if (!router) {
spin_unlock_irqrestore(&orig_hash_lock, flags);
return NET_RX_DROP;
}
/* don't lock while sending the packets ... we therefore /* don't lock while sending the packets ... we therefore
* copy the required data before sending */ * copy the required data before sending */
batman_if = orig_node->router->if_incoming;
memcpy(dstaddr, orig_node->router->addr, ETH_ALEN); batman_if = router->if_incoming;
memcpy(dstaddr, router->addr, ETH_ALEN);
spin_unlock_irqrestore(&orig_hash_lock, flags); spin_unlock_irqrestore(&orig_hash_lock, flags);
/* create a copy of the skb, if needed, to modify it. */ /* create a copy of the skb, if needed, to modify it. */
@ -927,21 +1165,18 @@ int recv_unicast_packet(struct sk_buff *skb)
skb = skb_copy(skb, GFP_ATOMIC); skb = skb_copy(skb, GFP_ATOMIC);
if (!skb) if (!skb)
return NET_RX_DROP; return NET_RX_DROP;
unicast_packet = (struct unicast_packet *)skb->data; unicast_packet = (struct unicast_packet *) skb->data;
ethhdr = (struct ethhdr *)skb_mac_header(skb); ethhdr = (struct ethhdr *)skb_mac_header(skb);
kfree_skb(skb_old); kfree_skb(skb_old);
} }
/* decrement ttl */ /* decrement ttl */
unicast_packet->ttl--; unicast_packet->ttl--;
/* route it */ /* route it */
send_skb_packet(skb, batman_if, dstaddr); send_skb_packet(skb, batman_if, dstaddr);
ret = NET_RX_SUCCESS;
} else return NET_RX_SUCCESS;
spin_unlock_irqrestore(&orig_hash_lock, flags);
return ret;
} }
int recv_bcast_packet(struct sk_buff *skb) int recv_bcast_packet(struct sk_buff *skb)
@ -950,7 +1185,7 @@ int recv_bcast_packet(struct sk_buff *skb)
struct bcast_packet *bcast_packet; struct bcast_packet *bcast_packet;
struct ethhdr *ethhdr; struct ethhdr *ethhdr;
int hdr_size = sizeof(struct bcast_packet); int hdr_size = sizeof(struct bcast_packet);
int16_t seq_diff; int32_t seq_diff;
unsigned long flags; unsigned long flags;
/* drop packet if it has not necessary minimum size */ /* drop packet if it has not necessary minimum size */
@ -977,6 +1212,9 @@ int recv_bcast_packet(struct sk_buff *skb)
if (is_my_mac(bcast_packet->orig)) if (is_my_mac(bcast_packet->orig))
return NET_RX_DROP; return NET_RX_DROP;
if (bcast_packet->ttl < 2)
return NET_RX_DROP;
spin_lock_irqsave(&orig_hash_lock, flags); spin_lock_irqsave(&orig_hash_lock, flags);
orig_node = ((struct orig_node *) orig_node = ((struct orig_node *)
hash_find(orig_hash, bcast_packet->orig)); hash_find(orig_hash, bcast_packet->orig));
@ -989,12 +1227,12 @@ int recv_bcast_packet(struct sk_buff *skb)
/* check whether the packet is a duplicate */ /* check whether the packet is a duplicate */
if (get_bit_status(orig_node->bcast_bits, if (get_bit_status(orig_node->bcast_bits,
orig_node->last_bcast_seqno, orig_node->last_bcast_seqno,
ntohs(bcast_packet->seqno))) { ntohl(bcast_packet->seqno))) {
spin_unlock_irqrestore(&orig_hash_lock, flags); spin_unlock_irqrestore(&orig_hash_lock, flags);
return NET_RX_DROP; return NET_RX_DROP;
} }
seq_diff = ntohs(bcast_packet->seqno) - orig_node->last_bcast_seqno; seq_diff = ntohl(bcast_packet->seqno) - orig_node->last_bcast_seqno;
/* check whether the packet is old and the host just restarted. */ /* check whether the packet is old and the host just restarted. */
if (window_protected(seq_diff, &orig_node->bcast_seqno_reset)) { if (window_protected(seq_diff, &orig_node->bcast_seqno_reset)) {
@ -1005,7 +1243,7 @@ int recv_bcast_packet(struct sk_buff *skb)
/* mark broadcast in flood history, update window position /* mark broadcast in flood history, update window position
* if required. */ * if required. */
if (bit_get_packet(orig_node->bcast_bits, seq_diff, 1)) if (bit_get_packet(orig_node->bcast_bits, seq_diff, 1))
orig_node->last_bcast_seqno = ntohs(bcast_packet->seqno); orig_node->last_bcast_seqno = ntohl(bcast_packet->seqno);
spin_unlock_irqrestore(&orig_hash_lock, flags); spin_unlock_irqrestore(&orig_hash_lock, flags);
/* rebroadcast packet */ /* rebroadcast packet */

View File

@ -19,9 +19,10 @@
* *
*/ */
#include "types.h" #ifndef _NET_BATMAN_ADV_ROUTING_H_
#define _NET_BATMAN_ADV_ROUTING_H_
extern wait_queue_head_t thread_wait; #include "types.h"
void slide_own_bcast_window(struct batman_if *batman_if); void slide_own_bcast_window(struct batman_if *batman_if);
void receive_bat_packet(struct ethhdr *ethhdr, void receive_bat_packet(struct ethhdr *ethhdr,
@ -32,8 +33,14 @@ void update_routes(struct orig_node *orig_node,
struct neigh_node *neigh_node, struct neigh_node *neigh_node,
unsigned char *hna_buff, int hna_buff_len); unsigned char *hna_buff, int hna_buff_len);
int recv_icmp_packet(struct sk_buff *skb); int recv_icmp_packet(struct sk_buff *skb);
int recv_unicast_packet(struct sk_buff *skb); int recv_unicast_packet(struct sk_buff *skb, struct batman_if *recv_if);
int recv_bcast_packet(struct sk_buff *skb); int recv_bcast_packet(struct sk_buff *skb);
int recv_vis_packet(struct sk_buff *skb); int recv_vis_packet(struct sk_buff *skb);
int recv_bat_packet(struct sk_buff *skb, int recv_bat_packet(struct sk_buff *skb,
struct batman_if *batman_if); struct batman_if *batman_if);
struct neigh_node *find_router(struct orig_node *orig_node,
struct batman_if *recv_if);
void update_bonding_candidates(struct bat_priv *bat_priv,
struct orig_node *orig_node);
#endif /* _NET_BATMAN_ADV_ROUTING_H_ */

View File

@ -29,6 +29,10 @@
#include "vis.h" #include "vis.h"
#include "aggregation.h" #include "aggregation.h"
#include <linux/netfilter_bridge.h>
static void send_outstanding_bcast_packet(struct work_struct *work);
/* apply hop penalty for a normal link */ /* apply hop penalty for a normal link */
static uint8_t hop_penalty(const uint8_t tq) static uint8_t hop_penalty(const uint8_t tq)
{ {
@ -38,15 +42,15 @@ static uint8_t hop_penalty(const uint8_t tq)
/* when do we schedule our own packet to be sent */ /* when do we schedule our own packet to be sent */
static unsigned long own_send_time(struct bat_priv *bat_priv) static unsigned long own_send_time(struct bat_priv *bat_priv)
{ {
return jiffies + return jiffies + msecs_to_jiffies(
(((atomic_read(&bat_priv->orig_interval) - JITTER + atomic_read(&bat_priv->orig_interval) -
(random32() % 2*JITTER)) * HZ) / 1000); JITTER + (random32() % 2*JITTER));
} }
/* when do we schedule a forwarded packet to be sent */ /* when do we schedule a forwarded packet to be sent */
static unsigned long forward_send_time(struct bat_priv *bat_priv) static unsigned long forward_send_time(struct bat_priv *bat_priv)
{ {
return jiffies + (((random32() % (JITTER/2)) * HZ) / 1000); return jiffies + msecs_to_jiffies(random32() % (JITTER/2));
} }
/* send out an already prepared packet to the given address via the /* send out an already prepared packet to the given address via the
@ -64,10 +68,8 @@ int send_skb_packet(struct sk_buff *skb,
goto send_skb_err; goto send_skb_err;
if (!(batman_if->net_dev->flags & IFF_UP)) { if (!(batman_if->net_dev->flags & IFF_UP)) {
printk(KERN_WARNING pr_warning("Interface %s is not up - can't send packet via "
"batman-adv:Interface %s " "that interface!\n", batman_if->dev);
"is not up - can't send packet via that interface!\n",
batman_if->dev);
goto send_skb_err; goto send_skb_err;
} }
@ -90,9 +92,12 @@ int send_skb_packet(struct sk_buff *skb,
/* dev_queue_xmit() returns a negative result on error. However on /* dev_queue_xmit() returns a negative result on error. However on
* congestion and traffic shaping, it drops and returns NET_XMIT_DROP * congestion and traffic shaping, it drops and returns NET_XMIT_DROP
* (which is > 0). This will not be treated as an error. */ * (which is > 0). This will not be treated as an error.
* Also, if netfilter/ebtables wants to block outgoing batman
* packets then giving them a chance to do so here */
return dev_queue_xmit(skb); return NF_HOOK(PF_BRIDGE, NF_BR_LOCAL_OUT, skb, NULL, skb->dev,
dev_queue_xmit);
send_skb_err: send_skb_err:
kfree_skb(skb); kfree_skb(skb);
return NET_XMIT_DROP; return NET_XMIT_DROP;
@ -119,6 +124,8 @@ void send_raw_packet(unsigned char *pack_buff, int pack_buff_len,
static void send_packet_to_if(struct forw_packet *forw_packet, static void send_packet_to_if(struct forw_packet *forw_packet,
struct batman_if *batman_if) struct batman_if *batman_if)
{ {
/* FIXME: each batman_if will be attached to a softif */
struct bat_priv *bat_priv = netdev_priv(soft_device);
char *fwd_str; char *fwd_str;
uint8_t packet_num; uint8_t packet_num;
int16_t buff_pos; int16_t buff_pos;
@ -148,11 +155,11 @@ static void send_packet_to_if(struct forw_packet *forw_packet,
fwd_str = (packet_num > 0 ? "Forwarding" : (forw_packet->own ? fwd_str = (packet_num > 0 ? "Forwarding" : (forw_packet->own ?
"Sending own" : "Sending own" :
"Forwarding")); "Forwarding"));
bat_dbg(DBG_BATMAN, bat_dbg(DBG_BATMAN, bat_priv,
"%s %spacket (originator %pM, seqno %d, TQ %d, TTL %d," "%s %spacket (originator %pM, seqno %d, TQ %d, TTL %d,"
" IDF %s) on interface %s [%s]\n", " IDF %s) on interface %s [%s]\n",
fwd_str, (packet_num > 0 ? "aggregated " : ""), fwd_str, (packet_num > 0 ? "aggregated " : ""),
batman_packet->orig, ntohs(batman_packet->seqno), batman_packet->orig, ntohl(batman_packet->seqno),
batman_packet->tq, batman_packet->ttl, batman_packet->tq, batman_packet->ttl,
(batman_packet->flags & DIRECTLINK ? (batman_packet->flags & DIRECTLINK ?
"on" : "off"), "on" : "off"),
@ -167,20 +174,22 @@ static void send_packet_to_if(struct forw_packet *forw_packet,
send_raw_packet(forw_packet->packet_buff, send_raw_packet(forw_packet->packet_buff,
forw_packet->packet_len, forw_packet->packet_len,
batman_if, broadcastAddr); batman_if, broadcast_addr);
} }
/* send a batman packet */ /* send a batman packet */
static void send_packet(struct forw_packet *forw_packet) static void send_packet(struct forw_packet *forw_packet)
{ {
/* FIXME: each batman_if will be attached to a softif */
struct bat_priv *bat_priv = netdev_priv(soft_device);
struct batman_if *batman_if; struct batman_if *batman_if;
struct batman_packet *batman_packet = struct batman_packet *batman_packet =
(struct batman_packet *)(forw_packet->packet_buff); (struct batman_packet *)(forw_packet->packet_buff);
unsigned char directlink = (batman_packet->flags & DIRECTLINK ? 1 : 0); unsigned char directlink = (batman_packet->flags & DIRECTLINK ? 1 : 0);
if (!forw_packet->if_incoming) { if (!forw_packet->if_incoming) {
printk(KERN_ERR "batman-adv: Error - can't forward packet: " pr_err("Error - can't forward packet: incoming iface not "
"incoming iface not specified\n"); "specified\n");
return; return;
} }
@ -193,18 +202,18 @@ static void send_packet(struct forw_packet *forw_packet)
(forw_packet->own && (forw_packet->if_incoming->if_num > 0))) { (forw_packet->own && (forw_packet->if_incoming->if_num > 0))) {
/* FIXME: what about aggregated packets ? */ /* FIXME: what about aggregated packets ? */
bat_dbg(DBG_BATMAN, bat_dbg(DBG_BATMAN, bat_priv,
"%s packet (originator %pM, seqno %d, TTL %d) " "%s packet (originator %pM, seqno %d, TTL %d) "
"on interface %s [%s]\n", "on interface %s [%s]\n",
(forw_packet->own ? "Sending own" : "Forwarding"), (forw_packet->own ? "Sending own" : "Forwarding"),
batman_packet->orig, ntohs(batman_packet->seqno), batman_packet->orig, ntohl(batman_packet->seqno),
batman_packet->ttl, forw_packet->if_incoming->dev, batman_packet->ttl, forw_packet->if_incoming->dev,
forw_packet->if_incoming->addr_str); forw_packet->if_incoming->addr_str);
send_raw_packet(forw_packet->packet_buff, send_raw_packet(forw_packet->packet_buff,
forw_packet->packet_len, forw_packet->packet_len,
forw_packet->if_incoming, forw_packet->if_incoming,
broadcastAddr); broadcast_addr);
return; return;
} }
@ -276,14 +285,14 @@ void schedule_own_packet(struct batman_if *batman_if)
batman_packet = (struct batman_packet *)batman_if->packet_buff; batman_packet = (struct batman_packet *)batman_if->packet_buff;
/* change sequence number to network order */ /* change sequence number to network order */
batman_packet->seqno = htons((uint16_t)atomic_read(&batman_if->seqno)); batman_packet->seqno =
htonl((uint32_t)atomic_read(&batman_if->seqno));
if (vis_server == VIS_TYPE_SERVER_SYNC) if (vis_server == VIS_TYPE_SERVER_SYNC)
batman_packet->flags = VIS_SERVER; batman_packet->flags |= VIS_SERVER;
else else
batman_packet->flags &= ~VIS_SERVER; batman_packet->flags &= ~VIS_SERVER;
/* could be read by receive_bat_packet() */
atomic_inc(&batman_if->seqno); atomic_inc(&batman_if->seqno);
slide_own_bcast_window(batman_if); slide_own_bcast_window(batman_if);
@ -306,7 +315,7 @@ void schedule_forward_packet(struct orig_node *orig_node,
unsigned long send_time; unsigned long send_time;
if (batman_packet->ttl <= 1) { if (batman_packet->ttl <= 1) {
bat_dbg(DBG_BATMAN, "ttl exceeded\n"); bat_dbg(DBG_BATMAN, bat_priv, "ttl exceeded\n");
return; return;
} }
@ -335,13 +344,16 @@ void schedule_forward_packet(struct orig_node *orig_node,
/* apply hop penalty */ /* apply hop penalty */
batman_packet->tq = hop_penalty(batman_packet->tq); batman_packet->tq = hop_penalty(batman_packet->tq);
bat_dbg(DBG_BATMAN, "Forwarding packet: tq_orig: %i, tq_avg: %i, " bat_dbg(DBG_BATMAN, bat_priv,
"Forwarding packet: tq_orig: %i, tq_avg: %i, "
"tq_forw: %i, ttl_orig: %i, ttl_forw: %i\n", "tq_forw: %i, ttl_orig: %i, ttl_forw: %i\n",
in_tq, tq_avg, batman_packet->tq, in_ttl - 1, in_tq, tq_avg, batman_packet->tq, in_ttl - 1,
batman_packet->ttl); batman_packet->ttl);
batman_packet->seqno = htons(batman_packet->seqno); batman_packet->seqno = htonl(batman_packet->seqno);
/* switch of primaries first hop flag when forwarding */
batman_packet->flags &= ~PRIMARIES_FIRST_HOP;
if (directlink) if (directlink)
batman_packet->flags |= DIRECTLINK; batman_packet->flags |= DIRECTLINK;
else else
@ -392,9 +404,12 @@ static void _add_bcast_packet_to_list(struct forw_packet *forw_packet,
int add_bcast_packet_to_list(struct sk_buff *skb) int add_bcast_packet_to_list(struct sk_buff *skb)
{ {
struct forw_packet *forw_packet; struct forw_packet *forw_packet;
struct bcast_packet *bcast_packet;
/* FIXME: each batman_if will be attached to a softif */
struct bat_priv *bat_priv = netdev_priv(soft_device);
if (!atomic_dec_not_zero(&bcast_queue_left)) { if (!atomic_dec_not_zero(&bcast_queue_left)) {
bat_dbg(DBG_BATMAN, "bcast packet queue full\n"); bat_dbg(DBG_BATMAN, bat_priv, "bcast packet queue full\n");
goto out; goto out;
} }
@ -407,6 +422,10 @@ int add_bcast_packet_to_list(struct sk_buff *skb)
if (!skb) if (!skb)
goto packet_free; goto packet_free;
/* as we have a copy now, it is safe to decrease the TTL */
bcast_packet = (struct bcast_packet *)skb->data;
bcast_packet->ttl--;
skb_reset_mac_header(skb); skb_reset_mac_header(skb);
forw_packet->skb = skb; forw_packet->skb = skb;
@ -426,7 +445,7 @@ out:
return NETDEV_TX_BUSY; return NETDEV_TX_BUSY;
} }
void send_outstanding_bcast_packet(struct work_struct *work) static void send_outstanding_bcast_packet(struct work_struct *work)
{ {
struct batman_if *batman_if; struct batman_if *batman_if;
struct delayed_work *delayed_work = struct delayed_work *delayed_work =
@ -450,7 +469,7 @@ void send_outstanding_bcast_packet(struct work_struct *work)
skb1 = skb_copy(forw_packet->skb, GFP_ATOMIC); skb1 = skb_copy(forw_packet->skb, GFP_ATOMIC);
if (skb1) if (skb1)
send_skb_packet(skb1, send_skb_packet(skb1,
batman_if, broadcastAddr); batman_if, broadcast_addr);
} }
rcu_read_unlock(); rcu_read_unlock();
@ -502,15 +521,19 @@ out:
void purge_outstanding_packets(struct batman_if *batman_if) void purge_outstanding_packets(struct batman_if *batman_if)
{ {
/* FIXME: each batman_if will be attached to a softif */
struct bat_priv *bat_priv = netdev_priv(soft_device);
struct forw_packet *forw_packet; struct forw_packet *forw_packet;
struct hlist_node *tmp_node, *safe_tmp_node; struct hlist_node *tmp_node, *safe_tmp_node;
unsigned long flags; unsigned long flags;
if (batman_if) if (batman_if)
bat_dbg(DBG_BATMAN, "purge_outstanding_packets(): %s\n", bat_dbg(DBG_BATMAN, bat_priv,
"purge_outstanding_packets(): %s\n",
batman_if->dev); batman_if->dev);
else else
bat_dbg(DBG_BATMAN, "purge_outstanding_packets()\n"); bat_dbg(DBG_BATMAN, bat_priv,
"purge_outstanding_packets()\n");
/* free bcast list */ /* free bcast list */
spin_lock_irqsave(&forw_bcast_list_lock, flags); spin_lock_irqsave(&forw_bcast_list_lock, flags);

View File

@ -19,9 +19,11 @@
* *
*/ */
#ifndef _NET_BATMAN_ADV_SEND_H_
#define _NET_BATMAN_ADV_SEND_H_
#include "types.h" #include "types.h"
void send_own_packet_work(struct work_struct *work);
int send_skb_packet(struct sk_buff *skb, int send_skb_packet(struct sk_buff *skb,
struct batman_if *batman_if, struct batman_if *batman_if,
uint8_t *dst_addr); uint8_t *dst_addr);
@ -34,6 +36,7 @@ void schedule_forward_packet(struct orig_node *orig_node,
uint8_t directlink, int hna_buff_len, uint8_t directlink, int hna_buff_len,
struct batman_if *if_outgoing); struct batman_if *if_outgoing);
int add_bcast_packet_to_list(struct sk_buff *skb); int add_bcast_packet_to_list(struct sk_buff *skb);
void send_outstanding_bcast_packet(struct work_struct *work);
void send_outstanding_bat_packet(struct work_struct *work); void send_outstanding_bat_packet(struct work_struct *work);
void purge_outstanding_packets(struct batman_if *batman_if); void purge_outstanding_packets(struct batman_if *batman_if);
#endif /* _NET_BATMAN_ADV_SEND_H_ */

View File

@ -22,6 +22,7 @@
#include "main.h" #include "main.h"
#include "soft-interface.h" #include "soft-interface.h"
#include "hard-interface.h" #include "hard-interface.h"
#include "routing.h"
#include "send.h" #include "send.h"
#include "translation-table.h" #include "translation-table.h"
#include "types.h" #include "types.h"
@ -30,13 +31,12 @@
#include <linux/ethtool.h> #include <linux/ethtool.h>
#include <linux/etherdevice.h> #include <linux/etherdevice.h>
static uint16_t bcast_seqno = 1; /* give own bcast messages seq numbers to avoid static uint32_t bcast_seqno = 1; /* give own bcast messages seq numbers to avoid
* broadcast storms */ * broadcast storms */
static int32_t skb_packets; static int32_t skb_packets;
static int32_t skb_bad_packets; static int32_t skb_bad_packets;
unsigned char mainIfAddr[ETH_ALEN]; unsigned char main_if_addr[ETH_ALEN];
static unsigned char mainIfAddr_default[ETH_ALEN];
static int bat_get_settings(struct net_device *dev, struct ethtool_cmd *cmd); static int bat_get_settings(struct net_device *dev, struct ethtool_cmd *cmd);
static void bat_get_drvinfo(struct net_device *dev, static void bat_get_drvinfo(struct net_device *dev,
struct ethtool_drvinfo *info); struct ethtool_drvinfo *info);
@ -58,12 +58,7 @@ static const struct ethtool_ops bat_ethtool_ops = {
void set_main_if_addr(uint8_t *addr) void set_main_if_addr(uint8_t *addr)
{ {
memcpy(mainIfAddr, addr, ETH_ALEN); memcpy(main_if_addr, addr, ETH_ALEN);
}
int main_if_was_up(void)
{
return (memcmp(mainIfAddr, mainIfAddr_default, ETH_ALEN) != 0 ? 1 : 0);
} }
int my_skb_push(struct sk_buff *skb, unsigned int len) int my_skb_push(struct sk_buff *skb, unsigned int len)
@ -83,69 +78,25 @@ int my_skb_push(struct sk_buff *skb, unsigned int len)
return 0; return 0;
} }
#ifdef HAVE_NET_DEVICE_OPS static int interface_open(struct net_device *dev)
static const struct net_device_ops bat_netdev_ops = {
.ndo_open = interface_open,
.ndo_stop = interface_release,
.ndo_get_stats = interface_stats,
.ndo_set_mac_address = interface_set_mac_addr,
.ndo_change_mtu = interface_change_mtu,
.ndo_start_xmit = interface_tx,
.ndo_validate_addr = eth_validate_addr
};
#endif
void interface_setup(struct net_device *dev)
{
struct bat_priv *priv = netdev_priv(dev);
char dev_addr[ETH_ALEN];
ether_setup(dev);
#ifdef HAVE_NET_DEVICE_OPS
dev->netdev_ops = &bat_netdev_ops;
#else
dev->open = interface_open;
dev->stop = interface_release;
dev->get_stats = interface_stats;
dev->set_mac_address = interface_set_mac_addr;
dev->change_mtu = interface_change_mtu;
dev->hard_start_xmit = interface_tx;
#endif
dev->destructor = free_netdev;
dev->mtu = hardif_min_mtu();
dev->hard_header_len = BAT_HEADER_LEN; /* reserve more space in the
* skbuff for our header */
/* generate random address */
random_ether_addr(dev_addr);
memcpy(dev->dev_addr, dev_addr, ETH_ALEN);
SET_ETHTOOL_OPS(dev, &bat_ethtool_ops);
memset(priv, 0, sizeof(struct bat_priv));
}
int interface_open(struct net_device *dev)
{ {
netif_start_queue(dev); netif_start_queue(dev);
return 0; return 0;
} }
int interface_release(struct net_device *dev) static int interface_release(struct net_device *dev)
{ {
netif_stop_queue(dev); netif_stop_queue(dev);
return 0; return 0;
} }
struct net_device_stats *interface_stats(struct net_device *dev) static struct net_device_stats *interface_stats(struct net_device *dev)
{ {
struct bat_priv *priv = netdev_priv(dev); struct bat_priv *priv = netdev_priv(dev);
return &priv->stats; return &priv->stats;
} }
int interface_set_mac_addr(struct net_device *dev, void *p) static int interface_set_mac_addr(struct net_device *dev, void *p)
{ {
struct sockaddr *addr = p; struct sockaddr *addr = p;
@ -163,7 +114,7 @@ int interface_set_mac_addr(struct net_device *dev, void *p)
return 0; return 0;
} }
int interface_change_mtu(struct net_device *dev, int new_mtu) static int interface_change_mtu(struct net_device *dev, int new_mtu)
{ {
/* check ranges */ /* check ranges */
if ((new_mtu < 68) || (new_mtu > hardif_min_mtu())) if ((new_mtu < 68) || (new_mtu > hardif_min_mtu()))
@ -179,6 +130,7 @@ int interface_tx(struct sk_buff *skb, struct net_device *dev)
struct unicast_packet *unicast_packet; struct unicast_packet *unicast_packet;
struct bcast_packet *bcast_packet; struct bcast_packet *bcast_packet;
struct orig_node *orig_node; struct orig_node *orig_node;
struct neigh_node *router;
struct ethhdr *ethhdr = (struct ethhdr *)skb->data; struct ethhdr *ethhdr = (struct ethhdr *)skb->data;
struct bat_priv *priv = netdev_priv(dev); struct bat_priv *priv = netdev_priv(dev);
struct batman_if *batman_if; struct batman_if *batman_if;
@ -205,16 +157,17 @@ int interface_tx(struct sk_buff *skb, struct net_device *dev)
bcast_packet = (struct bcast_packet *)skb->data; bcast_packet = (struct bcast_packet *)skb->data;
bcast_packet->version = COMPAT_VERSION; bcast_packet->version = COMPAT_VERSION;
bcast_packet->ttl = TTL;
/* batman packet type: broadcast */ /* batman packet type: broadcast */
bcast_packet->packet_type = BAT_BCAST; bcast_packet->packet_type = BAT_BCAST;
/* hw address of first interface is the orig mac because only /* hw address of first interface is the orig mac because only
* this mac is known throughout the mesh */ * this mac is known throughout the mesh */
memcpy(bcast_packet->orig, mainIfAddr, ETH_ALEN); memcpy(bcast_packet->orig, main_if_addr, ETH_ALEN);
/* set broadcast sequence number */ /* set broadcast sequence number */
bcast_packet->seqno = htons(bcast_seqno); bcast_packet->seqno = htonl(bcast_seqno);
/* broadcast packet. on success, increase seqno. */ /* broadcast packet. on success, increase seqno. */
if (add_bcast_packet_to_list(skb) == NETDEV_TX_OK) if (add_bcast_packet_to_list(skb) == NETDEV_TX_OK)
@ -235,12 +188,24 @@ int interface_tx(struct sk_buff *skb, struct net_device *dev)
if (!orig_node) if (!orig_node)
orig_node = transtable_search(ethhdr->h_dest); orig_node = transtable_search(ethhdr->h_dest);
if ((orig_node) && router = find_router(orig_node, NULL);
(orig_node->router)) {
struct neigh_node *router = orig_node->router; if (!router)
goto unlock;
/* don't lock while sending the packets ... we therefore
* copy the required data before sending */
batman_if = router->if_incoming;
memcpy(dstaddr, router->addr, ETH_ALEN);
spin_unlock_irqrestore(&orig_hash_lock, flags);
if (batman_if->if_status != IF_ACTIVE)
goto dropped;
if (my_skb_push(skb, sizeof(struct unicast_packet)) < 0) if (my_skb_push(skb, sizeof(struct unicast_packet)) < 0)
goto unlock; goto dropped;
unicast_packet = (struct unicast_packet *)skb->data; unicast_packet = (struct unicast_packet *)skb->data;
@ -252,21 +217,7 @@ int interface_tx(struct sk_buff *skb, struct net_device *dev)
/* copy the destination for faster routing */ /* copy the destination for faster routing */
memcpy(unicast_packet->dest, orig_node->orig, ETH_ALEN); memcpy(unicast_packet->dest, orig_node->orig, ETH_ALEN);
/* net_dev won't be available when not active */
if (router->if_incoming->if_status != IF_ACTIVE)
goto unlock;
/* don't lock while sending the packets ... we therefore
* copy the required data before sending */
batman_if = router->if_incoming;
memcpy(dstaddr, router->addr, ETH_ALEN);
spin_unlock_irqrestore(&orig_hash_lock, flags);
send_skb_packet(skb, batman_if, dstaddr); send_skb_packet(skb, batman_if, dstaddr);
} else {
goto unlock;
}
} }
priv->stats.tx_packets++; priv->stats.tx_packets++;
@ -315,6 +266,50 @@ void interface_rx(struct sk_buff *skb, int hdr_size)
netif_rx(skb); netif_rx(skb);
} }
#ifdef HAVE_NET_DEVICE_OPS
static const struct net_device_ops bat_netdev_ops = {
.ndo_open = interface_open,
.ndo_stop = interface_release,
.ndo_get_stats = interface_stats,
.ndo_set_mac_address = interface_set_mac_addr,
.ndo_change_mtu = interface_change_mtu,
.ndo_start_xmit = interface_tx,
.ndo_validate_addr = eth_validate_addr
};
#endif
void interface_setup(struct net_device *dev)
{
struct bat_priv *priv = netdev_priv(dev);
char dev_addr[ETH_ALEN];
ether_setup(dev);
#ifdef HAVE_NET_DEVICE_OPS
dev->netdev_ops = &bat_netdev_ops;
#else
dev->open = interface_open;
dev->stop = interface_release;
dev->get_stats = interface_stats;
dev->set_mac_address = interface_set_mac_addr;
dev->change_mtu = interface_change_mtu;
dev->hard_start_xmit = interface_tx;
#endif
dev->destructor = free_netdev;
dev->mtu = hardif_min_mtu();
dev->hard_header_len = BAT_HEADER_LEN; /* reserve more space in the
* skbuff for our header */
/* generate random address */
random_ether_addr(dev_addr);
memcpy(dev->dev_addr, dev_addr, ETH_ALEN);
SET_ETHTOOL_OPS(dev, &bat_ethtool_ops);
memset(priv, 0, sizeof(struct bat_priv));
}
/* ethtool */ /* ethtool */
static int bat_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) static int bat_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
{ {

View File

@ -19,16 +19,15 @@
* *
*/ */
#ifndef _NET_BATMAN_ADV_SOFT_INTERFACE_H_
#define _NET_BATMAN_ADV_SOFT_INTERFACE_H_
void set_main_if_addr(uint8_t *addr); void set_main_if_addr(uint8_t *addr);
int main_if_was_up(void);
void interface_setup(struct net_device *dev); void interface_setup(struct net_device *dev);
int interface_open(struct net_device *dev);
int interface_release(struct net_device *dev);
struct net_device_stats *interface_stats(struct net_device *dev);
int interface_set_mac_addr(struct net_device *dev, void *addr);
int interface_change_mtu(struct net_device *dev, int new_mtu);
int interface_tx(struct sk_buff *skb, struct net_device *dev); int interface_tx(struct sk_buff *skb, struct net_device *dev);
void interface_rx(struct sk_buff *skb, int hdr_size); void interface_rx(struct sk_buff *skb, int hdr_size);
int my_skb_push(struct sk_buff *skb, unsigned int len); int my_skb_push(struct sk_buff *skb, unsigned int len);
extern unsigned char mainIfAddr[]; extern unsigned char main_if_addr[];
#endif /* _NET_BATMAN_ADV_SOFT_INTERFACE_H_ */

View File

@ -0,0 +1,14 @@
What: /sys/class/net/<iface>/batman-adv/mesh_iface
Date: May 2010
Contact: Marek Lindner <lindner_marek@yahoo.de>
Description:
The /sys/class/net/<iface>/batman-adv/mesh_iface file
displays the batman mesh interface this <iface>
currently is associated with.
What: /sys/class/net/<iface>/batman-adv/iface_status
Date: May 2010
Contact: Marek Lindner <lindner_marek@yahoo.de>
Description:
Indicates the status of <iface> as it is seen by batman.

View File

@ -0,0 +1,33 @@
What: /sys/class/net/<mesh_iface>/mesh/aggregated_ogms
Date: May 2010
Contact: Marek Lindner <lindner_marek@yahoo.de>
Description:
Indicates whether the batman protocol messages of the
mesh <mesh_iface> shall be aggregated or not.
What: /sys/class/net/<mesh_iface>/mesh/bonding
Date: June 2010
Contact: Simon Wunderlich <siwu@hrz.tu-chemnitz.de>
Description:
Indicates whether the data traffic going through the
mesh will be sent using multiple interfaces at the
same time (if available).
What: /sys/class/net/<mesh_iface>/mesh/orig_interval
Date: May 2010
Contact: Marek Lindner <lindner_marek@yahoo.de>
Description:
Defines the interval in milliseconds in which batman
sends its protocol messages.
What: /sys/class/net/<mesh_iface>/mesh/vis_mode
Date: May 2010
Contact: Marek Lindner <lindner_marek@yahoo.de>
Description:
Each batman node only maintains information about its
own local neighborhood, therefore generating graphs
showing the topology of the entire mesh is not easily
feasible without having a central instance to collect
the local topologies from all nodes. This file allows
to activate the collecting (server) mode.

View File

@ -32,7 +32,10 @@ atomic_t hna_local_changed;
DEFINE_SPINLOCK(hna_local_hash_lock); DEFINE_SPINLOCK(hna_local_hash_lock);
static DEFINE_SPINLOCK(hna_global_hash_lock); static DEFINE_SPINLOCK(hna_global_hash_lock);
static void hna_local_purge(struct work_struct *work);
static DECLARE_DELAYED_WORK(hna_local_purge_wq, hna_local_purge); static DECLARE_DELAYED_WORK(hna_local_purge_wq, hna_local_purge);
static void _hna_global_del_orig(struct hna_global_entry *hna_global_entry,
char *message);
static void hna_local_start_timer(void) static void hna_local_start_timer(void)
{ {
@ -57,6 +60,8 @@ int hna_local_init(void)
void hna_local_add(uint8_t *addr) void hna_local_add(uint8_t *addr)
{ {
/* FIXME: each orig_node->batman_if will be attached to a softif */
struct bat_priv *bat_priv = netdev_priv(soft_device);
struct hna_local_entry *hna_local_entry; struct hna_local_entry *hna_local_entry;
struct hna_global_entry *hna_global_entry; struct hna_global_entry *hna_global_entry;
struct hashtable_t *swaphash; struct hashtable_t *swaphash;
@ -77,15 +82,15 @@ void hna_local_add(uint8_t *addr)
MAC-flooding. */ MAC-flooding. */
if ((num_hna + 1 > (ETH_DATA_LEN - BAT_PACKET_LEN) / ETH_ALEN) || if ((num_hna + 1 > (ETH_DATA_LEN - BAT_PACKET_LEN) / ETH_ALEN) ||
(num_hna + 1 > 255)) { (num_hna + 1 > 255)) {
bat_dbg(DBG_ROUTES, bat_dbg(DBG_ROUTES, bat_priv,
"Can't add new local hna entry (%pM): " "Can't add new local hna entry (%pM): "
"number of local hna entries exceeds packet size\n", "number of local hna entries exceeds packet size\n",
addr); addr);
return; return;
} }
bat_dbg(DBG_ROUTES, "Creating new local hna entry: %pM\n", bat_dbg(DBG_ROUTES, bat_priv,
addr); "Creating new local hna entry: %pM\n", addr);
hna_local_entry = kmalloc(sizeof(struct hna_local_entry), GFP_ATOMIC); hna_local_entry = kmalloc(sizeof(struct hna_local_entry), GFP_ATOMIC);
if (!hna_local_entry) if (!hna_local_entry)
@ -111,8 +116,7 @@ void hna_local_add(uint8_t *addr)
hna_local_hash->size * 2); hna_local_hash->size * 2);
if (swaphash == NULL) if (swaphash == NULL)
printk(KERN_ERR "batman-adv:" pr_err("Couldn't resize local hna hash table\n");
"Couldn't resize local hna hash table\n");
else else
hna_local_hash = swaphash; hna_local_hash = swaphash;
} }
@ -160,59 +164,54 @@ int hna_local_fill_buffer(unsigned char *buff, int buff_len)
return i; return i;
} }
int hna_local_fill_buffer_text(struct net_device *net_dev, char *buff, int hna_local_seq_print_text(struct seq_file *seq, void *offset)
size_t count, loff_t off)
{ {
struct net_device *net_dev = (struct net_device *)seq->private;
struct bat_priv *bat_priv = netdev_priv(net_dev); struct bat_priv *bat_priv = netdev_priv(net_dev);
struct hna_local_entry *hna_local_entry; struct hna_local_entry *hna_local_entry;
HASHIT(hashit); HASHIT(hashit);
int bytes_written = 0; HASHIT(hashit_count);
unsigned long flags; unsigned long flags;
size_t hdr_len; size_t buf_size, pos;
char *buff;
if (!bat_priv->primary_if) { if (!bat_priv->primary_if) {
if (off == 0) return seq_printf(seq, "BATMAN mesh %s disabled - "
return sprintf(buff,
"BATMAN mesh %s disabled - "
"please specify interfaces to enable it\n", "please specify interfaces to enable it\n",
net_dev->name); net_dev->name);
return 0;
} }
hdr_len = sprintf(buff, seq_printf(seq, "Locally retrieved addresses (from %s) "
"Locally retrieved addresses (from %s) "
"announced via HNA:\n", "announced via HNA:\n",
net_dev->name); net_dev->name);
if (off < hdr_len)
bytes_written = hdr_len;
spin_lock_irqsave(&hna_local_hash_lock, flags); spin_lock_irqsave(&hna_local_hash_lock, flags);
buf_size = 1;
/* Estimate length for: " * xx:xx:xx:xx:xx:xx\n" */
while (hash_iterate(hna_local_hash, &hashit_count))
buf_size += 21;
buff = kmalloc(buf_size, GFP_ATOMIC);
if (!buff) {
spin_unlock_irqrestore(&hna_local_hash_lock, flags);
return -ENOMEM;
}
buff[0] = '\0';
pos = 0;
while (hash_iterate(hna_local_hash, &hashit)) { while (hash_iterate(hna_local_hash, &hashit)) {
hdr_len += 21;
if (count < bytes_written + 22)
break;
if (off >= hdr_len)
continue;
hna_local_entry = hashit.bucket->data; hna_local_entry = hashit.bucket->data;
bytes_written += snprintf(buff + bytes_written, 22, pos += snprintf(buff + pos, 22, " * %pM\n",
" * " MAC_FMT "\n", hna_local_entry->addr);
hna_local_entry->addr[0],
hna_local_entry->addr[1],
hna_local_entry->addr[2],
hna_local_entry->addr[3],
hna_local_entry->addr[4],
hna_local_entry->addr[5]);
} }
spin_unlock_irqrestore(&hna_local_hash_lock, flags); spin_unlock_irqrestore(&hna_local_hash_lock, flags);
return bytes_written;
seq_printf(seq, "%s", buff);
kfree(buff);
return 0;
} }
static void _hna_local_del(void *data) static void _hna_local_del(void *data)
@ -225,7 +224,9 @@ static void _hna_local_del(void *data)
static void hna_local_del(struct hna_local_entry *hna_local_entry, static void hna_local_del(struct hna_local_entry *hna_local_entry,
char *message) char *message)
{ {
bat_dbg(DBG_ROUTES, "Deleting local hna entry (%pM): %s\n", /* FIXME: each orig_node->batman_if will be attached to a softif */
struct bat_priv *bat_priv = netdev_priv(soft_device);
bat_dbg(DBG_ROUTES, bat_priv, "Deleting local hna entry (%pM): %s\n",
hna_local_entry->addr, message); hna_local_entry->addr, message);
hash_remove(hna_local_hash, hna_local_entry->addr); hash_remove(hna_local_hash, hna_local_entry->addr);
@ -247,7 +248,7 @@ void hna_local_remove(uint8_t *addr, char *message)
spin_unlock_irqrestore(&hna_local_hash_lock, flags); spin_unlock_irqrestore(&hna_local_hash_lock, flags);
} }
void hna_local_purge(struct work_struct *work) static void hna_local_purge(struct work_struct *work)
{ {
struct hna_local_entry *hna_local_entry; struct hna_local_entry *hna_local_entry;
HASHIT(hashit); HASHIT(hashit);
@ -259,8 +260,7 @@ void hna_local_purge(struct work_struct *work)
while (hash_iterate(hna_local_hash, &hashit)) { while (hash_iterate(hna_local_hash, &hashit)) {
hna_local_entry = hashit.bucket->data; hna_local_entry = hashit.bucket->data;
timeout = hna_local_entry->last_seen + timeout = hna_local_entry->last_seen + LOCAL_HNA_TIMEOUT * HZ;
((LOCAL_HNA_TIMEOUT / 1000) * HZ);
if ((!hna_local_entry->never_purge) && if ((!hna_local_entry->never_purge) &&
time_after(jiffies, timeout)) time_after(jiffies, timeout))
hna_local_del(hna_local_entry, "address timed out"); hna_local_del(hna_local_entry, "address timed out");
@ -296,6 +296,8 @@ int hna_global_init(void)
void hna_global_add_orig(struct orig_node *orig_node, void hna_global_add_orig(struct orig_node *orig_node,
unsigned char *hna_buff, int hna_buff_len) unsigned char *hna_buff, int hna_buff_len)
{ {
/* FIXME: each orig_node->batman_if will be attached to a softif */
struct bat_priv *bat_priv = netdev_priv(soft_device);
struct hna_global_entry *hna_global_entry; struct hna_global_entry *hna_global_entry;
struct hna_local_entry *hna_local_entry; struct hna_local_entry *hna_local_entry;
struct hashtable_t *swaphash; struct hashtable_t *swaphash;
@ -322,7 +324,7 @@ void hna_global_add_orig(struct orig_node *orig_node,
memcpy(hna_global_entry->addr, hna_ptr, ETH_ALEN); memcpy(hna_global_entry->addr, hna_ptr, ETH_ALEN);
bat_dbg(DBG_ROUTES, bat_dbg(DBG_ROUTES, bat_priv,
"Creating new global hna entry: " "Creating new global hna entry: "
"%pM (via %pM)\n", "%pM (via %pM)\n",
hna_global_entry->addr, orig_node->orig); hna_global_entry->addr, orig_node->orig);
@ -369,8 +371,7 @@ void hna_global_add_orig(struct orig_node *orig_node,
hna_global_hash->size * 2); hna_global_hash->size * 2);
if (swaphash == NULL) if (swaphash == NULL)
printk(KERN_ERR "batman-adv:" pr_err("Couldn't resize global hna hash table\n");
"Couldn't resize global hna hash table\n");
else else
hna_global_hash = swaphash; hna_global_hash = swaphash;
} }
@ -378,71 +379,63 @@ void hna_global_add_orig(struct orig_node *orig_node,
spin_unlock_irqrestore(&hna_global_hash_lock, flags); spin_unlock_irqrestore(&hna_global_hash_lock, flags);
} }
int hna_global_fill_buffer_text(struct net_device *net_dev, char *buff, int hna_global_seq_print_text(struct seq_file *seq, void *offset)
size_t count, loff_t off)
{ {
struct net_device *net_dev = (struct net_device *)seq->private;
struct bat_priv *bat_priv = netdev_priv(net_dev); struct bat_priv *bat_priv = netdev_priv(net_dev);
struct hna_global_entry *hna_global_entry; struct hna_global_entry *hna_global_entry;
HASHIT(hashit); HASHIT(hashit);
int bytes_written = 0; HASHIT(hashit_count);
unsigned long flags; unsigned long flags;
size_t hdr_len; size_t buf_size, pos;
char *buff;
if (!bat_priv->primary_if) { if (!bat_priv->primary_if) {
if (off == 0) return seq_printf(seq, "BATMAN mesh %s disabled - "
return sprintf(buff,
"BATMAN mesh %s disabled - "
"please specify interfaces to enable it\n", "please specify interfaces to enable it\n",
net_dev->name); net_dev->name);
return 0;
} }
hdr_len = sprintf(buff, seq_printf(seq, "Globally announced HNAs received via the mesh %s\n",
"Globally announced HNAs received via the mesh %s "
"(translation table):\n",
net_dev->name); net_dev->name);
if (off < hdr_len)
bytes_written = hdr_len;
spin_lock_irqsave(&hna_global_hash_lock, flags); spin_lock_irqsave(&hna_global_hash_lock, flags);
buf_size = 1;
/* Estimate length for: " * xx:xx:xx:xx:xx:xx via xx:xx:xx:xx:xx:xx\n"*/
while (hash_iterate(hna_global_hash, &hashit_count))
buf_size += 43;
buff = kmalloc(buf_size, GFP_ATOMIC);
if (!buff) {
spin_unlock_irqrestore(&hna_global_hash_lock, flags);
return -ENOMEM;
}
buff[0] = '\0';
pos = 0;
while (hash_iterate(hna_global_hash, &hashit)) { while (hash_iterate(hna_global_hash, &hashit)) {
hdr_len += 43;
if (count < bytes_written + 44)
break;
if (off >= hdr_len)
continue;
hna_global_entry = hashit.bucket->data; hna_global_entry = hashit.bucket->data;
bytes_written += snprintf(buff + bytes_written, 44, pos += snprintf(buff + pos, 44,
" * " MAC_FMT " via " MAC_FMT "\n", " * %pM via %pM\n", hna_global_entry->addr,
hna_global_entry->addr[0], hna_global_entry->orig_node->orig);
hna_global_entry->addr[1],
hna_global_entry->addr[2],
hna_global_entry->addr[3],
hna_global_entry->addr[4],
hna_global_entry->addr[5],
hna_global_entry->orig_node->orig[0],
hna_global_entry->orig_node->orig[1],
hna_global_entry->orig_node->orig[2],
hna_global_entry->orig_node->orig[3],
hna_global_entry->orig_node->orig[4],
hna_global_entry->orig_node->orig[5]);
} }
spin_unlock_irqrestore(&hna_global_hash_lock, flags); spin_unlock_irqrestore(&hna_global_hash_lock, flags);
return bytes_written;
seq_printf(seq, "%s", buff);
kfree(buff);
return 0;
} }
void _hna_global_del_orig(struct hna_global_entry *hna_global_entry, static void _hna_global_del_orig(struct hna_global_entry *hna_global_entry,
char *message) char *message)
{ {
bat_dbg(DBG_ROUTES, "Deleting global hna entry %pM (via %pM): %s\n", /* FIXME: each orig_node->batman_if will be attached to a softif */
struct bat_priv *bat_priv = netdev_priv(soft_device);
bat_dbg(DBG_ROUTES, bat_priv,
"Deleting global hna entry %pM (via %pM): %s\n",
hna_global_entry->addr, hna_global_entry->orig_node->orig, hna_global_entry->addr, hna_global_entry->orig_node->orig,
message); message);

View File

@ -19,23 +19,21 @@
* *
*/ */
#ifndef _NET_BATMAN_ADV_TRANSLATION_TABLE_H_
#define _NET_BATMAN_ADV_TRANSLATION_TABLE_H_
#include "types.h" #include "types.h"
int hna_local_init(void); int hna_local_init(void);
void hna_local_add(uint8_t *addr); void hna_local_add(uint8_t *addr);
void hna_local_remove(uint8_t *addr, char *message); void hna_local_remove(uint8_t *addr, char *message);
int hna_local_fill_buffer(unsigned char *buff, int buff_len); int hna_local_fill_buffer(unsigned char *buff, int buff_len);
int hna_local_fill_buffer_text(struct net_device *net_dev, char *buff, int hna_local_seq_print_text(struct seq_file *seq, void *offset);
size_t count, loff_t off);
void hna_local_purge(struct work_struct *work);
void hna_local_free(void); void hna_local_free(void);
int hna_global_init(void); int hna_global_init(void);
void hna_global_add_orig(struct orig_node *orig_node, unsigned char *hna_buff, void hna_global_add_orig(struct orig_node *orig_node, unsigned char *hna_buff,
int hna_buff_len); int hna_buff_len);
int hna_global_fill_buffer_text(struct net_device *net_dev, char *buff, int hna_global_seq_print_text(struct seq_file *seq, void *offset);
size_t count, loff_t off);
void _hna_global_del_orig(struct hna_global_entry *hna_global_entry,
char *orig_str);
void hna_global_del_orig(struct orig_node *orig_node, char *message); void hna_global_del_orig(struct orig_node *orig_node, char *message);
void hna_global_free(void); void hna_global_free(void);
struct orig_node *transtable_search(uint8_t *addr); struct orig_node *transtable_search(uint8_t *addr);
@ -43,3 +41,5 @@ struct orig_node *transtable_search(uint8_t *addr);
extern spinlock_t hna_local_hash_lock; extern spinlock_t hna_local_hash_lock;
extern struct hashtable_t *hna_local_hash; extern struct hashtable_t *hna_local_hash;
extern atomic_t hna_local_changed; extern atomic_t hna_local_changed;
#endif /* _NET_BATMAN_ADV_TRANSLATION_TABLE_H_ */

View File

@ -21,10 +21,8 @@
#ifndef _NET_BATMAN_ADV_TYPES_H_
#define _NET_BATMAN_ADV_TYPES_H_
#ifndef TYPES_H
#define TYPES_H
#include "packet.h" #include "packet.h"
#include "bitarray.h" #include "bitarray.h"
@ -52,6 +50,7 @@ struct batman_if {
/** /**
* orig_node - structure for orig_list maintaining nodes of mesh * orig_node - structure for orig_list maintaining nodes of mesh
* @primary_addr: hosts primary interface address
* @last_valid: when last packet from this node was received * @last_valid: when last packet from this node was received
* @bcast_seqno_reset: time when the broadcast seqno window was reset * @bcast_seqno_reset: time when the broadcast seqno window was reset
* @batman_seqno_reset: time when the batman seqno window was reset * @batman_seqno_reset: time when the batman seqno window was reset
@ -59,9 +58,13 @@ struct batman_if {
* @last_real_seqno: last and best known squence number * @last_real_seqno: last and best known squence number
* @last_ttl: ttl of last received packet * @last_ttl: ttl of last received packet
* @last_bcast_seqno: last broadcast sequence number received by this host * @last_bcast_seqno: last broadcast sequence number received by this host
*
* @candidates: how many candidates are available
* @selected: next bonding candidate
*/ */
struct orig_node { struct orig_node {
uint8_t orig[ETH_ALEN]; uint8_t orig[ETH_ALEN];
uint8_t primary_addr[ETH_ALEN];
struct neigh_node *router; struct neigh_node *router;
TYPE_OF_WORD *bcast_own; TYPE_OF_WORD *bcast_own;
uint8_t *bcast_own_sum; uint8_t *bcast_own_sum;
@ -73,11 +76,15 @@ struct orig_node {
uint8_t flags; uint8_t flags;
unsigned char *hna_buff; unsigned char *hna_buff;
int16_t hna_buff_len; int16_t hna_buff_len;
uint16_t last_real_seqno; uint32_t last_real_seqno;
uint8_t last_ttl; uint8_t last_ttl;
TYPE_OF_WORD bcast_bits[NUM_WORDS]; TYPE_OF_WORD bcast_bits[NUM_WORDS];
uint16_t last_bcast_seqno; uint32_t last_bcast_seqno;
struct list_head neigh_list; struct list_head neigh_list;
struct {
uint8_t candidates;
struct neigh_node *selected;
} bond;
}; };
/** /**
@ -92,6 +99,7 @@ struct neigh_node {
uint8_t tq_index; uint8_t tq_index;
uint8_t tq_avg; uint8_t tq_avg;
uint8_t last_ttl; uint8_t last_ttl;
struct neigh_node *next_bond_candidate;
unsigned long last_valid; unsigned long last_valid;
TYPE_OF_WORD real_bits[NUM_WORDS]; TYPE_OF_WORD real_bits[NUM_WORDS];
struct orig_node *orig_node; struct orig_node *orig_node;
@ -101,14 +109,18 @@ struct neigh_node {
struct bat_priv { struct bat_priv {
struct net_device_stats stats; struct net_device_stats stats;
atomic_t aggregation_enabled; atomic_t aggregation_enabled;
atomic_t bonding_enabled;
atomic_t vis_mode; atomic_t vis_mode;
atomic_t orig_interval; atomic_t orig_interval;
atomic_t log_level;
char num_ifaces; char num_ifaces;
struct debug_log *debug_log;
struct batman_if *primary_if; struct batman_if *primary_if;
struct kobject *mesh_obj; struct kobject *mesh_obj;
struct dentry *debug_dir;
}; };
struct device_client { struct socket_client {
struct list_head queue_list; struct list_head queue_list;
unsigned int queue_len; unsigned int queue_len;
unsigned char index; unsigned char index;
@ -116,9 +128,10 @@ struct device_client {
wait_queue_head_t queue_wait; wait_queue_head_t queue_wait;
}; };
struct device_packet { struct socket_packet {
struct list_head list; struct list_head list;
struct icmp_packet icmp_packet; size_t icmp_len;
struct icmp_packet_rr icmp_packet;
}; };
struct hna_local_entry { struct hna_local_entry {
@ -159,4 +172,12 @@ struct if_list_entry {
struct hlist_node list; struct hlist_node list;
}; };
#endif struct debug_log {
char log_buff[LOG_BUF_LEN];
unsigned long log_start;
unsigned long log_end;
spinlock_t lock;
wait_queue_head_t queue_wait;
};
#endif /* _NET_BATMAN_ADV_TYPES_H_ */

View File

@ -43,8 +43,8 @@
_dummy > smallest_signed_int(_dummy); }) _dummy > smallest_signed_int(_dummy); })
#define seq_after(x, y) seq_before(y, x) #define seq_after(x, y) seq_before(y, x)
struct hashtable_t *vis_hash; static struct hashtable_t *vis_hash;
DEFINE_SPINLOCK(vis_hash_lock); static DEFINE_SPINLOCK(vis_hash_lock);
static DEFINE_SPINLOCK(recv_list_lock); static DEFINE_SPINLOCK(recv_list_lock);
static struct vis_info *my_vis_info; static struct vis_info *my_vis_info;
static struct list_head send_list; /* always locked with vis_hash_lock */ static struct list_head send_list; /* always locked with vis_hash_lock */
@ -115,7 +115,7 @@ static void vis_data_insert_interface(const uint8_t *interface,
} }
/* its a new address, add it to the list */ /* its a new address, add it to the list */
entry = kmalloc(sizeof(*entry), GFP_KERNEL); entry = kmalloc(sizeof(*entry), GFP_ATOMIC);
if (!entry) if (!entry)
return; return;
memcpy(entry->addr, interface, ETH_ALEN); memcpy(entry->addr, interface, ETH_ALEN);
@ -142,12 +142,29 @@ static ssize_t vis_data_read_prim_sec(char *buff, struct hlist_head *if_list)
return len; return len;
} }
static size_t vis_data_count_prim_sec(struct hlist_head *if_list)
{
struct if_list_entry *entry;
struct hlist_node *pos;
size_t count = 0;
hlist_for_each_entry(entry, pos, if_list, list) {
if (entry->primary)
count += 9;
else
count += 23;
}
return count;
}
/* read an entry */ /* read an entry */
static ssize_t vis_data_read_entry(char *buff, struct vis_info_entry *entry, static ssize_t vis_data_read_entry(char *buff, struct vis_info_entry *entry,
uint8_t *src, bool primary) uint8_t *src, bool primary)
{ {
char to[40]; char to[18];
/* maximal length: max(4+17+2, 3+17+1+3+2) == 26 */
addr_to_string(to, entry->dest); addr_to_string(to, entry->dest);
if (primary && entry->quality == 0) if (primary && entry->quality == 0)
return sprintf(buff, "HNA %s, ", to); return sprintf(buff, "HNA %s, ", to);
@ -157,38 +174,74 @@ static ssize_t vis_data_read_entry(char *buff, struct vis_info_entry *entry,
return 0; return 0;
} }
ssize_t vis_fill_buffer_text(struct net_device *net_dev, char *buff, int vis_seq_print_text(struct seq_file *seq, void *offset)
size_t count, loff_t off)
{ {
HASHIT(hashit); HASHIT(hashit);
HASHIT(hashit_count);
struct vis_info *info; struct vis_info *info;
struct vis_info_entry *entries; struct vis_info_entry *entries;
struct net_device *net_dev = (struct net_device *)seq->private;
struct bat_priv *bat_priv = netdev_priv(net_dev); struct bat_priv *bat_priv = netdev_priv(net_dev);
HLIST_HEAD(vis_if_list); HLIST_HEAD(vis_if_list);
struct if_list_entry *entry; struct if_list_entry *entry;
struct hlist_node *pos, *n; struct hlist_node *pos, *n;
size_t hdr_len, tmp_len; int i;
int i, bytes_written = 0;
char tmp_addr_str[ETH_STR_LEN]; char tmp_addr_str[ETH_STR_LEN];
unsigned long flags; unsigned long flags;
int vis_server = atomic_read(&bat_priv->vis_mode); int vis_server = atomic_read(&bat_priv->vis_mode);
size_t buff_pos, buf_size;
char *buff;
if ((!bat_priv->primary_if) || if ((!bat_priv->primary_if) ||
(vis_server == VIS_TYPE_CLIENT_UPDATE)) (vis_server == VIS_TYPE_CLIENT_UPDATE))
return 0; return 0;
hdr_len = 0; buf_size = 1;
/* Estimate length */
spin_lock_irqsave(&vis_hash_lock, flags); spin_lock_irqsave(&vis_hash_lock, flags);
while (hash_iterate(vis_hash, &hashit_count)) {
info = hashit_count.bucket->data;
entries = (struct vis_info_entry *)
((char *)info + sizeof(struct vis_info));
for (i = 0; i < info->packet.entries; i++) {
if (entries[i].quality == 0)
continue;
vis_data_insert_interface(entries[i].src, &vis_if_list,
compare_orig(entries[i].src,
info->packet.vis_orig));
}
hlist_for_each_entry(entry, pos, &vis_if_list, list) {
buf_size += 18 + 26 * info->packet.entries;
/* add primary/secondary records */
if (compare_orig(entry->addr, info->packet.vis_orig))
buf_size +=
vis_data_count_prim_sec(&vis_if_list);
buf_size += 1;
}
hlist_for_each_entry_safe(entry, pos, n, &vis_if_list, list) {
hlist_del(&entry->list);
kfree(entry);
}
}
buff = kmalloc(buf_size, GFP_ATOMIC);
if (!buff) {
spin_unlock_irqrestore(&vis_hash_lock, flags);
return -ENOMEM;
}
buff[0] = '\0';
buff_pos = 0;
while (hash_iterate(vis_hash, &hashit)) { while (hash_iterate(vis_hash, &hashit)) {
info = hashit.bucket->data; info = hashit.bucket->data;
entries = (struct vis_info_entry *) entries = (struct vis_info_entry *)
((char *)info + sizeof(struct vis_info)); ((char *)info + sizeof(struct vis_info));
/* estimated line length */
if (count < bytes_written + 200)
break;
for (i = 0; i < info->packet.entries; i++) { for (i = 0; i < info->packet.entries; i++) {
if (entries[i].quality == 0) if (entries[i].quality == 0)
continue; continue;
@ -199,30 +252,22 @@ ssize_t vis_fill_buffer_text(struct net_device *net_dev, char *buff,
hlist_for_each_entry(entry, pos, &vis_if_list, list) { hlist_for_each_entry(entry, pos, &vis_if_list, list) {
addr_to_string(tmp_addr_str, entry->addr); addr_to_string(tmp_addr_str, entry->addr);
tmp_len = sprintf(buff + bytes_written, buff_pos += sprintf(buff + buff_pos, "%s,",
"%s,", tmp_addr_str); tmp_addr_str);
for (i = 0; i < info->packet.entries; i++) for (i = 0; i < info->packet.entries; i++)
tmp_len += vis_data_read_entry( buff_pos += vis_data_read_entry(buff + buff_pos,
buff + bytes_written + tmp_len, &entries[i],
&entries[i], entry->addr, entry->addr,
entry->primary); entry->primary);
/* add primary/secondary records */ /* add primary/secondary records */
if (compare_orig(entry->addr, info->packet.vis_orig)) if (compare_orig(entry->addr, info->packet.vis_orig))
tmp_len += vis_data_read_prim_sec( buff_pos +=
buff + bytes_written + tmp_len, vis_data_read_prim_sec(buff + buff_pos,
&vis_if_list); &vis_if_list);
tmp_len += sprintf(buff + bytes_written + tmp_len, buff_pos += sprintf(buff + buff_pos, "\n");
"\n");
hdr_len += tmp_len;
if (off >= hdr_len)
continue;
bytes_written += tmp_len;
} }
hlist_for_each_entry_safe(entry, pos, n, &vis_if_list, list) { hlist_for_each_entry_safe(entry, pos, n, &vis_if_list, list) {
@ -230,9 +275,13 @@ ssize_t vis_fill_buffer_text(struct net_device *net_dev, char *buff,
kfree(entry); kfree(entry);
} }
} }
spin_unlock_irqrestore(&vis_hash_lock, flags); spin_unlock_irqrestore(&vis_hash_lock, flags);
return bytes_written; seq_printf(seq, "%s", buff);
kfree(buff);
return 0;
} }
/* add the info packet to the send list, if it was not /* add the info packet to the send list, if it was not
@ -308,7 +357,8 @@ static struct vis_info *add_packet(struct vis_packet *vis_packet,
old_info = hash_find(vis_hash, &search_elem); old_info = hash_find(vis_hash, &search_elem);
if (old_info != NULL) { if (old_info != NULL) {
if (!seq_after(vis_packet->seqno, old_info->packet.seqno)) { if (!seq_after(ntohl(vis_packet->seqno),
ntohl(old_info->packet.seqno))) {
if (old_info->packet.seqno == vis_packet->seqno) { if (old_info->packet.seqno == vis_packet->seqno) {
recv_list_add(&old_info->recv_list, recv_list_add(&old_info->recv_list,
vis_packet->sender_orig); vis_packet->sender_orig);
@ -340,7 +390,7 @@ static struct vis_info *add_packet(struct vis_packet *vis_packet,
/* Make it a broadcast packet, if required */ /* Make it a broadcast packet, if required */
if (make_broadcast) if (make_broadcast)
memcpy(info->packet.target_orig, broadcastAddr, ETH_ALEN); memcpy(info->packet.target_orig, broadcast_addr, ETH_ALEN);
/* repair if entries is longer than packet. */ /* repair if entries is longer than packet. */
if (info->packet.entries * sizeof(struct vis_info_entry) > vis_info_len) if (info->packet.entries * sizeof(struct vis_info_entry) > vis_info_len)
@ -474,9 +524,9 @@ static int generate_vis_packet(struct bat_priv *bat_priv)
info->packet.vis_type = atomic_read(&bat_priv->vis_mode); info->packet.vis_type = atomic_read(&bat_priv->vis_mode);
spin_lock_irqsave(&orig_hash_lock, flags); spin_lock_irqsave(&orig_hash_lock, flags);
memcpy(info->packet.target_orig, broadcastAddr, ETH_ALEN); memcpy(info->packet.target_orig, broadcast_addr, ETH_ALEN);
info->packet.ttl = TTL; info->packet.ttl = TTL;
info->packet.seqno++; info->packet.seqno = htonl(ntohl(info->packet.seqno) + 1);
info->packet.entries = 0; info->packet.entries = 0;
if (info->packet.vis_type == VIS_TYPE_CLIENT_UPDATE) { if (info->packet.vis_type == VIS_TYPE_CLIENT_UPDATE) {
@ -547,7 +597,7 @@ static void purge_vis_packets(void)
if (info == my_vis_info) /* never purge own data. */ if (info == my_vis_info) /* never purge own data. */
continue; continue;
if (time_after(jiffies, if (time_after(jiffies,
info->first_seen + (VIS_TIMEOUT*HZ)/1000)) { info->first_seen + VIS_TIMEOUT * HZ)) {
hash_remove_bucket(vis_hash, &hashit); hash_remove_bucket(vis_hash, &hashit);
send_list_del(info); send_list_del(info);
kref_put(&info->refcount, free_info); kref_put(&info->refcount, free_info);
@ -591,7 +641,7 @@ static void broadcast_vis_packet(struct vis_info *info, int packet_length)
} }
spin_unlock_irqrestore(&orig_hash_lock, flags); spin_unlock_irqrestore(&orig_hash_lock, flags);
memcpy(info->packet.target_orig, broadcastAddr, ETH_ALEN); memcpy(info->packet.target_orig, broadcast_addr, ETH_ALEN);
} }
static void unicast_vis_packet(struct vis_info *info, int packet_length) static void unicast_vis_packet(struct vis_info *info, int packet_length)
@ -628,11 +678,11 @@ static void send_vis_packet(struct vis_info *info)
int packet_length; int packet_length;
if (info->packet.ttl < 2) { if (info->packet.ttl < 2) {
printk(KERN_WARNING "batman-adv: Error - can't send vis packet: ttl exceeded\n"); pr_warning("Error - can't send vis packet: ttl exceeded\n");
return; return;
} }
memcpy(info->packet.sender_orig, mainIfAddr, ETH_ALEN); memcpy(info->packet.sender_orig, main_if_addr, ETH_ALEN);
info->packet.ttl--; info->packet.ttl--;
packet_length = sizeof(struct vis_packet) + packet_length = sizeof(struct vis_packet) +
@ -690,18 +740,18 @@ int vis_init(void)
vis_hash = hash_new(256, vis_info_cmp, vis_info_choose); vis_hash = hash_new(256, vis_info_cmp, vis_info_choose);
if (!vis_hash) { if (!vis_hash) {
printk(KERN_ERR "batman-adv:Can't initialize vis_hash\n"); pr_err("Can't initialize vis_hash\n");
goto err; goto err;
} }
my_vis_info = kmalloc(1000, GFP_ATOMIC); my_vis_info = kmalloc(1000, GFP_ATOMIC);
if (!my_vis_info) { if (!my_vis_info) {
printk(KERN_ERR "batman-adv:Can't initialize vis packet\n"); pr_err("Can't initialize vis packet\n");
goto err; goto err;
} }
/* prefill the vis info */ /* prefill the vis info */
my_vis_info->first_seen = jiffies - atomic_read(&vis_interval); my_vis_info->first_seen = jiffies - msecs_to_jiffies(VIS_INTERVAL);
INIT_LIST_HEAD(&my_vis_info->recv_list); INIT_LIST_HEAD(&my_vis_info->recv_list);
INIT_LIST_HEAD(&my_vis_info->send_list); INIT_LIST_HEAD(&my_vis_info->send_list);
kref_init(&my_vis_info->refcount); kref_init(&my_vis_info->refcount);
@ -713,12 +763,11 @@ int vis_init(void)
INIT_LIST_HEAD(&send_list); INIT_LIST_HEAD(&send_list);
memcpy(my_vis_info->packet.vis_orig, mainIfAddr, ETH_ALEN); memcpy(my_vis_info->packet.vis_orig, main_if_addr, ETH_ALEN);
memcpy(my_vis_info->packet.sender_orig, mainIfAddr, ETH_ALEN); memcpy(my_vis_info->packet.sender_orig, main_if_addr, ETH_ALEN);
if (hash_add(vis_hash, my_vis_info) < 0) { if (hash_add(vis_hash, my_vis_info) < 0) {
printk(KERN_ERR pr_err("Can't add own vis packet into hash\n");
"batman-adv:Can't add own vis packet into hash\n");
/* not in hash, need to remove it manually. */ /* not in hash, need to remove it manually. */
kref_put(&my_vis_info->refcount, free_info); kref_put(&my_vis_info->refcount, free_info);
goto err; goto err;
@ -764,5 +813,5 @@ void vis_quit(void)
static void start_vis_timer(void) static void start_vis_timer(void)
{ {
queue_delayed_work(bat_event_workqueue, &vis_timer_wq, queue_delayed_work(bat_event_workqueue, &vis_timer_wq,
(atomic_read(&vis_interval) * HZ) / 1000); (VIS_INTERVAL * HZ) / 1000);
} }

View File

@ -19,7 +19,10 @@
* *
*/ */
#define VIS_TIMEOUT 200000 #ifndef _NET_BATMAN_ADV_VIS_H_
#define _NET_BATMAN_ADV_VIS_H_
#define VIS_TIMEOUT 200 /* timeout of vis packets in seconds */
struct vis_info { struct vis_info {
unsigned long first_seen; unsigned long first_seen;
@ -44,11 +47,7 @@ struct recvlist_node {
uint8_t mac[ETH_ALEN]; uint8_t mac[ETH_ALEN];
}; };
extern struct hashtable_t *vis_hash; int vis_seq_print_text(struct seq_file *seq, void *offset);
extern spinlock_t vis_hash_lock;
ssize_t vis_fill_buffer_text(struct net_device *net_dev, char *buff,
size_t count, loff_t off);
void receive_server_sync_packet(struct bat_priv *bat_priv, void receive_server_sync_packet(struct bat_priv *bat_priv,
struct vis_packet *vis_packet, struct vis_packet *vis_packet,
int vis_info_len); int vis_info_len);
@ -57,3 +56,5 @@ void receive_client_update_packet(struct bat_priv *bat_priv,
int vis_info_len); int vis_info_len);
int vis_init(void); int vis_init(void);
void vis_quit(void); void vis_quit(void);
#endif /* _NET_BATMAN_ADV_VIS_H_ */

View File

@ -2,7 +2,6 @@ TODO:
- checkpatch.pl cleanups - checkpatch.pl cleanups
- Lindent - Lindent
- remove all wrappers - remove all wrappers
- remove typedefs
- audit userspace interface - audit userspace interface
- reserve major number - reserve major number
- cleanup the individual comedi drivers as well - cleanup the individual comedi drivers as well

View File

@ -1845,8 +1845,15 @@ ok:
} }
} }
if (dev->attached && dev->use_count == 0 && dev->open) if (dev->attached && dev->use_count == 0 && dev->open) {
dev->open(dev); int rc = dev->open(dev);
if (rc < 0) {
module_put(dev->driver->module);
module_put(THIS_MODULE);
mutex_unlock(&dev->mutex);
return rc;
}
}
dev->use_count++; dev->use_count++;

View File

@ -53,62 +53,6 @@
COMEDI_MINORVERSION, COMEDI_MICROVERSION) COMEDI_MINORVERSION, COMEDI_MICROVERSION)
#define COMEDI_RELEASE VERSION #define COMEDI_RELEASE VERSION
#define COMEDI_INITCLEANUP_NOMODULE(x) \
static int __init x ## _init_module(void) \
{return comedi_driver_register(&(x)); } \
static void __exit x ## _cleanup_module(void) \
{comedi_driver_unregister(&(x)); } \
module_init(x ## _init_module); \
module_exit(x ## _cleanup_module);
#define COMEDI_MODULE_MACROS \
MODULE_AUTHOR("Comedi http://www.comedi.org"); \
MODULE_DESCRIPTION("Comedi low-level driver"); \
MODULE_LICENSE("GPL");
#define COMEDI_INITCLEANUP(x) \
COMEDI_MODULE_MACROS \
COMEDI_INITCLEANUP_NOMODULE(x)
#define COMEDI_PCI_INITCLEANUP_NOMODULE(comedi_driver, pci_id_table) \
static int __devinit comedi_driver ## _pci_probe(struct pci_dev *dev, \
const struct pci_device_id *ent) \
{ \
return comedi_pci_auto_config(dev, comedi_driver.driver_name); \
} \
static void __devexit comedi_driver ## _pci_remove(\
struct pci_dev *dev) \
{ \
comedi_pci_auto_unconfig(dev); \
} \
static struct pci_driver comedi_driver ## _pci_driver = \
{ \
.id_table = pci_id_table, \
.probe = &comedi_driver ## _pci_probe, \
.remove = __devexit_p(&comedi_driver ## _pci_remove) \
}; \
static int __init comedi_driver ## _init_module(void) \
{ \
int retval; \
retval = comedi_driver_register(&comedi_driver); \
if (retval < 0) \
return retval; \
comedi_driver ## _pci_driver.name = \
(char *)comedi_driver.driver_name; \
return pci_register_driver(&comedi_driver ## _pci_driver); \
} \
static void __exit comedi_driver ## _cleanup_module(void) \
{ \
pci_unregister_driver(&comedi_driver ## _pci_driver); \
comedi_driver_unregister(&comedi_driver); \
} \
module_init(comedi_driver ## _init_module); \
module_exit(comedi_driver ## _cleanup_module);
#define COMEDI_PCI_INITCLEANUP(comedi_driver, pci_id_table) \
COMEDI_MODULE_MACROS \
COMEDI_PCI_INITCLEANUP_NOMODULE(comedi_driver, pci_id_table)
#define PCI_VENDOR_ID_ADLINK 0x144a #define PCI_VENDOR_ID_ADLINK 0x144a
#define PCI_VENDOR_ID_ICP 0x104c #define PCI_VENDOR_ID_ICP 0x104c
#define PCI_VENDOR_ID_CONTEC 0x1221 #define PCI_VENDOR_ID_CONTEC 0x1221
@ -285,7 +229,7 @@ struct comedi_device {
struct fasync_struct *async_queue; struct fasync_struct *async_queue;
void (*open) (struct comedi_device *dev); int (*open) (struct comedi_device *dev);
void (*close) (struct comedi_device *dev); void (*close) (struct comedi_device *dev);
}; };

View File

@ -117,7 +117,18 @@ static struct comedi_driver driver_8255 = {
.detach = dev_8255_detach, .detach = dev_8255_detach,
}; };
COMEDI_INITCLEANUP(driver_8255); static int __init driver_8255_init_module(void)
{
return comedi_driver_register(&driver_8255);
}
static void __exit driver_8255_cleanup_module(void)
{
comedi_driver_unregister(&driver_8255);
}
module_init(driver_8255_init_module);
module_exit(driver_8255_cleanup_module);
static void do_config(struct comedi_device *dev, struct comedi_subdevice *s); static void do_config(struct comedi_device *dev, struct comedi_subdevice *s);
@ -457,3 +468,7 @@ static int dev_8255_detach(struct comedi_device *dev)
return 0; return 0;
} }
MODULE_AUTHOR("Comedi http://www.comedi.org");
MODULE_DESCRIPTION("Comedi low-level driver");
MODULE_LICENSE("GPL");

View File

@ -49,7 +49,18 @@ static struct comedi_driver driver_acl7225b = {
.offset = sizeof(struct boardtype), .offset = sizeof(struct boardtype),
}; };
COMEDI_INITCLEANUP(driver_acl7225b); static int __init driver_acl7225b_init_module(void)
{
return comedi_driver_register(&driver_acl7225b);
}
static void __exit driver_acl7225b_cleanup_module(void)
{
comedi_driver_unregister(&driver_acl7225b);
}
module_init(driver_acl7225b_init_module);
module_exit(driver_acl7225b_cleanup_module);
static int acl7225b_do_insn(struct comedi_device *dev, static int acl7225b_do_insn(struct comedi_device *dev,
struct comedi_subdevice *s, struct comedi_subdevice *s,
@ -150,3 +161,7 @@ static int acl7225b_detach(struct comedi_device *dev)
return 0; return 0;
} }
MODULE_AUTHOR("Comedi http://www.comedi.org");
MODULE_DESCRIPTION("Comedi low-level driver");
MODULE_LICENSE("GPL");

View File

@ -247,16 +247,14 @@ int i_pci_card_data(struct pcilst_struct *amcc,
/* build list of amcc cards in this system */ /* build list of amcc cards in this system */
void v_pci_card_list_init(unsigned short pci_vendor, char display) void v_pci_card_list_init(unsigned short pci_vendor, char display)
{ {
struct pci_dev *pcidev; struct pci_dev *pcidev = NULL;
struct pcilst_struct *amcc, *last; struct pcilst_struct *amcc, *last;
int i; int i;
int i_Count = 0; int i_Count = 0;
amcc_devices = NULL; amcc_devices = NULL;
last = NULL; last = NULL;
for (pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, NULL); for_each_pci_dev(pcidev) {
pcidev != NULL;
pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pcidev)) {
for (i_Count = 0; i_Count < 2; i_Count++) { for (i_Count = 0; i_Count < 2; i_Count++) {
pci_vendor = i_ADDIDATADeviceID[i_Count]; pci_vendor = i_ADDIDATADeviceID[i_Count];
if (pcidev->vendor == pci_vendor) { if (pcidev->vendor == pci_vendor) {

View File

@ -2541,7 +2541,43 @@ static struct comedi_driver driver_addi = {
.offset = sizeof(struct addi_board), .offset = sizeof(struct addi_board),
}; };
COMEDI_PCI_INITCLEANUP(driver_addi, addi_apci_tbl); static int __devinit driver_addi_pci_probe(struct pci_dev *dev,
const struct pci_device_id *ent)
{
return comedi_pci_auto_config(dev, driver_addi.driver_name);
}
static void __devexit driver_addi_pci_remove(struct pci_dev *dev)
{
comedi_pci_auto_unconfig(dev);
}
static struct pci_driver driver_addi_pci_driver = {
.id_table = addi_apci_tbl,
.probe = &driver_addi_pci_probe,
.remove = __devexit_p(&driver_addi_pci_remove)
};
static int __init driver_addi_init_module(void)
{
int retval;
retval = comedi_driver_register(&driver_addi);
if (retval < 0)
return retval;
driver_addi_pci_driver.name = (char *)driver_addi.driver_name;
return pci_register_driver(&driver_addi_pci_driver);
}
static void __exit driver_addi_cleanup_module(void)
{
pci_unregister_driver(&driver_addi_pci_driver);
comedi_driver_unregister(&driver_addi);
}
module_init(driver_addi_init_module);
module_exit(driver_addi_cleanup_module);
/* /*
+----------------------------------------------------------------------------+ +----------------------------------------------------------------------------+

View File

@ -101,10 +101,10 @@ struct str_TimerMainHeader {
}; };
typedef struct { struct str_AnalogOutputHeader {
unsigned short w_Nchannel; unsigned short w_Nchannel;
unsigned char b_Resolution; unsigned char b_Resolution;
} str_AnalogOutputHeader; };
struct str_AnalogInputHeader { struct str_AnalogInputHeader {
unsigned short w_Nchannel; unsigned short w_Nchannel;
@ -136,7 +136,7 @@ int i_EepromReadTimerHeader(unsigned short w_PCIBoardEepromAddress,
int i_EepromReadAnlogOutputHeader(unsigned short w_PCIBoardEepromAddress, int i_EepromReadAnlogOutputHeader(unsigned short w_PCIBoardEepromAddress,
char *pc_PCIChipInformation, unsigned short w_Address, char *pc_PCIChipInformation, unsigned short w_Address,
str_AnalogOutputHeader *s_Header); struct str_AnalogOutputHeader *s_Header);
int i_EepromReadAnlogInputHeader(unsigned short w_PCIBoardEepromAddress, int i_EepromReadAnlogInputHeader(unsigned short w_PCIBoardEepromAddress,
char *pc_PCIChipInformation, unsigned short w_Address, char *pc_PCIChipInformation, unsigned short w_Address,
@ -635,7 +635,7 @@ void v_EepromSendCommand76(unsigned int dw_Address, unsigned int dw_EepromComman
| Input Parameters : unsigned int dw_Address : PCI eeprom base address | | Input Parameters : unsigned int dw_Address : PCI eeprom base address |
| unsigned short w_offset : Offset of the adress to read | | unsigned short w_offset : Offset of the address to read |
| unsigned short * pw_Value : PCI eeprom 16 bit read value. | | unsigned short * pw_Value : PCI eeprom 16 bit read value. |
@ -811,7 +811,7 @@ int i_EepromReadMainHeader(unsigned short w_PCIBoardEepromAddress,
struct str_DigitalInputHeader s_DigitalInputHeader; struct str_DigitalInputHeader s_DigitalInputHeader;
struct str_DigitalOutputHeader s_DigitalOutputHeader; struct str_DigitalOutputHeader s_DigitalOutputHeader;
/* struct str_TimerMainHeader s_TimerMainHeader,s_WatchdogMainHeader; */ /* struct str_TimerMainHeader s_TimerMainHeader,s_WatchdogMainHeader; */
str_AnalogOutputHeader s_AnalogOutputHeader; struct str_AnalogOutputHeader s_AnalogOutputHeader;
struct str_AnalogInputHeader s_AnalogInputHeader; struct str_AnalogInputHeader s_AnalogInputHeader;
/* Read size */ /* Read size */
@ -1081,7 +1081,7 @@ int i_EepromReadTimerHeader(unsigned short w_PCIBoardEepromAddress,
int i_EepromReadAnlogOutputHeader(unsigned short w_PCIBoardEepromAddress, int i_EepromReadAnlogOutputHeader(unsigned short w_PCIBoardEepromAddress,
char *pc_PCIChipInformation, unsigned short w_Address, char *pc_PCIChipInformation, unsigned short w_Address,
str_AnalogOutputHeader *s_Header) struct str_AnalogOutputHeader *s_Header)
{ {
unsigned short w_Temp; unsigned short w_Temp;
/* No of channels for 1st hard component */ /* No of channels for 1st hard component */

View File

@ -1090,13 +1090,13 @@ int i_APCI3120_CyclicAnalogInput(int mode, struct comedi_device *dev,
* and put into into an array array used may be for differnet pages * and put into into an array array used may be for differnet pages
*/ */
/* DMA Start Adress Low */ /* DMA Start Address Low */
outw(APCI3120_ADD_ON_MWAR_LOW, devpriv->i_IobaseAddon + 0); outw(APCI3120_ADD_ON_MWAR_LOW, devpriv->i_IobaseAddon + 0);
outw((devpriv->ul_DmaBufferHw[0] & 0xFFFF), outw((devpriv->ul_DmaBufferHw[0] & 0xFFFF),
devpriv->i_IobaseAddon + 2); devpriv->i_IobaseAddon + 2);
/*************************/ /*************************/
/* DMA Start Adress High */ /* DMA Start Address High */
/*************************/ /*************************/
outw(APCI3120_ADD_ON_MWAR_HIGH, devpriv->i_IobaseAddon + 0); outw(APCI3120_ADD_ON_MWAR_HIGH, devpriv->i_IobaseAddon + 0);
outw((devpriv->ul_DmaBufferHw[0] / 65536), outw((devpriv->ul_DmaBufferHw[0] / 65536),
@ -1733,11 +1733,11 @@ void v_APCI3120_InterruptDma(int irq, void *d)
var = devpriv->ul_DmaBufferHw[next_dma_buf]; var = devpriv->ul_DmaBufferHw[next_dma_buf];
high_word = var / 65536; high_word = var / 65536;
/* DMA Start Adress Low */ /* DMA Start Address Low */
outw(APCI3120_ADD_ON_MWAR_LOW, devpriv->i_IobaseAddon + 0); outw(APCI3120_ADD_ON_MWAR_LOW, devpriv->i_IobaseAddon + 0);
outw(low_word, devpriv->i_IobaseAddon + 2); outw(low_word, devpriv->i_IobaseAddon + 2);
/* DMA Start Adress High */ /* DMA Start Address High */
outw(APCI3120_ADD_ON_MWAR_HIGH, devpriv->i_IobaseAddon + 0); outw(APCI3120_ADD_ON_MWAR_HIGH, devpriv->i_IobaseAddon + 0);
outw(high_word, devpriv->i_IobaseAddon + 2); outw(high_word, devpriv->i_IobaseAddon + 2);

View File

@ -5,3 +5,7 @@
#define ADDIDATA_DRIVER_NAME "addi_apci_035" #define ADDIDATA_DRIVER_NAME "addi_apci_035"
#include "addi-data/addi_common.c" #include "addi-data/addi_common.c"
MODULE_AUTHOR("Comedi http://www.comedi.org");
MODULE_DESCRIPTION("Comedi low-level driver");
MODULE_LICENSE("GPL");

View File

@ -3,3 +3,7 @@
#define ADDIDATA_DRIVER_NAME "addi_apci_1032" #define ADDIDATA_DRIVER_NAME "addi_apci_1032"
#include "addi-data/addi_common.c" #include "addi-data/addi_common.c"
MODULE_AUTHOR("Comedi http://www.comedi.org");
MODULE_DESCRIPTION("Comedi low-level driver");
MODULE_LICENSE("GPL");

View File

@ -3,3 +3,7 @@
#define ADDIDATA_DRIVER_NAME "addi_apci_1500" #define ADDIDATA_DRIVER_NAME "addi_apci_1500"
#include "addi-data/addi_common.c" #include "addi-data/addi_common.c"
MODULE_AUTHOR("Comedi http://www.comedi.org");
MODULE_DESCRIPTION("Comedi low-level driver");
MODULE_LICENSE("GPL");

View File

@ -3,3 +3,7 @@
#define ADDIDATA_DRIVER_NAME "addi_apci_1516" #define ADDIDATA_DRIVER_NAME "addi_apci_1516"
#include "addi-data/addi_common.c" #include "addi-data/addi_common.c"
MODULE_AUTHOR("Comedi http://www.comedi.org");
MODULE_DESCRIPTION("Comedi low-level driver");
MODULE_LICENSE("GPL");

View File

@ -3,3 +3,7 @@
#define ADDIDATA_DRIVER_NAME "addi_apci_1564" #define ADDIDATA_DRIVER_NAME "addi_apci_1564"
#include "addi-data/addi_common.c" #include "addi-data/addi_common.c"
MODULE_AUTHOR("Comedi http://www.comedi.org");
MODULE_DESCRIPTION("Comedi low-level driver");
MODULE_LICENSE("GPL");

View File

@ -3,3 +3,7 @@
#define ADDIDATA_DRIVER_NAME "addi_apci_16xx" #define ADDIDATA_DRIVER_NAME "addi_apci_16xx"
#include "addi-data/addi_common.c" #include "addi-data/addi_common.c"
MODULE_AUTHOR("Comedi http://www.comedi.org");
MODULE_DESCRIPTION("Comedi low-level driver");
MODULE_LICENSE("GPL");

View File

@ -3,3 +3,7 @@
#define ADDIDATA_DRIVER_NAME "addi_apci_2016" #define ADDIDATA_DRIVER_NAME "addi_apci_2016"
#include "addi-data/addi_common.c" #include "addi-data/addi_common.c"
MODULE_AUTHOR("Comedi http://www.comedi.org");
MODULE_DESCRIPTION("Comedi low-level driver");
MODULE_LICENSE("GPL");

View File

@ -3,3 +3,7 @@
#define ADDIDATA_DRIVER_NAME "addi_apci_2032" #define ADDIDATA_DRIVER_NAME "addi_apci_2032"
#include "addi-data/addi_common.c" #include "addi-data/addi_common.c"
MODULE_AUTHOR("Comedi http://www.comedi.org");
MODULE_DESCRIPTION("Comedi low-level driver");
MODULE_LICENSE("GPL");

View File

@ -3,3 +3,7 @@
#define ADDIDATA_DRIVER_NAME "addi_apci_2200" #define ADDIDATA_DRIVER_NAME "addi_apci_2200"
#include "addi-data/addi_common.c" #include "addi-data/addi_common.c"
MODULE_AUTHOR("Comedi http://www.comedi.org");
MODULE_DESCRIPTION("Comedi low-level driver");
MODULE_LICENSE("GPL");

View File

@ -3,3 +3,7 @@
#define ADDIDATA_DRIVER_NAME "addi_apci_3001" #define ADDIDATA_DRIVER_NAME "addi_apci_3001"
#include "addi-data/addi_common.c" #include "addi-data/addi_common.c"
MODULE_AUTHOR("Comedi http://www.comedi.org");
MODULE_DESCRIPTION("Comedi low-level driver");
MODULE_LICENSE("GPL");

View File

@ -3,3 +3,7 @@
#define ADDIDATA_DRIVER_NAME "addi_apci_3120" #define ADDIDATA_DRIVER_NAME "addi_apci_3120"
#include "addi-data/addi_common.c" #include "addi-data/addi_common.c"
MODULE_AUTHOR("Comedi http://www.comedi.org");
MODULE_DESCRIPTION("Comedi low-level driver");
MODULE_LICENSE("GPL");

View File

@ -3,3 +3,7 @@
#define ADDIDATA_DRIVER_NAME "addi_apci_3501" #define ADDIDATA_DRIVER_NAME "addi_apci_3501"
#include "addi-data/addi_common.c" #include "addi-data/addi_common.c"
MODULE_AUTHOR("Comedi http://www.comedi.org");
MODULE_DESCRIPTION("Comedi low-level driver");
MODULE_LICENSE("GPL");

View File

@ -3,3 +3,7 @@
#define ADDIDATA_DRIVER_NAME "addi_apci_3xxx" #define ADDIDATA_DRIVER_NAME "addi_apci_3xxx"
#include "addi-data/addi_common.c" #include "addi-data/addi_common.c"
MODULE_AUTHOR("Comedi http://www.comedi.org");
MODULE_DESCRIPTION("Comedi low-level driver");
MODULE_LICENSE("GPL");

View File

@ -119,7 +119,43 @@ static struct comedi_driver driver_pci6208 = {
.detach = pci6208_detach, .detach = pci6208_detach,
}; };
COMEDI_PCI_INITCLEANUP(driver_pci6208, pci6208_pci_table); static int __devinit driver_pci6208_pci_probe(struct pci_dev *dev,
const struct pci_device_id *ent)
{
return comedi_pci_auto_config(dev, driver_pci6208.driver_name);
}
static void __devexit driver_pci6208_pci_remove(struct pci_dev *dev)
{
comedi_pci_auto_unconfig(dev);
}
static struct pci_driver driver_pci6208_pci_driver = {
.id_table = pci6208_pci_table,
.probe = &driver_pci6208_pci_probe,
.remove = __devexit_p(&driver_pci6208_pci_remove)
};
static int __init driver_pci6208_init_module(void)
{
int retval;
retval = comedi_driver_register(&driver_pci6208);
if (retval < 0)
return retval;
driver_pci6208_pci_driver.name = (char *)driver_pci6208.driver_name;
return pci_register_driver(&driver_pci6208_pci_driver);
}
static void __exit driver_pci6208_cleanup_module(void)
{
pci_unregister_driver(&driver_pci6208_pci_driver);
comedi_driver_unregister(&driver_pci6208);
}
module_init(driver_pci6208_init_module);
module_exit(driver_pci6208_cleanup_module);
static int pci6208_find_device(struct comedi_device *dev, int bus, int slot); static int pci6208_find_device(struct comedi_device *dev, int bus, int slot);
static int static int
@ -315,12 +351,10 @@ static int pci6208_ao_rinsn(struct comedi_device *dev,
static int pci6208_find_device(struct comedi_device *dev, int bus, int slot) static int pci6208_find_device(struct comedi_device *dev, int bus, int slot)
{ {
struct pci_dev *pci_dev; struct pci_dev *pci_dev = NULL;
int i; int i;
for (pci_dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, NULL); for_each_pci_dev(pci_dev) {
pci_dev != NULL;
pci_dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pci_dev)) {
if (pci_dev->vendor == PCI_VENDOR_ID_ADLINK) { if (pci_dev->vendor == PCI_VENDOR_ID_ADLINK) {
for (i = 0; i < ARRAY_SIZE(pci6208_boards); i++) { for (i = 0; i < ARRAY_SIZE(pci6208_boards); i++) {
if (pci6208_boards[i].dev_id == if (pci6208_boards[i].dev_id ==
@ -408,3 +442,7 @@ pci6208_pci_setup(struct pci_dev *pci_dev, unsigned long *io_base_ptr,
return 0; return 0;
} }
MODULE_AUTHOR("Comedi http://www.comedi.org");
MODULE_DESCRIPTION("Comedi low-level driver");
MODULE_LICENSE("GPL");

View File

@ -90,7 +90,7 @@ static int adl_pci7230_do_insn_bits(struct comedi_device *dev,
static int adl_pci7230_attach(struct comedi_device *dev, static int adl_pci7230_attach(struct comedi_device *dev,
struct comedi_devconfig *it) struct comedi_devconfig *it)
{ {
struct pci_dev *pcidev; struct pci_dev *pcidev = NULL;
struct comedi_subdevice *s; struct comedi_subdevice *s;
int bus, slot; int bus, slot;
@ -106,10 +106,7 @@ static int adl_pci7230_attach(struct comedi_device *dev,
if (alloc_subdevices(dev, 2) < 0) if (alloc_subdevices(dev, 2) < 0)
return -ENOMEM; return -ENOMEM;
for (pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, NULL); for_each_pci_dev(pcidev) {
pcidev != NULL;
pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pcidev)) {
if (pcidev->vendor == PCI_VENDOR_ID_ADLINK && if (pcidev->vendor == PCI_VENDOR_ID_ADLINK &&
pcidev->device == PCI_DEVICE_ID_PCI7230) { pcidev->device == PCI_DEVICE_ID_PCI7230) {
if (bus || slot) { if (bus || slot) {
@ -203,4 +200,46 @@ static int adl_pci7230_di_insn_bits(struct comedi_device *dev,
return 2; return 2;
} }
COMEDI_PCI_INITCLEANUP(driver_adl_pci7230, adl_pci7230_pci_table); static int __devinit driver_adl_pci7230_pci_probe(struct pci_dev *dev,
const struct pci_device_id
*ent)
{
return comedi_pci_auto_config(dev, driver_adl_pci7230.driver_name);
}
static void __devexit driver_adl_pci7230_pci_remove(struct pci_dev *dev)
{
comedi_pci_auto_unconfig(dev);
}
static struct pci_driver driver_adl_pci7230_pci_driver = {
.id_table = adl_pci7230_pci_table,
.probe = &driver_adl_pci7230_pci_probe,
.remove = __devexit_p(&driver_adl_pci7230_pci_remove)
};
static int __init driver_adl_pci7230_init_module(void)
{
int retval;
retval = comedi_driver_register(&driver_adl_pci7230);
if (retval < 0)
return retval;
driver_adl_pci7230_pci_driver.name =
(char *)driver_adl_pci7230.driver_name;
return pci_register_driver(&driver_adl_pci7230_pci_driver);
}
static void __exit driver_adl_pci7230_cleanup_module(void)
{
pci_unregister_driver(&driver_adl_pci7230_pci_driver);
comedi_driver_unregister(&driver_adl_pci7230);
}
module_init(driver_adl_pci7230_init_module);
module_exit(driver_adl_pci7230_cleanup_module);
MODULE_AUTHOR("Comedi http://www.comedi.org");
MODULE_DESCRIPTION("Comedi low-level driver");
MODULE_LICENSE("GPL");

View File

@ -77,7 +77,7 @@ static struct comedi_driver driver_adl_pci7296 = {
static int adl_pci7296_attach(struct comedi_device *dev, static int adl_pci7296_attach(struct comedi_device *dev,
struct comedi_devconfig *it) struct comedi_devconfig *it)
{ {
struct pci_dev *pcidev; struct pci_dev *pcidev = NULL;
struct comedi_subdevice *s; struct comedi_subdevice *s;
int bus, slot; int bus, slot;
int ret; int ret;
@ -94,10 +94,7 @@ static int adl_pci7296_attach(struct comedi_device *dev,
if (alloc_subdevices(dev, 4) < 0) if (alloc_subdevices(dev, 4) < 0)
return -ENOMEM; return -ENOMEM;
for (pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, NULL); for_each_pci_dev(pcidev) {
pcidev != NULL;
pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pcidev)) {
if (pcidev->vendor == PCI_VENDOR_ID_ADLINK && if (pcidev->vendor == PCI_VENDOR_ID_ADLINK &&
pcidev->device == PCI_DEVICE_ID_PCI7296) { pcidev->device == PCI_DEVICE_ID_PCI7296) {
if (bus || slot) { if (bus || slot) {
@ -177,4 +174,46 @@ static int adl_pci7296_detach(struct comedi_device *dev)
return 0; return 0;
} }
COMEDI_PCI_INITCLEANUP(driver_adl_pci7296, adl_pci7296_pci_table); static int __devinit driver_adl_pci7296_pci_probe(struct pci_dev *dev,
const struct pci_device_id
*ent)
{
return comedi_pci_auto_config(dev, driver_adl_pci7296.driver_name);
}
static void __devexit driver_adl_pci7296_pci_remove(struct pci_dev *dev)
{
comedi_pci_auto_unconfig(dev);
}
static struct pci_driver driver_adl_pci7296_pci_driver = {
.id_table = adl_pci7296_pci_table,
.probe = &driver_adl_pci7296_pci_probe,
.remove = __devexit_p(&driver_adl_pci7296_pci_remove)
};
static int __init driver_adl_pci7296_init_module(void)
{
int retval;
retval = comedi_driver_register(&driver_adl_pci7296);
if (retval < 0)
return retval;
driver_adl_pci7296_pci_driver.name =
(char *)driver_adl_pci7296.driver_name;
return pci_register_driver(&driver_adl_pci7296_pci_driver);
}
static void __exit driver_adl_pci7296_cleanup_module(void)
{
pci_unregister_driver(&driver_adl_pci7296_pci_driver);
comedi_driver_unregister(&driver_adl_pci7296);
}
module_init(driver_adl_pci7296_init_module);
module_exit(driver_adl_pci7296_cleanup_module);
MODULE_AUTHOR("Comedi http://www.comedi.org");
MODULE_DESCRIPTION("Comedi low-level driver");
MODULE_LICENSE("GPL");

View File

@ -86,7 +86,7 @@ static int adl_pci7432_do_insn_bits(struct comedi_device *dev,
static int adl_pci7432_attach(struct comedi_device *dev, static int adl_pci7432_attach(struct comedi_device *dev,
struct comedi_devconfig *it) struct comedi_devconfig *it)
{ {
struct pci_dev *pcidev; struct pci_dev *pcidev = NULL;
struct comedi_subdevice *s; struct comedi_subdevice *s;
int bus, slot; int bus, slot;
@ -102,10 +102,7 @@ static int adl_pci7432_attach(struct comedi_device *dev,
if (alloc_subdevices(dev, 2) < 0) if (alloc_subdevices(dev, 2) < 0)
return -ENOMEM; return -ENOMEM;
for (pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, NULL); for_each_pci_dev(pcidev) {
pcidev != NULL;
pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pcidev)) {
if (pcidev->vendor == PCI_VENDOR_ID_ADLINK && if (pcidev->vendor == PCI_VENDOR_ID_ADLINK &&
pcidev->device == PCI_DEVICE_ID_PCI7432) { pcidev->device == PCI_DEVICE_ID_PCI7432) {
if (bus || slot) { if (bus || slot) {
@ -210,4 +207,46 @@ static int adl_pci7432_di_insn_bits(struct comedi_device *dev,
return 2; return 2;
} }
COMEDI_PCI_INITCLEANUP(driver_adl_pci7432, adl_pci7432_pci_table); static int __devinit driver_adl_pci7432_pci_probe(struct pci_dev *dev,
const struct pci_device_id
*ent)
{
return comedi_pci_auto_config(dev, driver_adl_pci7432.driver_name);
}
static void __devexit driver_adl_pci7432_pci_remove(struct pci_dev *dev)
{
comedi_pci_auto_unconfig(dev);
}
static struct pci_driver driver_adl_pci7432_pci_driver = {
.id_table = adl_pci7432_pci_table,
.probe = &driver_adl_pci7432_pci_probe,
.remove = __devexit_p(&driver_adl_pci7432_pci_remove)
};
static int __init driver_adl_pci7432_init_module(void)
{
int retval;
retval = comedi_driver_register(&driver_adl_pci7432);
if (retval < 0)
return retval;
driver_adl_pci7432_pci_driver.name =
(char *)driver_adl_pci7432.driver_name;
return pci_register_driver(&driver_adl_pci7432_pci_driver);
}
static void __exit driver_adl_pci7432_cleanup_module(void)
{
pci_unregister_driver(&driver_adl_pci7432_pci_driver);
comedi_driver_unregister(&driver_adl_pci7432);
}
module_init(driver_adl_pci7432_init_module);
module_exit(driver_adl_pci7432_cleanup_module);
MODULE_AUTHOR("Comedi http://www.comedi.org");
MODULE_DESCRIPTION("Comedi low-level driver");
MODULE_LICENSE("GPL");

View File

@ -125,7 +125,7 @@ static int adl_pci8164_insn_write_buf1(struct comedi_device *dev,
static int adl_pci8164_attach(struct comedi_device *dev, static int adl_pci8164_attach(struct comedi_device *dev,
struct comedi_devconfig *it) struct comedi_devconfig *it)
{ {
struct pci_dev *pcidev; struct pci_dev *pcidev = NULL;
struct comedi_subdevice *s; struct comedi_subdevice *s;
int bus, slot; int bus, slot;
@ -142,10 +142,7 @@ static int adl_pci8164_attach(struct comedi_device *dev,
if (alloc_subdevices(dev, 4) < 0) if (alloc_subdevices(dev, 4) < 0)
return -ENOMEM; return -ENOMEM;
for (pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, NULL); for_each_pci_dev(pcidev) {
pcidev != NULL;
pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pcidev)) {
if (pcidev->vendor == PCI_VENDOR_ID_ADLINK && if (pcidev->vendor == PCI_VENDOR_ID_ADLINK &&
pcidev->device == PCI_DEVICE_ID_PCI8164) { pcidev->device == PCI_DEVICE_ID_PCI8164) {
if (bus || slot) { if (bus || slot) {
@ -389,4 +386,46 @@ static int adl_pci8164_insn_write_buf1(struct comedi_device *dev,
return 2; return 2;
} }
COMEDI_PCI_INITCLEANUP(driver_adl_pci8164, adl_pci8164_pci_table); static int __devinit driver_adl_pci8164_pci_probe(struct pci_dev *dev,
const struct pci_device_id
*ent)
{
return comedi_pci_auto_config(dev, driver_adl_pci8164.driver_name);
}
static void __devexit driver_adl_pci8164_pci_remove(struct pci_dev *dev)
{
comedi_pci_auto_unconfig(dev);
}
static struct pci_driver driver_adl_pci8164_pci_driver = {
.id_table = adl_pci8164_pci_table,
.probe = &driver_adl_pci8164_pci_probe,
.remove = __devexit_p(&driver_adl_pci8164_pci_remove)
};
static int __init driver_adl_pci8164_init_module(void)
{
int retval;
retval = comedi_driver_register(&driver_adl_pci8164);
if (retval < 0)
return retval;
driver_adl_pci8164_pci_driver.name =
(char *)driver_adl_pci8164.driver_name;
return pci_register_driver(&driver_adl_pci8164_pci_driver);
}
static void __exit driver_adl_pci8164_cleanup_module(void)
{
pci_unregister_driver(&driver_adl_pci8164_pci_driver);
comedi_driver_unregister(&driver_adl_pci8164);
}
module_init(driver_adl_pci8164_init_module);
module_exit(driver_adl_pci8164_cleanup_module);
MODULE_AUTHOR("Comedi http://www.comedi.org");
MODULE_DESCRIPTION("Comedi low-level driver");
MODULE_LICENSE("GPL");

View File

@ -68,8 +68,9 @@ CHANGELOG:
TODO: TODO:
- Really test implemented functionality. - Really test implemented functionality.
- Add support for the PCI-9111DG with a probe routine to identify the card type - Add support for the PCI-9111DG with a probe routine to identify the card
(perhaps with the help of the channel number readback of the A/D Data register). type (perhaps with the help of the channel number readback of the A/D Data
register).
- Add external multiplexer support. - Add external multiplexer support.
*/ */
@ -134,11 +135,13 @@ TODO:
/* IO address map */ /* IO address map */
#define PCI9111_REGISTER_AD_FIFO_VALUE 0x00 /* AD Data stored in FIFO */ #define PCI9111_REGISTER_AD_FIFO_VALUE 0x00 /* AD Data stored
in FIFO */
#define PCI9111_REGISTER_DA_OUTPUT 0x00 #define PCI9111_REGISTER_DA_OUTPUT 0x00
#define PCI9111_REGISTER_DIGITAL_IO 0x02 #define PCI9111_REGISTER_DIGITAL_IO 0x02
#define PCI9111_REGISTER_EXTENDED_IO_PORTS 0x04 #define PCI9111_REGISTER_EXTENDED_IO_PORTS 0x04
#define PCI9111_REGISTER_AD_CHANNEL_CONTROL 0x06 /* Channel selection */ #define PCI9111_REGISTER_AD_CHANNEL_CONTROL 0x06 /* Channel
selection */
#define PCI9111_REGISTER_AD_CHANNEL_READBACK 0x06 #define PCI9111_REGISTER_AD_CHANNEL_READBACK 0x06
#define PCI9111_REGISTER_INPUT_SIGNAL_RANGE 0x08 #define PCI9111_REGISTER_INPUT_SIGNAL_RANGE 0x08
#define PCI9111_REGISTER_RANGE_STATUS_READBACK 0x08 #define PCI9111_REGISTER_RANGE_STATUS_READBACK 0x08
@ -177,7 +180,7 @@ TODO:
#define PCI9111_FIFO_FULL_MASK 0x40 #define PCI9111_FIFO_FULL_MASK 0x40
#define PCI9111_AD_BUSY_MASK 0x80 #define PCI9111_AD_BUSY_MASK 0x80
#define PCI9111_IO_BASE dev->iobase #define PCI9111_IO_BASE (dev->iobase)
/* /*
* Define inlined function * Define inlined function
@ -190,7 +193,8 @@ TODO:
outb(flags, PCI9111_IO_BASE+PCI9111_REGISTER_TRIGGER_MODE_CONTROL) outb(flags, PCI9111_IO_BASE+PCI9111_REGISTER_TRIGGER_MODE_CONTROL)
#define pci9111_interrupt_and_fifo_get() \ #define pci9111_interrupt_and_fifo_get() \
((inb(PCI9111_IO_BASE+PCI9111_REGISTER_AD_MODE_INTERRUPT_READBACK) >> 4) &0x03) ((inb(PCI9111_IO_BASE+PCI9111_REGISTER_AD_MODE_INTERRUPT_READBACK) >> 4) \
&0x03)
#define pci9111_interrupt_and_fifo_set(flags) \ #define pci9111_interrupt_and_fifo_set(flags) \
outb(flags, PCI9111_IO_BASE+PCI9111_REGISTER_INTERRUPT_CONTROL) outb(flags, PCI9111_IO_BASE+PCI9111_REGISTER_INTERRUPT_CONTROL)
@ -201,45 +205,56 @@ TODO:
#define pci9111_software_trigger() \ #define pci9111_software_trigger() \
outb(0, PCI9111_IO_BASE+PCI9111_REGISTER_SOFTWARE_TRIGGER) outb(0, PCI9111_IO_BASE+PCI9111_REGISTER_SOFTWARE_TRIGGER)
#define pci9111_fifo_reset() \ #define pci9111_fifo_reset() do { \
outb(PCI9111_FFEN_SET_FIFO_ENABLE, PCI9111_IO_BASE+PCI9111_REGISTER_INTERRUPT_CONTROL); \ outb(PCI9111_FFEN_SET_FIFO_ENABLE, \
outb(PCI9111_FFEN_SET_FIFO_DISABLE, PCI9111_IO_BASE+PCI9111_REGISTER_INTERRUPT_CONTROL); \ PCI9111_IO_BASE+PCI9111_REGISTER_INTERRUPT_CONTROL); \
outb(PCI9111_FFEN_SET_FIFO_ENABLE, PCI9111_IO_BASE+PCI9111_REGISTER_INTERRUPT_CONTROL) outb(PCI9111_FFEN_SET_FIFO_DISABLE, \
PCI9111_IO_BASE+PCI9111_REGISTER_INTERRUPT_CONTROL); \
outb(PCI9111_FFEN_SET_FIFO_ENABLE, \
PCI9111_IO_BASE+PCI9111_REGISTER_INTERRUPT_CONTROL); \
} while (0)
#define pci9111_is_fifo_full() \ #define pci9111_is_fifo_full() \
((inb(PCI9111_IO_BASE+PCI9111_REGISTER_RANGE_STATUS_READBACK)& \ ((inb(PCI9111_IO_BASE+PCI9111_REGISTER_RANGE_STATUS_READBACK)& \
PCI9111_FIFO_FULL_MASK)==0) PCI9111_FIFO_FULL_MASK) == 0)
#define pci9111_is_fifo_half_full() \ #define pci9111_is_fifo_half_full() \
((inb(PCI9111_IO_BASE+PCI9111_REGISTER_RANGE_STATUS_READBACK)& \ ((inb(PCI9111_IO_BASE+PCI9111_REGISTER_RANGE_STATUS_READBACK)& \
PCI9111_FIFO_HALF_FULL_MASK)==0) PCI9111_FIFO_HALF_FULL_MASK) == 0)
#define pci9111_is_fifo_empty() \ #define pci9111_is_fifo_empty() \
((inb(PCI9111_IO_BASE+PCI9111_REGISTER_RANGE_STATUS_READBACK)& \ ((inb(PCI9111_IO_BASE+PCI9111_REGISTER_RANGE_STATUS_READBACK)& \
PCI9111_FIFO_EMPTY_MASK)==0) PCI9111_FIFO_EMPTY_MASK) == 0)
#define pci9111_ai_channel_set(channel) \ #define pci9111_ai_channel_set(channel) \
outb((channel)&PCI9111_CHANNEL_MASK, PCI9111_IO_BASE+PCI9111_REGISTER_AD_CHANNEL_CONTROL) outb((channel)&PCI9111_CHANNEL_MASK, \
PCI9111_IO_BASE+PCI9111_REGISTER_AD_CHANNEL_CONTROL)
#define pci9111_ai_channel_get() \ #define pci9111_ai_channel_get() \
inb(PCI9111_IO_BASE+PCI9111_REGISTER_AD_CHANNEL_READBACK)&PCI9111_CHANNEL_MASK (inb(PCI9111_IO_BASE+PCI9111_REGISTER_AD_CHANNEL_READBACK) \
&PCI9111_CHANNEL_MASK)
#define pci9111_ai_range_set(range) \ #define pci9111_ai_range_set(range) \
outb((range)&PCI9111_RANGE_MASK, PCI9111_IO_BASE+PCI9111_REGISTER_INPUT_SIGNAL_RANGE) outb((range)&PCI9111_RANGE_MASK, \
PCI9111_IO_BASE+PCI9111_REGISTER_INPUT_SIGNAL_RANGE)
#define pci9111_ai_range_get() \ #define pci9111_ai_range_get() \
inb(PCI9111_IO_BASE+PCI9111_REGISTER_RANGE_STATUS_READBACK)&PCI9111_RANGE_MASK (inb(PCI9111_IO_BASE+PCI9111_REGISTER_RANGE_STATUS_READBACK) \
&PCI9111_RANGE_MASK)
#define pci9111_ai_get_data() \ #define pci9111_ai_get_data() \
((inw(PCI9111_IO_BASE+PCI9111_REGISTER_AD_FIFO_VALUE)>>4)&PCI9111_AI_RESOLUTION_MASK) \ (((inw(PCI9111_IO_BASE+PCI9111_REGISTER_AD_FIFO_VALUE)>>4) \
^ PCI9111_AI_RESOLUTION_2_CMP_BIT &PCI9111_AI_RESOLUTION_MASK) \
^ PCI9111_AI_RESOLUTION_2_CMP_BIT)
#define pci9111_hr_ai_get_data() \ #define pci9111_hr_ai_get_data() \
(inw(PCI9111_IO_BASE+PCI9111_REGISTER_AD_FIFO_VALUE) & PCI9111_HR_AI_RESOLUTION_MASK) \ ((inw(PCI9111_IO_BASE+PCI9111_REGISTER_AD_FIFO_VALUE) \
^ PCI9111_HR_AI_RESOLUTION_2_CMP_BIT & PCI9111_HR_AI_RESOLUTION_MASK) \
^ PCI9111_HR_AI_RESOLUTION_2_CMP_BIT)
#define pci9111_ao_set_data(data) \ #define pci9111_ao_set_data(data) \
outw(data&PCI9111_AO_RESOLUTION_MASK, PCI9111_IO_BASE+PCI9111_REGISTER_DA_OUTPUT) outw(data&PCI9111_AO_RESOLUTION_MASK, \
PCI9111_IO_BASE+PCI9111_REGISTER_DA_OUTPUT)
#define pci9111_di_get_bits() \ #define pci9111_di_get_bits() \
inw(PCI9111_IO_BASE+PCI9111_REGISTER_DIGITAL_IO) inw(PCI9111_IO_BASE+PCI9111_REGISTER_DIGITAL_IO)
@ -284,12 +299,11 @@ static const struct comedi_lrange pci9111_hr_ai_range = {
}; };
static DEFINE_PCI_DEVICE_TABLE(pci9111_pci_table) = { static DEFINE_PCI_DEVICE_TABLE(pci9111_pci_table) = {
{ { PCI_VENDOR_ID_ADLINK, PCI9111_HR_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,
PCI_VENDOR_ID_ADLINK, PCI9111_HR_DEVICE_ID, PCI_ANY_ID, 0, 0, 0 },
PCI_ANY_ID, 0, 0, 0}, /* { PCI_VENDOR_ID_ADLINK, PCI9111_HG_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,
/* { PCI_VENDOR_ID_ADLINK, PCI9111_HG_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, */ * 0, 0, 0 }, */
{ { 0 }
0}
}; };
MODULE_DEVICE_TABLE(pci, pci9111_pci_table); MODULE_DEVICE_TABLE(pci, pci9111_pci_table);
@ -337,7 +351,43 @@ static struct comedi_driver pci9111_driver = {
.detach = pci9111_detach, .detach = pci9111_detach,
}; };
COMEDI_PCI_INITCLEANUP(pci9111_driver, pci9111_pci_table); static int __devinit pci9111_driver_pci_probe(struct pci_dev *dev,
const struct pci_device_id *ent)
{
return comedi_pci_auto_config(dev, pci9111_driver.driver_name);
}
static void __devexit pci9111_driver_pci_remove(struct pci_dev *dev)
{
comedi_pci_auto_unconfig(dev);
}
static struct pci_driver pci9111_driver_pci_driver = {
.id_table = pci9111_pci_table,
.probe = &pci9111_driver_pci_probe,
.remove = __devexit_p(&pci9111_driver_pci_remove)
};
static int __init pci9111_driver_init_module(void)
{
int retval;
retval = comedi_driver_register(&pci9111_driver);
if (retval < 0)
return retval;
pci9111_driver_pci_driver.name = (char *)pci9111_driver.driver_name;
return pci_register_driver(&pci9111_driver_pci_driver);
}
static void __exit pci9111_driver_cleanup_module(void)
{
pci_unregister_driver(&pci9111_driver_pci_driver);
comedi_driver_unregister(&pci9111_driver);
}
module_init(pci9111_driver_init_module);
module_exit(pci9111_driver_cleanup_module);
/* Private data structure */ /* Private data structure */
@ -345,7 +395,8 @@ struct pci9111_private_data {
struct pci_dev *pci_device; struct pci_dev *pci_device;
unsigned long io_range; /* PCI6503 io range */ unsigned long io_range; /* PCI6503 io range */
unsigned long lcr_io_base; /* Local configuration register base address */ unsigned long lcr_io_base; /* Local configuration register base
* address */
unsigned long lcr_io_range; unsigned long lcr_io_range;
int stop_counter; int stop_counter;
@ -358,7 +409,8 @@ struct pci9111_private_data {
int ao_readback; /* Last written analog output data */ int ao_readback; /* Last written analog output data */
unsigned int timer_divisor_1; /* Divisor values for the 8254 timer pacer */ unsigned int timer_divisor_1; /* Divisor values for the 8254 timer
* pacer */
unsigned int timer_divisor_2; unsigned int timer_divisor_2;
int is_valid; /* Is device valid */ int is_valid; /* Is device valid */
@ -548,10 +600,12 @@ static int pci9111_ai_cancel(struct comedi_device *dev,
/* Test analog input command */ /* Test analog input command */
#define pci9111_check_trigger_src(src, flags) \ #define pci9111_check_trigger_src(src, flags) do { \
tmp = src; \ tmp = src; \
src &= flags; \ src &= flags; \
if (!src || tmp != src) error++ if (!src || tmp != src) \
error++; \
} while (false);
static int static int
pci9111_ai_do_cmd_test(struct comedi_device *dev, pci9111_ai_do_cmd_test(struct comedi_device *dev,
@ -575,7 +629,8 @@ pci9111_ai_do_cmd_test(struct comedi_device *dev,
if (error) if (error)
return 1; return 1;
/* step 2 : make sure trigger sources are unique and mutually compatible */ /* step 2 : make sure trigger sources are unique and mutually
* compatible */
if (cmd->start_src != TRIG_NOW) if (cmd->start_src != TRIG_NOW)
error++; error++;
@ -637,7 +692,8 @@ pci9111_ai_do_cmd_test(struct comedi_device *dev,
cmd->scan_begin_arg = board->ai_acquisition_period_min_ns; cmd->scan_begin_arg = board->ai_acquisition_period_min_ns;
error++; error++;
} }
if ((cmd->scan_begin_src == TRIG_FOLLOW) && (cmd->scan_begin_arg != 0)) { if ((cmd->scan_begin_src == TRIG_FOLLOW)
&& (cmd->scan_begin_arg != 0)) {
cmd->scan_begin_arg = 0; cmd->scan_begin_arg = 0;
error++; error++;
} }
@ -1216,7 +1272,7 @@ static int pci9111_attach(struct comedi_device *dev,
{ {
struct comedi_subdevice *subdevice; struct comedi_subdevice *subdevice;
unsigned long io_base, io_range, lcr_io_base, lcr_io_range; unsigned long io_base, io_range, lcr_io_base, lcr_io_range;
struct pci_dev *pci_device; struct pci_dev *pci_device = NULL;
int error, i; int error, i;
const struct pci9111_board *board; const struct pci9111_board *board;
@ -1226,17 +1282,17 @@ static int pci9111_attach(struct comedi_device *dev,
printk("comedi%d: " PCI9111_DRIVER_NAME " driver\n", dev->minor); printk("comedi%d: " PCI9111_DRIVER_NAME " driver\n", dev->minor);
for (pci_device = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, NULL); for_each_pci_dev(pci_device) {
pci_device != NULL;
pci_device = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pci_device)) {
if (pci_device->vendor == PCI_VENDOR_ID_ADLINK) { if (pci_device->vendor == PCI_VENDOR_ID_ADLINK) {
for (i = 0; i < pci9111_board_nbr; i++) { for (i = 0; i < pci9111_board_nbr; i++) {
if (pci9111_boards[i].device_id == if (pci9111_boards[i].device_id ==
pci_device->device) { pci_device->device) {
/* was a particular bus/slot requested? */ /* was a particular bus/slot
* requested? */
if ((it->options[0] != 0) if ((it->options[0] != 0)
|| (it->options[1] != 0)) { || (it->options[1] != 0)) {
/* are we on the wrong bus/slot? */ /* are we on the wrong
* bus/slot? */
if (pci_device->bus->number != if (pci_device->bus->number !=
it->options[0] it->options[0]
|| ||
@ -1272,7 +1328,8 @@ found:
/* TODO: Warn about non-tested boards. */ /* TODO: Warn about non-tested boards. */
/* Read local configuration register base address [PCI_BASE_ADDRESS #1]. */ /* Read local configuration register base address
* [PCI_BASE_ADDRESS #1]. */
lcr_io_base = pci_resource_start(pci_device, 1); lcr_io_base = pci_resource_start(pci_device, 1);
lcr_io_range = pci_resource_len(pci_device, 1); lcr_io_range = pci_resource_len(pci_device, 1);
@ -1399,3 +1456,7 @@ static int pci9111_detach(struct comedi_device *dev)
return 0; return 0;
} }
MODULE_AUTHOR("Comedi http://www.comedi.org");
MODULE_DESCRIPTION("Comedi low-level driver");
MODULE_LICENSE("GPL");

View File

@ -289,7 +289,43 @@ static struct comedi_driver driver_pci9118 = {
.offset = sizeof(struct boardtype), .offset = sizeof(struct boardtype),
}; };
COMEDI_PCI_INITCLEANUP(driver_pci9118, pci9118_pci_table); static int __devinit driver_pci9118_pci_probe(struct pci_dev *dev,
const struct pci_device_id *ent)
{
return comedi_pci_auto_config(dev, driver_pci9118.driver_name);
}
static void __devexit driver_pci9118_pci_remove(struct pci_dev *dev)
{
comedi_pci_auto_unconfig(dev);
}
static struct pci_driver driver_pci9118_pci_driver = {
.id_table = pci9118_pci_table,
.probe = &driver_pci9118_pci_probe,
.remove = __devexit_p(&driver_pci9118_pci_remove)
};
static int __init driver_pci9118_init_module(void)
{
int retval;
retval = comedi_driver_register(&driver_pci9118);
if (retval < 0)
return retval;
driver_pci9118_pci_driver.name = (char *)driver_pci9118.driver_name;
return pci_register_driver(&driver_pci9118_pci_driver);
}
static void __exit driver_pci9118_cleanup_module(void)
{
pci_unregister_driver(&driver_pci9118_pci_driver);
comedi_driver_unregister(&driver_pci9118);
}
module_init(driver_pci9118_init_module);
module_exit(driver_pci9118_cleanup_module);
struct pci9118_private { struct pci9118_private {
unsigned long iobase_a; /* base+size for AMCC chip */ unsigned long iobase_a; /* base+size for AMCC chip */
@ -2432,3 +2468,7 @@ static int pci9118_detach(struct comedi_device *dev)
/* /*
============================================================================== ==============================================================================
*/ */
MODULE_AUTHOR("Comedi http://www.comedi.org");
MODULE_DESCRIPTION("Comedi low-level driver");
MODULE_LICENSE("GPL");

View File

@ -402,4 +402,19 @@ static int adq12b_do_insn_bits(struct comedi_device *dev,
* A convenient macro that defines init_module() and cleanup_module(), * A convenient macro that defines init_module() and cleanup_module(),
* as necessary. * as necessary.
*/ */
COMEDI_INITCLEANUP(driver_adq12b); static int __init driver_adq12b_init_module(void)
{
return comedi_driver_register(&driver_adq12b);
}
static void __exit driver_adq12b_cleanup_module(void)
{
comedi_driver_unregister(&driver_adq12b);
}
module_init(driver_adq12b_init_module);
module_exit(driver_adq12b_cleanup_module);
MODULE_AUTHOR("Comedi http://www.comedi.org");
MODULE_DESCRIPTION("Comedi low-level driver");
MODULE_LICENSE("GPL");

View File

@ -50,7 +50,9 @@ Configuration options:
#include "8253.h" #include "8253.h"
#include "amcc_s5933.h" #include "amcc_s5933.h"
#define PCI171x_PARANOIDCHECK /* if defined, then is used code which control correct channel number on every 12 bit sample */ #define PCI171x_PARANOIDCHECK /* if defined, then is used code which control
* correct channel number on every 12 bit
* sample */
#undef PCI171X_EXTDEBUG #undef PCI171X_EXTDEBUG
@ -91,13 +93,15 @@ Configuration options:
#define PCI171x_CNT2 28 /* R/W: 8254 counter 2 */ #define PCI171x_CNT2 28 /* R/W: 8254 counter 2 */
#define PCI171x_CNTCTRL 30 /* W: 8254 counter control */ #define PCI171x_CNTCTRL 30 /* W: 8254 counter control */
/* upper bits from status register (PCI171x_STATUS) (lower is same woth control reg) */ /* upper bits from status register (PCI171x_STATUS) (lower is same with control
* reg) */
#define Status_FE 0x0100 /* 1=FIFO is empty */ #define Status_FE 0x0100 /* 1=FIFO is empty */
#define Status_FH 0x0200 /* 1=FIFO is half full */ #define Status_FH 0x0200 /* 1=FIFO is half full */
#define Status_FF 0x0400 /* 1=FIFO is full, fatal error */ #define Status_FF 0x0400 /* 1=FIFO is full, fatal error */
#define Status_IRQ 0x0800 /* 1=IRQ occured */ #define Status_IRQ 0x0800 /* 1=IRQ occured */
/* bits from control register (PCI171x_CONTROL) */ /* bits from control register (PCI171x_CONTROL) */
#define Control_CNT0 0x0040 /* 1=CNT0 have external source, 0=have internal 100kHz source */ #define Control_CNT0 0x0040 /* 1=CNT0 have external source,
* 0=have internal 100kHz source */
#define Control_ONEFH 0x0020 /* 1=IRQ on FIFO is half full, 0=every sample */ #define Control_ONEFH 0x0020 /* 1=IRQ on FIFO is half full, 0=every sample */
#define Control_IRQEN 0x0010 /* 1=enable IRQ */ #define Control_IRQEN 0x0010 /* 1=enable IRQ */
#define Control_GATE 0x0008 /* 1=enable external trigger GATE (8254?) */ #define Control_GATE 0x0008 /* 1=enable external trigger GATE (8254?) */
@ -112,7 +116,8 @@ Configuration options:
#define Counter_RW0 0x0010 /* RW0/RW1 select read/write mode */ #define Counter_RW0 0x0010 /* RW0/RW1 select read/write mode */
#define Counter_RW1 0x0020 #define Counter_RW1 0x0020
#define Counter_SC0 0x0040 /* Select Counter. Only 00 or 11 may */ #define Counter_SC0 0x0040 /* Select Counter. Only 00 or 11 may */
#define Counter_SC1 0x0080 /* be used, 00 for CNT0, 11 for read-back command */ #define Counter_SC1 0x0080 /* be used, 00 for CNT0,
* 11 for read-back command */
#define PCI1720_DA0 0 /* W: D/A register 0 */ #define PCI1720_DA0 0 /* W: D/A register 0 */
#define PCI1720_DA1 2 /* W: D/A register 1 */ #define PCI1720_DA1 2 /* W: D/A register 1 */
@ -138,8 +143,8 @@ static const struct comedi_lrange range_pci1710_3 = { 9, {
} }
}; };
static const char range_codes_pci1710_3[] = static const char range_codes_pci1710_3[] = { 0x00, 0x01, 0x02, 0x03, 0x04,
{ 0x00, 0x01, 0x02, 0x03, 0x04, 0x10, 0x11, 0x12, 0x13 }; 0x10, 0x11, 0x12, 0x13 };
static const struct comedi_lrange range_pci1710hg = { 12, { static const struct comedi_lrange range_pci1710hg = { 12, {
BIP_RANGE(5), BIP_RANGE(5),
@ -157,10 +162,9 @@ static const struct comedi_lrange range_pci1710hg = { 12, {
} }
}; };
static const char range_codes_pci1710hg[] = static const char range_codes_pci1710hg[] = { 0x00, 0x01, 0x02, 0x03, 0x04,
{ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x10, 0x11, 0x12, 0x05, 0x06, 0x07, 0x10, 0x11,
0x13 0x12, 0x13 };
};
static const struct comedi_lrange range_pci17x1 = { 5, { static const struct comedi_lrange range_pci17x1 = { 5, {
BIP_RANGE(10), BIP_RANGE(10),
@ -301,7 +305,8 @@ struct pci1710_private {
unsigned int ai_timer1; /* timers */ unsigned int ai_timer1; /* timers */
unsigned int ai_timer2; unsigned int ai_timer2;
short ao_data[4]; /* data output buffer */ short ao_data[4]; /* data output buffer */
unsigned int cnt0_write_wait; /* after a write, wait for update of the internal state */ unsigned int cnt0_write_wait; /* after a write, wait for update of the
* internal state */
}; };
#define devpriv ((struct pci1710_private *)dev->private) #define devpriv ((struct pci1710_private *)dev->private)
@ -324,7 +329,9 @@ static int pci1710_reset(struct comedi_device *dev);
static int pci171x_ai_cancel(struct comedi_device *dev, static int pci171x_ai_cancel(struct comedi_device *dev,
struct comedi_subdevice *s); struct comedi_subdevice *s);
static const unsigned int muxonechan[] = { 0x0000, 0x0101, 0x0202, 0x0303, 0x0404, 0x0505, 0x0606, 0x0707, /* used for gain list programming */ /* used for gain list programming */
static const unsigned int muxonechan[] = {
0x0000, 0x0101, 0x0202, 0x0303, 0x0404, 0x0505, 0x0606, 0x0707,
0x0808, 0x0909, 0x0a0a, 0x0b0b, 0x0c0c, 0x0d0d, 0x0e0e, 0x0f0f, 0x0808, 0x0909, 0x0a0a, 0x0b0b, 0x0c0c, 0x0d0d, 0x0e0e, 0x0f0f,
0x1010, 0x1111, 0x1212, 0x1313, 0x1414, 0x1515, 0x1616, 0x1717, 0x1010, 0x1111, 0x1212, 0x1313, 0x1414, 0x1515, 0x1616, 0x1717,
0x1818, 0x1919, 0x1a1a, 0x1b1b, 0x1c1c, 0x1d1d, 0x1e1e, 0x1f1f 0x1818, 0x1919, 0x1a1a, 0x1b1b, 0x1c1c, 0x1d1d, 0x1e1e, 0x1f1f
@ -774,7 +781,8 @@ static void interrupt_pci1710_half_fifo(void *d)
} }
if (!devpriv->neverending_ai) if (!devpriv->neverending_ai)
if (devpriv->ai_act_scan >= devpriv->ai_scans) { /* all data sampled */ if (devpriv->ai_act_scan >= devpriv->ai_scans) { /* all data
sampled */
pci171x_ai_cancel(dev, s); pci171x_ai_cancel(dev, s);
s->async->events |= COMEDI_CB_EOA; s->async->events |= COMEDI_CB_EOA;
comedi_event(dev, s); comedi_event(dev, s);
@ -1559,7 +1567,8 @@ static int pci1710_attach(struct comedi_device *dev,
s->maxdata = 1; s->maxdata = 1;
s->len_chanlist = this_board->n_dochan; s->len_chanlist = this_board->n_dochan;
s->range_table = &range_digital; s->range_table = &range_digital;
s->io_bits = (1 << this_board->n_dochan) - 1; /* all bits output */ /* all bits output */
s->io_bits = (1 << this_board->n_dochan) - 1;
s->state = 0; s->state = 0;
s->insn_bits = pci171x_insn_bits_do; s->insn_bits = pci171x_insn_bits_do;
subdev++; subdev++;
@ -1609,7 +1618,47 @@ static int pci1710_detach(struct comedi_device *dev)
/* /*
============================================================================== ==============================================================================
*/ */
COMEDI_PCI_INITCLEANUP(driver_pci1710, pci1710_pci_table); static int __devinit driver_pci1710_pci_probe(struct pci_dev *dev,
const struct pci_device_id *ent)
{
return comedi_pci_auto_config(dev, driver_pci1710.driver_name);
}
static void __devexit driver_pci1710_pci_remove(struct pci_dev *dev)
{
comedi_pci_auto_unconfig(dev);
}
static struct pci_driver driver_pci1710_pci_driver = {
.id_table = pci1710_pci_table,
.probe = &driver_pci1710_pci_probe,
.remove = __devexit_p(&driver_pci1710_pci_remove)
};
static int __init driver_pci1710_init_module(void)
{
int retval;
retval = comedi_driver_register(&driver_pci1710);
if (retval < 0)
return retval;
driver_pci1710_pci_driver.name = (char *)driver_pci1710.driver_name;
return pci_register_driver(&driver_pci1710_pci_driver);
}
static void __exit driver_pci1710_cleanup_module(void)
{
pci_unregister_driver(&driver_pci1710_pci_driver);
comedi_driver_unregister(&driver_pci1710);
}
module_init(driver_pci1710_init_module);
module_exit(driver_pci1710_cleanup_module);
/* /*
============================================================================== ==============================================================================
*/ */
MODULE_AUTHOR("Comedi http://www.comedi.org");
MODULE_DESCRIPTION("Comedi low-level driver");
MODULE_LICENSE("GPL");

View File

@ -496,4 +496,44 @@ static int pci1723_detach(struct comedi_device *dev)
* A convenient macro that defines init_module() and cleanup_module(), * A convenient macro that defines init_module() and cleanup_module(),
* as necessary. * as necessary.
*/ */
COMEDI_PCI_INITCLEANUP(driver_pci1723, pci1723_pci_table); static int __devinit driver_pci1723_pci_probe(struct pci_dev *dev,
const struct pci_device_id *ent)
{
return comedi_pci_auto_config(dev, driver_pci1723.driver_name);
}
static void __devexit driver_pci1723_pci_remove(struct pci_dev *dev)
{
comedi_pci_auto_unconfig(dev);
}
static struct pci_driver driver_pci1723_pci_driver = {
.id_table = pci1723_pci_table,
.probe = &driver_pci1723_pci_probe,
.remove = __devexit_p(&driver_pci1723_pci_remove)
};
static int __init driver_pci1723_init_module(void)
{
int retval;
retval = comedi_driver_register(&driver_pci1723);
if (retval < 0)
return retval;
driver_pci1723_pci_driver.name = (char *)driver_pci1723.driver_name;
return pci_register_driver(&driver_pci1723_pci_driver);
}
static void __exit driver_pci1723_cleanup_module(void)
{
pci_unregister_driver(&driver_pci1723_pci_driver);
comedi_driver_unregister(&driver_pci1723);
}
module_init(driver_pci1723_init_module);
module_exit(driver_pci1723_cleanup_module);
MODULE_AUTHOR("Comedi http://www.comedi.org");
MODULE_DESCRIPTION("Comedi low-level driver");
MODULE_LICENSE("GPL");

View File

@ -67,9 +67,12 @@ enum hw_io_access {
#define MAX_DI_SUBDEVS 2 /* max number of DI subdevices per card */ #define MAX_DI_SUBDEVS 2 /* max number of DI subdevices per card */
#define MAX_DO_SUBDEVS 2 /* max number of DO subdevices per card */ #define MAX_DO_SUBDEVS 2 /* max number of DO subdevices per card */
#define MAX_DIO_SUBDEVG 2 /* max number of DIO subdevices group per card */ #define MAX_DIO_SUBDEVG 2 /* max number of DIO subdevices group per
#define MAX_8254_SUBDEVS 1 /* max number of 8254 counter subdevs per card */ * card */
/* (could be more than one 8254 per subdevice) */ #define MAX_8254_SUBDEVS 1 /* max number of 8254 counter subdevs per
* card */
/* (could be more than one 8254 per
* subdevice) */
#define SIZE_8254 4 /* 8254 IO space length */ #define SIZE_8254 4 /* 8254 IO space length */
#define SIZE_8255 4 /* 8255 IO space length */ #define SIZE_8255 4 /* 8255 IO space length */
@ -84,7 +87,8 @@ enum hw_io_access {
#define PCI1730_DO 2 /* W: Digital output 0-15 */ #define PCI1730_DO 2 /* W: Digital output 0-15 */
#define PCI1733_IDI 0 /* R: Isolated digital input 0-31 */ #define PCI1733_IDI 0 /* R: Isolated digital input 0-31 */
#define PCI1730_3_INT_EN 0x08 /* R/W: enable/disable interrupts */ #define PCI1730_3_INT_EN 0x08 /* R/W: enable/disable interrupts */
#define PCI1730_3_INT_RF 0x0c /* R/W: set falling/raising edge for interrupts */ #define PCI1730_3_INT_RF 0x0c /* R/W: set falling/raising edge for
* interrupts */
#define PCI1730_3_INT_CLR 0x10 /* R/W: clear interrupts */ #define PCI1730_3_INT_CLR 0x10 /* R/W: clear interrupts */
#define PCI1734_IDO 0 /* W: Isolated digital output 0-31 */ #define PCI1734_IDO 0 /* W: Isolated digital output 0-31 */
#define PCI173x_BOARDID 4 /* R: Board I/D switch for 1730/3/4 */ #define PCI173x_BOARDID 4 /* R: Board I/D switch for 1730/3/4 */
@ -99,7 +103,8 @@ enum hw_io_access {
#define PCI1736_IDI 0 /* R: Isolated digital input 0-15 */ #define PCI1736_IDI 0 /* R: Isolated digital input 0-15 */
#define PCI1736_IDO 0 /* W: Isolated digital output 0-15 */ #define PCI1736_IDO 0 /* W: Isolated digital output 0-15 */
#define PCI1736_3_INT_EN 0x08 /* R/W: enable/disable interrupts */ #define PCI1736_3_INT_EN 0x08 /* R/W: enable/disable interrupts */
#define PCI1736_3_INT_RF 0x0c /* R/W: set falling/raising edge for interrupts */ #define PCI1736_3_INT_RF 0x0c /* R/W: set falling/raising edge for
* interrupts */
#define PCI1736_3_INT_CLR 0x10 /* R/W: clear interrupts */ #define PCI1736_3_INT_CLR 0x10 /* R/W: clear interrupts */
#define PCI1736_BOARDID 4 /* R: Board I/D switch for 1736UP */ #define PCI1736_BOARDID 4 /* R: Board I/D switch for 1736UP */
#define PCI1736_MAINREG 0 /* Normal register (2) doesn't work */ #define PCI1736_MAINREG 0 /* Normal register (2) doesn't work */
@ -161,37 +166,66 @@ enum hw_io_access {
#define INTCSR3 0x3b #define INTCSR3 0x3b
/* PCI-1760 mailbox commands */ /* PCI-1760 mailbox commands */
#define CMD_ClearIMB2 0x00 /* Clear IMB2 status and return actaul DI status in IMB3 */ #define CMD_ClearIMB2 0x00 /* Clear IMB2 status and return actual
* DI status in IMB3 */
#define CMD_SetRelaysOutput 0x01 /* Set relay output from OMB0 */ #define CMD_SetRelaysOutput 0x01 /* Set relay output from OMB0 */
#define CMD_GetRelaysStatus 0x02 /* Get relay status to IMB0 */ #define CMD_GetRelaysStatus 0x02 /* Get relay status to IMB0 */
#define CMD_ReadCurrentStatus 0x07 /* Read the current status of the register in OMB0, result in IMB0 */ #define CMD_ReadCurrentStatus 0x07 /* Read the current status of the
#define CMD_ReadFirmwareVersion 0x0e /* Read the firmware ver., result in IMB1.IMB0 */ * register in OMB0, result in IMB0 */
#define CMD_ReadHardwareVersion 0x0f /* Read the hardware ver., result in IMB1.IMB0 */ #define CMD_ReadFirmwareVersion 0x0e /* Read the firmware ver., result in
#define CMD_EnableIDIFilters 0x20 /* Enable IDI filters based on bits in OMB0 */ * IMB1.IMB0 */
#define CMD_EnableIDIPatternMatch 0x21 /* Enable IDI pattern match based on bits in OMB0 */ #define CMD_ReadHardwareVersion 0x0f /* Read the hardware ver., result in
#define CMD_SetIDIPatternMatch 0x22 /* Enable IDI pattern match based on bits in OMB0 */ * IMB1.IMB0 */
#define CMD_EnableIDICounters 0x28 /* Enable IDI counters based on bits in OMB0 */ #define CMD_EnableIDIFilters 0x20 /* Enable IDI filters based on bits in
#define CMD_ResetIDICounters 0x29 /* Reset IDI counters based on bits in OMB0 to its reset values */ * OMB0 */
#define CMD_OverflowIDICounters 0x2a /* Enable IDI counters overflow interrupts based on bits in OMB0 */ #define CMD_EnableIDIPatternMatch 0x21 /* Enable IDI pattern match based on
#define CMD_MatchIntIDICounters 0x2b /* Enable IDI counters match value interrupts based on bits in OMB0 */ * bits in OMB0 */
#define CMD_EdgeIDICounters 0x2c /* Set IDI up counters count edge (bit=0 - rising, =1 - falling) */ #define CMD_SetIDIPatternMatch 0x22 /* Enable IDI pattern match based on
#define CMD_GetIDICntCurValue 0x2f /* Read IDI{OMB0} up counter current value */ * bits in OMB0 */
#define CMD_SetIDI0CntResetValue 0x40 /* Set IDI0 Counter Reset Value 256*OMB1+OMB0 */ #define CMD_EnableIDICounters 0x28 /* Enable IDI counters based on bits in
#define CMD_SetIDI1CntResetValue 0x41 /* Set IDI1 Counter Reset Value 256*OMB1+OMB0 */ * OMB0 */
#define CMD_SetIDI2CntResetValue 0x42 /* Set IDI2 Counter Reset Value 256*OMB1+OMB0 */ #define CMD_ResetIDICounters 0x29 /* Reset IDI counters based on bits in
#define CMD_SetIDI3CntResetValue 0x43 /* Set IDI3 Counter Reset Value 256*OMB1+OMB0 */ * OMB0 to its reset values */
#define CMD_SetIDI4CntResetValue 0x44 /* Set IDI4 Counter Reset Value 256*OMB1+OMB0 */ #define CMD_OverflowIDICounters 0x2a /* Enable IDI counters overflow
#define CMD_SetIDI5CntResetValue 0x45 /* Set IDI5 Counter Reset Value 256*OMB1+OMB0 */ * interrupts based on bits in OMB0 */
#define CMD_SetIDI6CntResetValue 0x46 /* Set IDI6 Counter Reset Value 256*OMB1+OMB0 */ #define CMD_MatchIntIDICounters 0x2b /* Enable IDI counters match value
#define CMD_SetIDI7CntResetValue 0x47 /* Set IDI7 Counter Reset Value 256*OMB1+OMB0 */ * interrupts based on bits in OMB0 */
#define CMD_SetIDI0CntMatchValue 0x48 /* Set IDI0 Counter Match Value 256*OMB1+OMB0 */ #define CMD_EdgeIDICounters 0x2c /* Set IDI up counters count edge (bit=0
#define CMD_SetIDI1CntMatchValue 0x49 /* Set IDI1 Counter Match Value 256*OMB1+OMB0 */ * - rising, =1 - falling) */
#define CMD_SetIDI2CntMatchValue 0x4a /* Set IDI2 Counter Match Value 256*OMB1+OMB0 */ #define CMD_GetIDICntCurValue 0x2f /* Read IDI{OMB0} up counter current
#define CMD_SetIDI3CntMatchValue 0x4b /* Set IDI3 Counter Match Value 256*OMB1+OMB0 */ * value */
#define CMD_SetIDI4CntMatchValue 0x4c /* Set IDI4 Counter Match Value 256*OMB1+OMB0 */ #define CMD_SetIDI0CntResetValue 0x40 /* Set IDI0 Counter Reset Value
#define CMD_SetIDI5CntMatchValue 0x4d /* Set IDI5 Counter Match Value 256*OMB1+OMB0 */ * 256*OMB1+OMB0 */
#define CMD_SetIDI6CntMatchValue 0x4e /* Set IDI6 Counter Match Value 256*OMB1+OMB0 */ #define CMD_SetIDI1CntResetValue 0x41 /* Set IDI1 Counter Reset Value
#define CMD_SetIDI7CntMatchValue 0x4f /* Set IDI7 Counter Match Value 256*OMB1+OMB0 */ * 256*OMB1+OMB0 */
#define CMD_SetIDI2CntResetValue 0x42 /* Set IDI2 Counter Reset Value
* 256*OMB1+OMB0 */
#define CMD_SetIDI3CntResetValue 0x43 /* Set IDI3 Counter Reset Value
* 256*OMB1+OMB0 */
#define CMD_SetIDI4CntResetValue 0x44 /* Set IDI4 Counter Reset Value
* 256*OMB1+OMB0 */
#define CMD_SetIDI5CntResetValue 0x45 /* Set IDI5 Counter Reset Value
* 256*OMB1+OMB0 */
#define CMD_SetIDI6CntResetValue 0x46 /* Set IDI6 Counter Reset Value
* 256*OMB1+OMB0 */
#define CMD_SetIDI7CntResetValue 0x47 /* Set IDI7 Counter Reset Value
* 256*OMB1+OMB0 */
#define CMD_SetIDI0CntMatchValue 0x48 /* Set IDI0 Counter Match Value
* 256*OMB1+OMB0 */
#define CMD_SetIDI1CntMatchValue 0x49 /* Set IDI1 Counter Match Value
* 256*OMB1+OMB0 */
#define CMD_SetIDI2CntMatchValue 0x4a /* Set IDI2 Counter Match Value
* 256*OMB1+OMB0 */
#define CMD_SetIDI3CntMatchValue 0x4b /* Set IDI3 Counter Match Value
* 256*OMB1+OMB0 */
#define CMD_SetIDI4CntMatchValue 0x4c /* Set IDI4 Counter Match Value
* 256*OMB1+OMB0 */
#define CMD_SetIDI5CntMatchValue 0x4d /* Set IDI5 Counter Match Value
* 256*OMB1+OMB0 */
#define CMD_SetIDI6CntMatchValue 0x4e /* Set IDI6 Counter Match Value
* 256*OMB1+OMB0 */
#define CMD_SetIDI7CntMatchValue 0x4f /* Set IDI7 Counter Match Value
* 256*OMB1+OMB0 */
#define OMBCMD_RETRY 0x03 /* 3 times try request before error */ #define OMBCMD_RETRY 0x03 /* 3 times try request before error */
@ -244,115 +278,115 @@ MODULE_DEVICE_TABLE(pci, pci_dio_pci_table);
static const struct dio_boardtype boardtypes[] = { static const struct dio_boardtype boardtypes[] = {
{"pci1730", PCI_VENDOR_ID_ADVANTECH, 0x1730, PCIDIO_MAINREG, {"pci1730", PCI_VENDOR_ID_ADVANTECH, 0x1730, PCIDIO_MAINREG,
TYPE_PCI1730, TYPE_PCI1730,
{{16, PCI1730_DI, 2, 0}, {16, PCI1730_IDI, 2, 0}}, { {16, PCI1730_DI, 2, 0}, {16, PCI1730_IDI, 2, 0} },
{{16, PCI1730_DO, 2, 0}, {16, PCI1730_IDO, 2, 0}}, { {16, PCI1730_DO, 2, 0}, {16, PCI1730_IDO, 2, 0} },
{{0, 0, 0, 0}, {0, 0, 0, 0}}, { {0, 0, 0, 0}, {0, 0, 0, 0} },
{4, PCI173x_BOARDID, 1, SDF_INTERNAL}, {4, PCI173x_BOARDID, 1, SDF_INTERNAL},
{{0, 0, 0, 0}}, { {0, 0, 0, 0} },
IO_8b}, IO_8b},
{"pci1733", PCI_VENDOR_ID_ADVANTECH, 0x1733, PCIDIO_MAINREG, {"pci1733", PCI_VENDOR_ID_ADVANTECH, 0x1733, PCIDIO_MAINREG,
TYPE_PCI1733, TYPE_PCI1733,
{{0, 0, 0, 0}, {32, PCI1733_IDI, 4, 0}}, { {0, 0, 0, 0}, {32, PCI1733_IDI, 4, 0} },
{{0, 0, 0, 0}, {0, 0, 0, 0}}, { {0, 0, 0, 0}, {0, 0, 0, 0} },
{{0, 0, 0, 0}, {0, 0, 0, 0}}, { {0, 0, 0, 0}, {0, 0, 0, 0} },
{4, PCI173x_BOARDID, 1, SDF_INTERNAL}, {4, PCI173x_BOARDID, 1, SDF_INTERNAL},
{{0, 0, 0, 0}}, { {0, 0, 0, 0} },
IO_8b}, IO_8b},
{"pci1734", PCI_VENDOR_ID_ADVANTECH, 0x1734, PCIDIO_MAINREG, {"pci1734", PCI_VENDOR_ID_ADVANTECH, 0x1734, PCIDIO_MAINREG,
TYPE_PCI1734, TYPE_PCI1734,
{{0, 0, 0, 0}, {0, 0, 0, 0}}, { {0, 0, 0, 0}, {0, 0, 0, 0} },
{{0, 0, 0, 0}, {32, PCI1734_IDO, 4, 0}}, { {0, 0, 0, 0}, {32, PCI1734_IDO, 4, 0} },
{{0, 0, 0, 0}, {0, 0, 0, 0}}, { {0, 0, 0, 0}, {0, 0, 0, 0} },
{4, PCI173x_BOARDID, 1, SDF_INTERNAL}, {4, PCI173x_BOARDID, 1, SDF_INTERNAL},
{{0, 0, 0, 0}}, { {0, 0, 0, 0} },
IO_8b}, IO_8b},
{"pci1735", PCI_VENDOR_ID_ADVANTECH, 0x1735, PCIDIO_MAINREG, {"pci1735", PCI_VENDOR_ID_ADVANTECH, 0x1735, PCIDIO_MAINREG,
TYPE_PCI1735, TYPE_PCI1735,
{{32, PCI1735_DI, 4, 0}, {0, 0, 0, 0}}, { {32, PCI1735_DI, 4, 0}, {0, 0, 0, 0} },
{{32, PCI1735_DO, 4, 0}, {0, 0, 0, 0}}, { {32, PCI1735_DO, 4, 0}, {0, 0, 0, 0} },
{{0, 0, 0, 0}, {0, 0, 0, 0}}, { {0, 0, 0, 0}, {0, 0, 0, 0} },
{ 4, PCI1735_BOARDID, 1, SDF_INTERNAL}, { 4, PCI1735_BOARDID, 1, SDF_INTERNAL},
{{3, PCI1735_C8254, 1, 0}}, { {3, PCI1735_C8254, 1, 0} },
IO_8b}, IO_8b},
{"pci1736", PCI_VENDOR_ID_ADVANTECH, 0x1736, PCI1736_MAINREG, {"pci1736", PCI_VENDOR_ID_ADVANTECH, 0x1736, PCI1736_MAINREG,
TYPE_PCI1736, TYPE_PCI1736,
{{0, 0, 0, 0}, {16, PCI1736_IDI, 2, 0}}, { {0, 0, 0, 0}, {16, PCI1736_IDI, 2, 0} },
{{0, 0, 0, 0}, {16, PCI1736_IDO, 2, 0}}, { {0, 0, 0, 0}, {16, PCI1736_IDO, 2, 0} },
{{0, 0, 0, 0}, {0, 0, 0, 0}}, { {0, 0, 0, 0}, {0, 0, 0, 0} },
{4, PCI1736_BOARDID, 1, SDF_INTERNAL}, {4, PCI1736_BOARDID, 1, SDF_INTERNAL},
{{0, 0, 0, 0}}, { {0, 0, 0, 0} },
IO_8b}, IO_8b},
{"pci1750", PCI_VENDOR_ID_ADVANTECH, 0x1750, PCIDIO_MAINREG, {"pci1750", PCI_VENDOR_ID_ADVANTECH, 0x1750, PCIDIO_MAINREG,
TYPE_PCI1750, TYPE_PCI1750,
{{0, 0, 0, 0}, {16, PCI1750_IDI, 2, 0}}, { {0, 0, 0, 0}, {16, PCI1750_IDI, 2, 0} },
{{0, 0, 0, 0}, {16, PCI1750_IDO, 2, 0}}, { {0, 0, 0, 0}, {16, PCI1750_IDO, 2, 0} },
{{0, 0, 0, 0}, {0, 0, 0, 0}}, { {0, 0, 0, 0}, {0, 0, 0, 0} },
{0, 0, 0, 0}, {0, 0, 0, 0},
{{0, 0, 0, 0}}, { {0, 0, 0, 0} },
IO_8b}, IO_8b},
{"pci1751", PCI_VENDOR_ID_ADVANTECH, 0x1751, PCIDIO_MAINREG, {"pci1751", PCI_VENDOR_ID_ADVANTECH, 0x1751, PCIDIO_MAINREG,
TYPE_PCI1751, TYPE_PCI1751,
{{0, 0, 0, 0}, {0, 0, 0, 0}}, { {0, 0, 0, 0}, {0, 0, 0, 0} },
{{0, 0, 0, 0}, {0, 0, 0, 0}}, { {0, 0, 0, 0}, {0, 0, 0, 0} },
{{48, PCI1751_DIO, 2, 0}, {0, 0, 0, 0}}, { {48, PCI1751_DIO, 2, 0}, {0, 0, 0, 0} },
{0, 0, 0, 0}, {0, 0, 0, 0},
{{0, 0, 0, 0}}, { {0, 0, 0, 0} },
IO_8b}, IO_8b},
{"pci1752", PCI_VENDOR_ID_ADVANTECH, 0x1752, PCIDIO_MAINREG, {"pci1752", PCI_VENDOR_ID_ADVANTECH, 0x1752, PCIDIO_MAINREG,
TYPE_PCI1752, TYPE_PCI1752,
{{0, 0, 0, 0}, {0, 0, 0, 0}}, { {0, 0, 0, 0}, {0, 0, 0, 0} },
{{32, PCI1752_IDO, 2, 0}, {32, PCI1752_IDO2, 2, 0}}, { {32, PCI1752_IDO, 2, 0}, {32, PCI1752_IDO2, 2, 0} },
{{0, 0, 0, 0}, {0, 0, 0, 0}}, { {0, 0, 0, 0}, {0, 0, 0, 0} },
{4, PCI175x_BOARDID, 1, SDF_INTERNAL}, {4, PCI175x_BOARDID, 1, SDF_INTERNAL},
{{0, 0, 0, 0}}, { {0, 0, 0, 0} },
IO_16b}, IO_16b},
{"pci1753", PCI_VENDOR_ID_ADVANTECH, 0x1753, PCIDIO_MAINREG, {"pci1753", PCI_VENDOR_ID_ADVANTECH, 0x1753, PCIDIO_MAINREG,
TYPE_PCI1753, TYPE_PCI1753,
{{0, 0, 0, 0}, {0, 0, 0, 0}}, { {0, 0, 0, 0}, {0, 0, 0, 0} },
{{0, 0, 0, 0}, {0, 0, 0, 0}}, { {0, 0, 0, 0}, {0, 0, 0, 0} },
{{96, PCI1753_DIO, 4, 0}, {0, 0, 0, 0}}, { {96, PCI1753_DIO, 4, 0}, {0, 0, 0, 0} },
{0, 0, 0, 0}, {0, 0, 0, 0},
{{0, 0, 0, 0}}, { {0, 0, 0, 0} },
IO_8b}, IO_8b},
{"pci1753e", PCI_VENDOR_ID_ADVANTECH, 0x1753, PCIDIO_MAINREG, {"pci1753e", PCI_VENDOR_ID_ADVANTECH, 0x1753, PCIDIO_MAINREG,
TYPE_PCI1753E, TYPE_PCI1753E,
{{0, 0, 0, 0}, {0, 0, 0, 0}}, { {0, 0, 0, 0}, {0, 0, 0, 0} },
{{0, 0, 0, 0}, {0, 0, 0, 0}}, { {0, 0, 0, 0}, {0, 0, 0, 0} },
{{96, PCI1753_DIO, 4, 0}, {96, PCI1753E_DIO, 4, 0}}, { {96, PCI1753_DIO, 4, 0}, {96, PCI1753E_DIO, 4, 0} },
{0, 0, 0, 0}, {0, 0, 0, 0},
{{0, 0, 0, 0}}, { {0, 0, 0, 0} },
IO_8b}, IO_8b},
{"pci1754", PCI_VENDOR_ID_ADVANTECH, 0x1754, PCIDIO_MAINREG, {"pci1754", PCI_VENDOR_ID_ADVANTECH, 0x1754, PCIDIO_MAINREG,
TYPE_PCI1754, TYPE_PCI1754,
{{32, PCI1754_IDI, 2, 0}, {32, PCI1754_IDI2, 2, 0}}, { {32, PCI1754_IDI, 2, 0}, {32, PCI1754_IDI2, 2, 0} },
{{0, 0, 0, 0}, {0, 0, 0, 0}}, { {0, 0, 0, 0}, {0, 0, 0, 0} },
{{0, 0, 0, 0}, {0, 0, 0, 0}}, { {0, 0, 0, 0}, {0, 0, 0, 0} },
{4, PCI175x_BOARDID, 1, SDF_INTERNAL}, {4, PCI175x_BOARDID, 1, SDF_INTERNAL},
{{0, 0, 0, 0}}, { {0, 0, 0, 0} },
IO_16b}, IO_16b},
{"pci1756", PCI_VENDOR_ID_ADVANTECH, 0x1756, PCIDIO_MAINREG, {"pci1756", PCI_VENDOR_ID_ADVANTECH, 0x1756, PCIDIO_MAINREG,
TYPE_PCI1756, TYPE_PCI1756,
{{0, 0, 0, 0}, {32, PCI1756_IDI, 2, 0}}, { {0, 0, 0, 0}, {32, PCI1756_IDI, 2, 0} },
{{0, 0, 0, 0}, {32, PCI1756_IDO, 2, 0}}, { {0, 0, 0, 0}, {32, PCI1756_IDO, 2, 0} },
{{0, 0, 0, 0}, {0, 0, 0, 0}}, { {0, 0, 0, 0}, {0, 0, 0, 0} },
{4, PCI175x_BOARDID, 1, SDF_INTERNAL}, {4, PCI175x_BOARDID, 1, SDF_INTERNAL},
{{0, 0, 0, 0}}, { {0, 0, 0, 0} },
IO_16b}, IO_16b},
{"pci1760", PCI_VENDOR_ID_ADVANTECH, 0x1760, 0, {"pci1760", PCI_VENDOR_ID_ADVANTECH, 0x1760, 0,
TYPE_PCI1760, TYPE_PCI1760,
{{0, 0, 0, 0}, {0, 0, 0, 0}}, /* This card have own setup work */ { {0, 0, 0, 0}, {0, 0, 0, 0} }, /* This card have own setup work */
{{0, 0, 0, 0}, {0, 0, 0, 0}}, { {0, 0, 0, 0}, {0, 0, 0, 0} },
{{0, 0, 0, 0}, {0, 0, 0, 0}}, { {0, 0, 0, 0}, {0, 0, 0, 0} },
{0, 0, 0, 0}, {0, 0, 0, 0},
{{0, 0, 0, 0}}, { {0, 0, 0, 0} },
IO_8b}, IO_8b},
{"pci1762", PCI_VENDOR_ID_ADVANTECH, 0x1762, PCIDIO_MAINREG, {"pci1762", PCI_VENDOR_ID_ADVANTECH, 0x1762, PCIDIO_MAINREG,
TYPE_PCI1762, TYPE_PCI1762,
{{0, 0, 0, 0}, {16, PCI1762_IDI, 1, 0}}, { {0, 0, 0, 0}, {16, PCI1762_IDI, 1, 0} },
{{0, 0, 0, 0}, {16, PCI1762_RO, 1, 0}}, { {0, 0, 0, 0}, {16, PCI1762_RO, 1, 0} },
{{0, 0, 0, 0}, {0, 0, 0, 0}}, { {0, 0, 0, 0}, {0, 0, 0, 0} },
{4, PCI1762_BOARDID, 1, SDF_INTERNAL}, {4, PCI1762_BOARDID, 1, SDF_INTERNAL},
{{0, 0, 0, 0}}, { {0, 0, 0, 0} },
IO_16b} IO_16b}
}; };
@ -373,9 +407,12 @@ struct pci_dio_private {
char GlobalIrqEnabled; /* 1= any IRQ source is enabled */ char GlobalIrqEnabled; /* 1= any IRQ source is enabled */
/* PCI-1760 specific data */ /* PCI-1760 specific data */
unsigned char IDICntEnable; /* counter's counting enable status */ unsigned char IDICntEnable; /* counter's counting enable status */
unsigned char IDICntOverEnable; /* counter's overflow interrupts enable status */ unsigned char IDICntOverEnable; /* counter's overflow interrupts enable
unsigned char IDICntMatchEnable; /* counter's match interrupts enable status */ * status */
unsigned char IDICntEdge; /* counter's count edge value (bit=0 - rising, =1 - falling) */ unsigned char IDICntMatchEnable; /* counter's match interrupts
* enable status */
unsigned char IDICntEdge; /* counter's count edge value
* (bit=0 - rising, =1 - falling) */
unsigned short CntResValue[8]; /* counters' reset value */ unsigned short CntResValue[8]; /* counters' reset value */
unsigned short CntMatchValue[8]; /* counters' match interrupt value */ unsigned short CntMatchValue[8]; /* counters' match interrupt value */
unsigned char IDIFiltersEn; /* IDI's digital filters enable status */ unsigned char IDIFiltersEn; /* IDI's digital filters enable status */
@ -691,7 +728,8 @@ static int pci1760_insn_cnt_write(struct comedi_device *dev,
}; };
unsigned char imb[4]; unsigned char imb[4];
if (devpriv->CntResValue[chan] != (data[0] & 0xffff)) { /* Set reset value if different */ /* Set reset value if different */
if (devpriv->CntResValue[chan] != (data[0] & 0xffff)) {
ret = pci1760_mbxrequest(dev, omb, imb); ret = pci1760_mbxrequest(dev, omb, imb);
if (!ret) if (!ret)
return ret; return ret;
@ -704,7 +742,8 @@ static int pci1760_insn_cnt_write(struct comedi_device *dev,
if (!ret) if (!ret)
return ret; return ret;
if (!(bitmask & devpriv->IDICntEnable)) { /* start counter if it don't run */ /* start counter if it don't run */
if (!(bitmask & devpriv->IDICntEnable)) {
omb[0] = bitmask; omb[0] = bitmask;
omb[2] = CMD_EnableIDICounters; omb[2] = CMD_EnableIDICounters;
ret = pci1760_mbxrequest(dev, omb, imb); ret = pci1760_mbxrequest(dev, omb, imb);
@ -740,12 +779,14 @@ static int pci1760_reset(struct comedi_device *dev)
devpriv->IDICntEnable = 0; devpriv->IDICntEnable = 0;
omb[0] = 0x00; omb[0] = 0x00;
omb[2] = CMD_OverflowIDICounters; /* disable counters overflow interrupts */ omb[2] = CMD_OverflowIDICounters; /* disable counters overflow
* interrupts */
pci1760_mbxrequest(dev, omb, imb); pci1760_mbxrequest(dev, omb, imb);
devpriv->IDICntOverEnable = 0; devpriv->IDICntOverEnable = 0;
omb[0] = 0x00; omb[0] = 0x00;
omb[2] = CMD_MatchIntIDICounters; /* disable counters match value interrupts */ omb[2] = CMD_MatchIntIDICounters; /* disable counters match value
* interrupts */
pci1760_mbxrequest(dev, omb, imb); pci1760_mbxrequest(dev, omb, imb);
devpriv->IDICntMatchEnable = 0; devpriv->IDICntMatchEnable = 0;
@ -766,7 +807,8 @@ static int pci1760_reset(struct comedi_device *dev)
} }
omb[0] = 0xff; omb[0] = 0xff;
omb[2] = CMD_ResetIDICounters; /* reset IDI up counters to reset values */ omb[2] = CMD_ResetIDICounters; /* reset IDI up counters to reset
* values */
pci1760_mbxrequest(dev, omb, imb); pci1760_mbxrequest(dev, omb, imb);
omb[0] = 0x00; omb[0] = 0x00;
@ -807,9 +849,12 @@ static int pci_dio_reset(struct comedi_device *dev)
outb(0, dev->iobase + PCI1730_IDO + 1); outb(0, dev->iobase + PCI1730_IDO + 1);
/* NO break there! */ /* NO break there! */
case TYPE_PCI1733: case TYPE_PCI1733:
outb(0, dev->iobase + PCI1730_3_INT_EN); /* disable interrupts */ /* disable interrupts */
outb(0x0f, dev->iobase + PCI1730_3_INT_CLR); /* clear interrupts */ outb(0, dev->iobase + PCI1730_3_INT_EN);
outb(0, dev->iobase + PCI1730_3_INT_RF); /* set rising edge trigger */ /* clear interrupts */
outb(0x0f, dev->iobase + PCI1730_3_INT_CLR);
/* set rising edge trigger */
outb(0, dev->iobase + PCI1730_3_INT_RF);
break; break;
case TYPE_PCI1734: case TYPE_PCI1734:
outb(0, dev->iobase + PCI1734_IDO); /* clear outputs */ outb(0, dev->iobase + PCI1734_IDO); /* clear outputs */
@ -830,43 +875,53 @@ static int pci_dio_reset(struct comedi_device *dev)
case TYPE_PCI1736: case TYPE_PCI1736:
outb(0, dev->iobase + PCI1736_IDO); outb(0, dev->iobase + PCI1736_IDO);
outb(0, dev->iobase + PCI1736_IDO + 1); outb(0, dev->iobase + PCI1736_IDO + 1);
outb(0, dev->iobase + PCI1736_3_INT_EN); /* disable interrupts */ /* disable interrupts */
outb(0x0f, dev->iobase + PCI1736_3_INT_CLR); /* clear interrupts */ outb(0, dev->iobase + PCI1736_3_INT_EN);
outb(0, dev->iobase + PCI1736_3_INT_RF); /* set rising edge trigger */ /* clear interrupts */
outb(0x0f, dev->iobase + PCI1736_3_INT_CLR);
/* set rising edge trigger */
outb(0, dev->iobase + PCI1736_3_INT_RF);
break; break;
case TYPE_PCI1750: case TYPE_PCI1750:
case TYPE_PCI1751: case TYPE_PCI1751:
outb(0x88, dev->iobase + PCI1750_ICR); /* disable & clear interrupts */ /* disable & clear interrupts */
outb(0x88, dev->iobase + PCI1750_ICR);
break; break;
case TYPE_PCI1752: case TYPE_PCI1752:
outw(0, dev->iobase + PCI1752_6_CFC); /* disable channel freeze function */ outw(0, dev->iobase + PCI1752_6_CFC); /* disable channel freeze
* function */
outw(0, dev->iobase + PCI1752_IDO); /* clear outputs */ outw(0, dev->iobase + PCI1752_IDO); /* clear outputs */
outw(0, dev->iobase + PCI1752_IDO + 2); outw(0, dev->iobase + PCI1752_IDO + 2);
outw(0, dev->iobase + PCI1752_IDO2); outw(0, dev->iobase + PCI1752_IDO2);
outw(0, dev->iobase + PCI1752_IDO2 + 2); outw(0, dev->iobase + PCI1752_IDO2 + 2);
break; break;
case TYPE_PCI1753E: case TYPE_PCI1753E:
outb(0x88, dev->iobase + PCI1753E_ICR0); /* disable & clear interrupts */ outb(0x88, dev->iobase + PCI1753E_ICR0); /* disable & clear
* interrupts */
outb(0x80, dev->iobase + PCI1753E_ICR1); outb(0x80, dev->iobase + PCI1753E_ICR1);
outb(0x80, dev->iobase + PCI1753E_ICR2); outb(0x80, dev->iobase + PCI1753E_ICR2);
outb(0x80, dev->iobase + PCI1753E_ICR3); outb(0x80, dev->iobase + PCI1753E_ICR3);
/* NO break there! */ /* NO break there! */
case TYPE_PCI1753: case TYPE_PCI1753:
outb(0x88, dev->iobase + PCI1753_ICR0); /* disable & clear interrupts */ outb(0x88, dev->iobase + PCI1753_ICR0); /* disable & clear
* interrupts */
outb(0x80, dev->iobase + PCI1753_ICR1); outb(0x80, dev->iobase + PCI1753_ICR1);
outb(0x80, dev->iobase + PCI1753_ICR2); outb(0x80, dev->iobase + PCI1753_ICR2);
outb(0x80, dev->iobase + PCI1753_ICR3); outb(0x80, dev->iobase + PCI1753_ICR3);
break; break;
case TYPE_PCI1754: case TYPE_PCI1754:
outw(0x08, dev->iobase + PCI1754_6_ICR0); /* disable and clear interrupts */ outw(0x08, dev->iobase + PCI1754_6_ICR0); /* disable and clear
* interrupts */
outw(0x08, dev->iobase + PCI1754_6_ICR1); outw(0x08, dev->iobase + PCI1754_6_ICR1);
outw(0x08, dev->iobase + PCI1754_ICR2); outw(0x08, dev->iobase + PCI1754_ICR2);
outw(0x08, dev->iobase + PCI1754_ICR3); outw(0x08, dev->iobase + PCI1754_ICR3);
break; break;
case TYPE_PCI1756: case TYPE_PCI1756:
outw(0, dev->iobase + PCI1752_6_CFC); /* disable channel freeze function */ outw(0, dev->iobase + PCI1752_6_CFC); /* disable channel freeze
outw(0x08, dev->iobase + PCI1754_6_ICR0); /* disable and clear interrupts */ * function */
outw(0x08, dev->iobase + PCI1754_6_ICR0); /* disable and clear
* interrupts */
outw(0x08, dev->iobase + PCI1754_6_ICR1); outw(0x08, dev->iobase + PCI1754_6_ICR1);
outw(0, dev->iobase + PCI1756_IDO); /* clear outputs */ outw(0, dev->iobase + PCI1756_IDO); /* clear outputs */
outw(0, dev->iobase + PCI1756_IDO + 2); outw(0, dev->iobase + PCI1756_IDO + 2);
@ -875,7 +930,8 @@ static int pci_dio_reset(struct comedi_device *dev)
pci1760_reset(dev); pci1760_reset(dev);
break; break;
case TYPE_PCI1762: case TYPE_PCI1762:
outw(0x0101, dev->iobase + PCI1762_ICR); /* disable & clear interrupts */ outw(0x0101, dev->iobase + PCI1762_ICR); /* disable & clear
* interrupts */
break; break;
} }
@ -996,7 +1052,7 @@ static int pci_dio_add_do(struct comedi_device *dev, struct comedi_subdevice *s,
============================================================================== ==============================================================================
*/ */
static int pci_dio_add_8254(struct comedi_device *dev, static int pci_dio_add_8254(struct comedi_device *dev,
struct comedi_subdevice * s, struct comedi_subdevice *s,
const struct diosubd_data *d, int subdev) const struct diosubd_data *d, int subdev)
{ {
s->type = COMEDI_SUBD_COUNTER; s->type = COMEDI_SUBD_COUNTER;
@ -1048,7 +1104,7 @@ static int pci_dio_attach(struct comedi_device *dev,
struct comedi_subdevice *s; struct comedi_subdevice *s;
int ret, subdev, n_subdevices, i, j; int ret, subdev, n_subdevices, i, j;
unsigned long iobase; unsigned long iobase;
struct pci_dev *pcidev; struct pci_dev *pcidev = NULL;
printk("comedi%d: adv_pci_dio: ", dev->minor); printk("comedi%d: adv_pci_dio: ", dev->minor);
@ -1058,9 +1114,7 @@ static int pci_dio_attach(struct comedi_device *dev,
return -ENOMEM; return -ENOMEM;
} }
for (pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, NULL); for_each_pci_dev(pcidev) {
pcidev != NULL;
pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pcidev)) {
/* loop through cards supported by this driver */ /* loop through cards supported by this driver */
for (i = 0; i < n_boardtypes; ++i) { for (i = 0; i < n_boardtypes; ++i) {
if (boardtypes[i].vendor_id != pcidev->vendor) if (boardtypes[i].vendor_id != pcidev->vendor)
@ -1215,15 +1269,12 @@ static int pci_dio_detach(struct comedi_device *dev)
} }
} }
if (this_board->boardid.chans) { if (this_board->boardid.chans)
subdev++; subdev++;
}
for (i = 0; i < MAX_8254_SUBDEVS; i++) { for (i = 0; i < MAX_8254_SUBDEVS; i++)
if (this_board->s8254[i].chans) { if (this_board->s8254[i].chans)
subdev++; subdev++;
}
}
for (i = 0; i < dev->n_subdevices; i++) { for (i = 0; i < dev->n_subdevices; i++) {
s = dev->subdevices + i; s = dev->subdevices + i;
@ -1253,7 +1304,47 @@ static int pci_dio_detach(struct comedi_device *dev)
/* /*
============================================================================== ==============================================================================
*/ */
COMEDI_PCI_INITCLEANUP(driver_pci_dio, pci_dio_pci_table); static int __devinit driver_pci_dio_pci_probe(struct pci_dev *dev,
const struct pci_device_id *ent)
{
return comedi_pci_auto_config(dev, driver_pci_dio.driver_name);
}
static void __devexit driver_pci_dio_pci_remove(struct pci_dev *dev)
{
comedi_pci_auto_unconfig(dev);
}
static struct pci_driver driver_pci_dio_pci_driver = {
.id_table = pci_dio_pci_table,
.probe = &driver_pci_dio_pci_probe,
.remove = __devexit_p(&driver_pci_dio_pci_remove)
};
static int __init driver_pci_dio_init_module(void)
{
int retval;
retval = comedi_driver_register(&driver_pci_dio);
if (retval < 0)
return retval;
driver_pci_dio_pci_driver.name = (char *)driver_pci_dio.driver_name;
return pci_register_driver(&driver_pci_dio_pci_driver);
}
static void __exit driver_pci_dio_cleanup_module(void)
{
pci_unregister_driver(&driver_pci_dio_pci_driver);
comedi_driver_unregister(&driver_pci_dio);
}
module_init(driver_pci_dio_init_module);
module_exit(driver_pci_dio_cleanup_module);
/* /*
============================================================================== ==============================================================================
*/ */
MODULE_AUTHOR("Comedi http://www.comedi.org");
MODULE_DESCRIPTION("Comedi low-level driver");
MODULE_LICENSE("GPL");

View File

@ -227,4 +227,19 @@ static struct comedi_driver driver_aio_aio12_8 = {
.offset = sizeof(struct aio12_8_boardtype), .offset = sizeof(struct aio12_8_boardtype),
}; };
COMEDI_INITCLEANUP(driver_aio_aio12_8); static int __init driver_aio_aio12_8_init_module(void)
{
return comedi_driver_register(&driver_aio_aio12_8);
}
static void __exit driver_aio_aio12_8_cleanup_module(void)
{
comedi_driver_unregister(&driver_aio_aio12_8);
}
module_init(driver_aio_aio12_8_init_module);
module_exit(driver_aio_aio12_8_cleanup_module);
MODULE_AUTHOR("Comedi http://www.comedi.org");
MODULE_DESCRIPTION("Comedi low-level driver");
MODULE_LICENSE("GPL");

View File

@ -184,4 +184,19 @@ static int aio_iiro_16_dio_insn_bits_read(struct comedi_device *dev,
return 2; return 2;
} }
COMEDI_INITCLEANUP(driver_aio_iiro_16); static int __init driver_aio_iiro_16_init_module(void)
{
return comedi_driver_register(&driver_aio_iiro_16);
}
static void __exit driver_aio_iiro_16_cleanup_module(void)
{
comedi_driver_unregister(&driver_aio_iiro_16);
}
module_init(driver_aio_iiro_16_init_module);
module_exit(driver_aio_iiro_16_cleanup_module);
MODULE_AUTHOR("Comedi http://www.comedi.org");
MODULE_DESCRIPTION("Comedi low-level driver");
MODULE_LICENSE("GPL");

View File

@ -47,32 +47,32 @@
#ifdef Am9513_8BITBUS #ifdef Am9513_8BITBUS
#define Am9513_write_register(reg, val) \ #define Am9513_write_register(reg, val) \
do{ \ do { \
Am9513_output_control(reg); \ Am9513_output_control(reg); \
Am9513_output_data(val>>8); \ Am9513_output_data(val>>8); \
Am9513_output_data(val&0xff); \ Am9513_output_data(val&0xff); \
}while (0) } while (0)
#define Am9513_read_register(reg, val) \ #define Am9513_read_register(reg, val) \
do{ \ do { \
Am9513_output_control(reg); \ Am9513_output_control(reg); \
val=Am9513_input_data()<<8; \ val = Am9513_input_data()<<8; \
val|=Am9513_input_data(); \ val |= Am9513_input_data(); \
}while (0) } while (0)
#else /* Am9513_16BITBUS */ #else /* Am9513_16BITBUS */
#define Am9513_write_register(reg, val) \ #define Am9513_write_register(reg, val) \
do{ \ do { \
Am9513_output_control(reg); \ Am9513_output_control(reg); \
Am9513_output_data(val); \ Am9513_output_data(val); \
}while (0) } while (0)
#define Am9513_read_register(reg, val) \ #define Am9513_read_register(reg, val) \
do{ \ do { \
Am9513_output_control(reg); \ Am9513_output_control(reg); \
val=Am9513_input_data(); \ val = Am9513_input_data(); \
}while (0) } while (0)
#endif #endif

View File

@ -494,9 +494,58 @@ static struct comedi_driver driver_amplc_dio200 = {
}; };
#ifdef CONFIG_COMEDI_PCI #ifdef CONFIG_COMEDI_PCI
COMEDI_PCI_INITCLEANUP(driver_amplc_dio200, dio200_pci_table); static int __devinit driver_amplc_dio200_pci_probe(struct pci_dev *dev,
const struct pci_device_id
*ent)
{
return comedi_pci_auto_config(dev, driver_amplc_dio200.driver_name);
}
static void __devexit driver_amplc_dio200_pci_remove(struct pci_dev *dev)
{
comedi_pci_auto_unconfig(dev);
}
static struct pci_driver driver_amplc_dio200_pci_driver = {
.id_table = dio200_pci_table,
.probe = &driver_amplc_dio200_pci_probe,
.remove = __devexit_p(&driver_amplc_dio200_pci_remove)
};
static int __init driver_amplc_dio200_init_module(void)
{
int retval;
retval = comedi_driver_register(&driver_amplc_dio200);
if (retval < 0)
return retval;
driver_amplc_dio200_pci_driver.name =
(char *)driver_amplc_dio200.driver_name;
return pci_register_driver(&driver_amplc_dio200_pci_driver);
}
static void __exit driver_amplc_dio200_cleanup_module(void)
{
pci_unregister_driver(&driver_amplc_dio200_pci_driver);
comedi_driver_unregister(&driver_amplc_dio200);
}
module_init(driver_amplc_dio200_init_module);
module_exit(driver_amplc_dio200_cleanup_module);
#else #else
COMEDI_INITCLEANUP(driver_amplc_dio200); static int __init driver_amplc_dio200_init_module(void)
{
return comedi_driver_register(&driver_amplc_dio200);
}
static void __exit driver_amplc_dio200_cleanup_module(void)
{
comedi_driver_unregister(&driver_amplc_dio200);
}
module_init(driver_amplc_dio200_init_module);
module_exit(driver_amplc_dio200_cleanup_module);
#endif #endif
/* /*
@ -1501,3 +1550,7 @@ static int dio200_detach(struct comedi_device *dev)
return 0; return 0;
} }
MODULE_AUTHOR("Comedi http://www.comedi.org");
MODULE_DESCRIPTION("Comedi low-level driver");
MODULE_LICENSE("GPL");

View File

@ -182,9 +182,58 @@ static struct comedi_driver driver_amplc_pc236 = {
}; };
#ifdef CONFIG_COMEDI_PCI #ifdef CONFIG_COMEDI_PCI
COMEDI_PCI_INITCLEANUP(driver_amplc_pc236, pc236_pci_table); static int __devinit driver_amplc_pc236_pci_probe(struct pci_dev *dev,
const struct pci_device_id
*ent)
{
return comedi_pci_auto_config(dev, driver_amplc_pc236.driver_name);
}
static void __devexit driver_amplc_pc236_pci_remove(struct pci_dev *dev)
{
comedi_pci_auto_unconfig(dev);
}
static struct pci_driver driver_amplc_pc236_pci_driver = {
.id_table = pc236_pci_table,
.probe = &driver_amplc_pc236_pci_probe,
.remove = __devexit_p(&driver_amplc_pc236_pci_remove)
};
static int __init driver_amplc_pc236_init_module(void)
{
int retval;
retval = comedi_driver_register(&driver_amplc_pc236);
if (retval < 0)
return retval;
driver_amplc_pc236_pci_driver.name =
(char *)driver_amplc_pc236.driver_name;
return pci_register_driver(&driver_amplc_pc236_pci_driver);
}
static void __exit driver_amplc_pc236_cleanup_module(void)
{
pci_unregister_driver(&driver_amplc_pc236_pci_driver);
comedi_driver_unregister(&driver_amplc_pc236);
}
module_init(driver_amplc_pc236_init_module);
module_exit(driver_amplc_pc236_cleanup_module);
#else #else
COMEDI_INITCLEANUP(driver_amplc_pc236); static int __init driver_amplc_pc236_init_module(void)
{
return comedi_driver_register(&driver_amplc_pc236);
}
static void __exit driver_amplc_pc236_cleanup_module(void)
{
comedi_driver_unregister(&driver_amplc_pc236);
}
module_init(driver_amplc_pc236_init_module);
module_exit(driver_amplc_pc236_cleanup_module);
#endif #endif
static int pc236_request_region(unsigned minor, unsigned long from, static int pc236_request_region(unsigned minor, unsigned long from,
@ -664,3 +713,7 @@ static irqreturn_t pc236_interrupt(int irq, void *d)
} }
return IRQ_RETVAL(handled); return IRQ_RETVAL(handled);
} }
MODULE_AUTHOR("Comedi http://www.comedi.org");
MODULE_DESCRIPTION("Comedi low-level driver");
MODULE_LICENSE("GPL");

View File

@ -432,7 +432,60 @@ static int pc263_dio_insn_config(struct comedi_device *dev,
* as necessary. * as necessary.
*/ */
#ifdef CONFIG_COMEDI_PCI #ifdef CONFIG_COMEDI_PCI
COMEDI_PCI_INITCLEANUP(driver_amplc_pc263, pc263_pci_table); static int __devinit driver_amplc_pc263_pci_probe(struct pci_dev *dev,
const struct pci_device_id
*ent)
{
return comedi_pci_auto_config(dev, driver_amplc_pc263.driver_name);
}
static void __devexit driver_amplc_pc263_pci_remove(struct pci_dev *dev)
{
comedi_pci_auto_unconfig(dev);
}
static struct pci_driver driver_amplc_pc263_pci_driver = {
.id_table = pc263_pci_table,
.probe = &driver_amplc_pc263_pci_probe,
.remove = __devexit_p(&driver_amplc_pc263_pci_remove)
};
static int __init driver_amplc_pc263_init_module(void)
{
int retval;
retval = comedi_driver_register(&driver_amplc_pc263);
if (retval < 0)
return retval;
driver_amplc_pc263_pci_driver.name =
(char *)driver_amplc_pc263.driver_name;
return pci_register_driver(&driver_amplc_pc263_pci_driver);
}
static void __exit driver_amplc_pc263_cleanup_module(void)
{
pci_unregister_driver(&driver_amplc_pc263_pci_driver);
comedi_driver_unregister(&driver_amplc_pc263);
}
module_init(driver_amplc_pc263_init_module);
module_exit(driver_amplc_pc263_cleanup_module);
#else #else
COMEDI_INITCLEANUP(driver_amplc_pc263); static int __init driver_amplc_pc263_init_module(void)
{
return comedi_driver_register(&driver_amplc_pc263);
}
static void __exit driver_amplc_pc263_cleanup_module(void)
{
comedi_driver_unregister(&driver_amplc_pc263);
}
module_init(driver_amplc_pc263_init_module);
module_exit(driver_amplc_pc263_cleanup_module);
#endif #endif
MODULE_AUTHOR("Comedi http://www.comedi.org");
MODULE_DESCRIPTION("Comedi low-level driver");
MODULE_LICENSE("GPL");

View File

@ -443,7 +443,45 @@ static struct comedi_driver driver_amplc_pci224 = {
.num_names = ARRAY_SIZE(pci224_boards), .num_names = ARRAY_SIZE(pci224_boards),
}; };
COMEDI_PCI_INITCLEANUP(driver_amplc_pci224, pci224_pci_table); static int __devinit driver_amplc_pci224_pci_probe(struct pci_dev *dev,
const struct pci_device_id
*ent)
{
return comedi_pci_auto_config(dev, driver_amplc_pci224.driver_name);
}
static void __devexit driver_amplc_pci224_pci_remove(struct pci_dev *dev)
{
comedi_pci_auto_unconfig(dev);
}
static struct pci_driver driver_amplc_pci224_pci_driver = {
.id_table = pci224_pci_table,
.probe = &driver_amplc_pci224_pci_probe,
.remove = __devexit_p(&driver_amplc_pci224_pci_remove)
};
static int __init driver_amplc_pci224_init_module(void)
{
int retval;
retval = comedi_driver_register(&driver_amplc_pci224);
if (retval < 0)
return retval;
driver_amplc_pci224_pci_driver.name =
(char *)driver_amplc_pci224.driver_name;
return pci_register_driver(&driver_amplc_pci224_pci_driver);
}
static void __exit driver_amplc_pci224_cleanup_module(void)
{
pci_unregister_driver(&driver_amplc_pci224_pci_driver);
comedi_driver_unregister(&driver_amplc_pci224);
}
module_init(driver_amplc_pci224_init_module);
module_exit(driver_amplc_pci224_cleanup_module);
/* /*
* Called from the 'insn_write' function to perform a single write. * Called from the 'insn_write' function to perform a single write.
@ -1557,3 +1595,7 @@ static int pci224_detach(struct comedi_device *dev)
return 0; return 0;
} }
MODULE_AUTHOR("Comedi http://www.comedi.org");
MODULE_DESCRIPTION("Comedi low-level driver");
MODULE_LICENSE("GPL");

View File

@ -617,7 +617,45 @@ static struct comedi_driver driver_amplc_pci230 = {
.num_names = ARRAY_SIZE(pci230_boards), .num_names = ARRAY_SIZE(pci230_boards),
}; };
COMEDI_PCI_INITCLEANUP(driver_amplc_pci230, pci230_pci_table); static int __devinit driver_amplc_pci230_pci_probe(struct pci_dev *dev,
const struct pci_device_id
*ent)
{
return comedi_pci_auto_config(dev, driver_amplc_pci230.driver_name);
}
static void __devexit driver_amplc_pci230_pci_remove(struct pci_dev *dev)
{
comedi_pci_auto_unconfig(dev);
}
static struct pci_driver driver_amplc_pci230_pci_driver = {
.id_table = pci230_pci_table,
.probe = &driver_amplc_pci230_pci_probe,
.remove = __devexit_p(&driver_amplc_pci230_pci_remove)
};
static int __init driver_amplc_pci230_init_module(void)
{
int retval;
retval = comedi_driver_register(&driver_amplc_pci230);
if (retval < 0)
return retval;
driver_amplc_pci230_pci_driver.name =
(char *)driver_amplc_pci230.driver_name;
return pci_register_driver(&driver_amplc_pci230_pci_driver);
}
static void __exit driver_amplc_pci230_cleanup_module(void)
{
pci_unregister_driver(&driver_amplc_pci230_pci_driver);
comedi_driver_unregister(&driver_amplc_pci230);
}
module_init(driver_amplc_pci230_init_module);
module_exit(driver_amplc_pci230_cleanup_module);
static int pci230_ai_rinsn(struct comedi_device *dev, static int pci230_ai_rinsn(struct comedi_device *dev,
struct comedi_subdevice *s, struct comedi_insn *insn, struct comedi_subdevice *s, struct comedi_insn *insn,
@ -726,7 +764,7 @@ static int pci230_attach(struct comedi_device *dev, struct comedi_devconfig *it)
struct comedi_subdevice *s; struct comedi_subdevice *s;
unsigned long iobase1, iobase2; unsigned long iobase1, iobase2;
/* PCI230's I/O spaces 1 and 2 respectively. */ /* PCI230's I/O spaces 1 and 2 respectively. */
struct pci_dev *pci_dev; struct pci_dev *pci_dev = NULL;
int i = 0, irq_hdl, rc; int i = 0, irq_hdl, rc;
printk("comedi%d: amplc_pci230: attach %s %d,%d\n", dev->minor, printk("comedi%d: amplc_pci230: attach %s %d,%d\n", dev->minor,
@ -742,9 +780,7 @@ static int pci230_attach(struct comedi_device *dev, struct comedi_devconfig *it)
spin_lock_init(&devpriv->ai_stop_spinlock); spin_lock_init(&devpriv->ai_stop_spinlock);
spin_lock_init(&devpriv->ao_stop_spinlock); spin_lock_init(&devpriv->ao_stop_spinlock);
/* Find card */ /* Find card */
for (pci_dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, NULL); for_each_pci_dev(pci_dev) {
pci_dev != NULL;
pci_dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pci_dev)) {
if (it->options[0] || it->options[1]) { if (it->options[0] || it->options[1]) {
/* Match against bus/slot options. */ /* Match against bus/slot options. */
if (it->options[0] != pci_dev->bus->number || if (it->options[0] != pci_dev->bus->number ||
@ -3014,3 +3050,7 @@ static int pci230_ai_cancel(struct comedi_device *dev,
pci230_ai_stop(dev, s); pci230_ai_stop(dev, s);
return 0; return 0;
} }
MODULE_AUTHOR("Comedi http://www.comedi.org");
MODULE_DESCRIPTION("Comedi low-level driver");
MODULE_LICENSE("GPL");

View File

@ -517,4 +517,19 @@ static int c6xdigio_detach(struct comedi_device *dev)
return 0; return 0;
} }
COMEDI_INITCLEANUP(driver_c6xdigio); static int __init driver_c6xdigio_init_module(void)
{
return comedi_driver_register(&driver_c6xdigio);
}
static void __exit driver_c6xdigio_cleanup_module(void)
{
comedi_driver_unregister(&driver_c6xdigio);
}
module_init(driver_c6xdigio_init_module);
module_exit(driver_c6xdigio_cleanup_module);
MODULE_AUTHOR("Comedi http://www.comedi.org");
MODULE_DESCRIPTION("Comedi low-level driver");
MODULE_LICENSE("GPL");

View File

@ -719,7 +719,6 @@ static void das16cs_pcmcia_detach(struct pcmcia_device *link)
((struct local_info_t *)link->priv)->stop = 1; ((struct local_info_t *)link->priv)->stop = 1;
das16cs_pcmcia_release(link); das16cs_pcmcia_release(link);
/* This points to the parent struct local_info_t struct */ /* This points to the parent struct local_info_t struct */
if (link->priv)
kfree(link->priv); kfree(link->priv);
} /* das16cs_pcmcia_detach */ } /* das16cs_pcmcia_detach */
@ -881,5 +880,16 @@ void __exit cleanup_module(void)
} }
#else #else
COMEDI_INITCLEANUP(driver_das16cs); static int __init driver_das16cs_init_module(void)
{
return comedi_driver_register(&driver_das16cs);
}
static void __exit driver_das16cs_cleanup_module(void)
{
comedi_driver_unregister(&driver_das16cs);
}
module_init(driver_das16cs_init_module);
module_exit(driver_das16cs_cleanup_module);
#endif /* CONFIG_PCMCIA */ #endif /* CONFIG_PCMCIA */

View File

@ -533,7 +533,7 @@ static int cb_pcidas_attach(struct comedi_device *dev,
struct comedi_devconfig *it) struct comedi_devconfig *it)
{ {
struct comedi_subdevice *s; struct comedi_subdevice *s;
struct pci_dev *pcidev; struct pci_dev *pcidev = NULL;
int index; int index;
int i; int i;
@ -550,9 +550,7 @@ static int cb_pcidas_attach(struct comedi_device *dev,
*/ */
printk("\n"); printk("\n");
for (pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, NULL); for_each_pci_dev(pcidev) {
pcidev != NULL;
pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pcidev)) {
/* is it not a computer boards card? */ /* is it not a computer boards card? */
if (pcidev->vendor != PCI_VENDOR_ID_CB) if (pcidev->vendor != PCI_VENDOR_ID_CB)
continue; continue;
@ -1871,4 +1869,44 @@ static int nvram_read(struct comedi_device *dev, unsigned int address,
* A convenient macro that defines init_module() and cleanup_module(), * A convenient macro that defines init_module() and cleanup_module(),
* as necessary. * as necessary.
*/ */
COMEDI_PCI_INITCLEANUP(driver_cb_pcidas, cb_pcidas_pci_table); static int __devinit driver_cb_pcidas_pci_probe(struct pci_dev *dev,
const struct pci_device_id *ent)
{
return comedi_pci_auto_config(dev, driver_cb_pcidas.driver_name);
}
static void __devexit driver_cb_pcidas_pci_remove(struct pci_dev *dev)
{
comedi_pci_auto_unconfig(dev);
}
static struct pci_driver driver_cb_pcidas_pci_driver = {
.id_table = cb_pcidas_pci_table,
.probe = &driver_cb_pcidas_pci_probe,
.remove = __devexit_p(&driver_cb_pcidas_pci_remove)
};
static int __init driver_cb_pcidas_init_module(void)
{
int retval;
retval = comedi_driver_register(&driver_cb_pcidas);
if (retval < 0)
return retval;
driver_cb_pcidas_pci_driver.name = (char *)driver_cb_pcidas.driver_name;
return pci_register_driver(&driver_cb_pcidas_pci_driver);
}
static void __exit driver_cb_pcidas_cleanup_module(void)
{
pci_unregister_driver(&driver_cb_pcidas_pci_driver);
comedi_driver_unregister(&driver_cb_pcidas);
}
module_init(driver_cb_pcidas_init_module);
module_exit(driver_cb_pcidas_cleanup_module);
MODULE_AUTHOR("Comedi http://www.comedi.org");
MODULE_DESCRIPTION("Comedi low-level driver");
MODULE_LICENSE("GPL");

View File

@ -1237,7 +1237,43 @@ static unsigned int get_ao_divisor(unsigned int ns, unsigned int flags);
static void load_ao_dma(struct comedi_device *dev, static void load_ao_dma(struct comedi_device *dev,
const struct comedi_cmd *cmd); const struct comedi_cmd *cmd);
COMEDI_PCI_INITCLEANUP(driver_cb_pcidas, pcidas64_pci_table); static int __devinit driver_cb_pcidas_pci_probe(struct pci_dev *dev,
const struct pci_device_id *ent)
{
return comedi_pci_auto_config(dev, driver_cb_pcidas.driver_name);
}
static void __devexit driver_cb_pcidas_pci_remove(struct pci_dev *dev)
{
comedi_pci_auto_unconfig(dev);
}
static struct pci_driver driver_cb_pcidas_pci_driver = {
.id_table = pcidas64_pci_table,
.probe = &driver_cb_pcidas_pci_probe,
.remove = __devexit_p(&driver_cb_pcidas_pci_remove)
};
static int __init driver_cb_pcidas_init_module(void)
{
int retval;
retval = comedi_driver_register(&driver_cb_pcidas);
if (retval < 0)
return retval;
driver_cb_pcidas_pci_driver.name = (char *)driver_cb_pcidas.driver_name;
return pci_register_driver(&driver_cb_pcidas_pci_driver);
}
static void __exit driver_cb_pcidas_cleanup_module(void)
{
pci_unregister_driver(&driver_cb_pcidas_pci_driver);
comedi_driver_unregister(&driver_cb_pcidas);
}
module_init(driver_cb_pcidas_init_module);
module_exit(driver_cb_pcidas_cleanup_module);
static unsigned int ai_range_bits_6xxx(const struct comedi_device *dev, static unsigned int ai_range_bits_6xxx(const struct comedi_device *dev,
unsigned int range_index) unsigned int range_index)
@ -1718,7 +1754,7 @@ static inline void warn_external_queue(struct comedi_device *dev)
*/ */
static int attach(struct comedi_device *dev, struct comedi_devconfig *it) static int attach(struct comedi_device *dev, struct comedi_devconfig *it)
{ {
struct pci_dev *pcidev; struct pci_dev *pcidev = NULL;
int index; int index;
uint32_t local_range, local_decode; uint32_t local_range, local_decode;
int retval; int retval;
@ -1735,9 +1771,7 @@ static int attach(struct comedi_device *dev, struct comedi_devconfig *it)
* Probe the device to determine what device in the series it is. * Probe the device to determine what device in the series it is.
*/ */
for (pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, NULL); for_each_pci_dev(pcidev) {
pcidev != NULL;
pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pcidev)) {
/* is it not a computer boards card? */ /* is it not a computer boards card? */
if (pcidev->vendor != PCI_VENDOR_ID_COMPUTERBOARDS) if (pcidev->vendor != PCI_VENDOR_ID_COMPUTERBOARDS)
continue; continue;
@ -4303,3 +4337,7 @@ static void i2c_write(struct comedi_device *dev, unsigned int address,
} }
i2c_stop(dev); i2c_stop(dev);
} }
MODULE_AUTHOR("Comedi http://www.comedi.org");
MODULE_DESCRIPTION("Comedi low-level driver");
MODULE_LICENSE("GPL");

View File

@ -280,7 +280,7 @@ static int cb_pcidda_attach(struct comedi_device *dev,
struct comedi_devconfig *it) struct comedi_devconfig *it)
{ {
struct comedi_subdevice *s; struct comedi_subdevice *s;
struct pci_dev *pcidev; struct pci_dev *pcidev = NULL;
int index; int index;
printk("comedi%d: cb_pcidda: ", dev->minor); printk("comedi%d: cb_pcidda: ", dev->minor);
@ -296,9 +296,7 @@ static int cb_pcidda_attach(struct comedi_device *dev,
*/ */
printk("\n"); printk("\n");
for (pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, NULL); for_each_pci_dev(pcidev) {
pcidev != NULL;
pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pcidev)) {
if (pcidev->vendor == PCI_VENDOR_ID_CB) { if (pcidev->vendor == PCI_VENDOR_ID_CB) {
if (it->options[0] || it->options[1]) { if (it->options[0] || it->options[1]) {
if (pcidev->bus->number != it->options[0] || if (pcidev->bus->number != it->options[0] ||
@ -856,4 +854,44 @@ static void cb_pcidda_calibrate(struct comedi_device *dev, unsigned int channel,
* A convenient macro that defines init_module() and cleanup_module(), * A convenient macro that defines init_module() and cleanup_module(),
* as necessary. * as necessary.
*/ */
COMEDI_PCI_INITCLEANUP(driver_cb_pcidda, cb_pcidda_pci_table); static int __devinit driver_cb_pcidda_pci_probe(struct pci_dev *dev,
const struct pci_device_id *ent)
{
return comedi_pci_auto_config(dev, driver_cb_pcidda.driver_name);
}
static void __devexit driver_cb_pcidda_pci_remove(struct pci_dev *dev)
{
comedi_pci_auto_unconfig(dev);
}
static struct pci_driver driver_cb_pcidda_pci_driver = {
.id_table = cb_pcidda_pci_table,
.probe = &driver_cb_pcidda_pci_probe,
.remove = __devexit_p(&driver_cb_pcidda_pci_remove)
};
static int __init driver_cb_pcidda_init_module(void)
{
int retval;
retval = comedi_driver_register(&driver_cb_pcidda);
if (retval < 0)
return retval;
driver_cb_pcidda_pci_driver.name = (char *)driver_cb_pcidda.driver_name;
return pci_register_driver(&driver_cb_pcidda_pci_driver);
}
static void __exit driver_cb_pcidda_cleanup_module(void)
{
pci_unregister_driver(&driver_cb_pcidda_pci_driver);
comedi_driver_unregister(&driver_cb_pcidda);
}
module_init(driver_cb_pcidda_init_module);
module_exit(driver_cb_pcidda_cleanup_module);
MODULE_AUTHOR("Comedi http://www.comedi.org");
MODULE_DESCRIPTION("Comedi low-level driver");
MODULE_LICENSE("GPL");

View File

@ -202,9 +202,7 @@ static int pcidio_attach(struct comedi_device *dev, struct comedi_devconfig *it)
* Probe the device to determine what device in the series it is. * Probe the device to determine what device in the series it is.
*/ */
for (pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, NULL); for_each_pci_dev(pcidev) {
pcidev != NULL;
pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pcidev)) {
/* is it not a computer boards card? */ /* is it not a computer boards card? */
if (pcidev->vendor != PCI_VENDOR_ID_CB) if (pcidev->vendor != PCI_VENDOR_ID_CB)
continue; continue;
@ -300,4 +298,44 @@ static int pcidio_detach(struct comedi_device *dev)
* A convenient macro that defines init_module() and cleanup_module(), * A convenient macro that defines init_module() and cleanup_module(),
* as necessary. * as necessary.
*/ */
COMEDI_PCI_INITCLEANUP(driver_cb_pcidio, pcidio_pci_table); static int __devinit driver_cb_pcidio_pci_probe(struct pci_dev *dev,
const struct pci_device_id *ent)
{
return comedi_pci_auto_config(dev, driver_cb_pcidio.driver_name);
}
static void __devexit driver_cb_pcidio_pci_remove(struct pci_dev *dev)
{
comedi_pci_auto_unconfig(dev);
}
static struct pci_driver driver_cb_pcidio_pci_driver = {
.id_table = pcidio_pci_table,
.probe = &driver_cb_pcidio_pci_probe,
.remove = __devexit_p(&driver_cb_pcidio_pci_remove)
};
static int __init driver_cb_pcidio_init_module(void)
{
int retval;
retval = comedi_driver_register(&driver_cb_pcidio);
if (retval < 0)
return retval;
driver_cb_pcidio_pci_driver.name = (char *)driver_cb_pcidio.driver_name;
return pci_register_driver(&driver_cb_pcidio_pci_driver);
}
static void __exit driver_cb_pcidio_cleanup_module(void)
{
pci_unregister_driver(&driver_cb_pcidio_pci_driver);
comedi_driver_unregister(&driver_cb_pcidio);
}
module_init(driver_cb_pcidio_init_module);
module_exit(driver_cb_pcidio_cleanup_module);
MODULE_AUTHOR("Comedi http://www.comedi.org");
MODULE_DESCRIPTION("Comedi low-level driver");
MODULE_LICENSE("GPL");

View File

@ -210,7 +210,7 @@ static int cb_pcimdas_attach(struct comedi_device *dev,
struct comedi_devconfig *it) struct comedi_devconfig *it)
{ {
struct comedi_subdevice *s; struct comedi_subdevice *s;
struct pci_dev *pcidev; struct pci_dev *pcidev = NULL;
int index; int index;
/* int i; */ /* int i; */
@ -227,9 +227,7 @@ static int cb_pcimdas_attach(struct comedi_device *dev,
*/ */
printk("\n"); printk("\n");
for (pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, NULL); for_each_pci_dev(pcidev) {
pcidev != NULL;
pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pcidev)) {
/* is it not a computer boards card? */ /* is it not a computer boards card? */
if (pcidev->vendor != PCI_VENDOR_ID_COMPUTERBOARDS) if (pcidev->vendor != PCI_VENDOR_ID_COMPUTERBOARDS)
continue; continue;
@ -491,4 +489,46 @@ static int cb_pcimdas_ao_rinsn(struct comedi_device *dev,
* A convenient macro that defines init_module() and cleanup_module(), * A convenient macro that defines init_module() and cleanup_module(),
* as necessary. * as necessary.
*/ */
COMEDI_PCI_INITCLEANUP(driver_cb_pcimdas, cb_pcimdas_pci_table); static int __devinit driver_cb_pcimdas_pci_probe(struct pci_dev *dev,
const struct pci_device_id
*ent)
{
return comedi_pci_auto_config(dev, driver_cb_pcimdas.driver_name);
}
static void __devexit driver_cb_pcimdas_pci_remove(struct pci_dev *dev)
{
comedi_pci_auto_unconfig(dev);
}
static struct pci_driver driver_cb_pcimdas_pci_driver = {
.id_table = cb_pcimdas_pci_table,
.probe = &driver_cb_pcimdas_pci_probe,
.remove = __devexit_p(&driver_cb_pcimdas_pci_remove)
};
static int __init driver_cb_pcimdas_init_module(void)
{
int retval;
retval = comedi_driver_register(&driver_cb_pcimdas);
if (retval < 0)
return retval;
driver_cb_pcimdas_pci_driver.name =
(char *)driver_cb_pcimdas.driver_name;
return pci_register_driver(&driver_cb_pcimdas_pci_driver);
}
static void __exit driver_cb_pcimdas_cleanup_module(void)
{
pci_unregister_driver(&driver_cb_pcimdas_pci_driver);
comedi_driver_unregister(&driver_cb_pcimdas);
}
module_init(driver_cb_pcimdas_init_module);
module_exit(driver_cb_pcimdas_cleanup_module);
MODULE_AUTHOR("Comedi http://www.comedi.org");
MODULE_DESCRIPTION("Comedi low-level driver");
MODULE_LICENSE("GPL");

View File

@ -195,7 +195,45 @@ MODULE_DESCRIPTION("Comedi low-level driver for the Computerboards PCIM-DDA "
"series. Currently only supports PCIM-DDA06-16 (which " "series. Currently only supports PCIM-DDA06-16 (which "
"also happens to be the only board in this series. :) ) "); "also happens to be the only board in this series. :) ) ");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
COMEDI_PCI_INITCLEANUP_NOMODULE(cb_pcimdda_driver, pci_table); static int __devinit cb_pcimdda_driver_pci_probe(struct pci_dev *dev,
const struct pci_device_id
*ent)
{
return comedi_pci_auto_config(dev, cb_pcimdda_driver.driver_name);
}
static void __devexit cb_pcimdda_driver_pci_remove(struct pci_dev *dev)
{
comedi_pci_auto_unconfig(dev);
}
static struct pci_driver cb_pcimdda_driver_pci_driver = {
.id_table = pci_table,
.probe = &cb_pcimdda_driver_pci_probe,
.remove = __devexit_p(&cb_pcimdda_driver_pci_remove)
};
static int __init cb_pcimdda_driver_init_module(void)
{
int retval;
retval = comedi_driver_register(&cb_pcimdda_driver);
if (retval < 0)
return retval;
cb_pcimdda_driver_pci_driver.name =
(char *)cb_pcimdda_driver.driver_name;
return pci_register_driver(&cb_pcimdda_driver_pci_driver);
}
static void __exit cb_pcimdda_driver_cleanup_module(void)
{
pci_unregister_driver(&cb_pcimdda_driver_pci_driver);
comedi_driver_unregister(&cb_pcimdda_driver);
}
module_init(cb_pcimdda_driver_init_module);
module_exit(cb_pcimdda_driver_cleanup_module);
static int ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s, static int ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data); struct comedi_insn *insn, unsigned int *data);
@ -426,13 +464,11 @@ static int ao_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
*/ */
static int probe(struct comedi_device *dev, const struct comedi_devconfig *it) static int probe(struct comedi_device *dev, const struct comedi_devconfig *it)
{ {
struct pci_dev *pcidev; struct pci_dev *pcidev = NULL;
int index; int index;
unsigned long registers; unsigned long registers;
for (pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, NULL); for_each_pci_dev(pcidev) {
pcidev != NULL;
pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pcidev)) {
/* is it not a computer boards card? */ /* is it not a computer boards card? */
if (pcidev->vendor != PCI_VENDOR_ID_COMPUTERBOARDS) if (pcidev->vendor != PCI_VENDOR_ID_COMPUTERBOARDS)
continue; continue;

View File

@ -50,43 +50,6 @@ Configuration Options:
within each minor will be concatenated together in the order given here. within each minor will be concatenated together in the order given here.
*/ */
/*
* The previous block comment is used to automatically generate
* documentation in Comedi and Comedilib. The fields:
*
* Driver: the name of the driver
* Description: a short phrase describing the driver. Don't list boards.
* Devices: a full list of the boards that attempt to be supported by
* the driver. Format is "(manufacturer) board name [comedi name]",
* where comedi_name is the name that is used to configure the board.
* See the comment near board_name: in the struct comedi_driver structure
* below. If (manufacturer) or [comedi name] is missing, the previous
* value is used.
* Author: you
* Updated: date when the _documentation_ was last updated. Use 'date -R'
* to get a value for this.
* Status: a one-word description of the status. Valid values are:
* works - driver works correctly on most boards supported, and
* passes comedi_test.
* unknown - unknown. Usually put there by ds.
* experimental - may not work in any particular release. Author
* probably wants assistance testing it.
* bitrotten - driver has not been update in a long time, probably
* doesn't work, and probably is missing support for significant
* Comedi interface features.
* untested - author probably wrote it "blind", and is believed to
* work, but no confirmation.
*
* These headers should be followed by a blank line, and any comments
* you wish to say about the driver. The comment area is the place
* to put any known bugs, limitations, unsupported features, supported
* command triggers, whether or not commands are supported on particular
* subdevices, etc.
*
* Somewhere in the comment should be information about configuration
* options that are used with comedi_config.
*/
#include <linux/string.h> #include <linux/string.h>
#include <linux/slab.h> #include <linux/slab.h>
#include "../comedi.h" #include "../comedi.h"

View File

@ -101,7 +101,18 @@ static struct comedi_driver driver_parport = {
.detach = parport_detach, .detach = parport_detach,
}; };
COMEDI_INITCLEANUP(driver_parport); static int __init driver_parport_init_module(void)
{
return comedi_driver_register(&driver_parport);
}
static void __exit driver_parport_cleanup_module(void)
{
comedi_driver_unregister(&driver_parport);
}
module_init(driver_parport_init_module);
module_exit(driver_parport_cleanup_module);
struct parport_private { struct parport_private {
unsigned int a_data; unsigned int a_data;
@ -396,3 +407,7 @@ static int parport_detach(struct comedi_device *dev)
return 0; return 0;
} }
MODULE_AUTHOR("Comedi http://www.comedi.org");
MODULE_DESCRIPTION("Comedi low-level driver");
MODULE_LICENSE("GPL");

View File

@ -107,7 +107,18 @@ static struct comedi_driver driver_waveform = {
.num_names = ARRAY_SIZE(waveform_boards), .num_names = ARRAY_SIZE(waveform_boards),
}; };
COMEDI_INITCLEANUP(driver_waveform); static int __init driver_waveform_init_module(void)
{
return comedi_driver_register(&driver_waveform);
}
static void __exit driver_waveform_cleanup_module(void)
{
comedi_driver_unregister(&driver_waveform);
}
module_init(driver_waveform_init_module);
module_exit(driver_waveform_cleanup_module);
static int waveform_ai_cmdtest(struct comedi_device *dev, static int waveform_ai_cmdtest(struct comedi_device *dev,
struct comedi_subdevice *s, struct comedi_subdevice *s,
@ -549,3 +560,7 @@ static int waveform_ao_insn_write(struct comedi_device *dev,
return insn->n; return insn->n;
} }
MODULE_AUTHOR("Comedi http://www.comedi.org");
MODULE_DESCRIPTION("Comedi low-level driver");
MODULE_LICENSE("GPL");

View File

@ -103,7 +103,7 @@ static int contec_ns_to_timer(unsigned int *ns, int round);
static int contec_attach(struct comedi_device *dev, struct comedi_devconfig *it) static int contec_attach(struct comedi_device *dev, struct comedi_devconfig *it)
{ {
struct pci_dev *pcidev; struct pci_dev *pcidev = NULL;
struct comedi_subdevice *s; struct comedi_subdevice *s;
printk("comedi%d: contec: ", dev->minor); printk("comedi%d: contec: ", dev->minor);
@ -116,10 +116,7 @@ static int contec_attach(struct comedi_device *dev, struct comedi_devconfig *it)
if (alloc_subdevices(dev, 2) < 0) if (alloc_subdevices(dev, 2) < 0)
return -ENOMEM; return -ENOMEM;
for (pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, NULL); for_each_pci_dev(pcidev) {
pcidev != NULL;
pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pcidev)) {
if (pcidev->vendor == PCI_VENDOR_ID_CONTEC && if (pcidev->vendor == PCI_VENDOR_ID_CONTEC &&
pcidev->device == PCI_DEVICE_ID_PIO1616L) { pcidev->device == PCI_DEVICE_ID_PIO1616L) {
if (it->options[0] || it->options[1]) { if (it->options[0] || it->options[1]) {
@ -232,4 +229,44 @@ static int contec_di_insn_bits(struct comedi_device *dev,
return 2; return 2;
} }
COMEDI_PCI_INITCLEANUP(driver_contec, contec_pci_table); static int __devinit driver_contec_pci_probe(struct pci_dev *dev,
const struct pci_device_id *ent)
{
return comedi_pci_auto_config(dev, driver_contec.driver_name);
}
static void __devexit driver_contec_pci_remove(struct pci_dev *dev)
{
comedi_pci_auto_unconfig(dev);
}
static struct pci_driver driver_contec_pci_driver = {
.id_table = contec_pci_table,
.probe = &driver_contec_pci_probe,
.remove = __devexit_p(&driver_contec_pci_remove)
};
static int __init driver_contec_init_module(void)
{
int retval;
retval = comedi_driver_register(&driver_contec);
if (retval < 0)
return retval;
driver_contec_pci_driver.name = (char *)driver_contec.driver_name;
return pci_register_driver(&driver_contec_pci_driver);
}
static void __exit driver_contec_cleanup_module(void)
{
pci_unregister_driver(&driver_contec_pci_driver);
comedi_driver_unregister(&driver_contec);
}
module_init(driver_contec_init_module);
module_exit(driver_contec_cleanup_module);
MODULE_AUTHOR("Comedi http://www.comedi.org");
MODULE_DESCRIPTION("Comedi low-level driver");
MODULE_LICENSE("GPL");

View File

@ -887,4 +887,46 @@ static int daqboard2000_detach(struct comedi_device *dev)
return 0; return 0;
} }
COMEDI_PCI_INITCLEANUP(driver_daqboard2000, daqboard2000_pci_table); static int __devinit driver_daqboard2000_pci_probe(struct pci_dev *dev,
const struct pci_device_id
*ent)
{
return comedi_pci_auto_config(dev, driver_daqboard2000.driver_name);
}
static void __devexit driver_daqboard2000_pci_remove(struct pci_dev *dev)
{
comedi_pci_auto_unconfig(dev);
}
static struct pci_driver driver_daqboard2000_pci_driver = {
.id_table = daqboard2000_pci_table,
.probe = &driver_daqboard2000_pci_probe,
.remove = __devexit_p(&driver_daqboard2000_pci_remove)
};
static int __init driver_daqboard2000_init_module(void)
{
int retval;
retval = comedi_driver_register(&driver_daqboard2000);
if (retval < 0)
return retval;
driver_daqboard2000_pci_driver.name =
(char *)driver_daqboard2000.driver_name;
return pci_register_driver(&driver_daqboard2000_pci_driver);
}
static void __exit driver_daqboard2000_cleanup_module(void)
{
pci_unregister_driver(&driver_daqboard2000_pci_driver);
comedi_driver_unregister(&driver_daqboard2000);
}
module_init(driver_daqboard2000_init_module);
module_exit(driver_daqboard2000_cleanup_module);
MODULE_AUTHOR("Comedi http://www.comedi.org");
MODULE_DESCRIPTION("Comedi low-level driver");
MODULE_LICENSE("GPL");

View File

@ -980,7 +980,7 @@ static int das08_attach(struct comedi_device *dev, struct comedi_devconfig *it)
unsigned long iobase; unsigned long iobase;
#ifdef CONFIG_COMEDI_PCI #ifdef CONFIG_COMEDI_PCI
unsigned long pci_iobase = 0; unsigned long pci_iobase = 0;
struct pci_dev *pdev; struct pci_dev *pdev = NULL;
#endif #endif
ret = alloc_private(dev, sizeof(struct das08_private_struct)); ret = alloc_private(dev, sizeof(struct das08_private_struct));
@ -997,9 +997,7 @@ static int das08_attach(struct comedi_device *dev, struct comedi_devconfig *it)
} }
printk("\n"); printk("\n");
/* find card */ /* find card */
for (pdev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, NULL); for_each_pci_dev(pdev) {
pdev != NULL;
pdev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pdev)) {
if (pdev->vendor == PCI_VENDOR_ID_COMPUTERBOARDS if (pdev->vendor == PCI_VENDOR_ID_COMPUTERBOARDS
&& pdev->device == PCI_DEVICE_ID_PCIDAS08) { && pdev->device == PCI_DEVICE_ID_PCIDAS08) {
if (it->options[0] || it->options[1]) { if (it->options[0] || it->options[1]) {
@ -1082,11 +1080,62 @@ int das08_common_detach(struct comedi_device *dev)
EXPORT_SYMBOL_GPL(das08_common_detach); EXPORT_SYMBOL_GPL(das08_common_detach);
#ifdef CONFIG_COMEDI_PCI #ifdef CONFIG_COMEDI_PCI
COMEDI_PCI_INITCLEANUP(driver_das08, das08_pci_table); static int __devinit driver_das08_pci_probe(struct pci_dev *dev,
const struct pci_device_id *ent)
{
return comedi_pci_auto_config(dev, driver_das08.driver_name);
}
static void __devexit driver_das08_pci_remove(struct pci_dev *dev)
{
comedi_pci_auto_unconfig(dev);
}
static struct pci_driver driver_das08_pci_driver = {
.id_table = das08_pci_table,
.probe = &driver_das08_pci_probe,
.remove = __devexit_p(&driver_das08_pci_remove)
};
static int __init driver_das08_init_module(void)
{
int retval;
retval = comedi_driver_register(&driver_das08);
if (retval < 0)
return retval;
driver_das08_pci_driver.name = (char *)driver_das08.driver_name;
return pci_register_driver(&driver_das08_pci_driver);
}
static void __exit driver_das08_cleanup_module(void)
{
pci_unregister_driver(&driver_das08_pci_driver);
comedi_driver_unregister(&driver_das08);
}
module_init(driver_das08_init_module);
module_exit(driver_das08_cleanup_module);
#else #else
COMEDI_INITCLEANUP(driver_das08); static int __init driver_das08_init_module(void)
{
return comedi_driver_register(&driver_das08);
}
static void __exit driver_das08_cleanup_module(void)
{
comedi_driver_unregister(&driver_das08);
}
module_init(driver_das08_init_module);
module_exit(driver_das08_cleanup_module);
#endif #endif
#ifdef CONFIG_COMEDI_PCMCIA #ifdef CONFIG_COMEDI_PCMCIA
EXPORT_SYMBOL_GPL(das08_cs_boards); EXPORT_SYMBOL_GPL(das08_cs_boards);
#endif #endif
MODULE_AUTHOR("Comedi http://www.comedi.org");
MODULE_DESCRIPTION("Comedi low-level driver");
MODULE_LICENSE("GPL");

View File

@ -206,7 +206,6 @@ static void das08_pcmcia_detach(struct pcmcia_device *link)
das08_pcmcia_release(link); das08_pcmcia_release(link);
/* This points to the parent struct local_info_t struct */ /* This points to the parent struct local_info_t struct */
if (link->priv)
kfree(link->priv); kfree(link->priv);
} /* das08_pcmcia_detach */ } /* das08_pcmcia_detach */

View File

@ -1717,7 +1717,18 @@ static int das16_detach(struct comedi_device *dev)
return 0; return 0;
} }
COMEDI_INITCLEANUP(driver_das16); static int __init driver_das16_init_module(void)
{
return comedi_driver_register(&driver_das16);
}
static void __exit driver_das16_cleanup_module(void)
{
comedi_driver_unregister(&driver_das16);
}
module_init(driver_das16_init_module);
module_exit(driver_das16_cleanup_module);
/* utility function that suggests a dma transfer size in bytes */ /* utility function that suggests a dma transfer size in bytes */
static unsigned int das16_suggest_transfer_size(struct comedi_device *dev, static unsigned int das16_suggest_transfer_size(struct comedi_device *dev,
@ -1776,3 +1787,7 @@ static void das16_ai_munge(struct comedi_device *dev,
} }
} }
MODULE_AUTHOR("Comedi http://www.comedi.org");
MODULE_DESCRIPTION("Comedi low-level driver");
MODULE_LICENSE("GPL");

Some files were not shown because too many files have changed in this diff Show More