mirror of
https://github.com/torvalds/linux.git
synced 2024-11-02 18:21:49 +00:00
Merge git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging-2.6: (524 commits) Staging: wlan-ng: Update prism2_set_tx_power() to use mBm Staging: ti-st: update TODO Staging: wlags49_h2: use common PCI_VENDOR/DEVICE_ID name format Staging: comedi : fix brace coding style issue in wwrap.c Staging: quatech_usb2: remove unused qt2_box_flush function Staging: slicoss: Remove net_device_stats from the driver's private staging: rtl8192su: check whether requests succeeded staging: panel: fix error path staging: otus: check kmalloc() return value staging: octeon: check request_irq() return value Staging: wlan-ng: remove typedef in p80211hdr.h Staging: wlan-ng: fix checkpatch issues in headers. Staging: wlan-ng: remove typedef in p80211ioctl.h Staging: wlan-ng: fix style issues in p80211conv.h Staging: wlan-ng: fix style issues for p80211hdr.h staging: vt6656: removed NTSTATUS definition staging: vt6656: simplified tests involving both multi/broad-casts Staging: vt6655: replace BOOL with in kernel bool Staging: vt6655: replace FALSE with in kernel false Staging: vt6655: replace TRUE with in kernel true ...
This commit is contained in:
commit
cc41f5cede
@ -18,6 +18,7 @@
|
||||
#include <asm/mshyperv.h>
|
||||
|
||||
struct ms_hyperv_info ms_hyperv;
|
||||
EXPORT_SYMBOL_GPL(ms_hyperv);
|
||||
|
||||
static bool __init ms_hyperv_platform(void)
|
||||
{
|
||||
|
@ -97,6 +97,8 @@ source "drivers/staging/octeon/Kconfig"
|
||||
|
||||
source "drivers/staging/serqt_usb2/Kconfig"
|
||||
|
||||
source "drivers/staging/spectra/Kconfig"
|
||||
|
||||
source "drivers/staging/quatech_usb2/Kconfig"
|
||||
|
||||
source "drivers/staging/vt6655/Kconfig"
|
||||
@ -115,7 +117,7 @@ source "drivers/staging/sep/Kconfig"
|
||||
|
||||
source "drivers/staging/iio/Kconfig"
|
||||
|
||||
source "drivers/staging/ramzswap/Kconfig"
|
||||
source "drivers/staging/zram/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/dt3155/Kconfig"
|
||||
|
||||
source "drivers/staging/dt3155v4l/Kconfig"
|
||||
|
||||
source "drivers/staging/crystalhd/Kconfig"
|
||||
@ -147,5 +147,13 @@ source "drivers/staging/msm/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
|
||||
|
@ -23,6 +23,7 @@ obj-$(CONFIG_R8187SE) += rtl8187se/
|
||||
obj-$(CONFIG_RTL8192SU) += rtl8192su/
|
||||
obj-$(CONFIG_RTL8192U) += rtl8192u/
|
||||
obj-$(CONFIG_RTL8192E) += rtl8192e/
|
||||
obj-$(CONFIG_SPECTRA) += spectra/
|
||||
obj-$(CONFIG_TRANZPORT) += frontier/
|
||||
obj-$(CONFIG_DREAM) += dream/
|
||||
obj-$(CONFIG_POHMELFS) += pohmelfs/
|
||||
@ -39,13 +40,12 @@ obj-$(CONFIG_VME_BUS) += vme/
|
||||
obj-$(CONFIG_MRST_RAR_HANDLER) += memrar/
|
||||
obj-$(CONFIG_DX_SEP) += sep/
|
||||
obj-$(CONFIG_IIO) += iio/
|
||||
obj-$(CONFIG_RAMZSWAP) += ramzswap/
|
||||
obj-$(CONFIG_ZRAM) += zram/
|
||||
obj-$(CONFIG_WLAGS49_H2) += wlags49_h2/
|
||||
obj-$(CONFIG_WLAGS49_H25) += wlags49_h25/
|
||||
obj-$(CONFIG_BATMAN_ADV) += batman-adv/
|
||||
obj-$(CONFIG_SAMSUNG_LAPTOP) += samsung-laptop/
|
||||
obj-$(CONFIG_FB_SM7XX) += sm7xx/
|
||||
obj-$(CONFIG_DT3155) += dt3155/
|
||||
obj-$(CONFIG_VIDEO_DT3155) += dt3155v4l/
|
||||
obj-$(CONFIG_CRYSTALHD) += crystalhd/
|
||||
obj-$(CONFIG_CXT1E1) += cxt1e1/
|
||||
@ -54,3 +54,7 @@ obj-$(CONFIG_ADIS16255) += adis16255/
|
||||
obj-$(CONFIG_FB_XGI) += xgifb/
|
||||
obj-$(CONFIG_TOUCHSCREEN_MRSTOUCH) += mrst-touchscreen/
|
||||
obj-$(CONFIG_MSM_STAGING) += msm/
|
||||
obj-$(CONFIG_EASYCAP) += easycap/
|
||||
obj-$(CONFIG_SOLO6X10) += solo6x10/
|
||||
obj-$(CONFIG_TIDSPBRIDGE) += tidspbridge/
|
||||
obj-$(CONFIG_ACPI_QUICKSTART) += quickstart/
|
||||
|
@ -303,7 +303,7 @@ static int spi_adis16255_bringup(struct spi_adis16255_data *spiadis)
|
||||
if (status != 0)
|
||||
goto err;
|
||||
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);
|
||||
}
|
||||
|
||||
@ -338,7 +338,7 @@ static int spi_adis16255_bringup(struct spi_adis16255_data *spiadis)
|
||||
status = -ENODEV;
|
||||
goto err;
|
||||
} else if (value & 0x3) {
|
||||
dev_warn(&spiadis->spi->dev, "Sensor voltage"
|
||||
dev_warn(&spiadis->spi->dev, "Sensor voltage "
|
||||
"out of range.\n");
|
||||
status = -ENODEV;
|
||||
goto err;
|
||||
|
@ -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:
|
||||
|
||||
* support latest kernels (2.6.20 - 2.6.33)
|
||||
|
@ -4,7 +4,7 @@
|
||||
|
||||
config BATMAN_ADV
|
||||
tristate "B.A.T.M.A.N. Advanced Meshing Protocol"
|
||||
depends on PROC_FS && NET
|
||||
depends on NET
|
||||
default n
|
||||
---help---
|
||||
|
||||
|
@ -18,5 +18,5 @@
|
||||
# 02110-1301, USA
|
||||
#
|
||||
|
||||
obj-m += 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
|
||||
obj-$(CONFIG_BATMAN_ADV) += batman-adv.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
|
||||
|
@ -1,4 +1,4 @@
|
||||
[state: 03-05-2010]
|
||||
[state: 12-06-2010]
|
||||
|
||||
BATMAN-ADV
|
||||
----------
|
||||
|
@ -1,6 +1,9 @@
|
||||
Request a review.
|
||||
Process the comments from the review.
|
||||
Move into mainline proper.
|
||||
* Use hweight* for hamming weight calculation
|
||||
* Save/cache packets direktly as skb instead of using a normal memory region
|
||||
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:
|
||||
Marek Lindner <lindner_marek@yahoo.de>
|
||||
|
@ -106,11 +106,14 @@ static void new_aggregated_packet(unsigned char *packet_buff,
|
||||
{
|
||||
struct forw_packet *forw_packet_aggr;
|
||||
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 */
|
||||
if (!own_packet) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
@ -252,9 +255,9 @@ void receive_aggr_bat_packet(struct ethhdr *ethhdr, unsigned char *packet_buff,
|
||||
while (aggregated_packet(buff_pos, packet_len,
|
||||
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. */
|
||||
batman_packet->seqno = ntohs(batman_packet->seqno);
|
||||
batman_packet->seqno = ntohl(batman_packet->seqno);
|
||||
|
||||
hna_buff = packet_buff + buff_pos + BAT_PACKET_LEN;
|
||||
receive_bat_packet(ethhdr, batman_packet,
|
||||
|
@ -19,6 +19,9 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _NET_BATMAN_ADV_AGGREGATION_H_
|
||||
#define _NET_BATMAN_ADV_AGGREGATION_H_
|
||||
|
||||
#include "main.h"
|
||||
|
||||
/* 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);
|
||||
void receive_aggr_bat_packet(struct ethhdr *ethhdr, unsigned char *packet_buff,
|
||||
int packet_len, struct batman_if *if_incoming);
|
||||
|
||||
#endif /* _NET_BATMAN_ADV_AGGREGATION_H_ */
|
||||
|
341
drivers/staging/batman-adv/bat_debugfs.c
Normal file
341
drivers/staging/batman-adv/bat_debugfs.c
Normal 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;
|
||||
}
|
||||
}
|
33
drivers/staging/batman-adv/bat_debugfs.h
Normal file
33
drivers/staging/batman-adv/bat_debugfs.h
Normal 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_ */
|
@ -28,22 +28,6 @@
|
||||
|
||||
#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) \
|
||||
struct bat_attribute bat_attr_##_name = { \
|
||||
.attr = {.name = __stringify(_name), \
|
||||
@ -52,34 +36,18 @@ struct bat_attribute bat_attr_##_name = { \
|
||||
.store = _store, \
|
||||
};
|
||||
|
||||
#define BAT_BIN_ATTR(_name, _mode, _read, _write) \
|
||||
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,
|
||||
static ssize_t show_aggr_ogms(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 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");
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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')
|
||||
buff[count - 1] = '\0';
|
||||
|
||||
printk(KERN_INFO "batman-adv:Invalid parameter for 'aggregate OGM' setting on mesh %s received: %s\n",
|
||||
net_dev->name, buff);
|
||||
bat_info(net_dev,
|
||||
"Invalid parameter for 'aggregate OGM' setting"
|
||||
"received: %s\n", buff);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (atomic_read(&bat_priv->aggregation_enabled) == aggr_tmp)
|
||||
return count;
|
||||
|
||||
printk(KERN_INFO "batman-adv:Changing aggregation from: %s to: %s on mesh: %s\n",
|
||||
atomic_read(&bat_priv->aggregation_enabled) == 1 ?
|
||||
"enabled" : "disabled", aggr_tmp == 1 ? "enabled" : "disabled",
|
||||
net_dev->name);
|
||||
bat_info(net_dev, "Changing aggregation from: %s to: %s\n",
|
||||
atomic_read(&bat_priv->aggregation_enabled) == 1 ?
|
||||
"enabled" : "disabled", aggr_tmp == 1 ? "enabled" :
|
||||
"disabled");
|
||||
|
||||
atomic_set(&bat_priv->aggregation_enabled, (unsigned)aggr_tmp);
|
||||
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,
|
||||
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));
|
||||
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 ?
|
||||
"client" : "server",
|
||||
VIS_TYPE_SERVER_SYNC, VIS_TYPE_CLIENT_UPDATE);
|
||||
"client" : "server");
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
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;
|
||||
|
||||
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')
|
||||
buff[count - 1] = '\0';
|
||||
|
||||
printk(KERN_INFO "batman-adv:Invalid parameter for 'vis mode' setting on mesh %s received: %s\n",
|
||||
net_dev->name, buff);
|
||||
bat_info(net_dev,
|
||||
"Invalid parameter for 'vis mode' setting received: "
|
||||
"%s\n", buff);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (atomic_read(&bat_priv->vis_mode) == vis_mode_tmp)
|
||||
return count;
|
||||
|
||||
printk(KERN_INFO "batman-adv:Changing vis mode from: %s to: %s on mesh: %s\n",
|
||||
atomic_read(&bat_priv->vis_mode) == VIS_TYPE_CLIENT_UPDATE ?
|
||||
"client" : "server", vis_mode_tmp == VIS_TYPE_CLIENT_UPDATE ?
|
||||
"client" : "server", net_dev->name);
|
||||
bat_info(net_dev, "Changing vis mode from: %s to: %s\n",
|
||||
atomic_read(&bat_priv->vis_mode) == VIS_TYPE_CLIENT_UPDATE ?
|
||||
"client" : "server", vis_mode_tmp == VIS_TYPE_CLIENT_UPDATE ?
|
||||
"client" : "server");
|
||||
|
||||
atomic_set(&bat_priv->vis_mode, (unsigned)vis_mode_tmp);
|
||||
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 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));
|
||||
}
|
||||
|
||||
@ -190,91 +209,87 @@ static ssize_t store_orig_interval(struct kobject *kobj, struct attribute *attr,
|
||||
|
||||
ret = strict_strtoul(buff, 10, &orig_interval_tmp);
|
||||
if (ret) {
|
||||
printk(KERN_INFO "batman-adv:Invalid parameter for 'orig_interval' setting on mesh %s received: %s\n",
|
||||
net_dev->name, buff);
|
||||
bat_info(net_dev, "Invalid parameter for 'orig_interval' "
|
||||
"setting received: %s\n", buff);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (orig_interval_tmp <= JITTER * 2) {
|
||||
printk(KERN_INFO "batman-adv:New originator interval too small: %li (min: %i)\n",
|
||||
orig_interval_tmp, JITTER * 2);
|
||||
if (orig_interval_tmp < JITTER * 2) {
|
||||
bat_info(net_dev, "New originator interval too small: %li "
|
||||
"(min: %i)\n", orig_interval_tmp, JITTER * 2);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (atomic_read(&bat_priv->orig_interval) == orig_interval_tmp)
|
||||
return count;
|
||||
|
||||
printk(KERN_INFO "batman-adv:Changing originator interval from: %i to: %li on mesh: %s\n",
|
||||
atomic_read(&bat_priv->orig_interval),
|
||||
orig_interval_tmp, net_dev->name);
|
||||
bat_info(net_dev, "Changing originator interval from: %i to: %li\n",
|
||||
atomic_read(&bat_priv->orig_interval),
|
||||
orig_interval_tmp);
|
||||
|
||||
atomic_set(&bat_priv->orig_interval, orig_interval_tmp);
|
||||
return count;
|
||||
}
|
||||
|
||||
static BAT_ATTR(aggregate_ogm, S_IRUGO | S_IWUSR,
|
||||
show_aggr_ogm, store_aggr_ogm);
|
||||
#ifdef CONFIG_BATMAN_ADV_DEBUG
|
||||
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(orig_interval, S_IRUGO | S_IWUSR,
|
||||
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[] = {
|
||||
&bat_attr_aggregate_ogm,
|
||||
&bat_attr_aggregated_ogms,
|
||||
&bat_attr_bonding,
|
||||
&bat_attr_vis_mode,
|
||||
&bat_attr_orig_interval,
|
||||
NULL,
|
||||
};
|
||||
|
||||
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,
|
||||
#ifdef CONFIG_BATMAN_ADV_DEBUG
|
||||
&bat_attr_log_level,
|
||||
#endif
|
||||
NULL,
|
||||
};
|
||||
|
||||
@ -283,22 +298,24 @@ int sysfs_add_meshif(struct net_device *dev)
|
||||
struct kobject *batif_kobject = &dev->dev.kobj;
|
||||
struct bat_priv *bat_priv = netdev_priv(dev);
|
||||
struct bat_attribute **bat_attr;
|
||||
struct bin_attribute **bin_attr;
|
||||
int err;
|
||||
|
||||
/* FIXME: should be done in the general mesh setup
|
||||
routine as soon as we have it */
|
||||
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->orig_interval, 1000);
|
||||
atomic_set(&bat_priv->log_level, 0);
|
||||
|
||||
bat_priv->primary_if = NULL;
|
||||
bat_priv->num_ifaces = 0;
|
||||
|
||||
bat_priv->mesh_obj = kobject_create_and_add(SYSFS_IF_MESH_SUBDIR,
|
||||
batif_kobject);
|
||||
if (!bat_priv->mesh_obj) {
|
||||
printk(KERN_ERR "batman-adv:Can't add sysfs directory: %s/%s\n",
|
||||
dev->name, SYSFS_IF_MESH_SUBDIR);
|
||||
bat_err(dev, "Can't add sysfs directory: %s/%s\n", dev->name,
|
||||
SYSFS_IF_MESH_SUBDIR);
|
||||
goto out;
|
||||
}
|
||||
|
||||
@ -306,28 +323,15 @@ int sysfs_add_meshif(struct net_device *dev)
|
||||
err = sysfs_create_file(bat_priv->mesh_obj,
|
||||
&((*bat_attr)->attr));
|
||||
if (err) {
|
||||
printk(KERN_ERR "batman-adv:Can't add sysfs file: %s/%s/%s\n",
|
||||
dev->name, SYSFS_IF_MESH_SUBDIR,
|
||||
((*bat_attr)->attr).name);
|
||||
bat_err(dev, "Can't add sysfs file: %s/%s/%s\n",
|
||||
dev->name, SYSFS_IF_MESH_SUBDIR,
|
||||
((*bat_attr)->attr).name);
|
||||
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;
|
||||
|
||||
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:
|
||||
for (bat_attr = mesh_attrs; *bat_attr; ++bat_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_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)
|
||||
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)
|
||||
return 0;
|
||||
|
||||
return sprintf(buff, "status: %s\ncommands: none, bat0\n",
|
||||
return sprintf(buff, "%s\n",
|
||||
batman_if->if_status == IF_NOT_IN_USE ?
|
||||
"none" : "bat0");
|
||||
}
|
||||
@ -390,8 +390,8 @@ static ssize_t store_mesh_iface(struct kobject *kobj, struct attribute *attr,
|
||||
if (buff[count - 1] == '\n')
|
||||
buff[count - 1] = '\0';
|
||||
|
||||
printk(KERN_ERR "batman-adv:Invalid parameter for 'mesh_iface' setting received: %s\n",
|
||||
buff);
|
||||
pr_err("Invalid parameter for 'mesh_iface' setting received: "
|
||||
"%s\n", buff);
|
||||
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,
|
||||
show_mesh_iface, store_mesh_iface);
|
||||
static HARDIF_ATTR(iface_status, S_IRUGO, show_iface_status, NULL);
|
||||
static BAT_ATTR(mesh_iface, S_IRUGO | S_IWUSR,
|
||||
show_mesh_iface, store_mesh_iface);
|
||||
static BAT_ATTR(iface_status, S_IRUGO, show_iface_status, NULL);
|
||||
|
||||
static struct hardif_attribute *batman_attrs[] = {
|
||||
&hardif_attr_mesh_iface,
|
||||
&hardif_attr_iface_status,
|
||||
static struct bat_attribute *batman_attrs[] = {
|
||||
&bat_attr_mesh_iface,
|
||||
&bat_attr_iface_status,
|
||||
NULL,
|
||||
};
|
||||
|
||||
int sysfs_add_hardif(struct kobject **hardif_obj, struct net_device *dev)
|
||||
{
|
||||
struct kobject *hardif_kobject = &dev->dev.kobj;
|
||||
struct hardif_attribute **hardif_attr;
|
||||
struct bat_attribute **bat_attr;
|
||||
int err;
|
||||
|
||||
*hardif_obj = kobject_create_and_add(SYSFS_IF_BAT_SUBDIR,
|
||||
hardif_kobject);
|
||||
|
||||
if (!*hardif_obj) {
|
||||
printk(KERN_ERR "batman-adv:Can't add sysfs directory: %s/%s\n",
|
||||
dev->name, SYSFS_IF_BAT_SUBDIR);
|
||||
bat_err(dev, "Can't add sysfs directory: %s/%s\n", dev->name,
|
||||
SYSFS_IF_BAT_SUBDIR);
|
||||
goto out;
|
||||
}
|
||||
|
||||
for (hardif_attr = batman_attrs; *hardif_attr; ++hardif_attr) {
|
||||
err = sysfs_create_file(*hardif_obj, &((*hardif_attr)->attr));
|
||||
for (bat_attr = batman_attrs; *bat_attr; ++bat_attr) {
|
||||
err = sysfs_create_file(*hardif_obj, &((*bat_attr)->attr));
|
||||
if (err) {
|
||||
printk(KERN_ERR "batman-adv:Can't add sysfs file: %s/%s/%s\n",
|
||||
dev->name, SYSFS_IF_BAT_SUBDIR,
|
||||
((*hardif_attr)->attr).name);
|
||||
bat_err(dev, "Can't add sysfs file: %s/%s/%s\n",
|
||||
dev->name, SYSFS_IF_BAT_SUBDIR,
|
||||
((*bat_attr)->attr).name);
|
||||
goto rem_attr;
|
||||
}
|
||||
}
|
||||
@ -471,8 +471,8 @@ int sysfs_add_hardif(struct kobject **hardif_obj, struct net_device *dev)
|
||||
return 0;
|
||||
|
||||
rem_attr:
|
||||
for (hardif_attr = batman_attrs; *hardif_attr; ++hardif_attr)
|
||||
sysfs_remove_file(*hardif_obj, &((*hardif_attr)->attr));
|
||||
for (bat_attr = batman_attrs; *bat_attr; ++bat_attr)
|
||||
sysfs_remove_file(*hardif_obj, &((*bat_attr)->attr));
|
||||
out:
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
@ -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_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);
|
||||
void sysfs_del_meshif(struct net_device *dev);
|
||||
int sysfs_add_hardif(struct kobject **hardif_obj, struct net_device *dev);
|
||||
void sysfs_del_hardif(struct kobject **hardif_obj);
|
||||
|
||||
#endif /* _NET_BATMAN_ADV_SYSFS_H_ */
|
||||
|
@ -24,10 +24,10 @@
|
||||
|
||||
/* returns true if the corresponding bit in the given seq_bits indicates true
|
||||
* and curr_seqno is within range of last_seqno */
|
||||
uint8_t get_bit_status(TYPE_OF_WORD *seq_bits, uint16_t last_seqno,
|
||||
uint16_t curr_seqno)
|
||||
uint8_t get_bit_status(TYPE_OF_WORD *seq_bits, uint32_t last_seqno,
|
||||
uint32_t curr_seqno)
|
||||
{
|
||||
int16_t diff, word_offset, word_num;
|
||||
int32_t diff, word_offset, word_num;
|
||||
|
||||
diff = last_seqno - curr_seqno;
|
||||
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. */
|
||||
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 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)
|
||||
* 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)
|
||||
{
|
||||
/* 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
|
||||
* 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)
|
||||
|| (seq_num_diff < EXPECTED_SEQNO_RANGE)) {
|
||||
bat_dbg(DBG_BATMAN,
|
||||
bat_dbg(DBG_BATMAN, bat_priv,
|
||||
"We missed a lot of packets (%i) !\n",
|
||||
seq_num_diff - 1);
|
||||
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)
|
||||
|| (seq_num_diff >= EXPECTED_SEQNO_RANGE)) {
|
||||
|
||||
bat_dbg(DBG_BATMAN,
|
||||
bat_dbg(DBG_BATMAN, bat_priv,
|
||||
"Other host probably restarted!\n");
|
||||
|
||||
bit_reset_window(seq_bits);
|
||||
|
@ -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 */
|
||||
#define TYPE_OF_WORD unsigned long
|
||||
@ -26,20 +28,19 @@
|
||||
|
||||
/* returns true if the corresponding bit in the given seq_bits indicates true
|
||||
* and curr_seqno is within range of last_seqno */
|
||||
uint8_t get_bit_status(TYPE_OF_WORD *seq_bits, uint16_t last_seqno,
|
||||
uint16_t curr_seqno);
|
||||
uint8_t get_bit_status(TYPE_OF_WORD *seq_bits, uint32_t last_seqno,
|
||||
uint32_t curr_seqno);
|
||||
|
||||
/* turn corresponding bit on, so we can remember that we got the packet */
|
||||
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
|
||||
* 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);
|
||||
|
||||
/* count the hamming weight, how many good packets did we receive? */
|
||||
int bit_packet_count(TYPE_OF_WORD *seq_bits);
|
||||
|
||||
#endif /* _NET_BATMAN_ADV_BITARRAY_H_ */
|
||||
|
@ -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);
|
||||
}
|
@ -30,6 +30,7 @@
|
||||
#include "hash.h"
|
||||
|
||||
#include <linux/if_arp.h>
|
||||
#include <linux/netfilter_bridge.h>
|
||||
|
||||
#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);
|
||||
|
||||
batman_packet = (struct batman_packet *)(batman_if->packet_buff);
|
||||
batman_packet->flags = 0;
|
||||
batman_packet->flags = PRIMARIES_FIRST_HOP;
|
||||
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))
|
||||
continue;
|
||||
|
||||
printk(KERN_WARNING "batman-adv:"
|
||||
"The newly added mac address (%pM) already exists on: %s\n",
|
||||
addr, batman_if->dev);
|
||||
printk(KERN_WARNING "batman-adv:"
|
||||
"It is strongly recommended to keep mac addresses unique"
|
||||
"to avoid problems!\n");
|
||||
pr_warning("The newly added mac address (%pM) already exists "
|
||||
"on: %s\n", addr, batman_if->dev);
|
||||
pr_warning("It is strongly recommended to keep mac addresses "
|
||||
"unique to avoid problems!\n");
|
||||
}
|
||||
rcu_read_unlock();
|
||||
}
|
||||
@ -188,7 +187,8 @@ void update_min_mtu(void)
|
||||
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)
|
||||
{
|
||||
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)
|
||||
set_primary_if(bat_priv, batman_if);
|
||||
|
||||
printk(KERN_INFO "batman-adv:Interface activated: %s\n",
|
||||
batman_if->dev);
|
||||
bat_info(net_dev, "Interface activated: %s\n", batman_if->dev);
|
||||
|
||||
if (atomic_read(&module_state) == MODULE_INACTIVE)
|
||||
activate_module();
|
||||
@ -216,7 +215,8 @@ static void hardif_activate_interface(struct bat_priv *bat_priv,
|
||||
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) &&
|
||||
(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;
|
||||
|
||||
printk(KERN_INFO "batman-adv:Interface deactivated: %s\n",
|
||||
batman_if->dev);
|
||||
bat_info(net_dev, "Interface deactivated: %s\n", batman_if->dev);
|
||||
|
||||
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);
|
||||
|
||||
if (!batman_if->packet_buff) {
|
||||
printk(KERN_ERR "batman-adv:"
|
||||
"Can't add interface packet (%s): out of memory\n",
|
||||
batman_if->dev);
|
||||
bat_err(soft_device, "Can't add interface packet (%s): "
|
||||
"out of memory\n", batman_if->dev);
|
||||
goto err;
|
||||
}
|
||||
|
||||
@ -265,15 +263,14 @@ int hardif_enable_interface(struct batman_if *batman_if)
|
||||
orig_hash_add_if(batman_if, bat_priv->num_ifaces);
|
||||
|
||||
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))
|
||||
hardif_activate_interface(bat_priv, batman_if);
|
||||
hardif_activate_interface(soft_device, bat_priv, batman_if);
|
||||
else
|
||||
printk(KERN_ERR "batman-adv:"
|
||||
"Not using interface %s "
|
||||
"(retrying later): interface not active\n",
|
||||
batman_if->dev);
|
||||
bat_err(soft_device, "Not using interface %s "
|
||||
"(retrying later): interface not active\n",
|
||||
batman_if->dev);
|
||||
|
||||
/* begin scheduling originator messages on that interface */
|
||||
schedule_own_packet(batman_if);
|
||||
@ -291,12 +288,12 @@ void hardif_disable_interface(struct batman_if *batman_if)
|
||||
struct bat_priv *bat_priv = netdev_priv(soft_device);
|
||||
|
||||
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)
|
||||
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--;
|
||||
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);
|
||||
if (!batman_if) {
|
||||
printk(KERN_ERR "batman-adv:"
|
||||
"Can't add interface (%s): out of memory\n",
|
||||
pr_err("Can't add interface (%s): out of memory\n",
|
||||
net_dev->name);
|
||||
goto out;
|
||||
}
|
||||
@ -407,11 +403,11 @@ static int hard_if_event(struct notifier_block *this,
|
||||
case NETDEV_REGISTER:
|
||||
break;
|
||||
case NETDEV_UP:
|
||||
hardif_activate_interface(bat_priv, batman_if);
|
||||
hardif_activate_interface(soft_device, bat_priv, batman_if);
|
||||
break;
|
||||
case NETDEV_GOING_DOWN:
|
||||
case NETDEV_DOWN:
|
||||
hardif_deactivate_interface(batman_if);
|
||||
hardif_deactivate_interface(soft_device, batman_if);
|
||||
break;
|
||||
case NETDEV_UNREGISTER:
|
||||
hardif_remove_interface(batman_if);
|
||||
@ -432,11 +428,18 @@ out:
|
||||
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
|
||||
* interface */
|
||||
int batman_skb_recv(struct sk_buff *skb, struct net_device *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_if *batman_if;
|
||||
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)
|
||||
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 */
|
||||
if (unlikely(skb_headlen(skb) < 2))
|
||||
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;
|
||||
|
||||
if (batman_packet->version != COMPAT_VERSION) {
|
||||
bat_dbg(DBG_BATMAN,
|
||||
bat_dbg(DBG_BATMAN, bat_priv,
|
||||
"Drop packet: incompatible batman version (%i)\n",
|
||||
batman_packet->version);
|
||||
goto err_free;
|
||||
@ -500,7 +510,7 @@ int batman_skb_recv(struct sk_buff *skb, struct net_device *dev,
|
||||
|
||||
/* unicast packet */
|
||||
case BAT_UNICAST:
|
||||
ret = recv_unicast_packet(skb);
|
||||
ret = recv_unicast_packet(skb, batman_if);
|
||||
break;
|
||||
|
||||
/* broadcast packet */
|
||||
@ -531,7 +541,6 @@ err_out:
|
||||
return NET_RX_DROP;
|
||||
}
|
||||
|
||||
|
||||
struct notifier_block hard_if_notifier = {
|
||||
.notifier_call = hard_if_event,
|
||||
};
|
||||
|
@ -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_TO_BE_REMOVED 1
|
||||
#define IF_INACTIVE 2
|
||||
@ -38,3 +41,5 @@ int batman_skb_recv(struct sk_buff *skb,
|
||||
struct net_device *orig_dev);
|
||||
int hardif_min_mtu(void);
|
||||
void update_min_mtu(void);
|
||||
|
||||
#endif /* _NET_BATMAN_ADV_HARD_INTERFACE_H_ */
|
||||
|
@ -23,7 +23,7 @@
|
||||
#include "hash.h"
|
||||
|
||||
/* clears the hash */
|
||||
void hash_init(struct hashtable_t *hash)
|
||||
static void hash_init(struct hashtable_t *hash)
|
||||
{
|
||||
int i;
|
||||
|
||||
|
@ -19,8 +19,9 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _BATMAN_HASH_H
|
||||
#define _BATMAN_HASH_H
|
||||
#ifndef _NET_BATMAN_ADV_HASH_H_
|
||||
#define _NET_BATMAN_ADV_HASH_H_
|
||||
|
||||
#define HASHIT(name) struct hash_it_t name = { \
|
||||
.index = -1, .bucket = NULL, \
|
||||
.prev_bucket = NULL, \
|
||||
@ -56,9 +57,6 @@ struct hashtable_t {
|
||||
* argument and the size the second */
|
||||
};
|
||||
|
||||
/* clears the hash */
|
||||
void hash_init(struct hashtable_t *hash);
|
||||
|
||||
/* allocates and clears the hash */
|
||||
struct hashtable_t *hash_new(int size, hashdata_compare_cb compare,
|
||||
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 *iter_in);
|
||||
|
||||
/* print the hash table for debugging */
|
||||
void hash_debug(struct hashtable_t *hash);
|
||||
#endif
|
||||
#endif /* _NET_BATMAN_ADV_HASH_H_ */
|
||||
|
334
drivers/staging/batman-adv/icmp_socket.c
Normal file
334
drivers/staging/batman-adv/icmp_socket.c
Normal 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);
|
||||
}
|
@ -19,18 +19,16 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _NET_BATMAN_ADV_ICMP_SOCKET_H_
|
||||
#define _NET_BATMAN_ADV_ICMP_SOCKET_H_
|
||||
|
||||
#include "types.h"
|
||||
|
||||
void bat_device_init(void);
|
||||
int bat_device_setup(void);
|
||||
void bat_device_destroy(void);
|
||||
int bat_device_open(struct inode *inode, struct file *file);
|
||||
int bat_device_release(struct inode *inode, struct file *file);
|
||||
ssize_t bat_device_read(struct file *file, char __user *buf, size_t count,
|
||||
loff_t *ppos);
|
||||
ssize_t bat_device_write(struct file *file, const char __user *buff,
|
||||
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);
|
||||
#define ICMP_SOCKET "socket"
|
||||
|
||||
void bat_socket_init(void);
|
||||
int bat_socket_setup(struct bat_priv *bat_priv);
|
||||
void bat_socket_receive_packet(struct icmp_packet_rr *icmp_packet,
|
||||
size_t icmp_len);
|
||||
|
||||
#endif /* _NET_BATMAN_ADV_ICMP_SOCKET_H_ */
|
@ -21,11 +21,12 @@
|
||||
|
||||
#include "main.h"
|
||||
#include "bat_sysfs.h"
|
||||
#include "bat_debugfs.h"
|
||||
#include "routing.h"
|
||||
#include "send.h"
|
||||
#include "originator.h"
|
||||
#include "soft-interface.h"
|
||||
#include "device.h"
|
||||
#include "icmp_socket.h"
|
||||
#include "translation-table.h"
|
||||
#include "hard-interface.h"
|
||||
#include "types.h"
|
||||
@ -41,7 +42,6 @@ DEFINE_SPINLOCK(orig_hash_lock);
|
||||
DEFINE_SPINLOCK(forw_bat_list_lock);
|
||||
DEFINE_SPINLOCK(forw_bcast_list_lock);
|
||||
|
||||
atomic_t vis_interval;
|
||||
atomic_t bcast_queue_left;
|
||||
atomic_t batman_queue_left;
|
||||
|
||||
@ -49,7 +49,7 @@ int16_t num_hna;
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
|
||||
#ifdef CONFIG_BATMAN_ADV_DEBUG
|
||||
int debug;
|
||||
|
||||
module_param(debug, int, 0644);
|
||||
|
||||
int bat_debug_type(int type)
|
||||
{
|
||||
return debug & type;
|
||||
}
|
||||
#endif
|
||||
|
||||
int init_module(void)
|
||||
static int __init batman_init(void)
|
||||
{
|
||||
int retval;
|
||||
|
||||
@ -80,8 +69,6 @@ int init_module(void)
|
||||
|
||||
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(&batman_queue_left, BATMAN_QUEUE_LEN);
|
||||
|
||||
@ -92,23 +79,22 @@ int init_module(void)
|
||||
if (!bat_event_workqueue)
|
||||
return -ENOMEM;
|
||||
|
||||
bat_device_init();
|
||||
bat_socket_init();
|
||||
debugfs_init();
|
||||
|
||||
/* initialize layer 2 interface */
|
||||
soft_device = alloc_netdev(sizeof(struct bat_priv) , "bat%d",
|
||||
interface_setup);
|
||||
|
||||
if (!soft_device) {
|
||||
printk(KERN_ERR "batman-adv:"
|
||||
"Unable to allocate the batman interface\n");
|
||||
pr_err("Unable to allocate the batman interface\n");
|
||||
goto end;
|
||||
}
|
||||
|
||||
retval = register_netdev(soft_device);
|
||||
|
||||
if (retval < 0) {
|
||||
printk(KERN_ERR "batman-adv:"
|
||||
"Unable to register the batman interface: %i\n", retval);
|
||||
pr_err("Unable to register the batman interface: %i\n", retval);
|
||||
goto free_soft_device;
|
||||
}
|
||||
|
||||
@ -117,15 +103,22 @@ int init_module(void)
|
||||
if (retval < 0)
|
||||
goto unreg_soft_device;
|
||||
|
||||
retval = debugfs_add_meshif(soft_device);
|
||||
|
||||
if (retval < 0)
|
||||
goto unreg_sysfs;
|
||||
|
||||
register_netdevice_notifier(&hard_if_notifier);
|
||||
dev_add_pack(&batman_adv_packet_type);
|
||||
|
||||
printk(KERN_INFO "batman-adv:"
|
||||
"B.A.T.M.A.N. advanced %s%s (compatibility version %i) loaded\n",
|
||||
SOURCE_VERSION, REVISION_VERSION_STR, COMPAT_VERSION);
|
||||
pr_info("B.A.T.M.A.N. advanced %s%s (compatibility version %i) "
|
||||
"loaded\n", SOURCE_VERSION, REVISION_VERSION_STR,
|
||||
COMPAT_VERSION);
|
||||
|
||||
return 0;
|
||||
|
||||
unreg_sysfs:
|
||||
sysfs_del_meshif(soft_device);
|
||||
unreg_soft_device:
|
||||
unregister_netdev(soft_device);
|
||||
soft_device = NULL;
|
||||
@ -138,14 +131,16 @@ end:
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
void cleanup_module(void)
|
||||
static void __exit batman_exit(void)
|
||||
{
|
||||
deactivate_module();
|
||||
|
||||
debugfs_destroy();
|
||||
unregister_netdevice_notifier(&hard_if_notifier);
|
||||
hardif_remove_interfaces();
|
||||
|
||||
if (soft_device) {
|
||||
debugfs_del_meshif(soft_device);
|
||||
sysfs_del_meshif(soft_device);
|
||||
unregister_netdev(soft_device);
|
||||
soft_device = NULL;
|
||||
@ -157,7 +152,7 @@ void cleanup_module(void)
|
||||
bat_event_workqueue = NULL;
|
||||
}
|
||||
|
||||
/* activates the module, creates bat device, starts timer ... */
|
||||
/* activates the module, starts timer ... */
|
||||
void activate_module(void)
|
||||
{
|
||||
if (originator_init() < 1)
|
||||
@ -171,9 +166,6 @@ void activate_module(void)
|
||||
|
||||
hna_local_add(soft_device->dev_addr);
|
||||
|
||||
if (bat_device_setup() < 1)
|
||||
goto end;
|
||||
|
||||
if (vis_init() < 1)
|
||||
goto err;
|
||||
|
||||
@ -182,8 +174,7 @@ void activate_module(void)
|
||||
goto end;
|
||||
|
||||
err:
|
||||
printk(KERN_ERR "batman-adv:"
|
||||
"Unable to allocate memory for mesh information structures: "
|
||||
pr_err("Unable to allocate memory for mesh information structures: "
|
||||
"out of mem ?\n");
|
||||
deactivate_module();
|
||||
end:
|
||||
@ -208,7 +199,6 @@ void deactivate_module(void)
|
||||
hna_global_free();
|
||||
|
||||
synchronize_net();
|
||||
bat_device_destroy();
|
||||
|
||||
synchronize_rcu();
|
||||
atomic_set(&module_state, MODULE_INACTIVE);
|
||||
@ -226,8 +216,7 @@ void dec_module_count(void)
|
||||
|
||||
int addr_to_string(char *buff, uint8_t *addr)
|
||||
{
|
||||
return sprintf(buff, MAC_FMT,
|
||||
addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]);
|
||||
return sprintf(buff, "%pM", addr);
|
||||
}
|
||||
|
||||
/* returns 1 if they are the same originator */
|
||||
@ -284,6 +273,9 @@ int is_mcast(uint8_t *addr)
|
||||
return *addr & 0x01;
|
||||
}
|
||||
|
||||
module_init(batman_init);
|
||||
module_exit(batman_exit);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
MODULE_AUTHOR(DRIVER_AUTHOR);
|
||||
|
@ -19,6 +19,9 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _NET_BATMAN_ADV_MAIN_H_
|
||||
#define _NET_BATMAN_ADV_MAIN_H_
|
||||
|
||||
/* Kernel Programming */
|
||||
#define LINUX
|
||||
|
||||
@ -27,7 +30,7 @@
|
||||
#define DRIVER_DESC "B.A.T.M.A.N. advanced"
|
||||
#define DRIVER_DEVICE "batman-adv"
|
||||
|
||||
#define SOURCE_VERSION "0.2.2-beta"
|
||||
#define SOURCE_VERSION "maint"
|
||||
|
||||
|
||||
/* B.A.T.M.A.N. parameters */
|
||||
@ -36,10 +39,10 @@
|
||||
#define JITTER 20
|
||||
#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
|
||||
* 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
|
||||
* messages in squence numbers (should be a
|
||||
@ -57,44 +60,42 @@
|
||||
#define LOG_BUF_LEN 8192 /* has to be a power of 2 */
|
||||
#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
|
||||
* change the size of
|
||||
* forw_packet->direct_link_flags */
|
||||
#define MAX_AGGREGATION_MS 100
|
||||
|
||||
#define RESET_PROTECTION_MS 30000
|
||||
#define EXPECTED_SEQNO_RANGE 4096
|
||||
#define EXPECTED_SEQNO_RANGE 65536
|
||||
/* don't reset again within 30 seconds */
|
||||
|
||||
#define MODULE_INACTIVE 0
|
||||
#define MODULE_ACTIVE 1
|
||||
#define MODULE_DEACTIVATING 2
|
||||
|
||||
#define BCAST_QUEUE_LEN 256
|
||||
#define BCAST_QUEUE_LEN 256
|
||||
#define BATMAN_QUEUE_LEN 256
|
||||
|
||||
/*
|
||||
* 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 /
|
||||
* broadcasting / etc */
|
||||
#define DBG_ROUTES 2 /* route or hna added / changed / deleted */
|
||||
#define DBG_ALL 3
|
||||
|
||||
#ifdef CONFIG_BATMAN_ADV_DEBUG
|
||||
extern int debug;
|
||||
#define LOG_BUF_LEN 8192 /* has to be a power of 2 */
|
||||
|
||||
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
|
||||
@ -117,6 +118,7 @@ extern int bat_debug_type(int type);
|
||||
#include <linux/slab.h>
|
||||
#include <net/sock.h> /* struct sock */
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/seq_file.h>
|
||||
#include "types.h"
|
||||
|
||||
#ifndef REVISION_VERSION
|
||||
@ -134,14 +136,13 @@ extern spinlock_t orig_hash_lock;
|
||||
extern spinlock_t forw_bat_list_lock;
|
||||
extern spinlock_t forw_bcast_list_lock;
|
||||
|
||||
extern atomic_t vis_interval;
|
||||
extern atomic_t bcast_queue_left;
|
||||
extern atomic_t batman_queue_left;
|
||||
extern int16_t num_hna;
|
||||
|
||||
extern struct net_device *soft_device;
|
||||
|
||||
extern unsigned char broadcastAddr[];
|
||||
extern unsigned char broadcast_addr[];
|
||||
extern atomic_t module_state;
|
||||
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_bcast(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_ */
|
||||
|
@ -56,28 +56,16 @@ err:
|
||||
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 *
|
||||
create_neighbor(struct orig_node *orig_node, struct orig_node *orig_neigh_node,
|
||||
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;
|
||||
|
||||
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);
|
||||
if (!neigh_node)
|
||||
@ -93,7 +81,7 @@ create_neighbor(struct orig_node *orig_node, struct orig_node *orig_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 neigh_node *neigh_node;
|
||||
@ -114,6 +102,21 @@ void free_orig_node(void *data)
|
||||
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
|
||||
* address if it does not exits */
|
||||
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)
|
||||
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);
|
||||
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);
|
||||
|
||||
if (swaphash == NULL)
|
||||
printk(KERN_ERR
|
||||
"batman-adv:Couldn't resize orig hash table\n");
|
||||
bat_err(soft_device,
|
||||
"Couldn't resize orig hash table\n");
|
||||
else
|
||||
orig_hash = swaphash;
|
||||
}
|
||||
@ -182,6 +186,8 @@ free_orig_node:
|
||||
static bool purge_orig_neighbors(struct orig_node *orig_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 neigh_node *neigh_node;
|
||||
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);
|
||||
|
||||
if ((time_after(jiffies,
|
||||
(neigh_node->last_valid +
|
||||
((PURGE_TIMEOUT * HZ) / 1000)))) ||
|
||||
neigh_node->last_valid + PURGE_TIMEOUT * HZ)) ||
|
||||
(neigh_node->if_incoming->if_status ==
|
||||
IF_TO_BE_REMOVED)) {
|
||||
|
||||
if (neigh_node->if_incoming->if_status ==
|
||||
IF_TO_BE_REMOVED)
|
||||
bat_dbg(DBG_BATMAN,
|
||||
bat_dbg(DBG_BATMAN, bat_priv,
|
||||
"neighbor purge: originator %pM, "
|
||||
"neighbor: %pM, iface: %s\n",
|
||||
orig_node->orig, neigh_node->addr,
|
||||
neigh_node->if_incoming->dev);
|
||||
else
|
||||
bat_dbg(DBG_BATMAN,
|
||||
bat_dbg(DBG_BATMAN, bat_priv,
|
||||
"neighbor timeout: originator %pM, "
|
||||
"neighbor: %pM, last_valid: %lu\n",
|
||||
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)
|
||||
{
|
||||
/* 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;
|
||||
|
||||
if (time_after(jiffies,
|
||||
(orig_node->last_valid +
|
||||
((2 * PURGE_TIMEOUT * HZ) / 1000)))) {
|
||||
orig_node->last_valid + 2 * PURGE_TIMEOUT * HZ)) {
|
||||
|
||||
bat_dbg(DBG_BATMAN,
|
||||
bat_dbg(DBG_BATMAN, bat_priv,
|
||||
"Originator timeout: originator %pM, last_valid %lu\n",
|
||||
orig_node->orig, (orig_node->last_valid / HZ));
|
||||
return true;
|
||||
} 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,
|
||||
orig_node->hna_buff,
|
||||
orig_node->hna_buff_len);
|
||||
/* update bonding candidates, we could have lost
|
||||
* some candidates. */
|
||||
update_bonding_candidates(bat_priv, orig_node);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
@ -271,49 +281,41 @@ void purge_orig(struct work_struct *work)
|
||||
start_purge_timer();
|
||||
}
|
||||
|
||||
ssize_t orig_fill_buffer_text(struct net_device *net_dev, char *buff,
|
||||
size_t count, loff_t off)
|
||||
int orig_seq_print_text(struct seq_file *seq, void *offset)
|
||||
{
|
||||
HASHIT(hashit);
|
||||
struct net_device *net_dev = (struct net_device *)seq->private;
|
||||
struct bat_priv *bat_priv = netdev_priv(net_dev);
|
||||
struct orig_node *orig_node;
|
||||
struct neigh_node *neigh_node;
|
||||
size_t hdr_len, tmp_len;
|
||||
int batman_count = 0, bytes_written = 0;
|
||||
int batman_count = 0;
|
||||
int last_seen_secs;
|
||||
int last_seen_msecs;
|
||||
unsigned long flags;
|
||||
char orig_str[ETH_STR_LEN], router_str[ETH_STR_LEN];
|
||||
|
||||
if (!bat_priv->primary_if) {
|
||||
if (off == 0)
|
||||
return sprintf(buff,
|
||||
"BATMAN mesh %s disabled - "
|
||||
if ((!bat_priv->primary_if) ||
|
||||
(bat_priv->primary_if->if_status != IF_ACTIVE)) {
|
||||
if (!bat_priv->primary_if)
|
||||
return seq_printf(seq, "BATMAN mesh %s disabled - "
|
||||
"please specify interfaces to enable it\n",
|
||||
net_dev->name);
|
||||
|
||||
return 0;
|
||||
return seq_printf(seq, "BATMAN mesh %s "
|
||||
"disabled - primary interface not active\n",
|
||||
net_dev->name);
|
||||
}
|
||||
|
||||
if (bat_priv->primary_if->if_status != IF_ACTIVE && off == 0)
|
||||
return sprintf(buff,
|
||||
"BATMAN mesh %s "
|
||||
"disabled - primary interface not active\n",
|
||||
net_dev->name);
|
||||
else if (bat_priv->primary_if->if_status != IF_ACTIVE)
|
||||
return 0;
|
||||
|
||||
rcu_read_lock();
|
||||
hdr_len = sprintf(buff,
|
||||
" %-14s (%s/%i) %17s [%10s]: %20s "
|
||||
"... [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,
|
||||
seq_printf(seq, "[B.A.T.M.A.N. adv %s%s, MainIF/MAC: %s/%s (%s)]\n",
|
||||
SOURCE_VERSION, REVISION_VERSION_STR,
|
||||
bat_priv->primary_if->dev, bat_priv->primary_if->addr_str,
|
||||
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();
|
||||
|
||||
if (off < hdr_len)
|
||||
bytes_written = hdr_len;
|
||||
|
||||
spin_lock_irqsave(&orig_hash_lock, flags);
|
||||
|
||||
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)
|
||||
continue;
|
||||
|
||||
/* estimated line length */
|
||||
if (count < bytes_written + 200)
|
||||
break;
|
||||
|
||||
addr_to_string(orig_str, orig_node->orig);
|
||||
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,
|
||||
"%-17s (%3i) %17s [%10s]:",
|
||||
orig_str, orig_node->router->tq_avg,
|
||||
router_str,
|
||||
orig_node->router->if_incoming->dev);
|
||||
seq_printf(seq, "%-17s %4i.%03is (%3i) %17s [%10s]:",
|
||||
orig_str, last_seen_secs, last_seen_msecs,
|
||||
orig_node->router->tq_avg, router_str,
|
||||
orig_node->router->if_incoming->dev);
|
||||
|
||||
list_for_each_entry(neigh_node, &orig_node->neigh_list, list) {
|
||||
addr_to_string(orig_str, neigh_node->addr);
|
||||
tmp_len += sprintf(buff + bytes_written + tmp_len,
|
||||
" %17s (%3i)", orig_str,
|
||||
seq_printf(seq, " %17s (%3i)", orig_str,
|
||||
neigh_node->tq_avg);
|
||||
}
|
||||
|
||||
tmp_len += sprintf(buff + bytes_written + tmp_len, "\n");
|
||||
|
||||
seq_printf(seq, "\n");
|
||||
batman_count++;
|
||||
hdr_len += tmp_len;
|
||||
|
||||
if (off >= hdr_len)
|
||||
continue;
|
||||
|
||||
bytes_written += tmp_len;
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&orig_hash_lock, flags);
|
||||
|
||||
if ((batman_count == 0) && (off == 0))
|
||||
bytes_written += sprintf(buff + bytes_written,
|
||||
"No batman nodes in range ...\n");
|
||||
if ((batman_count == 0))
|
||||
seq_printf(seq, "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)
|
||||
@ -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,
|
||||
GFP_ATOMIC);
|
||||
if (!data_ptr) {
|
||||
printk(KERN_ERR
|
||||
"batman-adv:Can't resize orig: out of memory\n");
|
||||
pr_err("Can't resize orig: out of memory\n");
|
||||
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);
|
||||
if (!data_ptr) {
|
||||
printk(KERN_ERR
|
||||
"batman-adv:Can't resize orig: out of memory\n");
|
||||
pr_err("Can't resize orig: out of memory\n");
|
||||
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;
|
||||
data_ptr = kmalloc(max_if_num * chunk_size, GFP_ATOMIC);
|
||||
if (!data_ptr) {
|
||||
printk(KERN_ERR
|
||||
"batman-adv:Can't resize orig: out of memory\n");
|
||||
pr_err("Can't resize orig: out of memory\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -457,8 +446,7 @@ free_bcast_own:
|
||||
|
||||
data_ptr = kmalloc(max_if_num * sizeof(uint8_t), GFP_ATOMIC);
|
||||
if (!data_ptr) {
|
||||
printk(KERN_ERR
|
||||
"batman-adv:Can't resize orig: out of memory\n");
|
||||
pr_err("Can't resize orig: out of memory\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -19,16 +19,18 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _NET_BATMAN_ADV_ORIGINATOR_H_
|
||||
#define _NET_BATMAN_ADV_ORIGINATOR_H_
|
||||
|
||||
int originator_init(void);
|
||||
void free_orig_node(void *data);
|
||||
void originator_free(void);
|
||||
void purge_orig(struct work_struct *work);
|
||||
struct orig_node *orig_find(char *mac);
|
||||
struct orig_node *get_orig_node(uint8_t *addr);
|
||||
struct neigh_node *
|
||||
create_neighbor(struct orig_node *orig_node, struct orig_node *orig_neigh_node,
|
||||
uint8_t *neigh, struct batman_if *if_incoming);
|
||||
ssize_t orig_fill_buffer_text(struct net_device *net_dev, char *buff,
|
||||
size_t count, loff_t off);
|
||||
int orig_seq_print_text(struct seq_file *seq, void *offset);
|
||||
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);
|
||||
|
||||
#endif /* _NET_BATMAN_ADV_ORIGINATOR_H_ */
|
||||
|
@ -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 BAT_PACKET 0x01
|
||||
@ -28,9 +31,10 @@
|
||||
#define BAT_VIS 0x05
|
||||
|
||||
/* this file is included by batctl which needs these defines */
|
||||
#define COMPAT_VERSION 8
|
||||
#define COMPAT_VERSION 11
|
||||
#define DIRECTLINK 0x40
|
||||
#define VIS_SERVER 0x20
|
||||
#define PRIMARIES_FIRST_HOP 0x10
|
||||
|
||||
/* ICMP message types */
|
||||
#define ECHO_REPLY 0
|
||||
@ -48,7 +52,7 @@ struct batman_packet {
|
||||
uint8_t version; /* batman version field */
|
||||
uint8_t flags; /* 0x40: DIRECTLINK flag, 0x20 VIS_SERVER flag... */
|
||||
uint8_t tq;
|
||||
uint16_t seqno;
|
||||
uint32_t seqno;
|
||||
uint8_t orig[6];
|
||||
uint8_t prev_sender[6];
|
||||
uint8_t ttl;
|
||||
@ -68,6 +72,23 @@ struct icmp_packet {
|
||||
uint8_t uid;
|
||||
} __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 {
|
||||
uint8_t packet_type;
|
||||
uint8_t version; /* batman version field */
|
||||
@ -79,18 +100,21 @@ struct bcast_packet {
|
||||
uint8_t packet_type;
|
||||
uint8_t version; /* batman version field */
|
||||
uint8_t orig[6];
|
||||
uint16_t seqno;
|
||||
uint8_t ttl;
|
||||
uint32_t seqno;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct vis_packet {
|
||||
uint8_t packet_type;
|
||||
uint8_t version; /* batman version field */
|
||||
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 */
|
||||
uint32_t seqno; /* sequence number */
|
||||
uint8_t ttl; /* TTL */
|
||||
uint8_t vis_orig[6]; /* originator that informs about its
|
||||
* neighbors */
|
||||
uint8_t target_orig[6]; /* who should receive this packet */
|
||||
uint8_t sender_orig[6]; /* who sent or rebroadcasted this packet */
|
||||
} __attribute__((packed));
|
||||
|
||||
#endif /* _NET_BATMAN_ADV_PACKET_H_ */
|
||||
|
@ -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);
|
||||
uint8_t ring_buffer_avg(uint8_t lq_recv[]);
|
||||
|
||||
#endif /* _NET_BATMAN_ADV_RING_BUFFER_H_ */
|
||||
|
@ -25,7 +25,7 @@
|
||||
#include "hash.h"
|
||||
#include "soft-interface.h"
|
||||
#include "hard-interface.h"
|
||||
#include "device.h"
|
||||
#include "icmp_socket.h"
|
||||
#include "translation-table.h"
|
||||
#include "originator.h"
|
||||
#include "types.h"
|
||||
@ -33,7 +33,7 @@
|
||||
#include "vis.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)
|
||||
{
|
||||
@ -77,24 +77,27 @@ static void update_route(struct orig_node *orig_node,
|
||||
struct neigh_node *neigh_node,
|
||||
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 */
|
||||
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);
|
||||
hna_global_del_orig(orig_node, "originator timed out");
|
||||
|
||||
/* route added */
|
||||
} 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",
|
||||
orig_node->orig, neigh_node->addr);
|
||||
hna_global_add_orig(orig_node, hna_buff, hna_buff_len);
|
||||
|
||||
/* route changed */
|
||||
} else {
|
||||
bat_dbg(DBG_ROUTES,
|
||||
bat_dbg(DBG_ROUTES, bat_priv,
|
||||
"Changing route towards: %pM "
|
||||
"(now via %pM - was via %pM)\n",
|
||||
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);
|
||||
}
|
||||
|
||||
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 batman_packet *batman_packet,
|
||||
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;
|
||||
unsigned char total_count;
|
||||
|
||||
@ -211,7 +216,7 @@ static int isBidirectionalNeigh(struct orig_node *orig_node,
|
||||
orig_neigh_node->tq_asym_penalty) /
|
||||
(TQ_MAX_VALUE * TQ_MAX_VALUE));
|
||||
|
||||
bat_dbg(DBG_BATMAN,
|
||||
bat_dbg(DBG_BATMAN, bat_priv,
|
||||
"bidirectional: "
|
||||
"orig = %-15pM neigh = %-15pM => own_bcast = %2i, "
|
||||
"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,
|
||||
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;
|
||||
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");
|
||||
|
||||
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)
|
||||
return;
|
||||
} else
|
||||
bat_dbg(DBG_BATMAN,
|
||||
bat_dbg(DBG_BATMAN, bat_priv,
|
||||
"Updating existing last-hop neighbor of originator\n");
|
||||
|
||||
orig_node->flags = batman_packet->flags;
|
||||
@ -318,16 +325,19 @@ update_hna:
|
||||
* 0 if the packet is to be accepted
|
||||
* 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)
|
||||
{
|
||||
/* 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)
|
||||
|| (seq_num_diff >= EXPECTED_SEQNO_RANGE)) {
|
||||
if (time_after(jiffies, *last_reset +
|
||||
msecs_to_jiffies(RESET_PROTECTION_MS))) {
|
||||
|
||||
*last_reset = jiffies;
|
||||
bat_dbg(DBG_BATMAN,
|
||||
bat_dbg(DBG_BATMAN, bat_priv,
|
||||
"old packet received, start protection\n");
|
||||
|
||||
return 0;
|
||||
@ -349,10 +359,12 @@ static char count_real_packets(struct ethhdr *ethhdr,
|
||||
struct batman_packet *batman_packet,
|
||||
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 neigh_node *tmp_neigh_node;
|
||||
char is_duplicate = 0;
|
||||
int16_t seq_diff;
|
||||
int32_t seq_diff;
|
||||
int need_update = 0;
|
||||
int set_mark;
|
||||
|
||||
@ -387,7 +399,8 @@ static char count_real_packets(struct ethhdr *ethhdr,
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
@ -395,18 +408,127 @@ static char count_real_packets(struct ethhdr *ethhdr,
|
||||
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,
|
||||
struct batman_packet *batman_packet,
|
||||
unsigned char *hna_buff, int hna_buff_len,
|
||||
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 orig_node *orig_neigh_node, *orig_node;
|
||||
char has_directlink_flag;
|
||||
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_duplicate;
|
||||
unsigned short if_incoming_seqno;
|
||||
uint32_t if_incoming_seqno;
|
||||
|
||||
/* Silently drop when the batman packet is actually not a
|
||||
* correct packet.
|
||||
@ -431,7 +553,8 @@ void receive_bat_packet(struct ethhdr *ethhdr,
|
||||
is_single_hop_neigh = (compare_orig(ethhdr->h_source,
|
||||
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, "
|
||||
"TTL %d, V %d, IDF %d)\n",
|
||||
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))
|
||||
is_my_oldorig = 1;
|
||||
|
||||
if (compare_orig(ethhdr->h_source, broadcastAddr))
|
||||
if (compare_orig(ethhdr->h_source, broadcast_addr))
|
||||
is_broadcast = 1;
|
||||
}
|
||||
|
||||
if (batman_packet->version != COMPAT_VERSION) {
|
||||
bat_dbg(DBG_BATMAN,
|
||||
bat_dbg(DBG_BATMAN, bat_priv,
|
||||
"Drop packet: incompatible batman version (%i)\n",
|
||||
batman_packet->version);
|
||||
return;
|
||||
}
|
||||
|
||||
if (is_my_addr) {
|
||||
bat_dbg(DBG_BATMAN,
|
||||
bat_dbg(DBG_BATMAN, bat_priv,
|
||||
"Drop packet: received my own broadcast (sender: %pM"
|
||||
")\n",
|
||||
ethhdr->h_source);
|
||||
@ -475,7 +598,7 @@ void receive_bat_packet(struct ethhdr *ethhdr,
|
||||
}
|
||||
|
||||
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"
|
||||
")\n", ethhdr->h_source);
|
||||
return;
|
||||
@ -505,13 +628,13 @@ void receive_bat_packet(struct ethhdr *ethhdr,
|
||||
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");
|
||||
return;
|
||||
}
|
||||
|
||||
if (is_my_oldorig) {
|
||||
bat_dbg(DBG_BATMAN,
|
||||
bat_dbg(DBG_BATMAN, bat_priv,
|
||||
"Drop packet: ignoring all rebroadcast echos (sender: "
|
||||
"%pM)\n", ethhdr->h_source);
|
||||
return;
|
||||
@ -524,14 +647,14 @@ void receive_bat_packet(struct ethhdr *ethhdr,
|
||||
is_duplicate = count_real_packets(ethhdr, batman_packet, if_incoming);
|
||||
|
||||
if (is_duplicate == -1) {
|
||||
bat_dbg(DBG_BATMAN,
|
||||
bat_dbg(DBG_BATMAN, bat_priv,
|
||||
"Drop packet: packet within seqno protection time "
|
||||
"(sender: %pM)\n", ethhdr->h_source);
|
||||
return;
|
||||
}
|
||||
|
||||
if (batman_packet->tq == 0) {
|
||||
bat_dbg(DBG_BATMAN,
|
||||
bat_dbg(DBG_BATMAN, bat_priv,
|
||||
"Drop packet: originator packet with tq equal 0\n");
|
||||
return;
|
||||
}
|
||||
@ -544,7 +667,7 @@ void receive_bat_packet(struct ethhdr *ethhdr,
|
||||
!(compare_orig(batman_packet->orig, batman_packet->prev_sender)) &&
|
||||
(compare_orig(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 "
|
||||
"may make me loop (sender: %pM)\n", ethhdr->h_source);
|
||||
return;
|
||||
@ -561,11 +684,12 @@ void receive_bat_packet(struct ethhdr *ethhdr,
|
||||
* don't route towards it */
|
||||
if (!is_single_hop_neigh &&
|
||||
(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;
|
||||
}
|
||||
|
||||
is_bidirectional = isBidirectionalNeigh(orig_node, orig_neigh_node,
|
||||
is_bidirectional = is_bidirectional_neigh(orig_node, orig_neigh_node,
|
||||
batman_packet, if_incoming);
|
||||
|
||||
/* 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,
|
||||
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 */
|
||||
if (is_single_hop_neigh) {
|
||||
|
||||
@ -584,24 +712,25 @@ void receive_bat_packet(struct ethhdr *ethhdr,
|
||||
schedule_forward_packet(orig_node, ethhdr, batman_packet,
|
||||
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");
|
||||
return;
|
||||
}
|
||||
|
||||
/* multihop originator */
|
||||
if (!is_bidirectional) {
|
||||
bat_dbg(DBG_BATMAN,
|
||||
bat_dbg(DBG_BATMAN, bat_priv,
|
||||
"Drop packet: not received via bidirectional link\n");
|
||||
return;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
bat_dbg(DBG_BATMAN,
|
||||
bat_dbg(DBG_BATMAN, bat_priv,
|
||||
"Forwarding packet: rebroadcast originator packet\n");
|
||||
schedule_forward_packet(orig_node, ethhdr, batman_packet,
|
||||
0, hna_buff_len, if_incoming);
|
||||
@ -652,10 +781,10 @@ int recv_bat_packet(struct sk_buff *skb,
|
||||
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 icmp_packet *icmp_packet;
|
||||
struct icmp_packet_rr *icmp_packet;
|
||||
struct ethhdr *ethhdr;
|
||||
struct sk_buff *skb_old;
|
||||
struct batman_if *batman_if;
|
||||
@ -663,12 +792,12 @@ static int recv_my_icmp_packet(struct sk_buff *skb)
|
||||
unsigned long flags;
|
||||
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);
|
||||
|
||||
/* add data to device queue */
|
||||
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;
|
||||
}
|
||||
|
||||
@ -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. */
|
||||
skb_old = NULL;
|
||||
if (!skb_clone_writable(skb, sizeof(struct icmp_packet))) {
|
||||
if (!skb_clone_writable(skb, icmp_len)) {
|
||||
skb_old = skb;
|
||||
skb = skb_copy(skb, GFP_ATOMIC);
|
||||
if (!skb)
|
||||
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);
|
||||
kfree_skb(skb_old);
|
||||
}
|
||||
@ -715,7 +843,7 @@ static int recv_my_icmp_packet(struct sk_buff *skb)
|
||||
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 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) */
|
||||
if (icmp_packet->msg_type != ECHO_REQUEST) {
|
||||
printk(KERN_WARNING "batman-adv:"
|
||||
"Warning - can't forward icmp packet from %pM to %pM: "
|
||||
"ttl exceeded\n",
|
||||
icmp_packet->orig, icmp_packet->dst);
|
||||
pr_warning("Warning - can't forward icmp packet from %pM to "
|
||||
"%pM: ttl exceeded\n", icmp_packet->orig,
|
||||
icmp_packet->dst);
|
||||
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);
|
||||
|
||||
/* 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 = skb_copy(skb, GFP_ATOMIC);
|
||||
if (!skb)
|
||||
@ -781,7 +908,7 @@ static int recv_icmp_ttl_exceeded(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 orig_node *orig_node;
|
||||
struct sk_buff *skb_old;
|
||||
@ -791,6 +918,12 @@ int recv_icmp_packet(struct sk_buff *skb)
|
||||
unsigned long flags;
|
||||
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 */
|
||||
if (skb_headlen(skb) < hdr_size)
|
||||
return NET_RX_DROP;
|
||||
@ -809,15 +942,23 @@ int recv_icmp_packet(struct sk_buff *skb)
|
||||
if (!is_my_mac(ethhdr->h_dest))
|
||||
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 */
|
||||
if (is_my_mac(icmp_packet->dst))
|
||||
return recv_my_icmp_packet(skb);
|
||||
return recv_my_icmp_packet(skb, hdr_size);
|
||||
|
||||
/* TTL exceeded */
|
||||
if (icmp_packet->ttl < 2)
|
||||
return recv_icmp_ttl_exceeded(skb);
|
||||
return recv_icmp_ttl_exceeded(skb, hdr_size);
|
||||
|
||||
ret = NET_RX_DROP;
|
||||
|
||||
@ -836,12 +977,12 @@ int recv_icmp_packet(struct sk_buff *skb)
|
||||
spin_unlock_irqrestore(&orig_hash_lock, flags);
|
||||
|
||||
/* 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 = skb_copy(skb, GFP_ATOMIC);
|
||||
if (!skb)
|
||||
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);
|
||||
kfree_skb(skb_old);
|
||||
}
|
||||
@ -859,16 +1000,109 @@ int recv_icmp_packet(struct sk_buff *skb)
|
||||
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 orig_node *orig_node;
|
||||
struct neigh_node *router;
|
||||
struct ethhdr *ethhdr;
|
||||
struct batman_if *batman_if;
|
||||
struct sk_buff *skb_old;
|
||||
uint8_t dstaddr[ETH_ALEN];
|
||||
int hdr_size = sizeof(struct unicast_packet);
|
||||
int ret;
|
||||
unsigned long flags;
|
||||
|
||||
/* drop packet if it has not necessary minimum size */
|
||||
@ -899,49 +1133,50 @@ int recv_unicast_packet(struct sk_buff *skb)
|
||||
|
||||
/* TTL exceeded */
|
||||
if (unicast_packet->ttl < 2) {
|
||||
printk(KERN_WARNING "batman-adv:Warning - "
|
||||
"can't forward unicast packet from %pM to %pM: "
|
||||
"ttl exceeded\n",
|
||||
ethhdr->h_source, unicast_packet->dest);
|
||||
pr_warning("Warning - can't forward unicast packet from %pM to "
|
||||
"%pM: ttl exceeded\n", ethhdr->h_source,
|
||||
unicast_packet->dest);
|
||||
return NET_RX_DROP;
|
||||
}
|
||||
|
||||
ret = NET_RX_DROP;
|
||||
/* get routing information */
|
||||
spin_lock_irqsave(&orig_hash_lock, flags);
|
||||
orig_node = ((struct orig_node *)
|
||||
hash_find(orig_hash, unicast_packet->dest));
|
||||
|
||||
if ((orig_node != NULL) &&
|
||||
(orig_node->router != NULL)) {
|
||||
router = find_router(orig_node, recv_if);
|
||||
|
||||
/* don't lock while sending the packets ... we therefore
|
||||
* copy the required data before sending */
|
||||
batman_if = orig_node->router->if_incoming;
|
||||
memcpy(dstaddr, orig_node->router->addr, ETH_ALEN);
|
||||
if (!router) {
|
||||
spin_unlock_irqrestore(&orig_hash_lock, flags);
|
||||
return NET_RX_DROP;
|
||||
}
|
||||
|
||||
/* create a copy of the skb, if needed, to modify it. */
|
||||
if (!skb_clone_writable(skb, sizeof(struct unicast_packet))) {
|
||||
skb_old = skb;
|
||||
skb = skb_copy(skb, GFP_ATOMIC);
|
||||
if (!skb)
|
||||
return NET_RX_DROP;
|
||||
unicast_packet = (struct unicast_packet *)skb->data;
|
||||
ethhdr = (struct ethhdr *)skb_mac_header(skb);
|
||||
kfree_skb(skb_old);
|
||||
}
|
||||
/* decrement ttl */
|
||||
unicast_packet->ttl--;
|
||||
/* don't lock while sending the packets ... we therefore
|
||||
* copy the required data before sending */
|
||||
|
||||
/* route it */
|
||||
send_skb_packet(skb, batman_if, dstaddr);
|
||||
ret = NET_RX_SUCCESS;
|
||||
batman_if = router->if_incoming;
|
||||
memcpy(dstaddr, router->addr, ETH_ALEN);
|
||||
|
||||
} else
|
||||
spin_unlock_irqrestore(&orig_hash_lock, flags);
|
||||
spin_unlock_irqrestore(&orig_hash_lock, flags);
|
||||
|
||||
return ret;
|
||||
/* create a copy of the skb, if needed, to modify it. */
|
||||
if (!skb_clone_writable(skb, sizeof(struct unicast_packet))) {
|
||||
skb_old = skb;
|
||||
skb = skb_copy(skb, GFP_ATOMIC);
|
||||
if (!skb)
|
||||
return NET_RX_DROP;
|
||||
unicast_packet = (struct unicast_packet *) skb->data;
|
||||
ethhdr = (struct ethhdr *)skb_mac_header(skb);
|
||||
kfree_skb(skb_old);
|
||||
}
|
||||
|
||||
/* decrement ttl */
|
||||
unicast_packet->ttl--;
|
||||
|
||||
/* route it */
|
||||
send_skb_packet(skb, batman_if, dstaddr);
|
||||
|
||||
return NET_RX_SUCCESS;
|
||||
}
|
||||
|
||||
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 ethhdr *ethhdr;
|
||||
int hdr_size = sizeof(struct bcast_packet);
|
||||
int16_t seq_diff;
|
||||
int32_t seq_diff;
|
||||
unsigned long flags;
|
||||
|
||||
/* 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))
|
||||
return NET_RX_DROP;
|
||||
|
||||
if (bcast_packet->ttl < 2)
|
||||
return NET_RX_DROP;
|
||||
|
||||
spin_lock_irqsave(&orig_hash_lock, flags);
|
||||
orig_node = ((struct orig_node *)
|
||||
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 */
|
||||
if (get_bit_status(orig_node->bcast_bits,
|
||||
orig_node->last_bcast_seqno,
|
||||
ntohs(bcast_packet->seqno))) {
|
||||
ntohl(bcast_packet->seqno))) {
|
||||
spin_unlock_irqrestore(&orig_hash_lock, flags);
|
||||
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. */
|
||||
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
|
||||
* if required. */
|
||||
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);
|
||||
/* rebroadcast packet */
|
||||
|
@ -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 receive_bat_packet(struct ethhdr *ethhdr,
|
||||
@ -32,8 +33,14 @@ void update_routes(struct orig_node *orig_node,
|
||||
struct neigh_node *neigh_node,
|
||||
unsigned char *hna_buff, int hna_buff_len);
|
||||
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_vis_packet(struct sk_buff *skb);
|
||||
int recv_bat_packet(struct sk_buff *skb,
|
||||
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_ */
|
||||
|
@ -29,6 +29,10 @@
|
||||
#include "vis.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 */
|
||||
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 */
|
||||
static unsigned long own_send_time(struct bat_priv *bat_priv)
|
||||
{
|
||||
return jiffies +
|
||||
(((atomic_read(&bat_priv->orig_interval) - JITTER +
|
||||
(random32() % 2*JITTER)) * HZ) / 1000);
|
||||
return jiffies + msecs_to_jiffies(
|
||||
atomic_read(&bat_priv->orig_interval) -
|
||||
JITTER + (random32() % 2*JITTER));
|
||||
}
|
||||
|
||||
/* when do we schedule a forwarded packet to be sent */
|
||||
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
|
||||
@ -64,10 +68,8 @@ int send_skb_packet(struct sk_buff *skb,
|
||||
goto send_skb_err;
|
||||
|
||||
if (!(batman_if->net_dev->flags & IFF_UP)) {
|
||||
printk(KERN_WARNING
|
||||
"batman-adv:Interface %s "
|
||||
"is not up - can't send packet via that interface!\n",
|
||||
batman_if->dev);
|
||||
pr_warning("Interface %s is not up - can't send packet via "
|
||||
"that interface!\n", batman_if->dev);
|
||||
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
|
||||
* 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:
|
||||
kfree_skb(skb);
|
||||
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,
|
||||
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;
|
||||
uint8_t packet_num;
|
||||
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 ?
|
||||
"Sending own" :
|
||||
"Forwarding"));
|
||||
bat_dbg(DBG_BATMAN,
|
||||
bat_dbg(DBG_BATMAN, bat_priv,
|
||||
"%s %spacket (originator %pM, seqno %d, TQ %d, TTL %d,"
|
||||
" IDF %s) on interface %s [%s]\n",
|
||||
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->flags & DIRECTLINK ?
|
||||
"on" : "off"),
|
||||
@ -167,20 +174,22 @@ static void send_packet_to_if(struct forw_packet *forw_packet,
|
||||
|
||||
send_raw_packet(forw_packet->packet_buff,
|
||||
forw_packet->packet_len,
|
||||
batman_if, broadcastAddr);
|
||||
batman_if, broadcast_addr);
|
||||
}
|
||||
|
||||
/* send a batman 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_packet *batman_packet =
|
||||
(struct batman_packet *)(forw_packet->packet_buff);
|
||||
unsigned char directlink = (batman_packet->flags & DIRECTLINK ? 1 : 0);
|
||||
|
||||
if (!forw_packet->if_incoming) {
|
||||
printk(KERN_ERR "batman-adv: Error - can't forward packet: "
|
||||
"incoming iface not specified\n");
|
||||
pr_err("Error - can't forward packet: incoming iface not "
|
||||
"specified\n");
|
||||
return;
|
||||
}
|
||||
|
||||
@ -193,18 +202,18 @@ static void send_packet(struct forw_packet *forw_packet)
|
||||
(forw_packet->own && (forw_packet->if_incoming->if_num > 0))) {
|
||||
|
||||
/* FIXME: what about aggregated packets ? */
|
||||
bat_dbg(DBG_BATMAN,
|
||||
bat_dbg(DBG_BATMAN, bat_priv,
|
||||
"%s packet (originator %pM, seqno %d, TTL %d) "
|
||||
"on interface %s [%s]\n",
|
||||
(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,
|
||||
forw_packet->if_incoming->addr_str);
|
||||
|
||||
send_raw_packet(forw_packet->packet_buff,
|
||||
forw_packet->packet_len,
|
||||
forw_packet->if_incoming,
|
||||
broadcastAddr);
|
||||
broadcast_addr);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -276,14 +285,14 @@ void schedule_own_packet(struct batman_if *batman_if)
|
||||
batman_packet = (struct batman_packet *)batman_if->packet_buff;
|
||||
|
||||
/* 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)
|
||||
batman_packet->flags = VIS_SERVER;
|
||||
batman_packet->flags |= VIS_SERVER;
|
||||
else
|
||||
batman_packet->flags &= ~VIS_SERVER;
|
||||
|
||||
/* could be read by receive_bat_packet() */
|
||||
atomic_inc(&batman_if->seqno);
|
||||
|
||||
slide_own_bcast_window(batman_if);
|
||||
@ -306,7 +315,7 @@ void schedule_forward_packet(struct orig_node *orig_node,
|
||||
unsigned long send_time;
|
||||
|
||||
if (batman_packet->ttl <= 1) {
|
||||
bat_dbg(DBG_BATMAN, "ttl exceeded\n");
|
||||
bat_dbg(DBG_BATMAN, bat_priv, "ttl exceeded\n");
|
||||
return;
|
||||
}
|
||||
|
||||
@ -335,13 +344,16 @@ void schedule_forward_packet(struct orig_node *orig_node,
|
||||
/* apply hop penalty */
|
||||
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",
|
||||
in_tq, tq_avg, batman_packet->tq, in_ttl - 1,
|
||||
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)
|
||||
batman_packet->flags |= DIRECTLINK;
|
||||
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)
|
||||
{
|
||||
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)) {
|
||||
bat_dbg(DBG_BATMAN, "bcast packet queue full\n");
|
||||
bat_dbg(DBG_BATMAN, bat_priv, "bcast packet queue full\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
@ -407,6 +422,10 @@ int add_bcast_packet_to_list(struct sk_buff *skb)
|
||||
if (!skb)
|
||||
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);
|
||||
|
||||
forw_packet->skb = skb;
|
||||
@ -426,7 +445,7 @@ out:
|
||||
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 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);
|
||||
if (skb1)
|
||||
send_skb_packet(skb1,
|
||||
batman_if, broadcastAddr);
|
||||
batman_if, broadcast_addr);
|
||||
}
|
||||
rcu_read_unlock();
|
||||
|
||||
@ -502,15 +521,19 @@ out:
|
||||
|
||||
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 hlist_node *tmp_node, *safe_tmp_node;
|
||||
unsigned long flags;
|
||||
|
||||
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);
|
||||
else
|
||||
bat_dbg(DBG_BATMAN, "purge_outstanding_packets()\n");
|
||||
bat_dbg(DBG_BATMAN, bat_priv,
|
||||
"purge_outstanding_packets()\n");
|
||||
|
||||
/* free bcast list */
|
||||
spin_lock_irqsave(&forw_bcast_list_lock, flags);
|
||||
|
@ -19,9 +19,11 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _NET_BATMAN_ADV_SEND_H_
|
||||
#define _NET_BATMAN_ADV_SEND_H_
|
||||
|
||||
#include "types.h"
|
||||
|
||||
void send_own_packet_work(struct work_struct *work);
|
||||
int send_skb_packet(struct sk_buff *skb,
|
||||
struct batman_if *batman_if,
|
||||
uint8_t *dst_addr);
|
||||
@ -34,6 +36,7 @@ void schedule_forward_packet(struct orig_node *orig_node,
|
||||
uint8_t directlink, int hna_buff_len,
|
||||
struct batman_if *if_outgoing);
|
||||
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 purge_outstanding_packets(struct batman_if *batman_if);
|
||||
|
||||
#endif /* _NET_BATMAN_ADV_SEND_H_ */
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include "main.h"
|
||||
#include "soft-interface.h"
|
||||
#include "hard-interface.h"
|
||||
#include "routing.h"
|
||||
#include "send.h"
|
||||
#include "translation-table.h"
|
||||
#include "types.h"
|
||||
@ -30,13 +31,12 @@
|
||||
#include <linux/ethtool.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 */
|
||||
static int32_t skb_packets;
|
||||
static int32_t skb_bad_packets;
|
||||
|
||||
unsigned char mainIfAddr[ETH_ALEN];
|
||||
static unsigned char mainIfAddr_default[ETH_ALEN];
|
||||
unsigned char main_if_addr[ETH_ALEN];
|
||||
static int bat_get_settings(struct net_device *dev, struct ethtool_cmd *cmd);
|
||||
static void bat_get_drvinfo(struct net_device *dev,
|
||||
struct ethtool_drvinfo *info);
|
||||
@ -58,12 +58,7 @@ static const struct ethtool_ops bat_ethtool_ops = {
|
||||
|
||||
void set_main_if_addr(uint8_t *addr)
|
||||
{
|
||||
memcpy(mainIfAddr, addr, ETH_ALEN);
|
||||
}
|
||||
|
||||
int main_if_was_up(void)
|
||||
{
|
||||
return (memcmp(mainIfAddr, mainIfAddr_default, ETH_ALEN) != 0 ? 1 : 0);
|
||||
memcpy(main_if_addr, addr, ETH_ALEN);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
#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));
|
||||
}
|
||||
|
||||
int interface_open(struct net_device *dev)
|
||||
static int interface_open(struct net_device *dev)
|
||||
{
|
||||
netif_start_queue(dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int interface_release(struct net_device *dev)
|
||||
static int interface_release(struct net_device *dev)
|
||||
{
|
||||
netif_stop_queue(dev);
|
||||
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);
|
||||
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;
|
||||
|
||||
@ -163,7 +114,7 @@ int interface_set_mac_addr(struct net_device *dev, void *p)
|
||||
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 */
|
||||
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 bcast_packet *bcast_packet;
|
||||
struct orig_node *orig_node;
|
||||
struct neigh_node *router;
|
||||
struct ethhdr *ethhdr = (struct ethhdr *)skb->data;
|
||||
struct bat_priv *priv = netdev_priv(dev);
|
||||
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->version = COMPAT_VERSION;
|
||||
bcast_packet->ttl = TTL;
|
||||
|
||||
/* batman packet type: broadcast */
|
||||
bcast_packet->packet_type = BAT_BCAST;
|
||||
|
||||
/* hw address of first interface is the orig mac because only
|
||||
* 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 */
|
||||
bcast_packet->seqno = htons(bcast_seqno);
|
||||
bcast_packet->seqno = htonl(bcast_seqno);
|
||||
|
||||
/* broadcast packet. on success, increase seqno. */
|
||||
if (add_bcast_packet_to_list(skb) == NETDEV_TX_OK)
|
||||
@ -235,38 +188,36 @@ int interface_tx(struct sk_buff *skb, struct net_device *dev)
|
||||
if (!orig_node)
|
||||
orig_node = transtable_search(ethhdr->h_dest);
|
||||
|
||||
if ((orig_node) &&
|
||||
(orig_node->router)) {
|
||||
struct neigh_node *router = orig_node->router;
|
||||
router = find_router(orig_node, NULL);
|
||||
|
||||
if (my_skb_push(skb, sizeof(struct unicast_packet)) < 0)
|
||||
goto unlock;
|
||||
|
||||
unicast_packet = (struct unicast_packet *)skb->data;
|
||||
|
||||
unicast_packet->version = COMPAT_VERSION;
|
||||
/* batman packet type: unicast */
|
||||
unicast_packet->packet_type = BAT_UNICAST;
|
||||
/* set unicast ttl */
|
||||
unicast_packet->ttl = TTL;
|
||||
/* copy the destination for faster routing */
|
||||
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);
|
||||
} else {
|
||||
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)
|
||||
goto dropped;
|
||||
|
||||
unicast_packet = (struct unicast_packet *)skb->data;
|
||||
|
||||
unicast_packet->version = COMPAT_VERSION;
|
||||
/* batman packet type: unicast */
|
||||
unicast_packet->packet_type = BAT_UNICAST;
|
||||
/* set unicast ttl */
|
||||
unicast_packet->ttl = TTL;
|
||||
/* copy the destination for faster routing */
|
||||
memcpy(unicast_packet->dest, orig_node->orig, ETH_ALEN);
|
||||
|
||||
send_skb_packet(skb, batman_if, dstaddr);
|
||||
}
|
||||
|
||||
priv->stats.tx_packets++;
|
||||
@ -315,6 +266,50 @@ void interface_rx(struct sk_buff *skb, int hdr_size)
|
||||
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 */
|
||||
static int bat_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
|
||||
{
|
||||
|
@ -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);
|
||||
int main_if_was_up(void);
|
||||
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);
|
||||
void interface_rx(struct sk_buff *skb, int hdr_size);
|
||||
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_ */
|
||||
|
14
drivers/staging/batman-adv/sysfs-class-net-batman-adv
Normal file
14
drivers/staging/batman-adv/sysfs-class-net-batman-adv
Normal 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.
|
33
drivers/staging/batman-adv/sysfs-class-net-mesh
Normal file
33
drivers/staging/batman-adv/sysfs-class-net-mesh
Normal 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.
|
@ -32,7 +32,10 @@ atomic_t hna_local_changed;
|
||||
DEFINE_SPINLOCK(hna_local_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 void _hna_global_del_orig(struct hna_global_entry *hna_global_entry,
|
||||
char *message);
|
||||
|
||||
static void hna_local_start_timer(void)
|
||||
{
|
||||
@ -57,6 +60,8 @@ int hna_local_init(void)
|
||||
|
||||
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_global_entry *hna_global_entry;
|
||||
struct hashtable_t *swaphash;
|
||||
@ -77,15 +82,15 @@ void hna_local_add(uint8_t *addr)
|
||||
MAC-flooding. */
|
||||
if ((num_hna + 1 > (ETH_DATA_LEN - BAT_PACKET_LEN) / ETH_ALEN) ||
|
||||
(num_hna + 1 > 255)) {
|
||||
bat_dbg(DBG_ROUTES,
|
||||
bat_dbg(DBG_ROUTES, bat_priv,
|
||||
"Can't add new local hna entry (%pM): "
|
||||
"number of local hna entries exceeds packet size\n",
|
||||
addr);
|
||||
return;
|
||||
}
|
||||
|
||||
bat_dbg(DBG_ROUTES, "Creating new local hna entry: %pM\n",
|
||||
addr);
|
||||
bat_dbg(DBG_ROUTES, bat_priv,
|
||||
"Creating new local hna entry: %pM\n", addr);
|
||||
|
||||
hna_local_entry = kmalloc(sizeof(struct hna_local_entry), GFP_ATOMIC);
|
||||
if (!hna_local_entry)
|
||||
@ -111,8 +116,7 @@ void hna_local_add(uint8_t *addr)
|
||||
hna_local_hash->size * 2);
|
||||
|
||||
if (swaphash == NULL)
|
||||
printk(KERN_ERR "batman-adv:"
|
||||
"Couldn't resize local hna hash table\n");
|
||||
pr_err("Couldn't resize local hna hash table\n");
|
||||
else
|
||||
hna_local_hash = swaphash;
|
||||
}
|
||||
@ -160,59 +164,54 @@ int hna_local_fill_buffer(unsigned char *buff, int buff_len)
|
||||
return i;
|
||||
}
|
||||
|
||||
int hna_local_fill_buffer_text(struct net_device *net_dev, char *buff,
|
||||
size_t count, loff_t off)
|
||||
int hna_local_seq_print_text(struct seq_file *seq, void *offset)
|
||||
{
|
||||
struct net_device *net_dev = (struct net_device *)seq->private;
|
||||
struct bat_priv *bat_priv = netdev_priv(net_dev);
|
||||
struct hna_local_entry *hna_local_entry;
|
||||
HASHIT(hashit);
|
||||
int bytes_written = 0;
|
||||
HASHIT(hashit_count);
|
||||
unsigned long flags;
|
||||
size_t hdr_len;
|
||||
size_t buf_size, pos;
|
||||
char *buff;
|
||||
|
||||
if (!bat_priv->primary_if) {
|
||||
if (off == 0)
|
||||
return sprintf(buff,
|
||||
"BATMAN mesh %s disabled - "
|
||||
"please specify interfaces to enable it\n",
|
||||
net_dev->name);
|
||||
|
||||
return 0;
|
||||
return seq_printf(seq, "BATMAN mesh %s disabled - "
|
||||
"please specify interfaces to enable it\n",
|
||||
net_dev->name);
|
||||
}
|
||||
|
||||
hdr_len = sprintf(buff,
|
||||
"Locally retrieved addresses (from %s) "
|
||||
"announced via HNA:\n",
|
||||
net_dev->name);
|
||||
|
||||
if (off < hdr_len)
|
||||
bytes_written = hdr_len;
|
||||
seq_printf(seq, "Locally retrieved addresses (from %s) "
|
||||
"announced via HNA:\n",
|
||||
net_dev->name);
|
||||
|
||||
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)) {
|
||||
hdr_len += 21;
|
||||
|
||||
if (count < bytes_written + 22)
|
||||
break;
|
||||
|
||||
if (off >= hdr_len)
|
||||
continue;
|
||||
|
||||
hna_local_entry = hashit.bucket->data;
|
||||
|
||||
bytes_written += snprintf(buff + bytes_written, 22,
|
||||
" * " MAC_FMT "\n",
|
||||
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]);
|
||||
pos += snprintf(buff + pos, 22, " * %pM\n",
|
||||
hna_local_entry->addr);
|
||||
}
|
||||
|
||||
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)
|
||||
@ -225,7 +224,9 @@ static void _hna_local_del(void *data)
|
||||
static void hna_local_del(struct hna_local_entry *hna_local_entry,
|
||||
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);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
void hna_local_purge(struct work_struct *work)
|
||||
static void hna_local_purge(struct work_struct *work)
|
||||
{
|
||||
struct hna_local_entry *hna_local_entry;
|
||||
HASHIT(hashit);
|
||||
@ -259,8 +260,7 @@ void hna_local_purge(struct work_struct *work)
|
||||
while (hash_iterate(hna_local_hash, &hashit)) {
|
||||
hna_local_entry = hashit.bucket->data;
|
||||
|
||||
timeout = hna_local_entry->last_seen +
|
||||
((LOCAL_HNA_TIMEOUT / 1000) * HZ);
|
||||
timeout = hna_local_entry->last_seen + LOCAL_HNA_TIMEOUT * HZ;
|
||||
if ((!hna_local_entry->never_purge) &&
|
||||
time_after(jiffies, timeout))
|
||||
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,
|
||||
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_local_entry *hna_local_entry;
|
||||
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);
|
||||
|
||||
bat_dbg(DBG_ROUTES,
|
||||
bat_dbg(DBG_ROUTES, bat_priv,
|
||||
"Creating new global hna entry: "
|
||||
"%pM (via %pM)\n",
|
||||
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);
|
||||
|
||||
if (swaphash == NULL)
|
||||
printk(KERN_ERR "batman-adv:"
|
||||
"Couldn't resize global hna hash table\n");
|
||||
pr_err("Couldn't resize global hna hash table\n");
|
||||
else
|
||||
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);
|
||||
}
|
||||
|
||||
int hna_global_fill_buffer_text(struct net_device *net_dev, char *buff,
|
||||
size_t count, loff_t off)
|
||||
int hna_global_seq_print_text(struct seq_file *seq, void *offset)
|
||||
{
|
||||
struct net_device *net_dev = (struct net_device *)seq->private;
|
||||
struct bat_priv *bat_priv = netdev_priv(net_dev);
|
||||
struct hna_global_entry *hna_global_entry;
|
||||
HASHIT(hashit);
|
||||
int bytes_written = 0;
|
||||
HASHIT(hashit_count);
|
||||
unsigned long flags;
|
||||
size_t hdr_len;
|
||||
size_t buf_size, pos;
|
||||
char *buff;
|
||||
|
||||
if (!bat_priv->primary_if) {
|
||||
if (off == 0)
|
||||
return sprintf(buff,
|
||||
"BATMAN mesh %s disabled - "
|
||||
"please specify interfaces to enable it\n",
|
||||
net_dev->name);
|
||||
|
||||
return 0;
|
||||
return seq_printf(seq, "BATMAN mesh %s disabled - "
|
||||
"please specify interfaces to enable it\n",
|
||||
net_dev->name);
|
||||
}
|
||||
|
||||
hdr_len = sprintf(buff,
|
||||
"Globally announced HNAs received via the mesh %s "
|
||||
"(translation table):\n",
|
||||
net_dev->name);
|
||||
|
||||
if (off < hdr_len)
|
||||
bytes_written = hdr_len;
|
||||
seq_printf(seq, "Globally announced HNAs received via the mesh %s\n",
|
||||
net_dev->name);
|
||||
|
||||
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)) {
|
||||
hdr_len += 43;
|
||||
|
||||
if (count < bytes_written + 44)
|
||||
break;
|
||||
|
||||
if (off >= hdr_len)
|
||||
continue;
|
||||
|
||||
hna_global_entry = hashit.bucket->data;
|
||||
|
||||
bytes_written += snprintf(buff + bytes_written, 44,
|
||||
" * " MAC_FMT " via " MAC_FMT "\n",
|
||||
hna_global_entry->addr[0],
|
||||
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]);
|
||||
pos += snprintf(buff + pos, 44,
|
||||
" * %pM via %pM\n", hna_global_entry->addr,
|
||||
hna_global_entry->orig_node->orig);
|
||||
}
|
||||
|
||||
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,
|
||||
char *message)
|
||||
static void _hna_global_del_orig(struct hna_global_entry *hna_global_entry,
|
||||
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,
|
||||
message);
|
||||
|
||||
|
@ -19,23 +19,21 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _NET_BATMAN_ADV_TRANSLATION_TABLE_H_
|
||||
#define _NET_BATMAN_ADV_TRANSLATION_TABLE_H_
|
||||
|
||||
#include "types.h"
|
||||
|
||||
int hna_local_init(void);
|
||||
void hna_local_add(uint8_t *addr);
|
||||
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_text(struct net_device *net_dev, char *buff,
|
||||
size_t count, loff_t off);
|
||||
void hna_local_purge(struct work_struct *work);
|
||||
int hna_local_seq_print_text(struct seq_file *seq, void *offset);
|
||||
void hna_local_free(void);
|
||||
int hna_global_init(void);
|
||||
void hna_global_add_orig(struct orig_node *orig_node, unsigned char *hna_buff,
|
||||
int hna_buff_len);
|
||||
int hna_global_fill_buffer_text(struct net_device *net_dev, char *buff,
|
||||
size_t count, loff_t off);
|
||||
void _hna_global_del_orig(struct hna_global_entry *hna_global_entry,
|
||||
char *orig_str);
|
||||
int hna_global_seq_print_text(struct seq_file *seq, void *offset);
|
||||
void hna_global_del_orig(struct orig_node *orig_node, char *message);
|
||||
void hna_global_free(void);
|
||||
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 struct hashtable_t *hna_local_hash;
|
||||
extern atomic_t hna_local_changed;
|
||||
|
||||
#endif /* _NET_BATMAN_ADV_TRANSLATION_TABLE_H_ */
|
||||
|
@ -21,10 +21,8 @@
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#ifndef TYPES_H
|
||||
#define TYPES_H
|
||||
#ifndef _NET_BATMAN_ADV_TYPES_H_
|
||||
#define _NET_BATMAN_ADV_TYPES_H_
|
||||
|
||||
#include "packet.h"
|
||||
#include "bitarray.h"
|
||||
@ -52,6 +50,7 @@ struct batman_if {
|
||||
|
||||
/**
|
||||
* 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
|
||||
* @bcast_seqno_reset: time when the broadcast 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_ttl: ttl of last received packet
|
||||
* @last_bcast_seqno: last broadcast sequence number received by this host
|
||||
*
|
||||
* @candidates: how many candidates are available
|
||||
* @selected: next bonding candidate
|
||||
*/
|
||||
struct orig_node {
|
||||
uint8_t orig[ETH_ALEN];
|
||||
uint8_t primary_addr[ETH_ALEN];
|
||||
struct neigh_node *router;
|
||||
TYPE_OF_WORD *bcast_own;
|
||||
uint8_t *bcast_own_sum;
|
||||
@ -72,12 +75,16 @@ struct orig_node {
|
||||
unsigned long batman_seqno_reset;
|
||||
uint8_t flags;
|
||||
unsigned char *hna_buff;
|
||||
int16_t hna_buff_len;
|
||||
uint16_t last_real_seqno;
|
||||
int16_t hna_buff_len;
|
||||
uint32_t last_real_seqno;
|
||||
uint8_t last_ttl;
|
||||
TYPE_OF_WORD bcast_bits[NUM_WORDS];
|
||||
uint16_t last_bcast_seqno;
|
||||
uint32_t last_bcast_seqno;
|
||||
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_avg;
|
||||
uint8_t last_ttl;
|
||||
struct neigh_node *next_bond_candidate;
|
||||
unsigned long last_valid;
|
||||
TYPE_OF_WORD real_bits[NUM_WORDS];
|
||||
struct orig_node *orig_node;
|
||||
@ -101,14 +109,18 @@ struct neigh_node {
|
||||
struct bat_priv {
|
||||
struct net_device_stats stats;
|
||||
atomic_t aggregation_enabled;
|
||||
atomic_t bonding_enabled;
|
||||
atomic_t vis_mode;
|
||||
atomic_t orig_interval;
|
||||
atomic_t log_level;
|
||||
char num_ifaces;
|
||||
struct debug_log *debug_log;
|
||||
struct batman_if *primary_if;
|
||||
struct kobject *mesh_obj;
|
||||
struct dentry *debug_dir;
|
||||
};
|
||||
|
||||
struct device_client {
|
||||
struct socket_client {
|
||||
struct list_head queue_list;
|
||||
unsigned int queue_len;
|
||||
unsigned char index;
|
||||
@ -116,9 +128,10 @@ struct device_client {
|
||||
wait_queue_head_t queue_wait;
|
||||
};
|
||||
|
||||
struct device_packet {
|
||||
struct socket_packet {
|
||||
struct list_head list;
|
||||
struct icmp_packet icmp_packet;
|
||||
size_t icmp_len;
|
||||
struct icmp_packet_rr icmp_packet;
|
||||
};
|
||||
|
||||
struct hna_local_entry {
|
||||
@ -159,4 +172,12 @@ struct if_list_entry {
|
||||
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_ */
|
||||
|
@ -43,8 +43,8 @@
|
||||
_dummy > smallest_signed_int(_dummy); })
|
||||
#define seq_after(x, y) seq_before(y, x)
|
||||
|
||||
struct hashtable_t *vis_hash;
|
||||
DEFINE_SPINLOCK(vis_hash_lock);
|
||||
static struct hashtable_t *vis_hash;
|
||||
static DEFINE_SPINLOCK(vis_hash_lock);
|
||||
static DEFINE_SPINLOCK(recv_list_lock);
|
||||
static struct vis_info *my_vis_info;
|
||||
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 */
|
||||
entry = kmalloc(sizeof(*entry), GFP_KERNEL);
|
||||
entry = kmalloc(sizeof(*entry), GFP_ATOMIC);
|
||||
if (!entry)
|
||||
return;
|
||||
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;
|
||||
}
|
||||
|
||||
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 */
|
||||
static ssize_t vis_data_read_entry(char *buff, struct vis_info_entry *entry,
|
||||
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);
|
||||
if (primary && entry->quality == 0)
|
||||
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;
|
||||
}
|
||||
|
||||
ssize_t vis_fill_buffer_text(struct net_device *net_dev, char *buff,
|
||||
size_t count, loff_t off)
|
||||
int vis_seq_print_text(struct seq_file *seq, void *offset)
|
||||
{
|
||||
HASHIT(hashit);
|
||||
HASHIT(hashit_count);
|
||||
struct vis_info *info;
|
||||
struct vis_info_entry *entries;
|
||||
struct net_device *net_dev = (struct net_device *)seq->private;
|
||||
struct bat_priv *bat_priv = netdev_priv(net_dev);
|
||||
HLIST_HEAD(vis_if_list);
|
||||
struct if_list_entry *entry;
|
||||
struct hlist_node *pos, *n;
|
||||
size_t hdr_len, tmp_len;
|
||||
int i, bytes_written = 0;
|
||||
int i;
|
||||
char tmp_addr_str[ETH_STR_LEN];
|
||||
unsigned long flags;
|
||||
int vis_server = atomic_read(&bat_priv->vis_mode);
|
||||
size_t buff_pos, buf_size;
|
||||
char *buff;
|
||||
|
||||
if ((!bat_priv->primary_if) ||
|
||||
(vis_server == VIS_TYPE_CLIENT_UPDATE))
|
||||
return 0;
|
||||
|
||||
hdr_len = 0;
|
||||
|
||||
buf_size = 1;
|
||||
/* Estimate length */
|
||||
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)) {
|
||||
info = hashit.bucket->data;
|
||||
entries = (struct vis_info_entry *)
|
||||
((char *)info + sizeof(struct vis_info));
|
||||
|
||||
/* estimated line length */
|
||||
if (count < bytes_written + 200)
|
||||
break;
|
||||
|
||||
for (i = 0; i < info->packet.entries; i++) {
|
||||
if (entries[i].quality == 0)
|
||||
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) {
|
||||
addr_to_string(tmp_addr_str, entry->addr);
|
||||
tmp_len = sprintf(buff + bytes_written,
|
||||
"%s,", tmp_addr_str);
|
||||
buff_pos += sprintf(buff + buff_pos, "%s,",
|
||||
tmp_addr_str);
|
||||
|
||||
for (i = 0; i < info->packet.entries; i++)
|
||||
tmp_len += vis_data_read_entry(
|
||||
buff + bytes_written + tmp_len,
|
||||
&entries[i], entry->addr,
|
||||
entry->primary);
|
||||
buff_pos += vis_data_read_entry(buff + buff_pos,
|
||||
&entries[i],
|
||||
entry->addr,
|
||||
entry->primary);
|
||||
|
||||
/* add primary/secondary records */
|
||||
if (compare_orig(entry->addr, info->packet.vis_orig))
|
||||
tmp_len += vis_data_read_prim_sec(
|
||||
buff + bytes_written + tmp_len,
|
||||
&vis_if_list);
|
||||
buff_pos +=
|
||||
vis_data_read_prim_sec(buff + buff_pos,
|
||||
&vis_if_list);
|
||||
|
||||
tmp_len += sprintf(buff + bytes_written + tmp_len,
|
||||
"\n");
|
||||
|
||||
hdr_len += tmp_len;
|
||||
|
||||
if (off >= hdr_len)
|
||||
continue;
|
||||
|
||||
bytes_written += tmp_len;
|
||||
buff_pos += sprintf(buff + buff_pos, "\n");
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
@ -308,7 +357,8 @@ static struct vis_info *add_packet(struct vis_packet *vis_packet,
|
||||
old_info = hash_find(vis_hash, &search_elem);
|
||||
|
||||
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) {
|
||||
recv_list_add(&old_info->recv_list,
|
||||
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 */
|
||||
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. */
|
||||
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);
|
||||
|
||||
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.seqno++;
|
||||
info->packet.seqno = htonl(ntohl(info->packet.seqno) + 1);
|
||||
info->packet.entries = 0;
|
||||
|
||||
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. */
|
||||
continue;
|
||||
if (time_after(jiffies,
|
||||
info->first_seen + (VIS_TIMEOUT*HZ)/1000)) {
|
||||
info->first_seen + VIS_TIMEOUT * HZ)) {
|
||||
hash_remove_bucket(vis_hash, &hashit);
|
||||
send_list_del(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);
|
||||
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)
|
||||
@ -628,11 +678,11 @@ static void send_vis_packet(struct vis_info *info)
|
||||
int packet_length;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
memcpy(info->packet.sender_orig, mainIfAddr, ETH_ALEN);
|
||||
memcpy(info->packet.sender_orig, main_if_addr, ETH_ALEN);
|
||||
info->packet.ttl--;
|
||||
|
||||
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);
|
||||
if (!vis_hash) {
|
||||
printk(KERN_ERR "batman-adv:Can't initialize vis_hash\n");
|
||||
pr_err("Can't initialize vis_hash\n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
my_vis_info = kmalloc(1000, GFP_ATOMIC);
|
||||
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;
|
||||
}
|
||||
|
||||
/* 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->send_list);
|
||||
kref_init(&my_vis_info->refcount);
|
||||
@ -713,12 +763,11 @@ int vis_init(void)
|
||||
|
||||
INIT_LIST_HEAD(&send_list);
|
||||
|
||||
memcpy(my_vis_info->packet.vis_orig, mainIfAddr, ETH_ALEN);
|
||||
memcpy(my_vis_info->packet.sender_orig, mainIfAddr, ETH_ALEN);
|
||||
memcpy(my_vis_info->packet.vis_orig, main_if_addr, ETH_ALEN);
|
||||
memcpy(my_vis_info->packet.sender_orig, main_if_addr, ETH_ALEN);
|
||||
|
||||
if (hash_add(vis_hash, my_vis_info) < 0) {
|
||||
printk(KERN_ERR
|
||||
"batman-adv:Can't add own vis packet into hash\n");
|
||||
pr_err("Can't add own vis packet into hash\n");
|
||||
/* not in hash, need to remove it manually. */
|
||||
kref_put(&my_vis_info->refcount, free_info);
|
||||
goto err;
|
||||
@ -764,5 +813,5 @@ void vis_quit(void)
|
||||
static void start_vis_timer(void)
|
||||
{
|
||||
queue_delayed_work(bat_event_workqueue, &vis_timer_wq,
|
||||
(atomic_read(&vis_interval) * HZ) / 1000);
|
||||
(VIS_INTERVAL * HZ) / 1000);
|
||||
}
|
||||
|
@ -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 {
|
||||
unsigned long first_seen;
|
||||
@ -44,11 +47,7 @@ struct recvlist_node {
|
||||
uint8_t mac[ETH_ALEN];
|
||||
};
|
||||
|
||||
extern struct hashtable_t *vis_hash;
|
||||
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);
|
||||
int vis_seq_print_text(struct seq_file *seq, void *offset);
|
||||
void receive_server_sync_packet(struct bat_priv *bat_priv,
|
||||
struct vis_packet *vis_packet,
|
||||
int vis_info_len);
|
||||
@ -57,3 +56,5 @@ void receive_client_update_packet(struct bat_priv *bat_priv,
|
||||
int vis_info_len);
|
||||
int vis_init(void);
|
||||
void vis_quit(void);
|
||||
|
||||
#endif /* _NET_BATMAN_ADV_VIS_H_ */
|
||||
|
@ -2,7 +2,6 @@ TODO:
|
||||
- checkpatch.pl cleanups
|
||||
- Lindent
|
||||
- remove all wrappers
|
||||
- remove typedefs
|
||||
- audit userspace interface
|
||||
- reserve major number
|
||||
- cleanup the individual comedi drivers as well
|
||||
|
@ -1845,8 +1845,15 @@ ok:
|
||||
}
|
||||
}
|
||||
|
||||
if (dev->attached && dev->use_count == 0 && dev->open)
|
||||
dev->open(dev);
|
||||
if (dev->attached && dev->use_count == 0 && dev->open) {
|
||||
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++;
|
||||
|
||||
|
@ -53,62 +53,6 @@
|
||||
COMEDI_MINORVERSION, COMEDI_MICROVERSION)
|
||||
#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_ICP 0x104c
|
||||
#define PCI_VENDOR_ID_CONTEC 0x1221
|
||||
@ -285,7 +229,7 @@ struct comedi_device {
|
||||
|
||||
struct fasync_struct *async_queue;
|
||||
|
||||
void (*open) (struct comedi_device *dev);
|
||||
int (*open) (struct comedi_device *dev);
|
||||
void (*close) (struct comedi_device *dev);
|
||||
};
|
||||
|
||||
|
@ -117,7 +117,18 @@ static struct comedi_driver driver_8255 = {
|
||||
.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);
|
||||
|
||||
@ -457,3 +468,7 @@ static int dev_8255_detach(struct comedi_device *dev)
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
MODULE_AUTHOR("Comedi http://www.comedi.org");
|
||||
MODULE_DESCRIPTION("Comedi low-level driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
@ -49,7 +49,18 @@ static struct comedi_driver driver_acl7225b = {
|
||||
.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,
|
||||
struct comedi_subdevice *s,
|
||||
@ -150,3 +161,7 @@ static int acl7225b_detach(struct comedi_device *dev)
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
MODULE_AUTHOR("Comedi http://www.comedi.org");
|
||||
MODULE_DESCRIPTION("Comedi low-level driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
@ -247,16 +247,14 @@ int i_pci_card_data(struct pcilst_struct *amcc,
|
||||
/* build list of amcc cards in this system */
|
||||
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;
|
||||
int i;
|
||||
int i_Count = 0;
|
||||
amcc_devices = NULL;
|
||||
last = NULL;
|
||||
|
||||
for (pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, NULL);
|
||||
pcidev != NULL;
|
||||
pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pcidev)) {
|
||||
for_each_pci_dev(pcidev) {
|
||||
for (i_Count = 0; i_Count < 2; i_Count++) {
|
||||
pci_vendor = i_ADDIDATADeviceID[i_Count];
|
||||
if (pcidev->vendor == pci_vendor) {
|
||||
|
@ -2541,7 +2541,43 @@ static struct comedi_driver driver_addi = {
|
||||
.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);
|
||||
|
||||
/*
|
||||
+----------------------------------------------------------------------------+
|
||||
|
@ -101,10 +101,10 @@ struct str_TimerMainHeader {
|
||||
};
|
||||
|
||||
|
||||
typedef struct {
|
||||
struct str_AnalogOutputHeader {
|
||||
unsigned short w_Nchannel;
|
||||
unsigned char b_Resolution;
|
||||
} str_AnalogOutputHeader;
|
||||
};
|
||||
|
||||
struct str_AnalogInputHeader {
|
||||
unsigned short w_Nchannel;
|
||||
@ -136,7 +136,7 @@ int i_EepromReadTimerHeader(unsigned short w_PCIBoardEepromAddress,
|
||||
|
||||
int i_EepromReadAnlogOutputHeader(unsigned short w_PCIBoardEepromAddress,
|
||||
char *pc_PCIChipInformation, unsigned short w_Address,
|
||||
str_AnalogOutputHeader *s_Header);
|
||||
struct str_AnalogOutputHeader *s_Header);
|
||||
|
||||
int i_EepromReadAnlogInputHeader(unsigned short w_PCIBoardEepromAddress,
|
||||
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 |
|
||||
|
||||
| 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. |
|
||||
|
||||
@ -811,7 +811,7 @@ int i_EepromReadMainHeader(unsigned short w_PCIBoardEepromAddress,
|
||||
struct str_DigitalInputHeader s_DigitalInputHeader;
|
||||
struct str_DigitalOutputHeader s_DigitalOutputHeader;
|
||||
/* struct str_TimerMainHeader s_TimerMainHeader,s_WatchdogMainHeader; */
|
||||
str_AnalogOutputHeader s_AnalogOutputHeader;
|
||||
struct str_AnalogOutputHeader s_AnalogOutputHeader;
|
||||
struct str_AnalogInputHeader s_AnalogInputHeader;
|
||||
|
||||
/* Read size */
|
||||
@ -1081,7 +1081,7 @@ int i_EepromReadTimerHeader(unsigned short w_PCIBoardEepromAddress,
|
||||
|
||||
int i_EepromReadAnlogOutputHeader(unsigned short w_PCIBoardEepromAddress,
|
||||
char *pc_PCIChipInformation, unsigned short w_Address,
|
||||
str_AnalogOutputHeader *s_Header)
|
||||
struct str_AnalogOutputHeader *s_Header)
|
||||
{
|
||||
unsigned short w_Temp;
|
||||
/* No of channels for 1st hard component */
|
||||
|
@ -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
|
||||
*/
|
||||
|
||||
/* DMA Start Adress Low */
|
||||
/* DMA Start Address Low */
|
||||
outw(APCI3120_ADD_ON_MWAR_LOW, devpriv->i_IobaseAddon + 0);
|
||||
outw((devpriv->ul_DmaBufferHw[0] & 0xFFFF),
|
||||
devpriv->i_IobaseAddon + 2);
|
||||
|
||||
/*************************/
|
||||
/* DMA Start Adress High */
|
||||
/* DMA Start Address High */
|
||||
/*************************/
|
||||
outw(APCI3120_ADD_ON_MWAR_HIGH, devpriv->i_IobaseAddon + 0);
|
||||
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];
|
||||
high_word = var / 65536;
|
||||
|
||||
/* DMA Start Adress Low */
|
||||
/* DMA Start Address Low */
|
||||
outw(APCI3120_ADD_ON_MWAR_LOW, devpriv->i_IobaseAddon + 0);
|
||||
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(high_word, devpriv->i_IobaseAddon + 2);
|
||||
|
||||
|
@ -5,3 +5,7 @@
|
||||
#define ADDIDATA_DRIVER_NAME "addi_apci_035"
|
||||
|
||||
#include "addi-data/addi_common.c"
|
||||
|
||||
MODULE_AUTHOR("Comedi http://www.comedi.org");
|
||||
MODULE_DESCRIPTION("Comedi low-level driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
@ -3,3 +3,7 @@
|
||||
#define ADDIDATA_DRIVER_NAME "addi_apci_1032"
|
||||
|
||||
#include "addi-data/addi_common.c"
|
||||
|
||||
MODULE_AUTHOR("Comedi http://www.comedi.org");
|
||||
MODULE_DESCRIPTION("Comedi low-level driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
@ -3,3 +3,7 @@
|
||||
#define ADDIDATA_DRIVER_NAME "addi_apci_1500"
|
||||
|
||||
#include "addi-data/addi_common.c"
|
||||
|
||||
MODULE_AUTHOR("Comedi http://www.comedi.org");
|
||||
MODULE_DESCRIPTION("Comedi low-level driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
@ -3,3 +3,7 @@
|
||||
#define ADDIDATA_DRIVER_NAME "addi_apci_1516"
|
||||
|
||||
#include "addi-data/addi_common.c"
|
||||
|
||||
MODULE_AUTHOR("Comedi http://www.comedi.org");
|
||||
MODULE_DESCRIPTION("Comedi low-level driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
@ -3,3 +3,7 @@
|
||||
#define ADDIDATA_DRIVER_NAME "addi_apci_1564"
|
||||
|
||||
#include "addi-data/addi_common.c"
|
||||
|
||||
MODULE_AUTHOR("Comedi http://www.comedi.org");
|
||||
MODULE_DESCRIPTION("Comedi low-level driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
@ -3,3 +3,7 @@
|
||||
#define ADDIDATA_DRIVER_NAME "addi_apci_16xx"
|
||||
|
||||
#include "addi-data/addi_common.c"
|
||||
|
||||
MODULE_AUTHOR("Comedi http://www.comedi.org");
|
||||
MODULE_DESCRIPTION("Comedi low-level driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
@ -3,3 +3,7 @@
|
||||
#define ADDIDATA_DRIVER_NAME "addi_apci_2016"
|
||||
|
||||
#include "addi-data/addi_common.c"
|
||||
|
||||
MODULE_AUTHOR("Comedi http://www.comedi.org");
|
||||
MODULE_DESCRIPTION("Comedi low-level driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
@ -3,3 +3,7 @@
|
||||
#define ADDIDATA_DRIVER_NAME "addi_apci_2032"
|
||||
|
||||
#include "addi-data/addi_common.c"
|
||||
|
||||
MODULE_AUTHOR("Comedi http://www.comedi.org");
|
||||
MODULE_DESCRIPTION("Comedi low-level driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
@ -3,3 +3,7 @@
|
||||
#define ADDIDATA_DRIVER_NAME "addi_apci_2200"
|
||||
|
||||
#include "addi-data/addi_common.c"
|
||||
|
||||
MODULE_AUTHOR("Comedi http://www.comedi.org");
|
||||
MODULE_DESCRIPTION("Comedi low-level driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
@ -3,3 +3,7 @@
|
||||
#define ADDIDATA_DRIVER_NAME "addi_apci_3001"
|
||||
|
||||
#include "addi-data/addi_common.c"
|
||||
|
||||
MODULE_AUTHOR("Comedi http://www.comedi.org");
|
||||
MODULE_DESCRIPTION("Comedi low-level driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
@ -3,3 +3,7 @@
|
||||
#define ADDIDATA_DRIVER_NAME "addi_apci_3120"
|
||||
|
||||
#include "addi-data/addi_common.c"
|
||||
|
||||
MODULE_AUTHOR("Comedi http://www.comedi.org");
|
||||
MODULE_DESCRIPTION("Comedi low-level driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
@ -3,3 +3,7 @@
|
||||
#define ADDIDATA_DRIVER_NAME "addi_apci_3501"
|
||||
|
||||
#include "addi-data/addi_common.c"
|
||||
|
||||
MODULE_AUTHOR("Comedi http://www.comedi.org");
|
||||
MODULE_DESCRIPTION("Comedi low-level driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
@ -3,3 +3,7 @@
|
||||
#define ADDIDATA_DRIVER_NAME "addi_apci_3xxx"
|
||||
|
||||
#include "addi-data/addi_common.c"
|
||||
|
||||
MODULE_AUTHOR("Comedi http://www.comedi.org");
|
||||
MODULE_DESCRIPTION("Comedi low-level driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
@ -119,7 +119,43 @@ static struct comedi_driver driver_pci6208 = {
|
||||
.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
|
||||
@ -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)
|
||||
{
|
||||
struct pci_dev *pci_dev;
|
||||
struct pci_dev *pci_dev = NULL;
|
||||
int i;
|
||||
|
||||
for (pci_dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, NULL);
|
||||
pci_dev != NULL;
|
||||
pci_dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pci_dev)) {
|
||||
for_each_pci_dev(pci_dev) {
|
||||
if (pci_dev->vendor == PCI_VENDOR_ID_ADLINK) {
|
||||
for (i = 0; i < ARRAY_SIZE(pci6208_boards); i++) {
|
||||
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;
|
||||
}
|
||||
|
||||
MODULE_AUTHOR("Comedi http://www.comedi.org");
|
||||
MODULE_DESCRIPTION("Comedi low-level driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
@ -90,7 +90,7 @@ static int adl_pci7230_do_insn_bits(struct comedi_device *dev,
|
||||
static int adl_pci7230_attach(struct comedi_device *dev,
|
||||
struct comedi_devconfig *it)
|
||||
{
|
||||
struct pci_dev *pcidev;
|
||||
struct pci_dev *pcidev = NULL;
|
||||
struct comedi_subdevice *s;
|
||||
int bus, slot;
|
||||
|
||||
@ -106,10 +106,7 @@ static int adl_pci7230_attach(struct comedi_device *dev,
|
||||
if (alloc_subdevices(dev, 2) < 0)
|
||||
return -ENOMEM;
|
||||
|
||||
for (pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, NULL);
|
||||
pcidev != NULL;
|
||||
pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pcidev)) {
|
||||
|
||||
for_each_pci_dev(pcidev) {
|
||||
if (pcidev->vendor == PCI_VENDOR_ID_ADLINK &&
|
||||
pcidev->device == PCI_DEVICE_ID_PCI7230) {
|
||||
if (bus || slot) {
|
||||
@ -203,4 +200,46 @@ static int adl_pci7230_di_insn_bits(struct comedi_device *dev,
|
||||
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");
|
||||
|
@ -77,7 +77,7 @@ static struct comedi_driver driver_adl_pci7296 = {
|
||||
static int adl_pci7296_attach(struct comedi_device *dev,
|
||||
struct comedi_devconfig *it)
|
||||
{
|
||||
struct pci_dev *pcidev;
|
||||
struct pci_dev *pcidev = NULL;
|
||||
struct comedi_subdevice *s;
|
||||
int bus, slot;
|
||||
int ret;
|
||||
@ -94,10 +94,7 @@ static int adl_pci7296_attach(struct comedi_device *dev,
|
||||
if (alloc_subdevices(dev, 4) < 0)
|
||||
return -ENOMEM;
|
||||
|
||||
for (pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, NULL);
|
||||
pcidev != NULL;
|
||||
pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pcidev)) {
|
||||
|
||||
for_each_pci_dev(pcidev) {
|
||||
if (pcidev->vendor == PCI_VENDOR_ID_ADLINK &&
|
||||
pcidev->device == PCI_DEVICE_ID_PCI7296) {
|
||||
if (bus || slot) {
|
||||
@ -177,4 +174,46 @@ static int adl_pci7296_detach(struct comedi_device *dev)
|
||||
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");
|
||||
|
@ -86,7 +86,7 @@ static int adl_pci7432_do_insn_bits(struct comedi_device *dev,
|
||||
static int adl_pci7432_attach(struct comedi_device *dev,
|
||||
struct comedi_devconfig *it)
|
||||
{
|
||||
struct pci_dev *pcidev;
|
||||
struct pci_dev *pcidev = NULL;
|
||||
struct comedi_subdevice *s;
|
||||
int bus, slot;
|
||||
|
||||
@ -102,10 +102,7 @@ static int adl_pci7432_attach(struct comedi_device *dev,
|
||||
if (alloc_subdevices(dev, 2) < 0)
|
||||
return -ENOMEM;
|
||||
|
||||
for (pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, NULL);
|
||||
pcidev != NULL;
|
||||
pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pcidev)) {
|
||||
|
||||
for_each_pci_dev(pcidev) {
|
||||
if (pcidev->vendor == PCI_VENDOR_ID_ADLINK &&
|
||||
pcidev->device == PCI_DEVICE_ID_PCI7432) {
|
||||
if (bus || slot) {
|
||||
@ -210,4 +207,46 @@ static int adl_pci7432_di_insn_bits(struct comedi_device *dev,
|
||||
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");
|
||||
|
@ -125,7 +125,7 @@ static int adl_pci8164_insn_write_buf1(struct comedi_device *dev,
|
||||
static int adl_pci8164_attach(struct comedi_device *dev,
|
||||
struct comedi_devconfig *it)
|
||||
{
|
||||
struct pci_dev *pcidev;
|
||||
struct pci_dev *pcidev = NULL;
|
||||
struct comedi_subdevice *s;
|
||||
int bus, slot;
|
||||
|
||||
@ -142,10 +142,7 @@ static int adl_pci8164_attach(struct comedi_device *dev,
|
||||
if (alloc_subdevices(dev, 4) < 0)
|
||||
return -ENOMEM;
|
||||
|
||||
for (pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, NULL);
|
||||
pcidev != NULL;
|
||||
pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pcidev)) {
|
||||
|
||||
for_each_pci_dev(pcidev) {
|
||||
if (pcidev->vendor == PCI_VENDOR_ID_ADLINK &&
|
||||
pcidev->device == PCI_DEVICE_ID_PCI8164) {
|
||||
if (bus || slot) {
|
||||
@ -389,4 +386,46 @@ static int adl_pci8164_insn_write_buf1(struct comedi_device *dev,
|
||||
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");
|
||||
|
@ -38,8 +38,8 @@ Supports:
|
||||
- do_insn read/write
|
||||
- ai_do_cmd mode with the following sources:
|
||||
|
||||
- start_src TRIG_NOW
|
||||
- scan_begin_src TRIG_FOLLOW TRIG_TIMER TRIG_EXT
|
||||
- start_src TRIG_NOW
|
||||
- scan_begin_src TRIG_FOLLOW TRIG_TIMER TRIG_EXT
|
||||
- convert_src TRIG_TIMER TRIG_EXT
|
||||
- scan_end_src TRIG_COUNT
|
||||
- stop_src TRIG_COUNT TRIG_NONE
|
||||
@ -68,8 +68,9 @@ CHANGELOG:
|
||||
TODO:
|
||||
|
||||
- Really test implemented functionality.
|
||||
- Add support for the PCI-9111DG with a probe routine to identify the card type
|
||||
(perhaps with the help of the channel number readback of the A/D Data register).
|
||||
- Add support for the PCI-9111DG with a probe routine to identify the card
|
||||
type (perhaps with the help of the channel number readback of the A/D Data
|
||||
register).
|
||||
- Add external multiplexer support.
|
||||
|
||||
*/
|
||||
@ -83,12 +84,12 @@ TODO:
|
||||
#include "comedi_pci.h"
|
||||
#include "comedi_fc.h"
|
||||
|
||||
#define PCI9111_DRIVER_NAME "adl_pci9111"
|
||||
#define PCI9111_HR_DEVICE_ID 0x9111
|
||||
#define PCI9111_DRIVER_NAME "adl_pci9111"
|
||||
#define PCI9111_HR_DEVICE_ID 0x9111
|
||||
|
||||
/* TODO: Add other pci9111 board id */
|
||||
|
||||
#define PCI9111_IO_RANGE 0x0100
|
||||
#define PCI9111_IO_RANGE 0x0100
|
||||
|
||||
#define PCI9111_FIFO_HALF_SIZE 512
|
||||
|
||||
@ -134,27 +135,29 @@ TODO:
|
||||
|
||||
/* IO address map */
|
||||
|
||||
#define PCI9111_REGISTER_AD_FIFO_VALUE 0x00 /* AD Data stored in FIFO */
|
||||
#define PCI9111_REGISTER_DA_OUTPUT 0x00
|
||||
#define PCI9111_REGISTER_DIGITAL_IO 0x02
|
||||
#define PCI9111_REGISTER_EXTENDED_IO_PORTS 0x04
|
||||
#define PCI9111_REGISTER_AD_CHANNEL_CONTROL 0x06 /* Channel selection */
|
||||
#define PCI9111_REGISTER_AD_CHANNEL_READBACK 0x06
|
||||
#define PCI9111_REGISTER_INPUT_SIGNAL_RANGE 0x08
|
||||
#define PCI9111_REGISTER_RANGE_STATUS_READBACK 0x08
|
||||
#define PCI9111_REGISTER_TRIGGER_MODE_CONTROL 0x0A
|
||||
#define PCI9111_REGISTER_AD_MODE_INTERRUPT_READBACK 0x0A
|
||||
#define PCI9111_REGISTER_SOFTWARE_TRIGGER 0x0E
|
||||
#define PCI9111_REGISTER_INTERRUPT_CONTROL 0x0C
|
||||
#define PCI9111_REGISTER_AD_FIFO_VALUE 0x00 /* AD Data stored
|
||||
in FIFO */
|
||||
#define PCI9111_REGISTER_DA_OUTPUT 0x00
|
||||
#define PCI9111_REGISTER_DIGITAL_IO 0x02
|
||||
#define PCI9111_REGISTER_EXTENDED_IO_PORTS 0x04
|
||||
#define PCI9111_REGISTER_AD_CHANNEL_CONTROL 0x06 /* Channel
|
||||
selection */
|
||||
#define PCI9111_REGISTER_AD_CHANNEL_READBACK 0x06
|
||||
#define PCI9111_REGISTER_INPUT_SIGNAL_RANGE 0x08
|
||||
#define PCI9111_REGISTER_RANGE_STATUS_READBACK 0x08
|
||||
#define PCI9111_REGISTER_TRIGGER_MODE_CONTROL 0x0A
|
||||
#define PCI9111_REGISTER_AD_MODE_INTERRUPT_READBACK 0x0A
|
||||
#define PCI9111_REGISTER_SOFTWARE_TRIGGER 0x0E
|
||||
#define PCI9111_REGISTER_INTERRUPT_CONTROL 0x0C
|
||||
#define PCI9111_REGISTER_8254_COUNTER_0 0x40
|
||||
#define PCI9111_REGISTER_8254_COUNTER_1 0x42
|
||||
#define PCI9111_REGISTER_8254_COUNTER_2 0X44
|
||||
#define PCI9111_REGISTER_8254_COUNTER_2 0X44
|
||||
#define PCI9111_REGISTER_8254_CONTROL 0x46
|
||||
#define PCI9111_REGISTER_INTERRUPT_CLEAR 0x48
|
||||
#define PCI9111_REGISTER_INTERRUPT_CLEAR 0x48
|
||||
|
||||
#define PCI9111_TRIGGER_MASK 0x0F
|
||||
#define PCI9111_PTRG_OFF (0 << 3)
|
||||
#define PCI9111_PTRG_ON (1 << 3)
|
||||
#define PCI9111_TRIGGER_MASK 0x0F
|
||||
#define PCI9111_PTRG_OFF (0 << 3)
|
||||
#define PCI9111_PTRG_ON (1 << 3)
|
||||
#define PCI9111_EITS_EXTERNAL (1 << 2)
|
||||
#define PCI9111_EITS_INTERNAL (0 << 2)
|
||||
#define PCI9111_TPST_SOFTWARE_TRIGGER (0 << 1)
|
||||
@ -164,9 +167,9 @@ TODO:
|
||||
|
||||
#define PCI9111_ISC0_SET_IRQ_ON_ENDING_OF_AD_CONVERSION (0 << 0)
|
||||
#define PCI9111_ISC0_SET_IRQ_ON_FIFO_HALF_FULL (1 << 0)
|
||||
#define PCI9111_ISC1_SET_IRQ_ON_TIMER_TICK (0 << 1)
|
||||
#define PCI9111_ISC1_SET_IRQ_ON_EXT_TRG (1 << 1)
|
||||
#define PCI9111_FFEN_SET_FIFO_ENABLE (0 << 2)
|
||||
#define PCI9111_ISC1_SET_IRQ_ON_TIMER_TICK (0 << 1)
|
||||
#define PCI9111_ISC1_SET_IRQ_ON_EXT_TRG (1 << 1)
|
||||
#define PCI9111_FFEN_SET_FIFO_ENABLE (0 << 2)
|
||||
#define PCI9111_FFEN_SET_FIFO_DISABLE (1 << 2)
|
||||
|
||||
#define PCI9111_CHANNEL_MASK 0x0F
|
||||
@ -177,7 +180,7 @@ TODO:
|
||||
#define PCI9111_FIFO_FULL_MASK 0x40
|
||||
#define PCI9111_AD_BUSY_MASK 0x80
|
||||
|
||||
#define PCI9111_IO_BASE dev->iobase
|
||||
#define PCI9111_IO_BASE (dev->iobase)
|
||||
|
||||
/*
|
||||
* Define inlined function
|
||||
@ -189,8 +192,9 @@ TODO:
|
||||
#define pci9111_trigger_and_autoscan_set(flags) \
|
||||
outb(flags, PCI9111_IO_BASE+PCI9111_REGISTER_TRIGGER_MODE_CONTROL)
|
||||
|
||||
#define pci9111_interrupt_and_fifo_get() \
|
||||
((inb(PCI9111_IO_BASE+PCI9111_REGISTER_AD_MODE_INTERRUPT_READBACK) >> 4) &0x03)
|
||||
#define pci9111_interrupt_and_fifo_get() \
|
||||
((inb(PCI9111_IO_BASE+PCI9111_REGISTER_AD_MODE_INTERRUPT_READBACK) >> 4) \
|
||||
&0x03)
|
||||
|
||||
#define pci9111_interrupt_and_fifo_set(flags) \
|
||||
outb(flags, PCI9111_IO_BASE+PCI9111_REGISTER_INTERRUPT_CONTROL)
|
||||
@ -201,45 +205,56 @@ TODO:
|
||||
#define pci9111_software_trigger() \
|
||||
outb(0, PCI9111_IO_BASE+PCI9111_REGISTER_SOFTWARE_TRIGGER)
|
||||
|
||||
#define pci9111_fifo_reset() \
|
||||
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)
|
||||
#define pci9111_fifo_reset() do { \
|
||||
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() \
|
||||
((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() \
|
||||
((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() \
|
||||
((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) \
|
||||
outb((channel)&PCI9111_CHANNEL_MASK, PCI9111_IO_BASE+PCI9111_REGISTER_AD_CHANNEL_CONTROL)
|
||||
#define pci9111_ai_channel_set(channel) \
|
||||
outb((channel)&PCI9111_CHANNEL_MASK, \
|
||||
PCI9111_IO_BASE+PCI9111_REGISTER_AD_CHANNEL_CONTROL)
|
||||
|
||||
#define pci9111_ai_channel_get() \
|
||||
inb(PCI9111_IO_BASE+PCI9111_REGISTER_AD_CHANNEL_READBACK)&PCI9111_CHANNEL_MASK
|
||||
#define pci9111_ai_channel_get() \
|
||||
(inb(PCI9111_IO_BASE+PCI9111_REGISTER_AD_CHANNEL_READBACK) \
|
||||
&PCI9111_CHANNEL_MASK)
|
||||
|
||||
#define pci9111_ai_range_set(range) \
|
||||
outb((range)&PCI9111_RANGE_MASK, PCI9111_IO_BASE+PCI9111_REGISTER_INPUT_SIGNAL_RANGE)
|
||||
#define pci9111_ai_range_set(range) \
|
||||
outb((range)&PCI9111_RANGE_MASK, \
|
||||
PCI9111_IO_BASE+PCI9111_REGISTER_INPUT_SIGNAL_RANGE)
|
||||
|
||||
#define pci9111_ai_range_get() \
|
||||
inb(PCI9111_IO_BASE+PCI9111_REGISTER_RANGE_STATUS_READBACK)&PCI9111_RANGE_MASK
|
||||
#define pci9111_ai_range_get() \
|
||||
(inb(PCI9111_IO_BASE+PCI9111_REGISTER_RANGE_STATUS_READBACK) \
|
||||
&PCI9111_RANGE_MASK)
|
||||
|
||||
#define pci9111_ai_get_data() \
|
||||
((inw(PCI9111_IO_BASE+PCI9111_REGISTER_AD_FIFO_VALUE)>>4)&PCI9111_AI_RESOLUTION_MASK) \
|
||||
^ PCI9111_AI_RESOLUTION_2_CMP_BIT
|
||||
#define pci9111_ai_get_data() \
|
||||
(((inw(PCI9111_IO_BASE+PCI9111_REGISTER_AD_FIFO_VALUE)>>4) \
|
||||
&PCI9111_AI_RESOLUTION_MASK) \
|
||||
^ PCI9111_AI_RESOLUTION_2_CMP_BIT)
|
||||
|
||||
#define pci9111_hr_ai_get_data() \
|
||||
(inw(PCI9111_IO_BASE+PCI9111_REGISTER_AD_FIFO_VALUE) & PCI9111_HR_AI_RESOLUTION_MASK) \
|
||||
^ PCI9111_HR_AI_RESOLUTION_2_CMP_BIT
|
||||
#define pci9111_hr_ai_get_data() \
|
||||
((inw(PCI9111_IO_BASE+PCI9111_REGISTER_AD_FIFO_VALUE) \
|
||||
& PCI9111_HR_AI_RESOLUTION_MASK) \
|
||||
^ PCI9111_HR_AI_RESOLUTION_2_CMP_BIT)
|
||||
|
||||
#define pci9111_ao_set_data(data) \
|
||||
outw(data&PCI9111_AO_RESOLUTION_MASK, PCI9111_IO_BASE+PCI9111_REGISTER_DA_OUTPUT)
|
||||
#define pci9111_ao_set_data(data) \
|
||||
outw(data&PCI9111_AO_RESOLUTION_MASK, \
|
||||
PCI9111_IO_BASE+PCI9111_REGISTER_DA_OUTPUT)
|
||||
|
||||
#define pci9111_di_get_bits() \
|
||||
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) = {
|
||||
{
|
||||
PCI_VENDOR_ID_ADLINK, PCI9111_HR_DEVICE_ID, PCI_ANY_ID,
|
||||
PCI_ANY_ID, 0, 0, 0},
|
||||
/* { PCI_VENDOR_ID_ADLINK, PCI9111_HG_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, */
|
||||
{
|
||||
0}
|
||||
{ PCI_VENDOR_ID_ADLINK, PCI9111_HR_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,
|
||||
0, 0, 0 },
|
||||
/* { PCI_VENDOR_ID_ADLINK, PCI9111_HG_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,
|
||||
* 0, 0, 0 }, */
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(pci, pci9111_pci_table);
|
||||
@ -337,7 +351,43 @@ static struct comedi_driver pci9111_driver = {
|
||||
.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 */
|
||||
|
||||
@ -345,7 +395,8 @@ struct pci9111_private_data {
|
||||
struct pci_dev *pci_device;
|
||||
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;
|
||||
|
||||
int stop_counter;
|
||||
@ -358,7 +409,8 @@ struct pci9111_private_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;
|
||||
|
||||
int is_valid; /* Is device valid */
|
||||
@ -366,7 +418,7 @@ struct pci9111_private_data {
|
||||
short ai_bounce_buffer[2 * PCI9111_FIFO_HALF_SIZE];
|
||||
};
|
||||
|
||||
#define dev_private ((struct pci9111_private_data *)dev->private)
|
||||
#define dev_private ((struct pci9111_private_data *)dev->private)
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
/* PLX9050 SECTION */
|
||||
@ -548,10 +600,12 @@ static int pci9111_ai_cancel(struct comedi_device *dev,
|
||||
|
||||
/* Test analog input command */
|
||||
|
||||
#define pci9111_check_trigger_src(src, flags) \
|
||||
tmp = src; \
|
||||
src &= flags; \
|
||||
if (!src || tmp != src) error++
|
||||
#define pci9111_check_trigger_src(src, flags) do { \
|
||||
tmp = src; \
|
||||
src &= flags; \
|
||||
if (!src || tmp != src) \
|
||||
error++; \
|
||||
} while (false);
|
||||
|
||||
static int
|
||||
pci9111_ai_do_cmd_test(struct comedi_device *dev,
|
||||
@ -575,7 +629,8 @@ pci9111_ai_do_cmd_test(struct comedi_device *dev,
|
||||
if (error)
|
||||
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)
|
||||
error++;
|
||||
@ -637,7 +692,8 @@ pci9111_ai_do_cmd_test(struct comedi_device *dev,
|
||||
cmd->scan_begin_arg = board->ai_acquisition_period_min_ns;
|
||||
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;
|
||||
error++;
|
||||
}
|
||||
@ -1216,7 +1272,7 @@ static int pci9111_attach(struct comedi_device *dev,
|
||||
{
|
||||
struct comedi_subdevice *subdevice;
|
||||
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;
|
||||
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);
|
||||
|
||||
for (pci_device = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, NULL);
|
||||
pci_device != NULL;
|
||||
pci_device = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pci_device)) {
|
||||
for_each_pci_dev(pci_device) {
|
||||
if (pci_device->vendor == PCI_VENDOR_ID_ADLINK) {
|
||||
for (i = 0; i < pci9111_board_nbr; i++) {
|
||||
if (pci9111_boards[i].device_id ==
|
||||
pci_device->device) {
|
||||
/* was a particular bus/slot requested? */
|
||||
/* was a particular bus/slot
|
||||
* requested? */
|
||||
if ((it->options[0] != 0)
|
||||
|| (it->options[1] != 0)) {
|
||||
/* are we on the wrong bus/slot? */
|
||||
/* are we on the wrong
|
||||
* bus/slot? */
|
||||
if (pci_device->bus->number !=
|
||||
it->options[0]
|
||||
||
|
||||
@ -1272,7 +1328,8 @@ found:
|
||||
|
||||
/* 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_range = pci_resource_len(pci_device, 1);
|
||||
@ -1399,3 +1456,7 @@ static int pci9111_detach(struct comedi_device *dev)
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
MODULE_AUTHOR("Comedi http://www.comedi.org");
|
||||
MODULE_DESCRIPTION("Comedi low-level driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
@ -289,7 +289,43 @@ static struct comedi_driver driver_pci9118 = {
|
||||
.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 {
|
||||
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");
|
||||
|
@ -402,4 +402,19 @@ static int adq12b_do_insn_bits(struct comedi_device *dev,
|
||||
* A convenient macro that defines init_module() and cleanup_module(),
|
||||
* 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");
|
||||
|
@ -19,7 +19,7 @@
|
||||
/*
|
||||
Driver: adv_pci1710
|
||||
Description: Advantech PCI-1710, PCI-1710HG, PCI-1711, PCI-1713,
|
||||
Advantech PCI-1720, PCI-1731
|
||||
Advantech PCI-1720, PCI-1731
|
||||
Author: Michal Dobes <dobes@tesnet.cz>
|
||||
Devices: [Advantech] PCI-1710 (adv_pci1710), PCI-1710HG (pci1710hg),
|
||||
PCI-1711 (adv_pci1710), PCI-1713, PCI-1720,
|
||||
@ -37,8 +37,8 @@ PCI driver.
|
||||
Configuration options:
|
||||
[0] - PCI bus of device (optional)
|
||||
[1] - PCI slot of device (optional)
|
||||
If bus/slot is not specified, the first available PCI
|
||||
device will be used.
|
||||
If bus/slot is not specified, the first available PCI
|
||||
device will be used.
|
||||
*/
|
||||
|
||||
#include <linux/interrupt.h>
|
||||
@ -50,7 +50,9 @@ Configuration options:
|
||||
#include "8253.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
|
||||
|
||||
@ -70,8 +72,8 @@ Configuration options:
|
||||
#define TYPE_PCI1713 2
|
||||
#define TYPE_PCI1720 3
|
||||
|
||||
#define IORANGE_171x 32
|
||||
#define IORANGE_1720 16
|
||||
#define IORANGE_171x 32
|
||||
#define IORANGE_1720 16
|
||||
|
||||
#define PCI171x_AD_DATA 0 /* R: A/D data */
|
||||
#define PCI171x_SOFTTRG 0 /* W: soft trigger for A/D */
|
||||
@ -91,13 +93,15 @@ Configuration options:
|
||||
#define PCI171x_CNT2 28 /* R/W: 8254 counter 2 */
|
||||
#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_FH 0x0200 /* 1=FIFO is half full */
|
||||
#define Status_FF 0x0400 /* 1=FIFO is full, fatal error */
|
||||
#define Status_IRQ 0x0800 /* 1=IRQ occured */
|
||||
/* 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_IRQEN 0x0010 /* 1=enable IRQ */
|
||||
#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_RW1 0x0020
|
||||
#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_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[] =
|
||||
{ 0x00, 0x01, 0x02, 0x03, 0x04, 0x10, 0x11, 0x12, 0x13 };
|
||||
static const char range_codes_pci1710_3[] = { 0x00, 0x01, 0x02, 0x03, 0x04,
|
||||
0x10, 0x11, 0x12, 0x13 };
|
||||
|
||||
static const struct comedi_lrange range_pci1710hg = { 12, {
|
||||
BIP_RANGE(5),
|
||||
@ -157,10 +162,9 @@ static const struct comedi_lrange range_pci1710hg = { 12, {
|
||||
}
|
||||
};
|
||||
|
||||
static const char range_codes_pci1710hg[] =
|
||||
{ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x10, 0x11, 0x12,
|
||||
0x13
|
||||
};
|
||||
static const char range_codes_pci1710hg[] = { 0x00, 0x01, 0x02, 0x03, 0x04,
|
||||
0x05, 0x06, 0x07, 0x10, 0x11,
|
||||
0x12, 0x13 };
|
||||
|
||||
static const struct comedi_lrange range_pci17x1 = { 5, {
|
||||
BIP_RANGE(10),
|
||||
@ -301,7 +305,8 @@ struct pci1710_private {
|
||||
unsigned int ai_timer1; /* timers */
|
||||
unsigned int ai_timer2;
|
||||
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)
|
||||
@ -324,7 +329,9 @@ static int pci1710_reset(struct comedi_device *dev);
|
||||
static int pci171x_ai_cancel(struct comedi_device *dev,
|
||||
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,
|
||||
0x1010, 0x1111, 0x1212, 0x1313, 0x1414, 0x1515, 0x1616, 0x1717,
|
||||
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->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);
|
||||
s->async->events |= COMEDI_CB_EOA;
|
||||
comedi_event(dev, s);
|
||||
@ -1559,7 +1567,8 @@ static int pci1710_attach(struct comedi_device *dev,
|
||||
s->maxdata = 1;
|
||||
s->len_chanlist = this_board->n_dochan;
|
||||
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->insn_bits = pci171x_insn_bits_do;
|
||||
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");
|
||||
|
@ -496,4 +496,44 @@ static int pci1723_detach(struct comedi_device *dev)
|
||||
* A convenient macro that defines init_module() and cleanup_module(),
|
||||
* 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");
|
||||
|
@ -8,8 +8,8 @@
|
||||
/*
|
||||
Driver: adv_pci_dio
|
||||
Description: Advantech PCI-1730, PCI-1733, PCI-1734, PCI-1735U,
|
||||
PCI-1736UP, PCI-1750, PCI-1751, PCI-1752, PCI-1753/E,
|
||||
PCI-1754, PCI-1756, PCI-1762
|
||||
PCI-1736UP, PCI-1750, PCI-1751, PCI-1752, PCI-1753/E,
|
||||
PCI-1754, PCI-1756, PCI-1762
|
||||
Author: Michal Dobes <dobes@tesnet.cz>
|
||||
Devices: [Advantech] PCI-1730 (adv_pci_dio), PCI-1733,
|
||||
PCI-1734, PCI-1735U, PCI-1736UP, PCI-1750,
|
||||
@ -24,8 +24,8 @@ This driver supports now only insn interface for DI/DO/DIO.
|
||||
Configuration options:
|
||||
[0] - PCI bus of device (optional)
|
||||
[1] - PCI slot of device (optional)
|
||||
If bus/slot is not specified, the first available PCI
|
||||
device will be used.
|
||||
If bus/slot is not specified, the first available PCI
|
||||
device will be used.
|
||||
|
||||
*/
|
||||
|
||||
@ -67,9 +67,12 @@ enum hw_io_access {
|
||||
|
||||
#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_DIO_SUBDEVG 2 /* max number of DIO subdevices group per card */
|
||||
#define MAX_8254_SUBDEVS 1 /* max number of 8254 counter subdevs per card */
|
||||
/* (could be more than one 8254 per subdevice) */
|
||||
#define MAX_DIO_SUBDEVG 2 /* max number of DIO subdevices group per
|
||||
* card */
|
||||
#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_8255 4 /* 8255 IO space length */
|
||||
@ -84,7 +87,8 @@ enum hw_io_access {
|
||||
#define PCI1730_DO 2 /* W: Digital output 0-15 */
|
||||
#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_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 PCI1734_IDO 0 /* W: Isolated digital output 0-31 */
|
||||
#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_IDO 0 /* W: Isolated digital output 0-15 */
|
||||
#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_BOARDID 4 /* R: Board I/D switch for 1736UP */
|
||||
#define PCI1736_MAINREG 0 /* Normal register (2) doesn't work */
|
||||
@ -161,37 +166,66 @@ enum hw_io_access {
|
||||
#define INTCSR3 0x3b
|
||||
|
||||
/* 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_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_ReadFirmwareVersion 0x0e /* Read the firmware ver., result in IMB1.IMB0 */
|
||||
#define CMD_ReadHardwareVersion 0x0f /* Read the hardware ver., result in IMB1.IMB0 */
|
||||
#define CMD_EnableIDIFilters 0x20 /* Enable IDI filters based on bits in OMB0 */
|
||||
#define CMD_EnableIDIPatternMatch 0x21 /* Enable IDI pattern match based on bits in OMB0 */
|
||||
#define CMD_SetIDIPatternMatch 0x22 /* Enable IDI pattern match based on bits in OMB0 */
|
||||
#define CMD_EnableIDICounters 0x28 /* Enable IDI counters based on bits in OMB0 */
|
||||
#define CMD_ResetIDICounters 0x29 /* Reset IDI counters based on bits in OMB0 to its reset values */
|
||||
#define CMD_OverflowIDICounters 0x2a /* Enable IDI counters overflow interrupts based on bits in OMB0 */
|
||||
#define CMD_MatchIntIDICounters 0x2b /* Enable IDI counters match value interrupts based on bits in OMB0 */
|
||||
#define CMD_EdgeIDICounters 0x2c /* Set IDI up counters count edge (bit=0 - rising, =1 - falling) */
|
||||
#define CMD_GetIDICntCurValue 0x2f /* Read IDI{OMB0} up counter current value */
|
||||
#define CMD_SetIDI0CntResetValue 0x40 /* Set IDI0 Counter Reset Value 256*OMB1+OMB0 */
|
||||
#define CMD_SetIDI1CntResetValue 0x41 /* Set IDI1 Counter Reset Value 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 CMD_ReadCurrentStatus 0x07 /* Read the current status of the
|
||||
* register in OMB0, result in IMB0 */
|
||||
#define CMD_ReadFirmwareVersion 0x0e /* Read the firmware ver., result in
|
||||
* IMB1.IMB0 */
|
||||
#define CMD_ReadHardwareVersion 0x0f /* Read the hardware ver., result in
|
||||
* IMB1.IMB0 */
|
||||
#define CMD_EnableIDIFilters 0x20 /* Enable IDI filters based on bits in
|
||||
* OMB0 */
|
||||
#define CMD_EnableIDIPatternMatch 0x21 /* Enable IDI pattern match based on
|
||||
* bits in OMB0 */
|
||||
#define CMD_SetIDIPatternMatch 0x22 /* Enable IDI pattern match based on
|
||||
* bits in OMB0 */
|
||||
#define CMD_EnableIDICounters 0x28 /* Enable IDI counters based on bits in
|
||||
* OMB0 */
|
||||
#define CMD_ResetIDICounters 0x29 /* Reset IDI counters based on bits in
|
||||
* OMB0 to its reset values */
|
||||
#define CMD_OverflowIDICounters 0x2a /* Enable IDI counters overflow
|
||||
* interrupts based on bits in OMB0 */
|
||||
#define CMD_MatchIntIDICounters 0x2b /* Enable IDI counters match value
|
||||
* interrupts based on bits in OMB0 */
|
||||
#define CMD_EdgeIDICounters 0x2c /* Set IDI up counters count edge (bit=0
|
||||
* - rising, =1 - falling) */
|
||||
#define CMD_GetIDICntCurValue 0x2f /* Read IDI{OMB0} up counter current
|
||||
* value */
|
||||
#define CMD_SetIDI0CntResetValue 0x40 /* Set IDI0 Counter Reset Value
|
||||
* 256*OMB1+OMB0 */
|
||||
#define CMD_SetIDI1CntResetValue 0x41 /* Set IDI1 Counter Reset Value
|
||||
* 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 */
|
||||
|
||||
@ -244,115 +278,115 @@ MODULE_DEVICE_TABLE(pci, pci_dio_pci_table);
|
||||
static const struct dio_boardtype boardtypes[] = {
|
||||
{"pci1730", PCI_VENDOR_ID_ADVANTECH, 0x1730, PCIDIO_MAINREG,
|
||||
TYPE_PCI1730,
|
||||
{{16, PCI1730_DI, 2, 0}, {16, PCI1730_IDI, 2, 0}},
|
||||
{{16, PCI1730_DO, 2, 0}, {16, PCI1730_IDO, 2, 0}},
|
||||
{{0, 0, 0, 0}, {0, 0, 0, 0}},
|
||||
{ {16, PCI1730_DI, 2, 0}, {16, PCI1730_IDI, 2, 0} },
|
||||
{ {16, PCI1730_DO, 2, 0}, {16, PCI1730_IDO, 2, 0} },
|
||||
{ {0, 0, 0, 0}, {0, 0, 0, 0} },
|
||||
{4, PCI173x_BOARDID, 1, SDF_INTERNAL},
|
||||
{{0, 0, 0, 0}},
|
||||
{ {0, 0, 0, 0} },
|
||||
IO_8b},
|
||||
{"pci1733", PCI_VENDOR_ID_ADVANTECH, 0x1733, PCIDIO_MAINREG,
|
||||
TYPE_PCI1733,
|
||||
{{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}, {32, PCI1733_IDI, 4, 0} },
|
||||
{ {0, 0, 0, 0}, {0, 0, 0, 0} },
|
||||
{ {0, 0, 0, 0}, {0, 0, 0, 0} },
|
||||
{4, PCI173x_BOARDID, 1, SDF_INTERNAL},
|
||||
{{0, 0, 0, 0}},
|
||||
{ {0, 0, 0, 0} },
|
||||
IO_8b},
|
||||
{"pci1734", PCI_VENDOR_ID_ADVANTECH, 0x1734, PCIDIO_MAINREG,
|
||||
TYPE_PCI1734,
|
||||
{{0, 0, 0, 0}, {0, 0, 0, 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} },
|
||||
{ {0, 0, 0, 0}, {32, PCI1734_IDO, 4, 0} },
|
||||
{ {0, 0, 0, 0}, {0, 0, 0, 0} },
|
||||
{4, PCI173x_BOARDID, 1, SDF_INTERNAL},
|
||||
{{0, 0, 0, 0}},
|
||||
{ {0, 0, 0, 0} },
|
||||
IO_8b},
|
||||
{"pci1735", PCI_VENDOR_ID_ADVANTECH, 0x1735, PCIDIO_MAINREG,
|
||||
TYPE_PCI1735,
|
||||
{{32, PCI1735_DI, 4, 0}, {0, 0, 0, 0}},
|
||||
{{32, PCI1735_DO, 4, 0}, {0, 0, 0, 0}},
|
||||
{{0, 0, 0, 0}, {0, 0, 0, 0}},
|
||||
{ {32, PCI1735_DI, 4, 0}, {0, 0, 0, 0} },
|
||||
{ {32, PCI1735_DO, 4, 0}, {0, 0, 0, 0} },
|
||||
{ {0, 0, 0, 0}, {0, 0, 0, 0} },
|
||||
{ 4, PCI1735_BOARDID, 1, SDF_INTERNAL},
|
||||
{{3, PCI1735_C8254, 1, 0}},
|
||||
{ {3, PCI1735_C8254, 1, 0} },
|
||||
IO_8b},
|
||||
{"pci1736", PCI_VENDOR_ID_ADVANTECH, 0x1736, PCI1736_MAINREG,
|
||||
TYPE_PCI1736,
|
||||
{{0, 0, 0, 0}, {16, PCI1736_IDI, 2, 0}},
|
||||
{{0, 0, 0, 0}, {16, PCI1736_IDO, 2, 0}},
|
||||
{{0, 0, 0, 0}, {0, 0, 0, 0}},
|
||||
{ {0, 0, 0, 0}, {16, PCI1736_IDI, 2, 0} },
|
||||
{ {0, 0, 0, 0}, {16, PCI1736_IDO, 2, 0} },
|
||||
{ {0, 0, 0, 0}, {0, 0, 0, 0} },
|
||||
{4, PCI1736_BOARDID, 1, SDF_INTERNAL},
|
||||
{{0, 0, 0, 0}},
|
||||
{ {0, 0, 0, 0} },
|
||||
IO_8b},
|
||||
{"pci1750", PCI_VENDOR_ID_ADVANTECH, 0x1750, PCIDIO_MAINREG,
|
||||
TYPE_PCI1750,
|
||||
{{0, 0, 0, 0}, {16, PCI1750_IDI, 2, 0}},
|
||||
{{0, 0, 0, 0}, {16, PCI1750_IDO, 2, 0}},
|
||||
{{0, 0, 0, 0}, {0, 0, 0, 0}},
|
||||
{ {0, 0, 0, 0}, {16, PCI1750_IDI, 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} },
|
||||
IO_8b},
|
||||
{"pci1751", PCI_VENDOR_ID_ADVANTECH, 0x1751, PCIDIO_MAINREG,
|
||||
TYPE_PCI1751,
|
||||
{{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}},
|
||||
{ {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} },
|
||||
{0, 0, 0, 0},
|
||||
{{0, 0, 0, 0}},
|
||||
{ {0, 0, 0, 0} },
|
||||
IO_8b},
|
||||
{"pci1752", PCI_VENDOR_ID_ADVANTECH, 0x1752, PCIDIO_MAINREG,
|
||||
TYPE_PCI1752,
|
||||
{{0, 0, 0, 0}, {0, 0, 0, 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} },
|
||||
{ {32, PCI1752_IDO, 2, 0}, {32, PCI1752_IDO2, 2, 0} },
|
||||
{ {0, 0, 0, 0}, {0, 0, 0, 0} },
|
||||
{4, PCI175x_BOARDID, 1, SDF_INTERNAL},
|
||||
{{0, 0, 0, 0}},
|
||||
{ {0, 0, 0, 0} },
|
||||
IO_16b},
|
||||
{"pci1753", PCI_VENDOR_ID_ADVANTECH, 0x1753, PCIDIO_MAINREG,
|
||||
TYPE_PCI1753,
|
||||
{{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}},
|
||||
{ {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} },
|
||||
{0, 0, 0, 0},
|
||||
{{0, 0, 0, 0}},
|
||||
{ {0, 0, 0, 0} },
|
||||
IO_8b},
|
||||
{"pci1753e", PCI_VENDOR_ID_ADVANTECH, 0x1753, PCIDIO_MAINREG,
|
||||
TYPE_PCI1753E,
|
||||
{{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}},
|
||||
{ {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} },
|
||||
{0, 0, 0, 0},
|
||||
{{0, 0, 0, 0}},
|
||||
{ {0, 0, 0, 0} },
|
||||
IO_8b},
|
||||
{"pci1754", PCI_VENDOR_ID_ADVANTECH, 0x1754, PCIDIO_MAINREG,
|
||||
TYPE_PCI1754,
|
||||
{{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}},
|
||||
{ {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} },
|
||||
{4, PCI175x_BOARDID, 1, SDF_INTERNAL},
|
||||
{{0, 0, 0, 0}},
|
||||
{ {0, 0, 0, 0} },
|
||||
IO_16b},
|
||||
{"pci1756", PCI_VENDOR_ID_ADVANTECH, 0x1756, PCIDIO_MAINREG,
|
||||
TYPE_PCI1756,
|
||||
{{0, 0, 0, 0}, {32, PCI1756_IDI, 2, 0}},
|
||||
{{0, 0, 0, 0}, {32, PCI1756_IDO, 2, 0}},
|
||||
{{0, 0, 0, 0}, {0, 0, 0, 0}},
|
||||
{ {0, 0, 0, 0}, {32, PCI1756_IDI, 2, 0} },
|
||||
{ {0, 0, 0, 0}, {32, PCI1756_IDO, 2, 0} },
|
||||
{ {0, 0, 0, 0}, {0, 0, 0, 0} },
|
||||
{4, PCI175x_BOARDID, 1, SDF_INTERNAL},
|
||||
{{0, 0, 0, 0}},
|
||||
{ {0, 0, 0, 0} },
|
||||
IO_16b},
|
||||
{"pci1760", PCI_VENDOR_ID_ADVANTECH, 0x1760, 0,
|
||||
TYPE_PCI1760,
|
||||
{{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} }, /* 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} },
|
||||
IO_8b},
|
||||
{"pci1762", PCI_VENDOR_ID_ADVANTECH, 0x1762, PCIDIO_MAINREG,
|
||||
TYPE_PCI1762,
|
||||
{{0, 0, 0, 0}, {16, PCI1762_IDI, 1, 0}},
|
||||
{{0, 0, 0, 0}, {16, PCI1762_RO, 1, 0}},
|
||||
{{0, 0, 0, 0}, {0, 0, 0, 0}},
|
||||
{ {0, 0, 0, 0}, {16, PCI1762_IDI, 1, 0} },
|
||||
{ {0, 0, 0, 0}, {16, PCI1762_RO, 1, 0} },
|
||||
{ {0, 0, 0, 0}, {0, 0, 0, 0} },
|
||||
{4, PCI1762_BOARDID, 1, SDF_INTERNAL},
|
||||
{{0, 0, 0, 0}},
|
||||
{ {0, 0, 0, 0} },
|
||||
IO_16b}
|
||||
};
|
||||
|
||||
@ -372,13 +406,16 @@ struct pci_dio_private {
|
||||
char valid; /* card is usable */
|
||||
char GlobalIrqEnabled; /* 1= any IRQ source is enabled */
|
||||
/* PCI-1760 specific data */
|
||||
unsigned char IDICntEnable; /* counter's counting enable status */
|
||||
unsigned char IDICntOverEnable; /* counter's overflow interrupts enable status */
|
||||
unsigned char IDICntMatchEnable; /* counter's match interrupts enable status */
|
||||
unsigned char IDICntEdge; /* counter's count edge value (bit=0 - rising, =1 - falling) */
|
||||
unsigned char IDICntEnable; /* counter's counting enable status */
|
||||
unsigned char IDICntOverEnable; /* counter's overflow interrupts enable
|
||||
* status */
|
||||
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 CntMatchValue[8]; /* counters' match interrupt value */
|
||||
unsigned char IDIFiltersEn; /* IDI's digital filters enable status */
|
||||
unsigned short CntMatchValue[8]; /* counters' match interrupt value */
|
||||
unsigned char IDIFiltersEn; /* IDI's digital filters enable status */
|
||||
unsigned char IDIPatMatchEn; /* IDI's pattern match enable status */
|
||||
unsigned char IDIPatMatchValue; /* IDI's pattern match value */
|
||||
unsigned short IDIFiltrLow[8]; /* IDI's filter value low signal */
|
||||
@ -691,7 +728,8 @@ static int pci1760_insn_cnt_write(struct comedi_device *dev,
|
||||
};
|
||||
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);
|
||||
if (!ret)
|
||||
return ret;
|
||||
@ -704,7 +742,8 @@ static int pci1760_insn_cnt_write(struct comedi_device *dev,
|
||||
if (!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[2] = CMD_EnableIDICounters;
|
||||
ret = pci1760_mbxrequest(dev, omb, imb);
|
||||
@ -740,12 +779,14 @@ static int pci1760_reset(struct comedi_device *dev)
|
||||
devpriv->IDICntEnable = 0;
|
||||
|
||||
omb[0] = 0x00;
|
||||
omb[2] = CMD_OverflowIDICounters; /* disable counters overflow interrupts */
|
||||
omb[2] = CMD_OverflowIDICounters; /* disable counters overflow
|
||||
* interrupts */
|
||||
pci1760_mbxrequest(dev, omb, imb);
|
||||
devpriv->IDICntOverEnable = 0;
|
||||
|
||||
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);
|
||||
devpriv->IDICntMatchEnable = 0;
|
||||
|
||||
@ -766,7 +807,8 @@ static int pci1760_reset(struct comedi_device *dev)
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
omb[0] = 0x00;
|
||||
@ -807,9 +849,12 @@ static int pci_dio_reset(struct comedi_device *dev)
|
||||
outb(0, dev->iobase + PCI1730_IDO + 1);
|
||||
/* NO break there! */
|
||||
case TYPE_PCI1733:
|
||||
outb(0, dev->iobase + PCI1730_3_INT_EN); /* disable interrupts */
|
||||
outb(0x0f, dev->iobase + PCI1730_3_INT_CLR); /* clear interrupts */
|
||||
outb(0, dev->iobase + PCI1730_3_INT_RF); /* set rising edge trigger */
|
||||
/* disable interrupts */
|
||||
outb(0, dev->iobase + PCI1730_3_INT_EN);
|
||||
/* clear interrupts */
|
||||
outb(0x0f, dev->iobase + PCI1730_3_INT_CLR);
|
||||
/* set rising edge trigger */
|
||||
outb(0, dev->iobase + PCI1730_3_INT_RF);
|
||||
break;
|
||||
case TYPE_PCI1734:
|
||||
outb(0, dev->iobase + PCI1734_IDO); /* clear outputs */
|
||||
@ -830,43 +875,53 @@ static int pci_dio_reset(struct comedi_device *dev)
|
||||
case TYPE_PCI1736:
|
||||
outb(0, dev->iobase + PCI1736_IDO);
|
||||
outb(0, dev->iobase + PCI1736_IDO + 1);
|
||||
outb(0, dev->iobase + PCI1736_3_INT_EN); /* disable interrupts */
|
||||
outb(0x0f, dev->iobase + PCI1736_3_INT_CLR); /* clear interrupts */
|
||||
outb(0, dev->iobase + PCI1736_3_INT_RF); /* set rising edge trigger */
|
||||
/* disable interrupts */
|
||||
outb(0, dev->iobase + PCI1736_3_INT_EN);
|
||||
/* clear interrupts */
|
||||
outb(0x0f, dev->iobase + PCI1736_3_INT_CLR);
|
||||
/* set rising edge trigger */
|
||||
outb(0, dev->iobase + PCI1736_3_INT_RF);
|
||||
break;
|
||||
|
||||
case TYPE_PCI1750:
|
||||
case TYPE_PCI1751:
|
||||
outb(0x88, dev->iobase + PCI1750_ICR); /* disable & clear interrupts */
|
||||
/* disable & clear interrupts */
|
||||
outb(0x88, dev->iobase + PCI1750_ICR);
|
||||
break;
|
||||
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 + 2);
|
||||
outw(0, dev->iobase + PCI1752_IDO2);
|
||||
outw(0, dev->iobase + PCI1752_IDO2 + 2);
|
||||
break;
|
||||
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_ICR2);
|
||||
outb(0x80, dev->iobase + PCI1753E_ICR3);
|
||||
/* NO break there! */
|
||||
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_ICR2);
|
||||
outb(0x80, dev->iobase + PCI1753_ICR3);
|
||||
break;
|
||||
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_ICR2);
|
||||
outw(0x08, dev->iobase + PCI1754_ICR3);
|
||||
break;
|
||||
case TYPE_PCI1756:
|
||||
outw(0, dev->iobase + PCI1752_6_CFC); /* disable channel freeze function */
|
||||
outw(0x08, dev->iobase + PCI1754_6_ICR0); /* disable and clear interrupts */
|
||||
outw(0, dev->iobase + PCI1752_6_CFC); /* disable channel freeze
|
||||
* function */
|
||||
outw(0x08, dev->iobase + PCI1754_6_ICR0); /* disable and clear
|
||||
* interrupts */
|
||||
outw(0x08, dev->iobase + PCI1754_6_ICR1);
|
||||
outw(0, dev->iobase + PCI1756_IDO); /* clear outputs */
|
||||
outw(0, dev->iobase + PCI1756_IDO + 2);
|
||||
@ -875,7 +930,8 @@ static int pci_dio_reset(struct comedi_device *dev)
|
||||
pci1760_reset(dev);
|
||||
break;
|
||||
case TYPE_PCI1762:
|
||||
outw(0x0101, dev->iobase + PCI1762_ICR); /* disable & clear interrupts */
|
||||
outw(0x0101, dev->iobase + PCI1762_ICR); /* disable & clear
|
||||
* interrupts */
|
||||
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,
|
||||
struct comedi_subdevice * s,
|
||||
struct comedi_subdevice *s,
|
||||
const struct diosubd_data *d, int subdev)
|
||||
{
|
||||
s->type = COMEDI_SUBD_COUNTER;
|
||||
@ -1023,7 +1079,7 @@ static int CheckAndAllocCard(struct comedi_device *dev,
|
||||
|
||||
for (pr = pci_priv, prev = NULL; pr != NULL; prev = pr, pr = pr->next) {
|
||||
if (pr->pcidev == pcidev)
|
||||
return 0; /* this card is used, look for another */
|
||||
return 0; /* this card is used, look for another */
|
||||
|
||||
}
|
||||
|
||||
@ -1048,7 +1104,7 @@ static int pci_dio_attach(struct comedi_device *dev,
|
||||
struct comedi_subdevice *s;
|
||||
int ret, subdev, n_subdevices, i, j;
|
||||
unsigned long iobase;
|
||||
struct pci_dev *pcidev;
|
||||
struct pci_dev *pcidev = NULL;
|
||||
|
||||
printk("comedi%d: adv_pci_dio: ", dev->minor);
|
||||
|
||||
@ -1058,9 +1114,7 @@ static int pci_dio_attach(struct comedi_device *dev,
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
for (pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, NULL);
|
||||
pcidev != NULL;
|
||||
pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pcidev)) {
|
||||
for_each_pci_dev(pcidev) {
|
||||
/* loop through cards supported by this driver */
|
||||
for (i = 0; i < n_boardtypes; ++i) {
|
||||
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++;
|
||||
}
|
||||
|
||||
for (i = 0; i < MAX_8254_SUBDEVS; i++) {
|
||||
if (this_board->s8254[i].chans) {
|
||||
for (i = 0; i < MAX_8254_SUBDEVS; i++)
|
||||
if (this_board->s8254[i].chans)
|
||||
subdev++;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < dev->n_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");
|
||||
|
@ -227,4 +227,19 @@ static struct comedi_driver driver_aio_aio12_8 = {
|
||||
.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");
|
||||
|
@ -184,4 +184,19 @@ static int aio_iiro_16_dio_insn_bits_read(struct comedi_device *dev,
|
||||
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");
|
||||
|
@ -47,32 +47,32 @@
|
||||
#ifdef Am9513_8BITBUS
|
||||
|
||||
#define Am9513_write_register(reg, val) \
|
||||
do{ \
|
||||
do { \
|
||||
Am9513_output_control(reg); \
|
||||
Am9513_output_data(val>>8); \
|
||||
Am9513_output_data(val&0xff); \
|
||||
}while (0)
|
||||
} while (0)
|
||||
|
||||
#define Am9513_read_register(reg, val) \
|
||||
do{ \
|
||||
do { \
|
||||
Am9513_output_control(reg); \
|
||||
val=Am9513_input_data()<<8; \
|
||||
val|=Am9513_input_data(); \
|
||||
}while (0)
|
||||
val = Am9513_input_data()<<8; \
|
||||
val |= Am9513_input_data(); \
|
||||
} while (0)
|
||||
|
||||
#else /* Am9513_16BITBUS */
|
||||
|
||||
#define Am9513_write_register(reg, val) \
|
||||
do{ \
|
||||
do { \
|
||||
Am9513_output_control(reg); \
|
||||
Am9513_output_data(val); \
|
||||
}while (0)
|
||||
} while (0)
|
||||
|
||||
#define Am9513_read_register(reg, val) \
|
||||
do{ \
|
||||
do { \
|
||||
Am9513_output_control(reg); \
|
||||
val=Am9513_input_data(); \
|
||||
}while (0)
|
||||
val = Am9513_input_data(); \
|
||||
} while (0)
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -494,9 +494,58 @@ static struct comedi_driver driver_amplc_dio200 = {
|
||||
};
|
||||
|
||||
#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
|
||||
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
|
||||
|
||||
/*
|
||||
@ -1501,3 +1550,7 @@ static int dio200_detach(struct comedi_device *dev)
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
MODULE_AUTHOR("Comedi http://www.comedi.org");
|
||||
MODULE_DESCRIPTION("Comedi low-level driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
@ -182,9 +182,58 @@ static struct comedi_driver driver_amplc_pc236 = {
|
||||
};
|
||||
|
||||
#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
|
||||
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
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
MODULE_AUTHOR("Comedi http://www.comedi.org");
|
||||
MODULE_DESCRIPTION("Comedi low-level driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
@ -432,7 +432,60 @@ static int pc263_dio_insn_config(struct comedi_device *dev,
|
||||
* as necessary.
|
||||
*/
|
||||
#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
|
||||
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
|
||||
|
||||
MODULE_AUTHOR("Comedi http://www.comedi.org");
|
||||
MODULE_DESCRIPTION("Comedi low-level driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
@ -443,7 +443,45 @@ static struct comedi_driver driver_amplc_pci224 = {
|
||||
.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.
|
||||
@ -1557,3 +1595,7 @@ static int pci224_detach(struct comedi_device *dev)
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
MODULE_AUTHOR("Comedi http://www.comedi.org");
|
||||
MODULE_DESCRIPTION("Comedi low-level driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
@ -617,7 +617,45 @@ static struct comedi_driver driver_amplc_pci230 = {
|
||||
.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,
|
||||
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;
|
||||
unsigned long iobase1, iobase2;
|
||||
/* 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;
|
||||
|
||||
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->ao_stop_spinlock);
|
||||
/* Find card */
|
||||
for (pci_dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, NULL);
|
||||
pci_dev != NULL;
|
||||
pci_dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pci_dev)) {
|
||||
for_each_pci_dev(pci_dev) {
|
||||
if (it->options[0] || it->options[1]) {
|
||||
/* Match against bus/slot options. */
|
||||
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);
|
||||
return 0;
|
||||
}
|
||||
|
||||
MODULE_AUTHOR("Comedi http://www.comedi.org");
|
||||
MODULE_DESCRIPTION("Comedi low-level driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
@ -517,4 +517,19 @@ static int c6xdigio_detach(struct comedi_device *dev)
|
||||
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");
|
||||
|
@ -719,8 +719,7 @@ static void das16cs_pcmcia_detach(struct pcmcia_device *link)
|
||||
((struct local_info_t *)link->priv)->stop = 1;
|
||||
das16cs_pcmcia_release(link);
|
||||
/* This points to the parent struct local_info_t struct */
|
||||
if (link->priv)
|
||||
kfree(link->priv);
|
||||
kfree(link->priv);
|
||||
} /* das16cs_pcmcia_detach */
|
||||
|
||||
|
||||
@ -881,5 +880,16 @@ void __exit cleanup_module(void)
|
||||
}
|
||||
|
||||
#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 */
|
||||
|
@ -533,7 +533,7 @@ static int cb_pcidas_attach(struct comedi_device *dev,
|
||||
struct comedi_devconfig *it)
|
||||
{
|
||||
struct comedi_subdevice *s;
|
||||
struct pci_dev *pcidev;
|
||||
struct pci_dev *pcidev = NULL;
|
||||
int index;
|
||||
int i;
|
||||
|
||||
@ -550,9 +550,7 @@ static int cb_pcidas_attach(struct comedi_device *dev,
|
||||
*/
|
||||
printk("\n");
|
||||
|
||||
for (pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, NULL);
|
||||
pcidev != NULL;
|
||||
pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pcidev)) {
|
||||
for_each_pci_dev(pcidev) {
|
||||
/* is it not a computer boards card? */
|
||||
if (pcidev->vendor != PCI_VENDOR_ID_CB)
|
||||
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(),
|
||||
* 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");
|
||||
|
@ -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,
|
||||
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,
|
||||
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)
|
||||
{
|
||||
struct pci_dev *pcidev;
|
||||
struct pci_dev *pcidev = NULL;
|
||||
int index;
|
||||
uint32_t local_range, local_decode;
|
||||
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.
|
||||
*/
|
||||
|
||||
for (pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, NULL);
|
||||
pcidev != NULL;
|
||||
pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pcidev)) {
|
||||
for_each_pci_dev(pcidev) {
|
||||
/* is it not a computer boards card? */
|
||||
if (pcidev->vendor != PCI_VENDOR_ID_COMPUTERBOARDS)
|
||||
continue;
|
||||
@ -4303,3 +4337,7 @@ static void i2c_write(struct comedi_device *dev, unsigned int address,
|
||||
}
|
||||
i2c_stop(dev);
|
||||
}
|
||||
|
||||
MODULE_AUTHOR("Comedi http://www.comedi.org");
|
||||
MODULE_DESCRIPTION("Comedi low-level driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
@ -280,7 +280,7 @@ static int cb_pcidda_attach(struct comedi_device *dev,
|
||||
struct comedi_devconfig *it)
|
||||
{
|
||||
struct comedi_subdevice *s;
|
||||
struct pci_dev *pcidev;
|
||||
struct pci_dev *pcidev = NULL;
|
||||
int index;
|
||||
|
||||
printk("comedi%d: cb_pcidda: ", dev->minor);
|
||||
@ -296,9 +296,7 @@ static int cb_pcidda_attach(struct comedi_device *dev,
|
||||
*/
|
||||
printk("\n");
|
||||
|
||||
for (pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, NULL);
|
||||
pcidev != NULL;
|
||||
pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pcidev)) {
|
||||
for_each_pci_dev(pcidev) {
|
||||
if (pcidev->vendor == PCI_VENDOR_ID_CB) {
|
||||
if (it->options[0] || it->options[1]) {
|
||||
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(),
|
||||
* 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");
|
||||
|
@ -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.
|
||||
*/
|
||||
|
||||
for (pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, NULL);
|
||||
pcidev != NULL;
|
||||
pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pcidev)) {
|
||||
for_each_pci_dev(pcidev) {
|
||||
/* is it not a computer boards card? */
|
||||
if (pcidev->vendor != PCI_VENDOR_ID_CB)
|
||||
continue;
|
||||
@ -300,4 +298,44 @@ static int pcidio_detach(struct comedi_device *dev)
|
||||
* A convenient macro that defines init_module() and cleanup_module(),
|
||||
* 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");
|
||||
|
@ -210,7 +210,7 @@ static int cb_pcimdas_attach(struct comedi_device *dev,
|
||||
struct comedi_devconfig *it)
|
||||
{
|
||||
struct comedi_subdevice *s;
|
||||
struct pci_dev *pcidev;
|
||||
struct pci_dev *pcidev = NULL;
|
||||
int index;
|
||||
/* int i; */
|
||||
|
||||
@ -227,9 +227,7 @@ static int cb_pcimdas_attach(struct comedi_device *dev,
|
||||
*/
|
||||
printk("\n");
|
||||
|
||||
for (pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, NULL);
|
||||
pcidev != NULL;
|
||||
pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pcidev)) {
|
||||
for_each_pci_dev(pcidev) {
|
||||
/* is it not a computer boards card? */
|
||||
if (pcidev->vendor != PCI_VENDOR_ID_COMPUTERBOARDS)
|
||||
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(),
|
||||
* 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");
|
||||
|
@ -195,7 +195,45 @@ MODULE_DESCRIPTION("Comedi low-level driver for the Computerboards PCIM-DDA "
|
||||
"series. Currently only supports PCIM-DDA06-16 (which "
|
||||
"also happens to be the only board in this series. :) ) ");
|
||||
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,
|
||||
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)
|
||||
{
|
||||
struct pci_dev *pcidev;
|
||||
struct pci_dev *pcidev = NULL;
|
||||
int index;
|
||||
unsigned long registers;
|
||||
|
||||
for (pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, NULL);
|
||||
pcidev != NULL;
|
||||
pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pcidev)) {
|
||||
for_each_pci_dev(pcidev) {
|
||||
/* is it not a computer boards card? */
|
||||
if (pcidev->vendor != PCI_VENDOR_ID_COMPUTERBOARDS)
|
||||
continue;
|
||||
|
@ -50,43 +50,6 @@ Configuration Options:
|
||||
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/slab.h>
|
||||
#include "../comedi.h"
|
||||
|
@ -101,7 +101,18 @@ static struct comedi_driver driver_parport = {
|
||||
.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 {
|
||||
unsigned int a_data;
|
||||
@ -396,3 +407,7 @@ static int parport_detach(struct comedi_device *dev)
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
MODULE_AUTHOR("Comedi http://www.comedi.org");
|
||||
MODULE_DESCRIPTION("Comedi low-level driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
@ -107,7 +107,18 @@ static struct comedi_driver driver_waveform = {
|
||||
.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,
|
||||
struct comedi_subdevice *s,
|
||||
@ -549,3 +560,7 @@ static int waveform_ao_insn_write(struct comedi_device *dev,
|
||||
|
||||
return insn->n;
|
||||
}
|
||||
|
||||
MODULE_AUTHOR("Comedi http://www.comedi.org");
|
||||
MODULE_DESCRIPTION("Comedi low-level driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
@ -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)
|
||||
{
|
||||
struct pci_dev *pcidev;
|
||||
struct pci_dev *pcidev = NULL;
|
||||
struct comedi_subdevice *s;
|
||||
|
||||
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)
|
||||
return -ENOMEM;
|
||||
|
||||
for (pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, NULL);
|
||||
pcidev != NULL;
|
||||
pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pcidev)) {
|
||||
|
||||
for_each_pci_dev(pcidev) {
|
||||
if (pcidev->vendor == PCI_VENDOR_ID_CONTEC &&
|
||||
pcidev->device == PCI_DEVICE_ID_PIO1616L) {
|
||||
if (it->options[0] || it->options[1]) {
|
||||
@ -232,4 +229,44 @@ static int contec_di_insn_bits(struct comedi_device *dev,
|
||||
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");
|
||||
|
@ -887,4 +887,46 @@ static int daqboard2000_detach(struct comedi_device *dev)
|
||||
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");
|
||||
|
@ -29,11 +29,11 @@
|
||||
* Description: DAS-08 compatible boards
|
||||
* Author: Warren Jasper, ds, Frank Hess
|
||||
* Devices: [Keithley Metrabyte] DAS08 (isa-das08),
|
||||
* [ComputerBoards] DAS08 (isa-das08), DAS08-PGM (das08-pgm),
|
||||
* DAS08-PGH (das08-pgh), DAS08-PGL (das08-pgl), DAS08-AOH (das08-aoh),
|
||||
* DAS08-AOL (das08-aol), DAS08-AOM (das08-aom), DAS08/JR-AO (das08/jr-ao),
|
||||
* DAS08/JR-16-AO (das08jr-16-ao), PCI-DAS08 (das08),
|
||||
* PC104-DAS08 (pc104-das08), DAS08/JR/16 (das08jr/16)
|
||||
* [ComputerBoards] DAS08 (isa-das08), DAS08-PGM (das08-pgm),
|
||||
* DAS08-PGH (das08-pgh), DAS08-PGL (das08-pgl), DAS08-AOH (das08-aoh),
|
||||
* DAS08-AOL (das08-aol), DAS08-AOM (das08-aom), DAS08/JR-AO (das08/jr-ao),
|
||||
* DAS08/JR-16-AO (das08jr-16-ao), PCI-DAS08 (das08),
|
||||
* PC104-DAS08 (pc104-das08), DAS08/JR/16 (das08jr/16)
|
||||
* Status: works
|
||||
*
|
||||
* This is a rewrite of the das08 and das08jr drivers.
|
||||
@ -980,7 +980,7 @@ static int das08_attach(struct comedi_device *dev, struct comedi_devconfig *it)
|
||||
unsigned long iobase;
|
||||
#ifdef CONFIG_COMEDI_PCI
|
||||
unsigned long pci_iobase = 0;
|
||||
struct pci_dev *pdev;
|
||||
struct pci_dev *pdev = NULL;
|
||||
#endif
|
||||
|
||||
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");
|
||||
/* find card */
|
||||
for (pdev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, NULL);
|
||||
pdev != NULL;
|
||||
pdev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pdev)) {
|
||||
for_each_pci_dev(pdev) {
|
||||
if (pdev->vendor == PCI_VENDOR_ID_COMPUTERBOARDS
|
||||
&& pdev->device == PCI_DEVICE_ID_PCIDAS08) {
|
||||
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);
|
||||
|
||||
#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
|
||||
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
|
||||
|
||||
#ifdef CONFIG_COMEDI_PCMCIA
|
||||
EXPORT_SYMBOL_GPL(das08_cs_boards);
|
||||
#endif
|
||||
|
||||
MODULE_AUTHOR("Comedi http://www.comedi.org");
|
||||
MODULE_DESCRIPTION("Comedi low-level driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
@ -206,8 +206,7 @@ static void das08_pcmcia_detach(struct pcmcia_device *link)
|
||||
das08_pcmcia_release(link);
|
||||
|
||||
/* This points to the parent struct local_info_t struct */
|
||||
if (link->priv)
|
||||
kfree(link->priv);
|
||||
kfree(link->priv);
|
||||
|
||||
} /* das08_pcmcia_detach */
|
||||
|
||||
|
@ -1717,7 +1717,18 @@ static int das16_detach(struct comedi_device *dev)
|
||||
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 */
|
||||
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
Loading…
Reference in New Issue
Block a user