Staging: Merge staging-next into Linus's tree
Conflicts: drivers/staging/Kconfig drivers/staging/batman-adv/bat_sysfs.c drivers/staging/batman-adv/device.c drivers/staging/batman-adv/hard-interface.c drivers/staging/cx25821/cx25821-audups11.c Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
This commit is contained in:
commit
e9563355ac
|
@ -18,6 +18,7 @@
|
||||||
#include <asm/mshyperv.h>
|
#include <asm/mshyperv.h>
|
||||||
|
|
||||||
struct ms_hyperv_info ms_hyperv;
|
struct ms_hyperv_info ms_hyperv;
|
||||||
|
EXPORT_SYMBOL_GPL(ms_hyperv);
|
||||||
|
|
||||||
static bool __init ms_hyperv_platform(void)
|
static bool __init ms_hyperv_platform(void)
|
||||||
{
|
{
|
||||||
|
|
|
@ -97,6 +97,8 @@ source "drivers/staging/octeon/Kconfig"
|
||||||
|
|
||||||
source "drivers/staging/serqt_usb2/Kconfig"
|
source "drivers/staging/serqt_usb2/Kconfig"
|
||||||
|
|
||||||
|
source "drivers/staging/spectra/Kconfig"
|
||||||
|
|
||||||
source "drivers/staging/quatech_usb2/Kconfig"
|
source "drivers/staging/quatech_usb2/Kconfig"
|
||||||
|
|
||||||
source "drivers/staging/vt6655/Kconfig"
|
source "drivers/staging/vt6655/Kconfig"
|
||||||
|
@ -115,7 +117,7 @@ source "drivers/staging/sep/Kconfig"
|
||||||
|
|
||||||
source "drivers/staging/iio/Kconfig"
|
source "drivers/staging/iio/Kconfig"
|
||||||
|
|
||||||
source "drivers/staging/ramzswap/Kconfig"
|
source "drivers/staging/zram/Kconfig"
|
||||||
|
|
||||||
source "drivers/staging/wlags49_h2/Kconfig"
|
source "drivers/staging/wlags49_h2/Kconfig"
|
||||||
|
|
||||||
|
@ -127,8 +129,6 @@ source "drivers/staging/samsung-laptop/Kconfig"
|
||||||
|
|
||||||
source "drivers/staging/sm7xx/Kconfig"
|
source "drivers/staging/sm7xx/Kconfig"
|
||||||
|
|
||||||
source "drivers/staging/dt3155/Kconfig"
|
|
||||||
|
|
||||||
source "drivers/staging/dt3155v4l/Kconfig"
|
source "drivers/staging/dt3155v4l/Kconfig"
|
||||||
|
|
||||||
source "drivers/staging/crystalhd/Kconfig"
|
source "drivers/staging/crystalhd/Kconfig"
|
||||||
|
@ -147,5 +147,13 @@ source "drivers/staging/msm/Kconfig"
|
||||||
|
|
||||||
source "drivers/staging/lirc/Kconfig"
|
source "drivers/staging/lirc/Kconfig"
|
||||||
|
|
||||||
|
source "drivers/staging/easycap/Kconfig"
|
||||||
|
|
||||||
|
source "drivers/staging/solo6x10/Kconfig"
|
||||||
|
|
||||||
|
source "drivers/staging/tidspbridge/Kconfig"
|
||||||
|
|
||||||
|
source "drivers/staging/quickstart/Kconfig"
|
||||||
|
|
||||||
endif # !STAGING_EXCLUDE_BUILD
|
endif # !STAGING_EXCLUDE_BUILD
|
||||||
endif # STAGING
|
endif # STAGING
|
||||||
|
|
|
@ -23,6 +23,7 @@ obj-$(CONFIG_R8187SE) += rtl8187se/
|
||||||
obj-$(CONFIG_RTL8192SU) += rtl8192su/
|
obj-$(CONFIG_RTL8192SU) += rtl8192su/
|
||||||
obj-$(CONFIG_RTL8192U) += rtl8192u/
|
obj-$(CONFIG_RTL8192U) += rtl8192u/
|
||||||
obj-$(CONFIG_RTL8192E) += rtl8192e/
|
obj-$(CONFIG_RTL8192E) += rtl8192e/
|
||||||
|
obj-$(CONFIG_SPECTRA) += spectra/
|
||||||
obj-$(CONFIG_TRANZPORT) += frontier/
|
obj-$(CONFIG_TRANZPORT) += frontier/
|
||||||
obj-$(CONFIG_DREAM) += dream/
|
obj-$(CONFIG_DREAM) += dream/
|
||||||
obj-$(CONFIG_POHMELFS) += pohmelfs/
|
obj-$(CONFIG_POHMELFS) += pohmelfs/
|
||||||
|
@ -39,13 +40,12 @@ obj-$(CONFIG_VME_BUS) += vme/
|
||||||
obj-$(CONFIG_MRST_RAR_HANDLER) += memrar/
|
obj-$(CONFIG_MRST_RAR_HANDLER) += memrar/
|
||||||
obj-$(CONFIG_DX_SEP) += sep/
|
obj-$(CONFIG_DX_SEP) += sep/
|
||||||
obj-$(CONFIG_IIO) += iio/
|
obj-$(CONFIG_IIO) += iio/
|
||||||
obj-$(CONFIG_RAMZSWAP) += ramzswap/
|
obj-$(CONFIG_ZRAM) += zram/
|
||||||
obj-$(CONFIG_WLAGS49_H2) += wlags49_h2/
|
obj-$(CONFIG_WLAGS49_H2) += wlags49_h2/
|
||||||
obj-$(CONFIG_WLAGS49_H25) += wlags49_h25/
|
obj-$(CONFIG_WLAGS49_H25) += wlags49_h25/
|
||||||
obj-$(CONFIG_BATMAN_ADV) += batman-adv/
|
obj-$(CONFIG_BATMAN_ADV) += batman-adv/
|
||||||
obj-$(CONFIG_SAMSUNG_LAPTOP) += samsung-laptop/
|
obj-$(CONFIG_SAMSUNG_LAPTOP) += samsung-laptop/
|
||||||
obj-$(CONFIG_FB_SM7XX) += sm7xx/
|
obj-$(CONFIG_FB_SM7XX) += sm7xx/
|
||||||
obj-$(CONFIG_DT3155) += dt3155/
|
|
||||||
obj-$(CONFIG_VIDEO_DT3155) += dt3155v4l/
|
obj-$(CONFIG_VIDEO_DT3155) += dt3155v4l/
|
||||||
obj-$(CONFIG_CRYSTALHD) += crystalhd/
|
obj-$(CONFIG_CRYSTALHD) += crystalhd/
|
||||||
obj-$(CONFIG_CXT1E1) += cxt1e1/
|
obj-$(CONFIG_CXT1E1) += cxt1e1/
|
||||||
|
@ -54,3 +54,7 @@ obj-$(CONFIG_ADIS16255) += adis16255/
|
||||||
obj-$(CONFIG_FB_XGI) += xgifb/
|
obj-$(CONFIG_FB_XGI) += xgifb/
|
||||||
obj-$(CONFIG_TOUCHSCREEN_MRSTOUCH) += mrst-touchscreen/
|
obj-$(CONFIG_TOUCHSCREEN_MRSTOUCH) += mrst-touchscreen/
|
||||||
obj-$(CONFIG_MSM_STAGING) += msm/
|
obj-$(CONFIG_MSM_STAGING) += msm/
|
||||||
|
obj-$(CONFIG_EASYCAP) += easycap/
|
||||||
|
obj-$(CONFIG_SOLO6X10) += solo6x10/
|
||||||
|
obj-$(CONFIG_TIDSPBRIDGE) += tidspbridge/
|
||||||
|
obj-$(CONFIG_ACPI_QUICKSTART) += quickstart/
|
||||||
|
|
|
@ -303,7 +303,7 @@ static int spi_adis16255_bringup(struct spi_adis16255_data *spiadis)
|
||||||
if (status != 0)
|
if (status != 0)
|
||||||
goto err;
|
goto err;
|
||||||
if (value != 0x0800) {
|
if (value != 0x0800) {
|
||||||
dev_warn(&spiadis->spi->dev, "Scale factor is none default"
|
dev_warn(&spiadis->spi->dev, "Scale factor is none default "
|
||||||
"value (%.4x)\n", value);
|
"value (%.4x)\n", value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -338,7 +338,7 @@ static int spi_adis16255_bringup(struct spi_adis16255_data *spiadis)
|
||||||
status = -ENODEV;
|
status = -ENODEV;
|
||||||
goto err;
|
goto err;
|
||||||
} else if (value & 0x3) {
|
} else if (value & 0x3) {
|
||||||
dev_warn(&spiadis->spi->dev, "Sensor voltage"
|
dev_warn(&spiadis->spi->dev, "Sensor voltage "
|
||||||
"out of range.\n");
|
"out of range.\n");
|
||||||
status = -ENODEV;
|
status = -ENODEV;
|
||||||
goto err;
|
goto err;
|
||||||
|
|
|
@ -1,3 +1,15 @@
|
||||||
|
batman-adv 2010.0.0:
|
||||||
|
|
||||||
|
* support latest kernels (2.6.21 - 2.6.35)
|
||||||
|
* further code refactoring and cleaning for coding style
|
||||||
|
* move from procfs based configuration to sysfs
|
||||||
|
* reorganized sequence number handling
|
||||||
|
* limit queue lengths for batman and broadcast packets
|
||||||
|
* many bugs (endless loop and rogue packets on shutdown, wrong tcpdump output,
|
||||||
|
missing frees in error situations, sleeps in atomic contexts) squashed
|
||||||
|
|
||||||
|
-- Fri, 18 Jun 2010 21:34:26 +0200
|
||||||
|
|
||||||
batman-adv 0.2.1:
|
batman-adv 0.2.1:
|
||||||
|
|
||||||
* support latest kernels (2.6.20 - 2.6.33)
|
* support latest kernels (2.6.20 - 2.6.33)
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
config BATMAN_ADV
|
config BATMAN_ADV
|
||||||
tristate "B.A.T.M.A.N. Advanced Meshing Protocol"
|
tristate "B.A.T.M.A.N. Advanced Meshing Protocol"
|
||||||
depends on PROC_FS && NET
|
depends on NET
|
||||||
default n
|
default n
|
||||||
---help---
|
---help---
|
||||||
|
|
||||||
|
|
|
@ -18,5 +18,5 @@
|
||||||
# 02110-1301, USA
|
# 02110-1301, USA
|
||||||
#
|
#
|
||||||
|
|
||||||
obj-m += batman-adv.o
|
obj-$(CONFIG_BATMAN_ADV) += batman-adv.o
|
||||||
batman-adv-objs := main.o send.o routing.o soft-interface.o device.o translation-table.o bitarray.o hash.o ring_buffer.o vis.o hard-interface.o aggregation.o originator.o bat_sysfs.o
|
batman-adv-objs := main.o bat_debugfs.o bat_sysfs.o send.o routing.o soft-interface.o icmp_socket.o translation-table.o bitarray.o hash.o ring_buffer.o vis.o hard-interface.o aggregation.o originator.o
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
[state: 03-05-2010]
|
[state: 12-06-2010]
|
||||||
|
|
||||||
BATMAN-ADV
|
BATMAN-ADV
|
||||||
----------
|
----------
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
Request a review.
|
* Use hweight* for hamming weight calculation
|
||||||
Process the comments from the review.
|
* Save/cache packets direktly as skb instead of using a normal memory region
|
||||||
Move into mainline proper.
|
and copying it in a skb using send_raw_packet and similar functions
|
||||||
|
* Request a new review
|
||||||
|
* Process the comments from the review
|
||||||
|
* Move into mainline proper
|
||||||
|
|
||||||
Please send all patches to:
|
Please send all patches to:
|
||||||
Marek Lindner <lindner_marek@yahoo.de>
|
Marek Lindner <lindner_marek@yahoo.de>
|
||||||
|
|
|
@ -106,11 +106,14 @@ static void new_aggregated_packet(unsigned char *packet_buff,
|
||||||
{
|
{
|
||||||
struct forw_packet *forw_packet_aggr;
|
struct forw_packet *forw_packet_aggr;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
/* FIXME: each batman_if will be attached to a softif */
|
||||||
|
struct bat_priv *bat_priv = netdev_priv(soft_device);
|
||||||
|
|
||||||
/* own packet should always be scheduled */
|
/* own packet should always be scheduled */
|
||||||
if (!own_packet) {
|
if (!own_packet) {
|
||||||
if (!atomic_dec_not_zero(&batman_queue_left)) {
|
if (!atomic_dec_not_zero(&batman_queue_left)) {
|
||||||
bat_dbg(DBG_BATMAN, "batman packet queue full\n");
|
bat_dbg(DBG_BATMAN, bat_priv,
|
||||||
|
"batman packet queue full\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -252,9 +255,9 @@ void receive_aggr_bat_packet(struct ethhdr *ethhdr, unsigned char *packet_buff,
|
||||||
while (aggregated_packet(buff_pos, packet_len,
|
while (aggregated_packet(buff_pos, packet_len,
|
||||||
batman_packet->num_hna)) {
|
batman_packet->num_hna)) {
|
||||||
|
|
||||||
/* network to host order for our 16bit seqno, and the
|
/* network to host order for our 32bit seqno, and the
|
||||||
orig_interval. */
|
orig_interval. */
|
||||||
batman_packet->seqno = ntohs(batman_packet->seqno);
|
batman_packet->seqno = ntohl(batman_packet->seqno);
|
||||||
|
|
||||||
hna_buff = packet_buff + buff_pos + BAT_PACKET_LEN;
|
hna_buff = packet_buff + buff_pos + BAT_PACKET_LEN;
|
||||||
receive_bat_packet(ethhdr, batman_packet,
|
receive_bat_packet(ethhdr, batman_packet,
|
||||||
|
|
|
@ -19,6 +19,9 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#ifndef _NET_BATMAN_ADV_AGGREGATION_H_
|
||||||
|
#define _NET_BATMAN_ADV_AGGREGATION_H_
|
||||||
|
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
|
|
||||||
/* is there another aggregated packet here? */
|
/* is there another aggregated packet here? */
|
||||||
|
@ -36,3 +39,5 @@ void add_bat_packet_to_list(struct bat_priv *bat_priv,
|
||||||
unsigned long send_time);
|
unsigned long send_time);
|
||||||
void receive_aggr_bat_packet(struct ethhdr *ethhdr, unsigned char *packet_buff,
|
void receive_aggr_bat_packet(struct ethhdr *ethhdr, unsigned char *packet_buff,
|
||||||
int packet_len, struct batman_if *if_incoming);
|
int packet_len, struct batman_if *if_incoming);
|
||||||
|
|
||||||
|
#endif /* _NET_BATMAN_ADV_AGGREGATION_H_ */
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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)
|
#define to_dev(obj) container_of(obj, struct device, kobj)
|
||||||
|
|
||||||
struct bat_attribute {
|
|
||||||
struct attribute attr;
|
|
||||||
ssize_t (*show)(struct kobject *kobj, struct attribute *attr,
|
|
||||||
char *buf);
|
|
||||||
ssize_t (*store)(struct kobject *kobj, struct attribute *attr,
|
|
||||||
char *buf, size_t count);
|
|
||||||
};
|
|
||||||
|
|
||||||
struct hardif_attribute {
|
|
||||||
struct attribute attr;
|
|
||||||
ssize_t (*show)(struct kobject *kobj, struct attribute *attr,
|
|
||||||
char *buf);
|
|
||||||
ssize_t (*store)(struct kobject *kobj, struct attribute *attr,
|
|
||||||
char *buf, size_t count);
|
|
||||||
};
|
|
||||||
|
|
||||||
#define BAT_ATTR(_name, _mode, _show, _store) \
|
#define BAT_ATTR(_name, _mode, _show, _store) \
|
||||||
struct bat_attribute bat_attr_##_name = { \
|
struct bat_attribute bat_attr_##_name = { \
|
||||||
.attr = {.name = __stringify(_name), \
|
.attr = {.name = __stringify(_name), \
|
||||||
|
@ -52,34 +36,18 @@ struct bat_attribute bat_attr_##_name = { \
|
||||||
.store = _store, \
|
.store = _store, \
|
||||||
};
|
};
|
||||||
|
|
||||||
#define BAT_BIN_ATTR(_name, _mode, _read, _write) \
|
static ssize_t show_aggr_ogms(struct kobject *kobj, struct attribute *attr,
|
||||||
struct bin_attribute bat_attr_##_name = { \
|
|
||||||
.attr = { .name = __stringify(_name), \
|
|
||||||
.mode = _mode, }, \
|
|
||||||
.read = _read, \
|
|
||||||
.write = _write, \
|
|
||||||
};
|
|
||||||
|
|
||||||
#define HARDIF_ATTR(_name, _mode, _show, _store) \
|
|
||||||
struct hardif_attribute hardif_attr_##_name = { \
|
|
||||||
.attr = {.name = __stringify(_name), \
|
|
||||||
.mode = _mode }, \
|
|
||||||
.show = _show, \
|
|
||||||
.store = _store, \
|
|
||||||
};
|
|
||||||
|
|
||||||
static ssize_t show_aggr_ogm(struct kobject *kobj, struct attribute *attr,
|
|
||||||
char *buff)
|
char *buff)
|
||||||
{
|
{
|
||||||
struct device *dev = to_dev(kobj->parent);
|
struct device *dev = to_dev(kobj->parent);
|
||||||
struct bat_priv *bat_priv = netdev_priv(to_net_dev(dev));
|
struct bat_priv *bat_priv = netdev_priv(to_net_dev(dev));
|
||||||
int aggr_status = atomic_read(&bat_priv->aggregation_enabled);
|
int aggr_status = atomic_read(&bat_priv->aggregation_enabled);
|
||||||
|
|
||||||
return sprintf(buff, "status: %s\ncommands: enable, disable, 0, 1\n",
|
return sprintf(buff, "%s\n",
|
||||||
aggr_status == 0 ? "disabled" : "enabled");
|
aggr_status == 0 ? "disabled" : "enabled");
|
||||||
}
|
}
|
||||||
|
|
||||||
static ssize_t store_aggr_ogm(struct kobject *kobj, struct attribute *attr,
|
static ssize_t store_aggr_ogms(struct kobject *kobj, struct attribute *attr,
|
||||||
char *buff, size_t count)
|
char *buff, size_t count)
|
||||||
{
|
{
|
||||||
struct device *dev = to_dev(kobj->parent);
|
struct device *dev = to_dev(kobj->parent);
|
||||||
|
@ -99,23 +67,73 @@ static ssize_t store_aggr_ogm(struct kobject *kobj, struct attribute *attr,
|
||||||
if (buff[count - 1] == '\n')
|
if (buff[count - 1] == '\n')
|
||||||
buff[count - 1] = '\0';
|
buff[count - 1] = '\0';
|
||||||
|
|
||||||
printk(KERN_INFO "batman-adv:Invalid parameter for 'aggregate OGM' setting on mesh %s received: %s\n",
|
bat_info(net_dev,
|
||||||
net_dev->name, buff);
|
"Invalid parameter for 'aggregate OGM' setting"
|
||||||
|
"received: %s\n", buff);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (atomic_read(&bat_priv->aggregation_enabled) == aggr_tmp)
|
if (atomic_read(&bat_priv->aggregation_enabled) == aggr_tmp)
|
||||||
return count;
|
return count;
|
||||||
|
|
||||||
printk(KERN_INFO "batman-adv:Changing aggregation from: %s to: %s on mesh: %s\n",
|
bat_info(net_dev, "Changing aggregation from: %s to: %s\n",
|
||||||
atomic_read(&bat_priv->aggregation_enabled) == 1 ?
|
atomic_read(&bat_priv->aggregation_enabled) == 1 ?
|
||||||
"enabled" : "disabled", aggr_tmp == 1 ? "enabled" : "disabled",
|
"enabled" : "disabled", aggr_tmp == 1 ? "enabled" :
|
||||||
net_dev->name);
|
"disabled");
|
||||||
|
|
||||||
atomic_set(&bat_priv->aggregation_enabled, (unsigned)aggr_tmp);
|
atomic_set(&bat_priv->aggregation_enabled, (unsigned)aggr_tmp);
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static ssize_t show_bond(struct kobject *kobj, struct attribute *attr,
|
||||||
|
char *buff)
|
||||||
|
{
|
||||||
|
struct device *dev = to_dev(kobj->parent);
|
||||||
|
struct bat_priv *bat_priv = netdev_priv(to_net_dev(dev));
|
||||||
|
int bond_status = atomic_read(&bat_priv->bonding_enabled);
|
||||||
|
|
||||||
|
return sprintf(buff, "%s\n",
|
||||||
|
bond_status == 0 ? "disabled" : "enabled");
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t store_bond(struct kobject *kobj, struct attribute *attr,
|
||||||
|
char *buff, size_t count)
|
||||||
|
{
|
||||||
|
struct device *dev = to_dev(kobj->parent);
|
||||||
|
struct net_device *net_dev = to_net_dev(dev);
|
||||||
|
struct bat_priv *bat_priv = netdev_priv(net_dev);
|
||||||
|
int bonding_enabled_tmp = -1;
|
||||||
|
|
||||||
|
if (((count == 2) && (buff[0] == '1')) ||
|
||||||
|
(strncmp(buff, "enable", 6) == 0))
|
||||||
|
bonding_enabled_tmp = 1;
|
||||||
|
|
||||||
|
if (((count == 2) && (buff[0] == '0')) ||
|
||||||
|
(strncmp(buff, "disable", 7) == 0))
|
||||||
|
bonding_enabled_tmp = 0;
|
||||||
|
|
||||||
|
if (bonding_enabled_tmp < 0) {
|
||||||
|
if (buff[count - 1] == '\n')
|
||||||
|
buff[count - 1] = '\0';
|
||||||
|
|
||||||
|
bat_err(net_dev,
|
||||||
|
"Invalid parameter for 'bonding' setting received: "
|
||||||
|
"%s\n", buff);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (atomic_read(&bat_priv->bonding_enabled) == bonding_enabled_tmp)
|
||||||
|
return count;
|
||||||
|
|
||||||
|
bat_info(net_dev, "Changing bonding from: %s to: %s\n",
|
||||||
|
atomic_read(&bat_priv->bonding_enabled) == 1 ?
|
||||||
|
"enabled" : "disabled",
|
||||||
|
bonding_enabled_tmp == 1 ? "enabled" : "disabled");
|
||||||
|
|
||||||
|
atomic_set(&bat_priv->bonding_enabled, (unsigned)bonding_enabled_tmp);
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
static ssize_t show_vis_mode(struct kobject *kobj, struct attribute *attr,
|
static ssize_t show_vis_mode(struct kobject *kobj, struct attribute *attr,
|
||||||
char *buff)
|
char *buff)
|
||||||
{
|
{
|
||||||
|
@ -123,10 +141,9 @@ static ssize_t show_vis_mode(struct kobject *kobj, struct attribute *attr,
|
||||||
struct bat_priv *bat_priv = netdev_priv(to_net_dev(dev));
|
struct bat_priv *bat_priv = netdev_priv(to_net_dev(dev));
|
||||||
int vis_mode = atomic_read(&bat_priv->vis_mode);
|
int vis_mode = atomic_read(&bat_priv->vis_mode);
|
||||||
|
|
||||||
return sprintf(buff, "status: %s\ncommands: client, server, %d, %d\n",
|
return sprintf(buff, "%s\n",
|
||||||
vis_mode == VIS_TYPE_CLIENT_UPDATE ?
|
vis_mode == VIS_TYPE_CLIENT_UPDATE ?
|
||||||
"client" : "server",
|
"client" : "server");
|
||||||
VIS_TYPE_SERVER_SYNC, VIS_TYPE_CLIENT_UPDATE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static ssize_t store_vis_mode(struct kobject *kobj, struct attribute *attr,
|
static ssize_t store_vis_mode(struct kobject *kobj, struct attribute *attr,
|
||||||
|
@ -141,7 +158,8 @@ static ssize_t store_vis_mode(struct kobject *kobj, struct attribute *attr,
|
||||||
ret = strict_strtoul(buff, 10, &val);
|
ret = strict_strtoul(buff, 10, &val);
|
||||||
|
|
||||||
if (((count == 2) && (!ret) && (val == VIS_TYPE_CLIENT_UPDATE)) ||
|
if (((count == 2) && (!ret) && (val == VIS_TYPE_CLIENT_UPDATE)) ||
|
||||||
(strncmp(buff, "client", 6) == 0))
|
(strncmp(buff, "client", 6) == 0) ||
|
||||||
|
(strncmp(buff, "off", 3) == 0))
|
||||||
vis_mode_tmp = VIS_TYPE_CLIENT_UPDATE;
|
vis_mode_tmp = VIS_TYPE_CLIENT_UPDATE;
|
||||||
|
|
||||||
if (((count == 2) && (!ret) && (val == VIS_TYPE_SERVER_SYNC)) ||
|
if (((count == 2) && (!ret) && (val == VIS_TYPE_SERVER_SYNC)) ||
|
||||||
|
@ -152,18 +170,19 @@ static ssize_t store_vis_mode(struct kobject *kobj, struct attribute *attr,
|
||||||
if (buff[count - 1] == '\n')
|
if (buff[count - 1] == '\n')
|
||||||
buff[count - 1] = '\0';
|
buff[count - 1] = '\0';
|
||||||
|
|
||||||
printk(KERN_INFO "batman-adv:Invalid parameter for 'vis mode' setting on mesh %s received: %s\n",
|
bat_info(net_dev,
|
||||||
net_dev->name, buff);
|
"Invalid parameter for 'vis mode' setting received: "
|
||||||
|
"%s\n", buff);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (atomic_read(&bat_priv->vis_mode) == vis_mode_tmp)
|
if (atomic_read(&bat_priv->vis_mode) == vis_mode_tmp)
|
||||||
return count;
|
return count;
|
||||||
|
|
||||||
printk(KERN_INFO "batman-adv:Changing vis mode from: %s to: %s on mesh: %s\n",
|
bat_info(net_dev, "Changing vis mode from: %s to: %s\n",
|
||||||
atomic_read(&bat_priv->vis_mode) == VIS_TYPE_CLIENT_UPDATE ?
|
atomic_read(&bat_priv->vis_mode) == VIS_TYPE_CLIENT_UPDATE ?
|
||||||
"client" : "server", vis_mode_tmp == VIS_TYPE_CLIENT_UPDATE ?
|
"client" : "server", vis_mode_tmp == VIS_TYPE_CLIENT_UPDATE ?
|
||||||
"client" : "server", net_dev->name);
|
"client" : "server");
|
||||||
|
|
||||||
atomic_set(&bat_priv->vis_mode, (unsigned)vis_mode_tmp);
|
atomic_set(&bat_priv->vis_mode, (unsigned)vis_mode_tmp);
|
||||||
return count;
|
return count;
|
||||||
|
@ -175,7 +194,7 @@ static ssize_t show_orig_interval(struct kobject *kobj, struct attribute *attr,
|
||||||
struct device *dev = to_dev(kobj->parent);
|
struct device *dev = to_dev(kobj->parent);
|
||||||
struct bat_priv *bat_priv = netdev_priv(to_net_dev(dev));
|
struct bat_priv *bat_priv = netdev_priv(to_net_dev(dev));
|
||||||
|
|
||||||
return sprintf(buff, "status: %i\n",
|
return sprintf(buff, "%i\n",
|
||||||
atomic_read(&bat_priv->orig_interval));
|
atomic_read(&bat_priv->orig_interval));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -190,91 +209,87 @@ static ssize_t store_orig_interval(struct kobject *kobj, struct attribute *attr,
|
||||||
|
|
||||||
ret = strict_strtoul(buff, 10, &orig_interval_tmp);
|
ret = strict_strtoul(buff, 10, &orig_interval_tmp);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
printk(KERN_INFO "batman-adv:Invalid parameter for 'orig_interval' setting on mesh %s received: %s\n",
|
bat_info(net_dev, "Invalid parameter for 'orig_interval' "
|
||||||
net_dev->name, buff);
|
"setting received: %s\n", buff);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (orig_interval_tmp <= JITTER * 2) {
|
if (orig_interval_tmp < JITTER * 2) {
|
||||||
printk(KERN_INFO "batman-adv:New originator interval too small: %li (min: %i)\n",
|
bat_info(net_dev, "New originator interval too small: %li "
|
||||||
orig_interval_tmp, JITTER * 2);
|
"(min: %i)\n", orig_interval_tmp, JITTER * 2);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (atomic_read(&bat_priv->orig_interval) == orig_interval_tmp)
|
if (atomic_read(&bat_priv->orig_interval) == orig_interval_tmp)
|
||||||
return count;
|
return count;
|
||||||
|
|
||||||
printk(KERN_INFO "batman-adv:Changing originator interval from: %i to: %li on mesh: %s\n",
|
bat_info(net_dev, "Changing originator interval from: %i to: %li\n",
|
||||||
atomic_read(&bat_priv->orig_interval),
|
atomic_read(&bat_priv->orig_interval),
|
||||||
orig_interval_tmp, net_dev->name);
|
orig_interval_tmp);
|
||||||
|
|
||||||
atomic_set(&bat_priv->orig_interval, orig_interval_tmp);
|
atomic_set(&bat_priv->orig_interval, orig_interval_tmp);
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
static BAT_ATTR(aggregate_ogm, S_IRUGO | S_IWUSR,
|
#ifdef CONFIG_BATMAN_ADV_DEBUG
|
||||||
show_aggr_ogm, store_aggr_ogm);
|
static ssize_t show_log_level(struct kobject *kobj, struct attribute *attr,
|
||||||
|
char *buff)
|
||||||
|
{
|
||||||
|
struct device *dev = to_dev(kobj->parent);
|
||||||
|
struct bat_priv *bat_priv = netdev_priv(to_net_dev(dev));
|
||||||
|
int log_level = atomic_read(&bat_priv->log_level);
|
||||||
|
|
||||||
|
return sprintf(buff, "%d\n", log_level);
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t store_log_level(struct kobject *kobj, struct attribute *attr,
|
||||||
|
char *buff, size_t count)
|
||||||
|
{
|
||||||
|
struct device *dev = to_dev(kobj->parent);
|
||||||
|
struct net_device *net_dev = to_net_dev(dev);
|
||||||
|
struct bat_priv *bat_priv = netdev_priv(net_dev);
|
||||||
|
unsigned long log_level_tmp;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = strict_strtoul(buff, 10, &log_level_tmp);
|
||||||
|
if (ret) {
|
||||||
|
bat_info(net_dev, "Invalid parameter for 'log_level' "
|
||||||
|
"setting received: %s\n", buff);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (log_level_tmp > 3) {
|
||||||
|
bat_info(net_dev, "New log level too big: %li "
|
||||||
|
"(max: %i)\n", log_level_tmp, 3);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (atomic_read(&bat_priv->log_level) == log_level_tmp)
|
||||||
|
return count;
|
||||||
|
|
||||||
|
atomic_set(&bat_priv->log_level, (unsigned)log_level_tmp);
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static BAT_ATTR(aggregated_ogms, S_IRUGO | S_IWUSR,
|
||||||
|
show_aggr_ogms, store_aggr_ogms);
|
||||||
|
static BAT_ATTR(bonding, S_IRUGO | S_IWUSR, show_bond, store_bond);
|
||||||
static BAT_ATTR(vis_mode, S_IRUGO | S_IWUSR, show_vis_mode, store_vis_mode);
|
static BAT_ATTR(vis_mode, S_IRUGO | S_IWUSR, show_vis_mode, store_vis_mode);
|
||||||
static BAT_ATTR(orig_interval, S_IRUGO | S_IWUSR,
|
static BAT_ATTR(orig_interval, S_IRUGO | S_IWUSR,
|
||||||
show_orig_interval, store_orig_interval);
|
show_orig_interval, store_orig_interval);
|
||||||
|
#ifdef CONFIG_BATMAN_ADV_DEBUG
|
||||||
|
static BAT_ATTR(log_level, S_IRUGO | S_IWUSR, show_log_level, store_log_level);
|
||||||
|
#endif
|
||||||
|
|
||||||
static struct bat_attribute *mesh_attrs[] = {
|
static struct bat_attribute *mesh_attrs[] = {
|
||||||
&bat_attr_aggregate_ogm,
|
&bat_attr_aggregated_ogms,
|
||||||
|
&bat_attr_bonding,
|
||||||
&bat_attr_vis_mode,
|
&bat_attr_vis_mode,
|
||||||
&bat_attr_orig_interval,
|
&bat_attr_orig_interval,
|
||||||
NULL,
|
#ifdef CONFIG_BATMAN_ADV_DEBUG
|
||||||
};
|
&bat_attr_log_level,
|
||||||
|
#endif
|
||||||
static ssize_t transtable_local_read(struct file *filp, struct kobject *kobj,
|
|
||||||
struct bin_attribute *bin_attr,
|
|
||||||
char *buff, loff_t off, size_t count)
|
|
||||||
{
|
|
||||||
struct device *dev = to_dev(kobj->parent);
|
|
||||||
struct net_device *net_dev = to_net_dev(dev);
|
|
||||||
|
|
||||||
return hna_local_fill_buffer_text(net_dev, buff, count, off);
|
|
||||||
}
|
|
||||||
|
|
||||||
static ssize_t transtable_global_read(struct file *filp, struct kobject *kobj,
|
|
||||||
struct bin_attribute *bin_attr,
|
|
||||||
char *buff, loff_t off, size_t count)
|
|
||||||
{
|
|
||||||
struct device *dev = to_dev(kobj->parent);
|
|
||||||
struct net_device *net_dev = to_net_dev(dev);
|
|
||||||
|
|
||||||
return hna_global_fill_buffer_text(net_dev, buff, count, off);
|
|
||||||
}
|
|
||||||
|
|
||||||
static ssize_t originators_read(struct file *filp, struct kobject *kobj,
|
|
||||||
struct bin_attribute *bin_attr,
|
|
||||||
char *buff, loff_t off, size_t count)
|
|
||||||
{
|
|
||||||
struct device *dev = to_dev(kobj->parent);
|
|
||||||
struct net_device *net_dev = to_net_dev(dev);
|
|
||||||
|
|
||||||
return orig_fill_buffer_text(net_dev, buff, count, off);
|
|
||||||
}
|
|
||||||
|
|
||||||
static ssize_t vis_data_read(struct file *filp, struct kobject *kobj,
|
|
||||||
struct bin_attribute *bin_attr,
|
|
||||||
char *buff, loff_t off, size_t count)
|
|
||||||
{
|
|
||||||
struct device *dev = to_dev(kobj->parent);
|
|
||||||
struct net_device *net_dev = to_net_dev(dev);
|
|
||||||
|
|
||||||
return vis_fill_buffer_text(net_dev, buff, count, off);
|
|
||||||
}
|
|
||||||
|
|
||||||
static BAT_BIN_ATTR(transtable_local, S_IRUGO, transtable_local_read, NULL);
|
|
||||||
static BAT_BIN_ATTR(transtable_global, S_IRUGO, transtable_global_read, NULL);
|
|
||||||
static BAT_BIN_ATTR(originators, S_IRUGO, originators_read, NULL);
|
|
||||||
static BAT_BIN_ATTR(vis_data, S_IRUGO, vis_data_read, NULL);
|
|
||||||
|
|
||||||
static struct bin_attribute *mesh_bin_attrs[] = {
|
|
||||||
&bat_attr_transtable_local,
|
|
||||||
&bat_attr_transtable_global,
|
|
||||||
&bat_attr_originators,
|
|
||||||
&bat_attr_vis_data,
|
|
||||||
NULL,
|
NULL,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -283,22 +298,24 @@ int sysfs_add_meshif(struct net_device *dev)
|
||||||
struct kobject *batif_kobject = &dev->dev.kobj;
|
struct kobject *batif_kobject = &dev->dev.kobj;
|
||||||
struct bat_priv *bat_priv = netdev_priv(dev);
|
struct bat_priv *bat_priv = netdev_priv(dev);
|
||||||
struct bat_attribute **bat_attr;
|
struct bat_attribute **bat_attr;
|
||||||
struct bin_attribute **bin_attr;
|
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
/* FIXME: should be done in the general mesh setup
|
/* FIXME: should be done in the general mesh setup
|
||||||
routine as soon as we have it */
|
routine as soon as we have it */
|
||||||
atomic_set(&bat_priv->aggregation_enabled, 1);
|
atomic_set(&bat_priv->aggregation_enabled, 1);
|
||||||
|
atomic_set(&bat_priv->bonding_enabled, 0);
|
||||||
atomic_set(&bat_priv->vis_mode, VIS_TYPE_CLIENT_UPDATE);
|
atomic_set(&bat_priv->vis_mode, VIS_TYPE_CLIENT_UPDATE);
|
||||||
atomic_set(&bat_priv->orig_interval, 1000);
|
atomic_set(&bat_priv->orig_interval, 1000);
|
||||||
|
atomic_set(&bat_priv->log_level, 0);
|
||||||
|
|
||||||
bat_priv->primary_if = NULL;
|
bat_priv->primary_if = NULL;
|
||||||
bat_priv->num_ifaces = 0;
|
bat_priv->num_ifaces = 0;
|
||||||
|
|
||||||
bat_priv->mesh_obj = kobject_create_and_add(SYSFS_IF_MESH_SUBDIR,
|
bat_priv->mesh_obj = kobject_create_and_add(SYSFS_IF_MESH_SUBDIR,
|
||||||
batif_kobject);
|
batif_kobject);
|
||||||
if (!bat_priv->mesh_obj) {
|
if (!bat_priv->mesh_obj) {
|
||||||
printk(KERN_ERR "batman-adv:Can't add sysfs directory: %s/%s\n",
|
bat_err(dev, "Can't add sysfs directory: %s/%s\n", dev->name,
|
||||||
dev->name, SYSFS_IF_MESH_SUBDIR);
|
SYSFS_IF_MESH_SUBDIR);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -306,28 +323,15 @@ int sysfs_add_meshif(struct net_device *dev)
|
||||||
err = sysfs_create_file(bat_priv->mesh_obj,
|
err = sysfs_create_file(bat_priv->mesh_obj,
|
||||||
&((*bat_attr)->attr));
|
&((*bat_attr)->attr));
|
||||||
if (err) {
|
if (err) {
|
||||||
printk(KERN_ERR "batman-adv:Can't add sysfs file: %s/%s/%s\n",
|
bat_err(dev, "Can't add sysfs file: %s/%s/%s\n",
|
||||||
dev->name, SYSFS_IF_MESH_SUBDIR,
|
dev->name, SYSFS_IF_MESH_SUBDIR,
|
||||||
((*bat_attr)->attr).name);
|
((*bat_attr)->attr).name);
|
||||||
goto rem_attr;
|
goto rem_attr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (bin_attr = mesh_bin_attrs; *bin_attr; ++bin_attr) {
|
|
||||||
err = sysfs_create_bin_file(bat_priv->mesh_obj, (*bin_attr));
|
|
||||||
if (err) {
|
|
||||||
printk(KERN_ERR "batman-adv:Can't add sysfs file: %s/%s/%s\n",
|
|
||||||
dev->name, SYSFS_IF_MESH_SUBDIR,
|
|
||||||
((*bin_attr)->attr).name);
|
|
||||||
goto rem_bin_attr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
rem_bin_attr:
|
|
||||||
for (bin_attr = mesh_bin_attrs; *bin_attr; ++bin_attr)
|
|
||||||
sysfs_remove_bin_file(bat_priv->mesh_obj, (*bin_attr));
|
|
||||||
rem_attr:
|
rem_attr:
|
||||||
for (bat_attr = mesh_attrs; *bat_attr; ++bat_attr)
|
for (bat_attr = mesh_attrs; *bat_attr; ++bat_attr)
|
||||||
sysfs_remove_file(bat_priv->mesh_obj, &((*bat_attr)->attr));
|
sysfs_remove_file(bat_priv->mesh_obj, &((*bat_attr)->attr));
|
||||||
|
@ -342,10 +346,6 @@ void sysfs_del_meshif(struct net_device *dev)
|
||||||
{
|
{
|
||||||
struct bat_priv *bat_priv = netdev_priv(dev);
|
struct bat_priv *bat_priv = netdev_priv(dev);
|
||||||
struct bat_attribute **bat_attr;
|
struct bat_attribute **bat_attr;
|
||||||
struct bin_attribute **bin_attr;
|
|
||||||
|
|
||||||
for (bin_attr = mesh_bin_attrs; *bin_attr; ++bin_attr)
|
|
||||||
sysfs_remove_bin_file(bat_priv->mesh_obj, (*bin_attr));
|
|
||||||
|
|
||||||
for (bat_attr = mesh_attrs; *bat_attr; ++bat_attr)
|
for (bat_attr = mesh_attrs; *bat_attr; ++bat_attr)
|
||||||
sysfs_remove_file(bat_priv->mesh_obj, &((*bat_attr)->attr));
|
sysfs_remove_file(bat_priv->mesh_obj, &((*bat_attr)->attr));
|
||||||
|
@ -364,7 +364,7 @@ static ssize_t show_mesh_iface(struct kobject *kobj, struct attribute *attr,
|
||||||
if (!batman_if)
|
if (!batman_if)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
return sprintf(buff, "status: %s\ncommands: none, bat0\n",
|
return sprintf(buff, "%s\n",
|
||||||
batman_if->if_status == IF_NOT_IN_USE ?
|
batman_if->if_status == IF_NOT_IN_USE ?
|
||||||
"none" : "bat0");
|
"none" : "bat0");
|
||||||
}
|
}
|
||||||
|
@ -390,8 +390,8 @@ static ssize_t store_mesh_iface(struct kobject *kobj, struct attribute *attr,
|
||||||
if (buff[count - 1] == '\n')
|
if (buff[count - 1] == '\n')
|
||||||
buff[count - 1] = '\0';
|
buff[count - 1] = '\0';
|
||||||
|
|
||||||
printk(KERN_ERR "batman-adv:Invalid parameter for 'mesh_iface' setting received: %s\n",
|
pr_err("Invalid parameter for 'mesh_iface' setting received: "
|
||||||
buff);
|
"%s\n", buff);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -433,37 +433,37 @@ static ssize_t show_iface_status(struct kobject *kobj, struct attribute *attr,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static HARDIF_ATTR(mesh_iface, S_IRUGO | S_IWUSR,
|
static BAT_ATTR(mesh_iface, S_IRUGO | S_IWUSR,
|
||||||
show_mesh_iface, store_mesh_iface);
|
show_mesh_iface, store_mesh_iface);
|
||||||
static HARDIF_ATTR(iface_status, S_IRUGO, show_iface_status, NULL);
|
static BAT_ATTR(iface_status, S_IRUGO, show_iface_status, NULL);
|
||||||
|
|
||||||
static struct hardif_attribute *batman_attrs[] = {
|
static struct bat_attribute *batman_attrs[] = {
|
||||||
&hardif_attr_mesh_iface,
|
&bat_attr_mesh_iface,
|
||||||
&hardif_attr_iface_status,
|
&bat_attr_iface_status,
|
||||||
NULL,
|
NULL,
|
||||||
};
|
};
|
||||||
|
|
||||||
int sysfs_add_hardif(struct kobject **hardif_obj, struct net_device *dev)
|
int sysfs_add_hardif(struct kobject **hardif_obj, struct net_device *dev)
|
||||||
{
|
{
|
||||||
struct kobject *hardif_kobject = &dev->dev.kobj;
|
struct kobject *hardif_kobject = &dev->dev.kobj;
|
||||||
struct hardif_attribute **hardif_attr;
|
struct bat_attribute **bat_attr;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
*hardif_obj = kobject_create_and_add(SYSFS_IF_BAT_SUBDIR,
|
*hardif_obj = kobject_create_and_add(SYSFS_IF_BAT_SUBDIR,
|
||||||
hardif_kobject);
|
hardif_kobject);
|
||||||
|
|
||||||
if (!*hardif_obj) {
|
if (!*hardif_obj) {
|
||||||
printk(KERN_ERR "batman-adv:Can't add sysfs directory: %s/%s\n",
|
bat_err(dev, "Can't add sysfs directory: %s/%s\n", dev->name,
|
||||||
dev->name, SYSFS_IF_BAT_SUBDIR);
|
SYSFS_IF_BAT_SUBDIR);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (hardif_attr = batman_attrs; *hardif_attr; ++hardif_attr) {
|
for (bat_attr = batman_attrs; *bat_attr; ++bat_attr) {
|
||||||
err = sysfs_create_file(*hardif_obj, &((*hardif_attr)->attr));
|
err = sysfs_create_file(*hardif_obj, &((*bat_attr)->attr));
|
||||||
if (err) {
|
if (err) {
|
||||||
printk(KERN_ERR "batman-adv:Can't add sysfs file: %s/%s/%s\n",
|
bat_err(dev, "Can't add sysfs file: %s/%s/%s\n",
|
||||||
dev->name, SYSFS_IF_BAT_SUBDIR,
|
dev->name, SYSFS_IF_BAT_SUBDIR,
|
||||||
((*hardif_attr)->attr).name);
|
((*bat_attr)->attr).name);
|
||||||
goto rem_attr;
|
goto rem_attr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -471,8 +471,8 @@ int sysfs_add_hardif(struct kobject **hardif_obj, struct net_device *dev)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
rem_attr:
|
rem_attr:
|
||||||
for (hardif_attr = batman_attrs; *hardif_attr; ++hardif_attr)
|
for (bat_attr = batman_attrs; *bat_attr; ++bat_attr)
|
||||||
sysfs_remove_file(*hardif_obj, &((*hardif_attr)->attr));
|
sysfs_remove_file(*hardif_obj, &((*bat_attr)->attr));
|
||||||
out:
|
out:
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,10 +20,23 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef _NET_BATMAN_ADV_SYSFS_H_
|
||||||
|
#define _NET_BATMAN_ADV_SYSFS_H_
|
||||||
|
|
||||||
#define SYSFS_IF_MESH_SUBDIR "mesh"
|
#define SYSFS_IF_MESH_SUBDIR "mesh"
|
||||||
#define SYSFS_IF_BAT_SUBDIR "batman_adv"
|
#define SYSFS_IF_BAT_SUBDIR "batman_adv"
|
||||||
|
|
||||||
|
struct bat_attribute {
|
||||||
|
struct attribute attr;
|
||||||
|
ssize_t (*show)(struct kobject *kobj, struct attribute *attr,
|
||||||
|
char *buf);
|
||||||
|
ssize_t (*store)(struct kobject *kobj, struct attribute *attr,
|
||||||
|
char *buf, size_t count);
|
||||||
|
};
|
||||||
|
|
||||||
int sysfs_add_meshif(struct net_device *dev);
|
int sysfs_add_meshif(struct net_device *dev);
|
||||||
void sysfs_del_meshif(struct net_device *dev);
|
void sysfs_del_meshif(struct net_device *dev);
|
||||||
int sysfs_add_hardif(struct kobject **hardif_obj, struct net_device *dev);
|
int sysfs_add_hardif(struct kobject **hardif_obj, struct net_device *dev);
|
||||||
void sysfs_del_hardif(struct kobject **hardif_obj);
|
void sysfs_del_hardif(struct kobject **hardif_obj);
|
||||||
|
|
||||||
|
#endif /* _NET_BATMAN_ADV_SYSFS_H_ */
|
||||||
|
|
|
@ -24,10 +24,10 @@
|
||||||
|
|
||||||
/* returns true if the corresponding bit in the given seq_bits indicates true
|
/* returns true if the corresponding bit in the given seq_bits indicates true
|
||||||
* and curr_seqno is within range of last_seqno */
|
* and curr_seqno is within range of last_seqno */
|
||||||
uint8_t get_bit_status(TYPE_OF_WORD *seq_bits, uint16_t last_seqno,
|
uint8_t get_bit_status(TYPE_OF_WORD *seq_bits, uint32_t last_seqno,
|
||||||
uint16_t curr_seqno)
|
uint32_t curr_seqno)
|
||||||
{
|
{
|
||||||
int16_t diff, word_offset, word_num;
|
int32_t diff, word_offset, word_num;
|
||||||
|
|
||||||
diff = last_seqno - curr_seqno;
|
diff = last_seqno - curr_seqno;
|
||||||
if (diff < 0 || diff >= TQ_LOCAL_WINDOW_SIZE) {
|
if (diff < 0 || diff >= TQ_LOCAL_WINDOW_SIZE) {
|
||||||
|
@ -63,7 +63,7 @@ void bit_mark(TYPE_OF_WORD *seq_bits, int32_t n)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* shift the packet array by n places. */
|
/* shift the packet array by n places. */
|
||||||
void bit_shift(TYPE_OF_WORD *seq_bits, int32_t n)
|
static void bit_shift(TYPE_OF_WORD *seq_bits, int32_t n)
|
||||||
{
|
{
|
||||||
int32_t word_offset, word_num;
|
int32_t word_offset, word_num;
|
||||||
int32_t i;
|
int32_t i;
|
||||||
|
@ -125,9 +125,12 @@ static void bit_reset_window(TYPE_OF_WORD *seq_bits)
|
||||||
* 1 if the window was moved (either new or very old)
|
* 1 if the window was moved (either new or very old)
|
||||||
* 0 if the window was not moved/shifted.
|
* 0 if the window was not moved/shifted.
|
||||||
*/
|
*/
|
||||||
char bit_get_packet(TYPE_OF_WORD *seq_bits, int16_t seq_num_diff,
|
char bit_get_packet(TYPE_OF_WORD *seq_bits, int32_t seq_num_diff,
|
||||||
int8_t set_mark)
|
int8_t set_mark)
|
||||||
{
|
{
|
||||||
|
/* FIXME: each orig_node->batman_if will be attached to a softif */
|
||||||
|
struct bat_priv *bat_priv = netdev_priv(soft_device);
|
||||||
|
|
||||||
/* sequence number is slightly older. We already got a sequence number
|
/* sequence number is slightly older. We already got a sequence number
|
||||||
* higher than this one, so we just mark it. */
|
* higher than this one, so we just mark it. */
|
||||||
|
|
||||||
|
@ -152,7 +155,7 @@ char bit_get_packet(TYPE_OF_WORD *seq_bits, int16_t seq_num_diff,
|
||||||
|
|
||||||
if ((seq_num_diff >= TQ_LOCAL_WINDOW_SIZE)
|
if ((seq_num_diff >= TQ_LOCAL_WINDOW_SIZE)
|
||||||
|| (seq_num_diff < EXPECTED_SEQNO_RANGE)) {
|
|| (seq_num_diff < EXPECTED_SEQNO_RANGE)) {
|
||||||
bat_dbg(DBG_BATMAN,
|
bat_dbg(DBG_BATMAN, bat_priv,
|
||||||
"We missed a lot of packets (%i) !\n",
|
"We missed a lot of packets (%i) !\n",
|
||||||
seq_num_diff - 1);
|
seq_num_diff - 1);
|
||||||
bit_reset_window(seq_bits);
|
bit_reset_window(seq_bits);
|
||||||
|
@ -169,7 +172,7 @@ char bit_get_packet(TYPE_OF_WORD *seq_bits, int16_t seq_num_diff,
|
||||||
if ((seq_num_diff <= -TQ_LOCAL_WINDOW_SIZE)
|
if ((seq_num_diff <= -TQ_LOCAL_WINDOW_SIZE)
|
||||||
|| (seq_num_diff >= EXPECTED_SEQNO_RANGE)) {
|
|| (seq_num_diff >= EXPECTED_SEQNO_RANGE)) {
|
||||||
|
|
||||||
bat_dbg(DBG_BATMAN,
|
bat_dbg(DBG_BATMAN, bat_priv,
|
||||||
"Other host probably restarted!\n");
|
"Other host probably restarted!\n");
|
||||||
|
|
||||||
bit_reset_window(seq_bits);
|
bit_reset_window(seq_bits);
|
||||||
|
|
|
@ -19,6 +19,8 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#ifndef _NET_BATMAN_ADV_BITARRAY_H_
|
||||||
|
#define _NET_BATMAN_ADV_BITARRAY_H_
|
||||||
|
|
||||||
/* you should choose something big, if you don't want to waste cpu */
|
/* you should choose something big, if you don't want to waste cpu */
|
||||||
#define TYPE_OF_WORD unsigned long
|
#define TYPE_OF_WORD unsigned long
|
||||||
|
@ -26,20 +28,19 @@
|
||||||
|
|
||||||
/* returns true if the corresponding bit in the given seq_bits indicates true
|
/* returns true if the corresponding bit in the given seq_bits indicates true
|
||||||
* and curr_seqno is within range of last_seqno */
|
* and curr_seqno is within range of last_seqno */
|
||||||
uint8_t get_bit_status(TYPE_OF_WORD *seq_bits, uint16_t last_seqno,
|
uint8_t get_bit_status(TYPE_OF_WORD *seq_bits, uint32_t last_seqno,
|
||||||
uint16_t curr_seqno);
|
uint32_t curr_seqno);
|
||||||
|
|
||||||
/* turn corresponding bit on, so we can remember that we got the packet */
|
/* turn corresponding bit on, so we can remember that we got the packet */
|
||||||
void bit_mark(TYPE_OF_WORD *seq_bits, int32_t n);
|
void bit_mark(TYPE_OF_WORD *seq_bits, int32_t n);
|
||||||
|
|
||||||
/* shift the packet array by n places. */
|
|
||||||
void bit_shift(TYPE_OF_WORD *seq_bits, int32_t n);
|
|
||||||
|
|
||||||
|
|
||||||
/* receive and process one packet, returns 1 if received seq_num is considered
|
/* receive and process one packet, returns 1 if received seq_num is considered
|
||||||
* new, 0 if old */
|
* new, 0 if old */
|
||||||
char bit_get_packet(TYPE_OF_WORD *seq_bits, int16_t seq_num_diff,
|
char bit_get_packet(TYPE_OF_WORD *seq_bits, int32_t seq_num_diff,
|
||||||
int8_t set_mark);
|
int8_t set_mark);
|
||||||
|
|
||||||
/* count the hamming weight, how many good packets did we receive? */
|
/* count the hamming weight, how many good packets did we receive? */
|
||||||
int bit_packet_count(TYPE_OF_WORD *seq_bits);
|
int bit_packet_count(TYPE_OF_WORD *seq_bits);
|
||||||
|
|
||||||
|
#endif /* _NET_BATMAN_ADV_BITARRAY_H_ */
|
||||||
|
|
|
@ -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 "hash.h"
|
||||||
|
|
||||||
#include <linux/if_arp.h>
|
#include <linux/if_arp.h>
|
||||||
|
#include <linux/netfilter_bridge.h>
|
||||||
|
|
||||||
#define MIN(x, y) ((x) < (y) ? (x) : (y))
|
#define MIN(x, y) ((x) < (y) ? (x) : (y))
|
||||||
|
|
||||||
|
@ -108,7 +109,7 @@ static void set_primary_if(struct bat_priv *bat_priv,
|
||||||
set_main_if_addr(batman_if->net_dev->dev_addr);
|
set_main_if_addr(batman_if->net_dev->dev_addr);
|
||||||
|
|
||||||
batman_packet = (struct batman_packet *)(batman_if->packet_buff);
|
batman_packet = (struct batman_packet *)(batman_if->packet_buff);
|
||||||
batman_packet->flags = 0;
|
batman_packet->flags = PRIMARIES_FIRST_HOP;
|
||||||
batman_packet->ttl = TTL;
|
batman_packet->ttl = TTL;
|
||||||
|
|
||||||
/***
|
/***
|
||||||
|
@ -149,12 +150,10 @@ static void check_known_mac_addr(uint8_t *addr)
|
||||||
if (!compare_orig(batman_if->net_dev->dev_addr, addr))
|
if (!compare_orig(batman_if->net_dev->dev_addr, addr))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
printk(KERN_WARNING "batman-adv:"
|
pr_warning("The newly added mac address (%pM) already exists "
|
||||||
"The newly added mac address (%pM) already exists on: %s\n",
|
"on: %s\n", addr, batman_if->dev);
|
||||||
addr, batman_if->dev);
|
pr_warning("It is strongly recommended to keep mac addresses "
|
||||||
printk(KERN_WARNING "batman-adv:"
|
"unique to avoid problems!\n");
|
||||||
"It is strongly recommended to keep mac addresses unique"
|
|
||||||
"to avoid problems!\n");
|
|
||||||
}
|
}
|
||||||
rcu_read_unlock();
|
rcu_read_unlock();
|
||||||
}
|
}
|
||||||
|
@ -188,7 +187,8 @@ void update_min_mtu(void)
|
||||||
soft_device->mtu = min_mtu;
|
soft_device->mtu = min_mtu;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void hardif_activate_interface(struct bat_priv *bat_priv,
|
static void hardif_activate_interface(struct net_device *net_dev,
|
||||||
|
struct bat_priv *bat_priv,
|
||||||
struct batman_if *batman_if)
|
struct batman_if *batman_if)
|
||||||
{
|
{
|
||||||
if (batman_if->if_status != IF_INACTIVE)
|
if (batman_if->if_status != IF_INACTIVE)
|
||||||
|
@ -206,8 +206,7 @@ static void hardif_activate_interface(struct bat_priv *bat_priv,
|
||||||
if (!bat_priv->primary_if)
|
if (!bat_priv->primary_if)
|
||||||
set_primary_if(bat_priv, batman_if);
|
set_primary_if(bat_priv, batman_if);
|
||||||
|
|
||||||
printk(KERN_INFO "batman-adv:Interface activated: %s\n",
|
bat_info(net_dev, "Interface activated: %s\n", batman_if->dev);
|
||||||
batman_if->dev);
|
|
||||||
|
|
||||||
if (atomic_read(&module_state) == MODULE_INACTIVE)
|
if (atomic_read(&module_state) == MODULE_INACTIVE)
|
||||||
activate_module();
|
activate_module();
|
||||||
|
@ -216,7 +215,8 @@ static void hardif_activate_interface(struct bat_priv *bat_priv,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void hardif_deactivate_interface(struct batman_if *batman_if)
|
static void hardif_deactivate_interface(struct net_device *net_dev,
|
||||||
|
struct batman_if *batman_if)
|
||||||
{
|
{
|
||||||
if ((batman_if->if_status != IF_ACTIVE) &&
|
if ((batman_if->if_status != IF_ACTIVE) &&
|
||||||
(batman_if->if_status != IF_TO_BE_ACTIVATED))
|
(batman_if->if_status != IF_TO_BE_ACTIVATED))
|
||||||
|
@ -226,8 +226,7 @@ static void hardif_deactivate_interface(struct batman_if *batman_if)
|
||||||
|
|
||||||
batman_if->if_status = IF_INACTIVE;
|
batman_if->if_status = IF_INACTIVE;
|
||||||
|
|
||||||
printk(KERN_INFO "batman-adv:Interface deactivated: %s\n",
|
bat_info(net_dev, "Interface deactivated: %s\n", batman_if->dev);
|
||||||
batman_if->dev);
|
|
||||||
|
|
||||||
update_min_mtu();
|
update_min_mtu();
|
||||||
}
|
}
|
||||||
|
@ -245,9 +244,8 @@ int hardif_enable_interface(struct batman_if *batman_if)
|
||||||
batman_if->packet_buff = kmalloc(batman_if->packet_len, GFP_ATOMIC);
|
batman_if->packet_buff = kmalloc(batman_if->packet_len, GFP_ATOMIC);
|
||||||
|
|
||||||
if (!batman_if->packet_buff) {
|
if (!batman_if->packet_buff) {
|
||||||
printk(KERN_ERR "batman-adv:"
|
bat_err(soft_device, "Can't add interface packet (%s): "
|
||||||
"Can't add interface packet (%s): out of memory\n",
|
"out of memory\n", batman_if->dev);
|
||||||
batman_if->dev);
|
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -265,13 +263,12 @@ int hardif_enable_interface(struct batman_if *batman_if)
|
||||||
orig_hash_add_if(batman_if, bat_priv->num_ifaces);
|
orig_hash_add_if(batman_if, bat_priv->num_ifaces);
|
||||||
|
|
||||||
atomic_set(&batman_if->seqno, 1);
|
atomic_set(&batman_if->seqno, 1);
|
||||||
printk(KERN_INFO "batman-adv:Adding interface: %s\n", batman_if->dev);
|
bat_info(soft_device, "Adding interface: %s\n", batman_if->dev);
|
||||||
|
|
||||||
if (hardif_is_iface_up(batman_if))
|
if (hardif_is_iface_up(batman_if))
|
||||||
hardif_activate_interface(bat_priv, batman_if);
|
hardif_activate_interface(soft_device, bat_priv, batman_if);
|
||||||
else
|
else
|
||||||
printk(KERN_ERR "batman-adv:"
|
bat_err(soft_device, "Not using interface %s "
|
||||||
"Not using interface %s "
|
|
||||||
"(retrying later): interface not active\n",
|
"(retrying later): interface not active\n",
|
||||||
batman_if->dev);
|
batman_if->dev);
|
||||||
|
|
||||||
|
@ -291,12 +288,12 @@ void hardif_disable_interface(struct batman_if *batman_if)
|
||||||
struct bat_priv *bat_priv = netdev_priv(soft_device);
|
struct bat_priv *bat_priv = netdev_priv(soft_device);
|
||||||
|
|
||||||
if (batman_if->if_status == IF_ACTIVE)
|
if (batman_if->if_status == IF_ACTIVE)
|
||||||
hardif_deactivate_interface(batman_if);
|
hardif_deactivate_interface(soft_device, batman_if);
|
||||||
|
|
||||||
if (batman_if->if_status != IF_INACTIVE)
|
if (batman_if->if_status != IF_INACTIVE)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
printk(KERN_INFO "batman-adv:Removing interface: %s\n", batman_if->dev);
|
bat_info(soft_device, "Removing interface: %s\n", batman_if->dev);
|
||||||
bat_priv->num_ifaces--;
|
bat_priv->num_ifaces--;
|
||||||
orig_hash_del_if(batman_if, bat_priv->num_ifaces);
|
orig_hash_del_if(batman_if, bat_priv->num_ifaces);
|
||||||
|
|
||||||
|
@ -323,8 +320,7 @@ static struct batman_if *hardif_add_interface(struct net_device *net_dev)
|
||||||
|
|
||||||
batman_if = kmalloc(sizeof(struct batman_if), GFP_ATOMIC);
|
batman_if = kmalloc(sizeof(struct batman_if), GFP_ATOMIC);
|
||||||
if (!batman_if) {
|
if (!batman_if) {
|
||||||
printk(KERN_ERR "batman-adv:"
|
pr_err("Can't add interface (%s): out of memory\n",
|
||||||
"Can't add interface (%s): out of memory\n",
|
|
||||||
net_dev->name);
|
net_dev->name);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
@ -407,11 +403,11 @@ static int hard_if_event(struct notifier_block *this,
|
||||||
case NETDEV_REGISTER:
|
case NETDEV_REGISTER:
|
||||||
break;
|
break;
|
||||||
case NETDEV_UP:
|
case NETDEV_UP:
|
||||||
hardif_activate_interface(bat_priv, batman_if);
|
hardif_activate_interface(soft_device, bat_priv, batman_if);
|
||||||
break;
|
break;
|
||||||
case NETDEV_GOING_DOWN:
|
case NETDEV_GOING_DOWN:
|
||||||
case NETDEV_DOWN:
|
case NETDEV_DOWN:
|
||||||
hardif_deactivate_interface(batman_if);
|
hardif_deactivate_interface(soft_device, batman_if);
|
||||||
break;
|
break;
|
||||||
case NETDEV_UNREGISTER:
|
case NETDEV_UNREGISTER:
|
||||||
hardif_remove_interface(batman_if);
|
hardif_remove_interface(batman_if);
|
||||||
|
@ -432,11 +428,18 @@ out:
|
||||||
return NOTIFY_DONE;
|
return NOTIFY_DONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int batman_skb_recv_finish(struct sk_buff *skb)
|
||||||
|
{
|
||||||
|
return NF_ACCEPT;
|
||||||
|
}
|
||||||
|
|
||||||
/* receive a packet with the batman ethertype coming on a hard
|
/* receive a packet with the batman ethertype coming on a hard
|
||||||
* interface */
|
* interface */
|
||||||
int batman_skb_recv(struct sk_buff *skb, struct net_device *dev,
|
int batman_skb_recv(struct sk_buff *skb, struct net_device *dev,
|
||||||
struct packet_type *ptype, struct net_device *orig_dev)
|
struct packet_type *ptype, struct net_device *orig_dev)
|
||||||
{
|
{
|
||||||
|
/* FIXME: each orig_node->batman_if will be attached to a softif */
|
||||||
|
struct bat_priv *bat_priv = netdev_priv(soft_device);
|
||||||
struct batman_packet *batman_packet;
|
struct batman_packet *batman_packet;
|
||||||
struct batman_if *batman_if;
|
struct batman_if *batman_if;
|
||||||
struct net_device_stats *stats;
|
struct net_device_stats *stats;
|
||||||
|
@ -452,6 +455,13 @@ int batman_skb_recv(struct sk_buff *skb, struct net_device *dev,
|
||||||
if (atomic_read(&module_state) != MODULE_ACTIVE)
|
if (atomic_read(&module_state) != MODULE_ACTIVE)
|
||||||
goto err_free;
|
goto err_free;
|
||||||
|
|
||||||
|
/* if netfilter/ebtables wants to block incoming batman
|
||||||
|
* packets then give them a chance to do so here */
|
||||||
|
ret = NF_HOOK(PF_BRIDGE, NF_BR_LOCAL_IN, skb, dev, NULL,
|
||||||
|
batman_skb_recv_finish);
|
||||||
|
if (ret != 1)
|
||||||
|
goto err_out;
|
||||||
|
|
||||||
/* packet should hold at least type and version */
|
/* packet should hold at least type and version */
|
||||||
if (unlikely(skb_headlen(skb) < 2))
|
if (unlikely(skb_headlen(skb) < 2))
|
||||||
goto err_free;
|
goto err_free;
|
||||||
|
@ -478,7 +488,7 @@ int batman_skb_recv(struct sk_buff *skb, struct net_device *dev,
|
||||||
batman_packet = (struct batman_packet *)skb->data;
|
batman_packet = (struct batman_packet *)skb->data;
|
||||||
|
|
||||||
if (batman_packet->version != COMPAT_VERSION) {
|
if (batman_packet->version != COMPAT_VERSION) {
|
||||||
bat_dbg(DBG_BATMAN,
|
bat_dbg(DBG_BATMAN, bat_priv,
|
||||||
"Drop packet: incompatible batman version (%i)\n",
|
"Drop packet: incompatible batman version (%i)\n",
|
||||||
batman_packet->version);
|
batman_packet->version);
|
||||||
goto err_free;
|
goto err_free;
|
||||||
|
@ -500,7 +510,7 @@ int batman_skb_recv(struct sk_buff *skb, struct net_device *dev,
|
||||||
|
|
||||||
/* unicast packet */
|
/* unicast packet */
|
||||||
case BAT_UNICAST:
|
case BAT_UNICAST:
|
||||||
ret = recv_unicast_packet(skb);
|
ret = recv_unicast_packet(skb, batman_if);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* broadcast packet */
|
/* broadcast packet */
|
||||||
|
@ -531,7 +541,6 @@ err_out:
|
||||||
return NET_RX_DROP;
|
return NET_RX_DROP;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
struct notifier_block hard_if_notifier = {
|
struct notifier_block hard_if_notifier = {
|
||||||
.notifier_call = hard_if_event,
|
.notifier_call = hard_if_event,
|
||||||
};
|
};
|
||||||
|
|
|
@ -19,6 +19,9 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#ifndef _NET_BATMAN_ADV_HARD_INTERFACE_H_
|
||||||
|
#define _NET_BATMAN_ADV_HARD_INTERFACE_H_
|
||||||
|
|
||||||
#define IF_NOT_IN_USE 0
|
#define IF_NOT_IN_USE 0
|
||||||
#define IF_TO_BE_REMOVED 1
|
#define IF_TO_BE_REMOVED 1
|
||||||
#define IF_INACTIVE 2
|
#define IF_INACTIVE 2
|
||||||
|
@ -38,3 +41,5 @@ int batman_skb_recv(struct sk_buff *skb,
|
||||||
struct net_device *orig_dev);
|
struct net_device *orig_dev);
|
||||||
int hardif_min_mtu(void);
|
int hardif_min_mtu(void);
|
||||||
void update_min_mtu(void);
|
void update_min_mtu(void);
|
||||||
|
|
||||||
|
#endif /* _NET_BATMAN_ADV_HARD_INTERFACE_H_ */
|
||||||
|
|
|
@ -23,7 +23,7 @@
|
||||||
#include "hash.h"
|
#include "hash.h"
|
||||||
|
|
||||||
/* clears the hash */
|
/* clears the hash */
|
||||||
void hash_init(struct hashtable_t *hash)
|
static void hash_init(struct hashtable_t *hash)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
|
|
@ -19,8 +19,9 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _BATMAN_HASH_H
|
#ifndef _NET_BATMAN_ADV_HASH_H_
|
||||||
#define _BATMAN_HASH_H
|
#define _NET_BATMAN_ADV_HASH_H_
|
||||||
|
|
||||||
#define HASHIT(name) struct hash_it_t name = { \
|
#define HASHIT(name) struct hash_it_t name = { \
|
||||||
.index = -1, .bucket = NULL, \
|
.index = -1, .bucket = NULL, \
|
||||||
.prev_bucket = NULL, \
|
.prev_bucket = NULL, \
|
||||||
|
@ -56,9 +57,6 @@ struct hashtable_t {
|
||||||
* argument and the size the second */
|
* argument and the size the second */
|
||||||
};
|
};
|
||||||
|
|
||||||
/* clears the hash */
|
|
||||||
void hash_init(struct hashtable_t *hash);
|
|
||||||
|
|
||||||
/* allocates and clears the hash */
|
/* allocates and clears the hash */
|
||||||
struct hashtable_t *hash_new(int size, hashdata_compare_cb compare,
|
struct hashtable_t *hash_new(int size, hashdata_compare_cb compare,
|
||||||
hashdata_choose_cb choose);
|
hashdata_choose_cb choose);
|
||||||
|
@ -99,6 +97,4 @@ struct hashtable_t *hash_resize(struct hashtable_t *hash, int size);
|
||||||
struct hash_it_t *hash_iterate(struct hashtable_t *hash,
|
struct hash_it_t *hash_iterate(struct hashtable_t *hash,
|
||||||
struct hash_it_t *iter_in);
|
struct hash_it_t *iter_in);
|
||||||
|
|
||||||
/* print the hash table for debugging */
|
#endif /* _NET_BATMAN_ADV_HASH_H_ */
|
||||||
void hash_debug(struct hashtable_t *hash);
|
|
||||||
#endif
|
|
||||||
|
|
|
@ -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"
|
#include "types.h"
|
||||||
|
|
||||||
void bat_device_init(void);
|
#define ICMP_SOCKET "socket"
|
||||||
int bat_device_setup(void);
|
|
||||||
void bat_device_destroy(void);
|
void bat_socket_init(void);
|
||||||
int bat_device_open(struct inode *inode, struct file *file);
|
int bat_socket_setup(struct bat_priv *bat_priv);
|
||||||
int bat_device_release(struct inode *inode, struct file *file);
|
void bat_socket_receive_packet(struct icmp_packet_rr *icmp_packet,
|
||||||
ssize_t bat_device_read(struct file *file, char __user *buf, size_t count,
|
size_t icmp_len);
|
||||||
loff_t *ppos);
|
|
||||||
ssize_t bat_device_write(struct file *file, const char __user *buff,
|
#endif /* _NET_BATMAN_ADV_ICMP_SOCKET_H_ */
|
||||||
size_t len, loff_t *off);
|
|
||||||
unsigned int bat_device_poll(struct file *file, poll_table *wait);
|
|
||||||
void bat_device_add_packet(struct device_client *device_client,
|
|
||||||
struct icmp_packet *icmp_packet);
|
|
||||||
void bat_device_receive_packet(struct icmp_packet *icmp_packet);
|
|
|
@ -21,11 +21,12 @@
|
||||||
|
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
#include "bat_sysfs.h"
|
#include "bat_sysfs.h"
|
||||||
|
#include "bat_debugfs.h"
|
||||||
#include "routing.h"
|
#include "routing.h"
|
||||||
#include "send.h"
|
#include "send.h"
|
||||||
#include "originator.h"
|
#include "originator.h"
|
||||||
#include "soft-interface.h"
|
#include "soft-interface.h"
|
||||||
#include "device.h"
|
#include "icmp_socket.h"
|
||||||
#include "translation-table.h"
|
#include "translation-table.h"
|
||||||
#include "hard-interface.h"
|
#include "hard-interface.h"
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
|
@ -41,7 +42,6 @@ DEFINE_SPINLOCK(orig_hash_lock);
|
||||||
DEFINE_SPINLOCK(forw_bat_list_lock);
|
DEFINE_SPINLOCK(forw_bat_list_lock);
|
||||||
DEFINE_SPINLOCK(forw_bcast_list_lock);
|
DEFINE_SPINLOCK(forw_bcast_list_lock);
|
||||||
|
|
||||||
atomic_t vis_interval;
|
|
||||||
atomic_t bcast_queue_left;
|
atomic_t bcast_queue_left;
|
||||||
atomic_t batman_queue_left;
|
atomic_t batman_queue_left;
|
||||||
|
|
||||||
|
@ -49,7 +49,7 @@ int16_t num_hna;
|
||||||
|
|
||||||
struct net_device *soft_device;
|
struct net_device *soft_device;
|
||||||
|
|
||||||
unsigned char broadcastAddr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
|
unsigned char broadcast_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
|
||||||
atomic_t module_state;
|
atomic_t module_state;
|
||||||
|
|
||||||
static struct packet_type batman_adv_packet_type __read_mostly = {
|
static struct packet_type batman_adv_packet_type __read_mostly = {
|
||||||
|
@ -59,18 +59,7 @@ static struct packet_type batman_adv_packet_type __read_mostly = {
|
||||||
|
|
||||||
struct workqueue_struct *bat_event_workqueue;
|
struct workqueue_struct *bat_event_workqueue;
|
||||||
|
|
||||||
#ifdef CONFIG_BATMAN_ADV_DEBUG
|
static int __init batman_init(void)
|
||||||
int debug;
|
|
||||||
|
|
||||||
module_param(debug, int, 0644);
|
|
||||||
|
|
||||||
int bat_debug_type(int type)
|
|
||||||
{
|
|
||||||
return debug & type;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
int init_module(void)
|
|
||||||
{
|
{
|
||||||
int retval;
|
int retval;
|
||||||
|
|
||||||
|
@ -80,8 +69,6 @@ int init_module(void)
|
||||||
|
|
||||||
atomic_set(&module_state, MODULE_INACTIVE);
|
atomic_set(&module_state, MODULE_INACTIVE);
|
||||||
|
|
||||||
atomic_set(&vis_interval, 1000);/* TODO: raise this later, this is only
|
|
||||||
* for debugging now. */
|
|
||||||
atomic_set(&bcast_queue_left, BCAST_QUEUE_LEN);
|
atomic_set(&bcast_queue_left, BCAST_QUEUE_LEN);
|
||||||
atomic_set(&batman_queue_left, BATMAN_QUEUE_LEN);
|
atomic_set(&batman_queue_left, BATMAN_QUEUE_LEN);
|
||||||
|
|
||||||
|
@ -92,23 +79,22 @@ int init_module(void)
|
||||||
if (!bat_event_workqueue)
|
if (!bat_event_workqueue)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
bat_device_init();
|
bat_socket_init();
|
||||||
|
debugfs_init();
|
||||||
|
|
||||||
/* initialize layer 2 interface */
|
/* initialize layer 2 interface */
|
||||||
soft_device = alloc_netdev(sizeof(struct bat_priv) , "bat%d",
|
soft_device = alloc_netdev(sizeof(struct bat_priv) , "bat%d",
|
||||||
interface_setup);
|
interface_setup);
|
||||||
|
|
||||||
if (!soft_device) {
|
if (!soft_device) {
|
||||||
printk(KERN_ERR "batman-adv:"
|
pr_err("Unable to allocate the batman interface\n");
|
||||||
"Unable to allocate the batman interface\n");
|
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
|
|
||||||
retval = register_netdev(soft_device);
|
retval = register_netdev(soft_device);
|
||||||
|
|
||||||
if (retval < 0) {
|
if (retval < 0) {
|
||||||
printk(KERN_ERR "batman-adv:"
|
pr_err("Unable to register the batman interface: %i\n", retval);
|
||||||
"Unable to register the batman interface: %i\n", retval);
|
|
||||||
goto free_soft_device;
|
goto free_soft_device;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -117,15 +103,22 @@ int init_module(void)
|
||||||
if (retval < 0)
|
if (retval < 0)
|
||||||
goto unreg_soft_device;
|
goto unreg_soft_device;
|
||||||
|
|
||||||
|
retval = debugfs_add_meshif(soft_device);
|
||||||
|
|
||||||
|
if (retval < 0)
|
||||||
|
goto unreg_sysfs;
|
||||||
|
|
||||||
register_netdevice_notifier(&hard_if_notifier);
|
register_netdevice_notifier(&hard_if_notifier);
|
||||||
dev_add_pack(&batman_adv_packet_type);
|
dev_add_pack(&batman_adv_packet_type);
|
||||||
|
|
||||||
printk(KERN_INFO "batman-adv:"
|
pr_info("B.A.T.M.A.N. advanced %s%s (compatibility version %i) "
|
||||||
"B.A.T.M.A.N. advanced %s%s (compatibility version %i) loaded\n",
|
"loaded\n", SOURCE_VERSION, REVISION_VERSION_STR,
|
||||||
SOURCE_VERSION, REVISION_VERSION_STR, COMPAT_VERSION);
|
COMPAT_VERSION);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
unreg_sysfs:
|
||||||
|
sysfs_del_meshif(soft_device);
|
||||||
unreg_soft_device:
|
unreg_soft_device:
|
||||||
unregister_netdev(soft_device);
|
unregister_netdev(soft_device);
|
||||||
soft_device = NULL;
|
soft_device = NULL;
|
||||||
|
@ -138,14 +131,16 @@ end:
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
void cleanup_module(void)
|
static void __exit batman_exit(void)
|
||||||
{
|
{
|
||||||
deactivate_module();
|
deactivate_module();
|
||||||
|
|
||||||
|
debugfs_destroy();
|
||||||
unregister_netdevice_notifier(&hard_if_notifier);
|
unregister_netdevice_notifier(&hard_if_notifier);
|
||||||
hardif_remove_interfaces();
|
hardif_remove_interfaces();
|
||||||
|
|
||||||
if (soft_device) {
|
if (soft_device) {
|
||||||
|
debugfs_del_meshif(soft_device);
|
||||||
sysfs_del_meshif(soft_device);
|
sysfs_del_meshif(soft_device);
|
||||||
unregister_netdev(soft_device);
|
unregister_netdev(soft_device);
|
||||||
soft_device = NULL;
|
soft_device = NULL;
|
||||||
|
@ -157,7 +152,7 @@ void cleanup_module(void)
|
||||||
bat_event_workqueue = NULL;
|
bat_event_workqueue = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* activates the module, creates bat device, starts timer ... */
|
/* activates the module, starts timer ... */
|
||||||
void activate_module(void)
|
void activate_module(void)
|
||||||
{
|
{
|
||||||
if (originator_init() < 1)
|
if (originator_init() < 1)
|
||||||
|
@ -171,9 +166,6 @@ void activate_module(void)
|
||||||
|
|
||||||
hna_local_add(soft_device->dev_addr);
|
hna_local_add(soft_device->dev_addr);
|
||||||
|
|
||||||
if (bat_device_setup() < 1)
|
|
||||||
goto end;
|
|
||||||
|
|
||||||
if (vis_init() < 1)
|
if (vis_init() < 1)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
|
@ -182,8 +174,7 @@ void activate_module(void)
|
||||||
goto end;
|
goto end;
|
||||||
|
|
||||||
err:
|
err:
|
||||||
printk(KERN_ERR "batman-adv:"
|
pr_err("Unable to allocate memory for mesh information structures: "
|
||||||
"Unable to allocate memory for mesh information structures: "
|
|
||||||
"out of mem ?\n");
|
"out of mem ?\n");
|
||||||
deactivate_module();
|
deactivate_module();
|
||||||
end:
|
end:
|
||||||
|
@ -208,7 +199,6 @@ void deactivate_module(void)
|
||||||
hna_global_free();
|
hna_global_free();
|
||||||
|
|
||||||
synchronize_net();
|
synchronize_net();
|
||||||
bat_device_destroy();
|
|
||||||
|
|
||||||
synchronize_rcu();
|
synchronize_rcu();
|
||||||
atomic_set(&module_state, MODULE_INACTIVE);
|
atomic_set(&module_state, MODULE_INACTIVE);
|
||||||
|
@ -226,8 +216,7 @@ void dec_module_count(void)
|
||||||
|
|
||||||
int addr_to_string(char *buff, uint8_t *addr)
|
int addr_to_string(char *buff, uint8_t *addr)
|
||||||
{
|
{
|
||||||
return sprintf(buff, MAC_FMT,
|
return sprintf(buff, "%pM", addr);
|
||||||
addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* returns 1 if they are the same originator */
|
/* returns 1 if they are the same originator */
|
||||||
|
@ -284,6 +273,9 @@ int is_mcast(uint8_t *addr)
|
||||||
return *addr & 0x01;
|
return *addr & 0x01;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
module_init(batman_init);
|
||||||
|
module_exit(batman_exit);
|
||||||
|
|
||||||
MODULE_LICENSE("GPL");
|
MODULE_LICENSE("GPL");
|
||||||
|
|
||||||
MODULE_AUTHOR(DRIVER_AUTHOR);
|
MODULE_AUTHOR(DRIVER_AUTHOR);
|
||||||
|
|
|
@ -19,6 +19,9 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#ifndef _NET_BATMAN_ADV_MAIN_H_
|
||||||
|
#define _NET_BATMAN_ADV_MAIN_H_
|
||||||
|
|
||||||
/* Kernel Programming */
|
/* Kernel Programming */
|
||||||
#define LINUX
|
#define LINUX
|
||||||
|
|
||||||
|
@ -27,7 +30,7 @@
|
||||||
#define DRIVER_DESC "B.A.T.M.A.N. advanced"
|
#define DRIVER_DESC "B.A.T.M.A.N. advanced"
|
||||||
#define DRIVER_DEVICE "batman-adv"
|
#define DRIVER_DEVICE "batman-adv"
|
||||||
|
|
||||||
#define SOURCE_VERSION "0.2.2-beta"
|
#define SOURCE_VERSION "maint"
|
||||||
|
|
||||||
|
|
||||||
/* B.A.T.M.A.N. parameters */
|
/* B.A.T.M.A.N. parameters */
|
||||||
|
@ -36,10 +39,10 @@
|
||||||
#define JITTER 20
|
#define JITTER 20
|
||||||
#define TTL 50 /* Time To Live of broadcast messages */
|
#define TTL 50 /* Time To Live of broadcast messages */
|
||||||
|
|
||||||
#define PURGE_TIMEOUT 200000 /* purge originators after time in ms if no
|
#define PURGE_TIMEOUT 200 /* purge originators after time in seconds if no
|
||||||
* valid packet comes in -> TODO: check
|
* valid packet comes in -> TODO: check
|
||||||
* influence on TQ_LOCAL_WINDOW_SIZE */
|
* influence on TQ_LOCAL_WINDOW_SIZE */
|
||||||
#define LOCAL_HNA_TIMEOUT 3600000
|
#define LOCAL_HNA_TIMEOUT 3600 /* in seconds */
|
||||||
|
|
||||||
#define TQ_LOCAL_WINDOW_SIZE 64 /* sliding packet range of received originator
|
#define TQ_LOCAL_WINDOW_SIZE 64 /* sliding packet range of received originator
|
||||||
* messages in squence numbers (should be a
|
* messages in squence numbers (should be a
|
||||||
|
@ -57,13 +60,20 @@
|
||||||
#define LOG_BUF_LEN 8192 /* has to be a power of 2 */
|
#define LOG_BUF_LEN 8192 /* has to be a power of 2 */
|
||||||
#define ETH_STR_LEN 20
|
#define ETH_STR_LEN 20
|
||||||
|
|
||||||
|
#define VIS_INTERVAL 5000 /* 5 seconds */
|
||||||
|
|
||||||
|
/* how much worse secondary interfaces may be to
|
||||||
|
* to be considered as bonding candidates */
|
||||||
|
|
||||||
|
#define BONDING_TQ_THRESHOLD 50
|
||||||
|
|
||||||
#define MAX_AGGREGATION_BYTES 512 /* should not be bigger than 512 bytes or
|
#define MAX_AGGREGATION_BYTES 512 /* should not be bigger than 512 bytes or
|
||||||
* change the size of
|
* change the size of
|
||||||
* forw_packet->direct_link_flags */
|
* forw_packet->direct_link_flags */
|
||||||
#define MAX_AGGREGATION_MS 100
|
#define MAX_AGGREGATION_MS 100
|
||||||
|
|
||||||
#define RESET_PROTECTION_MS 30000
|
#define RESET_PROTECTION_MS 30000
|
||||||
#define EXPECTED_SEQNO_RANGE 4096
|
#define EXPECTED_SEQNO_RANGE 65536
|
||||||
/* don't reset again within 30 seconds */
|
/* don't reset again within 30 seconds */
|
||||||
|
|
||||||
#define MODULE_INACTIVE 0
|
#define MODULE_INACTIVE 0
|
||||||
|
@ -76,25 +86,16 @@
|
||||||
/*
|
/*
|
||||||
* Debug Messages
|
* Debug Messages
|
||||||
*/
|
*/
|
||||||
|
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt /* Append 'batman-adv: ' before
|
||||||
|
* kernel messages */
|
||||||
|
|
||||||
#define DBG_BATMAN 1 /* all messages related to routing / flooding /
|
#define DBG_BATMAN 1 /* all messages related to routing / flooding /
|
||||||
* broadcasting / etc */
|
* broadcasting / etc */
|
||||||
#define DBG_ROUTES 2 /* route or hna added / changed / deleted */
|
#define DBG_ROUTES 2 /* route or hna added / changed / deleted */
|
||||||
|
#define DBG_ALL 3
|
||||||
|
|
||||||
#ifdef CONFIG_BATMAN_ADV_DEBUG
|
#define LOG_BUF_LEN 8192 /* has to be a power of 2 */
|
||||||
extern int debug;
|
|
||||||
|
|
||||||
extern int bat_debug_type(int type);
|
|
||||||
#define bat_dbg(type, fmt, arg...) do { \
|
|
||||||
if (bat_debug_type(type)) \
|
|
||||||
printk(KERN_DEBUG "batman-adv:" fmt, ## arg); \
|
|
||||||
} \
|
|
||||||
while (0)
|
|
||||||
#else /* !CONFIG_BATMAN_ADV_DEBUG */
|
|
||||||
#define bat_dbg(type, fmt, arg...) do { \
|
|
||||||
} \
|
|
||||||
while (0)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Vis
|
* Vis
|
||||||
|
@ -117,6 +118,7 @@ extern int bat_debug_type(int type);
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
#include <net/sock.h> /* struct sock */
|
#include <net/sock.h> /* struct sock */
|
||||||
#include <linux/jiffies.h>
|
#include <linux/jiffies.h>
|
||||||
|
#include <linux/seq_file.h>
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
|
|
||||||
#ifndef REVISION_VERSION
|
#ifndef REVISION_VERSION
|
||||||
|
@ -134,14 +136,13 @@ extern spinlock_t orig_hash_lock;
|
||||||
extern spinlock_t forw_bat_list_lock;
|
extern spinlock_t forw_bat_list_lock;
|
||||||
extern spinlock_t forw_bcast_list_lock;
|
extern spinlock_t forw_bcast_list_lock;
|
||||||
|
|
||||||
extern atomic_t vis_interval;
|
|
||||||
extern atomic_t bcast_queue_left;
|
extern atomic_t bcast_queue_left;
|
||||||
extern atomic_t batman_queue_left;
|
extern atomic_t batman_queue_left;
|
||||||
extern int16_t num_hna;
|
extern int16_t num_hna;
|
||||||
|
|
||||||
extern struct net_device *soft_device;
|
extern struct net_device *soft_device;
|
||||||
|
|
||||||
extern unsigned char broadcastAddr[];
|
extern unsigned char broadcast_addr[];
|
||||||
extern atomic_t module_state;
|
extern atomic_t module_state;
|
||||||
extern struct workqueue_struct *bat_event_workqueue;
|
extern struct workqueue_struct *bat_event_workqueue;
|
||||||
|
|
||||||
|
@ -155,3 +156,44 @@ int choose_orig(void *data, int32_t size);
|
||||||
int is_my_mac(uint8_t *addr);
|
int is_my_mac(uint8_t *addr);
|
||||||
int is_bcast(uint8_t *addr);
|
int is_bcast(uint8_t *addr);
|
||||||
int is_mcast(uint8_t *addr);
|
int is_mcast(uint8_t *addr);
|
||||||
|
|
||||||
|
#ifdef CONFIG_BATMAN_ADV_DEBUG
|
||||||
|
extern int debug_log(struct bat_priv *bat_priv, char *fmt, ...);
|
||||||
|
|
||||||
|
#define bat_dbg(type, bat_priv, fmt, arg...) \
|
||||||
|
do { \
|
||||||
|
if (atomic_read(&bat_priv->log_level) & type) \
|
||||||
|
debug_log(bat_priv, fmt, ## arg); \
|
||||||
|
} \
|
||||||
|
while (0)
|
||||||
|
#else /* !CONFIG_BATMAN_ADV_DEBUG */
|
||||||
|
static inline void bat_dbg(char type __attribute__((unused)),
|
||||||
|
struct bat_priv *bat_priv __attribute__((unused)),
|
||||||
|
char *fmt __attribute__((unused)), ...)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define bat_warning(net_dev, fmt, arg...) \
|
||||||
|
do { \
|
||||||
|
struct net_device *_netdev = (net_dev); \
|
||||||
|
struct bat_priv *_batpriv = netdev_priv(_netdev); \
|
||||||
|
bat_dbg(DBG_ALL, _batpriv, fmt, ## arg); \
|
||||||
|
pr_warning("%s: " fmt, _netdev->name, ## arg); \
|
||||||
|
} while (0)
|
||||||
|
#define bat_info(net_dev, fmt, arg...) \
|
||||||
|
do { \
|
||||||
|
struct net_device *_netdev = (net_dev); \
|
||||||
|
struct bat_priv *_batpriv = netdev_priv(_netdev); \
|
||||||
|
bat_dbg(DBG_ALL, _batpriv, fmt, ## arg); \
|
||||||
|
pr_info("%s: " fmt, _netdev->name, ## arg); \
|
||||||
|
} while (0)
|
||||||
|
#define bat_err(net_dev, fmt, arg...) \
|
||||||
|
do { \
|
||||||
|
struct net_device *_netdev = (net_dev); \
|
||||||
|
struct bat_priv *_batpriv = netdev_priv(_netdev); \
|
||||||
|
bat_dbg(DBG_ALL, _batpriv, fmt, ## arg); \
|
||||||
|
pr_err("%s: " fmt, _netdev->name, ## arg); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#endif /* _NET_BATMAN_ADV_MAIN_H_ */
|
||||||
|
|
|
@ -56,28 +56,16 @@ err:
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void originator_free(void)
|
|
||||||
{
|
|
||||||
unsigned long flags;
|
|
||||||
|
|
||||||
if (!orig_hash)
|
|
||||||
return;
|
|
||||||
|
|
||||||
cancel_delayed_work_sync(&purge_orig_wq);
|
|
||||||
|
|
||||||
spin_lock_irqsave(&orig_hash_lock, flags);
|
|
||||||
hash_delete(orig_hash, free_orig_node);
|
|
||||||
orig_hash = NULL;
|
|
||||||
spin_unlock_irqrestore(&orig_hash_lock, flags);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct neigh_node *
|
struct neigh_node *
|
||||||
create_neighbor(struct orig_node *orig_node, struct orig_node *orig_neigh_node,
|
create_neighbor(struct orig_node *orig_node, struct orig_node *orig_neigh_node,
|
||||||
uint8_t *neigh, struct batman_if *if_incoming)
|
uint8_t *neigh, struct batman_if *if_incoming)
|
||||||
{
|
{
|
||||||
|
/* FIXME: each orig_node->batman_if will be attached to a softif */
|
||||||
|
struct bat_priv *bat_priv = netdev_priv(soft_device);
|
||||||
struct neigh_node *neigh_node;
|
struct neigh_node *neigh_node;
|
||||||
|
|
||||||
bat_dbg(DBG_BATMAN, "Creating new last-hop neighbor of originator\n");
|
bat_dbg(DBG_BATMAN, bat_priv,
|
||||||
|
"Creating new last-hop neighbor of originator\n");
|
||||||
|
|
||||||
neigh_node = kzalloc(sizeof(struct neigh_node), GFP_ATOMIC);
|
neigh_node = kzalloc(sizeof(struct neigh_node), GFP_ATOMIC);
|
||||||
if (!neigh_node)
|
if (!neigh_node)
|
||||||
|
@ -93,7 +81,7 @@ create_neighbor(struct orig_node *orig_node, struct orig_node *orig_neigh_node,
|
||||||
return neigh_node;
|
return neigh_node;
|
||||||
}
|
}
|
||||||
|
|
||||||
void free_orig_node(void *data)
|
static void free_orig_node(void *data)
|
||||||
{
|
{
|
||||||
struct list_head *list_pos, *list_pos_tmp;
|
struct list_head *list_pos, *list_pos_tmp;
|
||||||
struct neigh_node *neigh_node;
|
struct neigh_node *neigh_node;
|
||||||
|
@ -114,6 +102,21 @@ void free_orig_node(void *data)
|
||||||
kfree(orig_node);
|
kfree(orig_node);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void originator_free(void)
|
||||||
|
{
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
|
if (!orig_hash)
|
||||||
|
return;
|
||||||
|
|
||||||
|
cancel_delayed_work_sync(&purge_orig_wq);
|
||||||
|
|
||||||
|
spin_lock_irqsave(&orig_hash_lock, flags);
|
||||||
|
hash_delete(orig_hash, free_orig_node);
|
||||||
|
orig_hash = NULL;
|
||||||
|
spin_unlock_irqrestore(&orig_hash_lock, flags);
|
||||||
|
}
|
||||||
|
|
||||||
/* this function finds or creates an originator entry for the given
|
/* this function finds or creates an originator entry for the given
|
||||||
* address if it does not exits */
|
* address if it does not exits */
|
||||||
struct orig_node *get_orig_node(uint8_t *addr)
|
struct orig_node *get_orig_node(uint8_t *addr)
|
||||||
|
@ -129,7 +132,8 @@ struct orig_node *get_orig_node(uint8_t *addr)
|
||||||
if (orig_node != NULL)
|
if (orig_node != NULL)
|
||||||
return orig_node;
|
return orig_node;
|
||||||
|
|
||||||
bat_dbg(DBG_BATMAN, "Creating new originator: %pM\n", addr);
|
bat_dbg(DBG_BATMAN, bat_priv,
|
||||||
|
"Creating new originator: %pM\n", addr);
|
||||||
|
|
||||||
orig_node = kzalloc(sizeof(struct orig_node), GFP_ATOMIC);
|
orig_node = kzalloc(sizeof(struct orig_node), GFP_ATOMIC);
|
||||||
if (!orig_node)
|
if (!orig_node)
|
||||||
|
@ -163,8 +167,8 @@ struct orig_node *get_orig_node(uint8_t *addr)
|
||||||
swaphash = hash_resize(orig_hash, orig_hash->size * 2);
|
swaphash = hash_resize(orig_hash, orig_hash->size * 2);
|
||||||
|
|
||||||
if (swaphash == NULL)
|
if (swaphash == NULL)
|
||||||
printk(KERN_ERR
|
bat_err(soft_device,
|
||||||
"batman-adv:Couldn't resize orig hash table\n");
|
"Couldn't resize orig hash table\n");
|
||||||
else
|
else
|
||||||
orig_hash = swaphash;
|
orig_hash = swaphash;
|
||||||
}
|
}
|
||||||
|
@ -182,6 +186,8 @@ free_orig_node:
|
||||||
static bool purge_orig_neighbors(struct orig_node *orig_node,
|
static bool purge_orig_neighbors(struct orig_node *orig_node,
|
||||||
struct neigh_node **best_neigh_node)
|
struct neigh_node **best_neigh_node)
|
||||||
{
|
{
|
||||||
|
/* FIXME: each orig_node->batman_if will be attached to a softif */
|
||||||
|
struct bat_priv *bat_priv = netdev_priv(soft_device);
|
||||||
struct list_head *list_pos, *list_pos_tmp;
|
struct list_head *list_pos, *list_pos_tmp;
|
||||||
struct neigh_node *neigh_node;
|
struct neigh_node *neigh_node;
|
||||||
bool neigh_purged = false;
|
bool neigh_purged = false;
|
||||||
|
@ -193,20 +199,19 @@ static bool purge_orig_neighbors(struct orig_node *orig_node,
|
||||||
neigh_node = list_entry(list_pos, struct neigh_node, list);
|
neigh_node = list_entry(list_pos, struct neigh_node, list);
|
||||||
|
|
||||||
if ((time_after(jiffies,
|
if ((time_after(jiffies,
|
||||||
(neigh_node->last_valid +
|
neigh_node->last_valid + PURGE_TIMEOUT * HZ)) ||
|
||||||
((PURGE_TIMEOUT * HZ) / 1000)))) ||
|
|
||||||
(neigh_node->if_incoming->if_status ==
|
(neigh_node->if_incoming->if_status ==
|
||||||
IF_TO_BE_REMOVED)) {
|
IF_TO_BE_REMOVED)) {
|
||||||
|
|
||||||
if (neigh_node->if_incoming->if_status ==
|
if (neigh_node->if_incoming->if_status ==
|
||||||
IF_TO_BE_REMOVED)
|
IF_TO_BE_REMOVED)
|
||||||
bat_dbg(DBG_BATMAN,
|
bat_dbg(DBG_BATMAN, bat_priv,
|
||||||
"neighbor purge: originator %pM, "
|
"neighbor purge: originator %pM, "
|
||||||
"neighbor: %pM, iface: %s\n",
|
"neighbor: %pM, iface: %s\n",
|
||||||
orig_node->orig, neigh_node->addr,
|
orig_node->orig, neigh_node->addr,
|
||||||
neigh_node->if_incoming->dev);
|
neigh_node->if_incoming->dev);
|
||||||
else
|
else
|
||||||
bat_dbg(DBG_BATMAN,
|
bat_dbg(DBG_BATMAN, bat_priv,
|
||||||
"neighbor timeout: originator %pM, "
|
"neighbor timeout: originator %pM, "
|
||||||
"neighbor: %pM, last_valid: %lu\n",
|
"neighbor: %pM, last_valid: %lu\n",
|
||||||
orig_node->orig, neigh_node->addr,
|
orig_node->orig, neigh_node->addr,
|
||||||
|
@ -226,21 +231,26 @@ static bool purge_orig_neighbors(struct orig_node *orig_node,
|
||||||
|
|
||||||
static bool purge_orig_node(struct orig_node *orig_node)
|
static bool purge_orig_node(struct orig_node *orig_node)
|
||||||
{
|
{
|
||||||
|
/* FIXME: each batman_if will be attached to a softif */
|
||||||
|
struct bat_priv *bat_priv = netdev_priv(soft_device);
|
||||||
struct neigh_node *best_neigh_node;
|
struct neigh_node *best_neigh_node;
|
||||||
|
|
||||||
if (time_after(jiffies,
|
if (time_after(jiffies,
|
||||||
(orig_node->last_valid +
|
orig_node->last_valid + 2 * PURGE_TIMEOUT * HZ)) {
|
||||||
((2 * PURGE_TIMEOUT * HZ) / 1000)))) {
|
|
||||||
|
|
||||||
bat_dbg(DBG_BATMAN,
|
bat_dbg(DBG_BATMAN, bat_priv,
|
||||||
"Originator timeout: originator %pM, last_valid %lu\n",
|
"Originator timeout: originator %pM, last_valid %lu\n",
|
||||||
orig_node->orig, (orig_node->last_valid / HZ));
|
orig_node->orig, (orig_node->last_valid / HZ));
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
if (purge_orig_neighbors(orig_node, &best_neigh_node))
|
if (purge_orig_neighbors(orig_node, &best_neigh_node)) {
|
||||||
update_routes(orig_node, best_neigh_node,
|
update_routes(orig_node, best_neigh_node,
|
||||||
orig_node->hna_buff,
|
orig_node->hna_buff,
|
||||||
orig_node->hna_buff_len);
|
orig_node->hna_buff_len);
|
||||||
|
/* update bonding candidates, we could have lost
|
||||||
|
* some candidates. */
|
||||||
|
update_bonding_candidates(bat_priv, orig_node);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
@ -271,49 +281,41 @@ void purge_orig(struct work_struct *work)
|
||||||
start_purge_timer();
|
start_purge_timer();
|
||||||
}
|
}
|
||||||
|
|
||||||
ssize_t orig_fill_buffer_text(struct net_device *net_dev, char *buff,
|
int orig_seq_print_text(struct seq_file *seq, void *offset)
|
||||||
size_t count, loff_t off)
|
|
||||||
{
|
{
|
||||||
HASHIT(hashit);
|
HASHIT(hashit);
|
||||||
|
struct net_device *net_dev = (struct net_device *)seq->private;
|
||||||
struct bat_priv *bat_priv = netdev_priv(net_dev);
|
struct bat_priv *bat_priv = netdev_priv(net_dev);
|
||||||
struct orig_node *orig_node;
|
struct orig_node *orig_node;
|
||||||
struct neigh_node *neigh_node;
|
struct neigh_node *neigh_node;
|
||||||
size_t hdr_len, tmp_len;
|
int batman_count = 0;
|
||||||
int batman_count = 0, bytes_written = 0;
|
int last_seen_secs;
|
||||||
|
int last_seen_msecs;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
char orig_str[ETH_STR_LEN], router_str[ETH_STR_LEN];
|
char orig_str[ETH_STR_LEN], router_str[ETH_STR_LEN];
|
||||||
|
|
||||||
if (!bat_priv->primary_if) {
|
if ((!bat_priv->primary_if) ||
|
||||||
if (off == 0)
|
(bat_priv->primary_if->if_status != IF_ACTIVE)) {
|
||||||
return sprintf(buff,
|
if (!bat_priv->primary_if)
|
||||||
"BATMAN mesh %s disabled - "
|
return seq_printf(seq, "BATMAN mesh %s disabled - "
|
||||||
"please specify interfaces to enable it\n",
|
"please specify interfaces to enable it\n",
|
||||||
net_dev->name);
|
net_dev->name);
|
||||||
|
|
||||||
return 0;
|
return seq_printf(seq, "BATMAN mesh %s "
|
||||||
}
|
|
||||||
|
|
||||||
if (bat_priv->primary_if->if_status != IF_ACTIVE && off == 0)
|
|
||||||
return sprintf(buff,
|
|
||||||
"BATMAN mesh %s "
|
|
||||||
"disabled - primary interface not active\n",
|
"disabled - primary interface not active\n",
|
||||||
net_dev->name);
|
net_dev->name);
|
||||||
else if (bat_priv->primary_if->if_status != IF_ACTIVE)
|
}
|
||||||
return 0;
|
|
||||||
|
|
||||||
rcu_read_lock();
|
rcu_read_lock();
|
||||||
hdr_len = sprintf(buff,
|
seq_printf(seq, "[B.A.T.M.A.N. adv %s%s, MainIF/MAC: %s/%s (%s)]\n",
|
||||||
" %-14s (%s/%i) %17s [%10s]: %20s "
|
SOURCE_VERSION, REVISION_VERSION_STR,
|
||||||
"... [B.A.T.M.A.N. adv %s%s, MainIF/MAC: %s/%s (%s)]\n",
|
|
||||||
"Originator", "#", TQ_MAX_VALUE, "Nexthop", "outgoingIF",
|
|
||||||
"Potential nexthops", SOURCE_VERSION, REVISION_VERSION_STR,
|
|
||||||
bat_priv->primary_if->dev, bat_priv->primary_if->addr_str,
|
bat_priv->primary_if->dev, bat_priv->primary_if->addr_str,
|
||||||
net_dev->name);
|
net_dev->name);
|
||||||
|
seq_printf(seq, " %-15s %s (%s/%i) %17s [%10s]: %20s ...\n",
|
||||||
|
"Originator", "last-seen", "#", TQ_MAX_VALUE, "Nexthop",
|
||||||
|
"outgoingIF", "Potential nexthops");
|
||||||
rcu_read_unlock();
|
rcu_read_unlock();
|
||||||
|
|
||||||
if (off < hdr_len)
|
|
||||||
bytes_written = hdr_len;
|
|
||||||
|
|
||||||
spin_lock_irqsave(&orig_hash_lock, flags);
|
spin_lock_irqsave(&orig_hash_lock, flags);
|
||||||
|
|
||||||
while (hash_iterate(orig_hash, &hashit)) {
|
while (hash_iterate(orig_hash, &hashit)) {
|
||||||
|
@ -326,44 +328,34 @@ ssize_t orig_fill_buffer_text(struct net_device *net_dev, char *buff,
|
||||||
if (orig_node->router->tq_avg == 0)
|
if (orig_node->router->tq_avg == 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* estimated line length */
|
|
||||||
if (count < bytes_written + 200)
|
|
||||||
break;
|
|
||||||
|
|
||||||
addr_to_string(orig_str, orig_node->orig);
|
addr_to_string(orig_str, orig_node->orig);
|
||||||
addr_to_string(router_str, orig_node->router->addr);
|
addr_to_string(router_str, orig_node->router->addr);
|
||||||
|
last_seen_secs = jiffies_to_msecs(jiffies -
|
||||||
|
orig_node->last_valid) / 1000;
|
||||||
|
last_seen_msecs = jiffies_to_msecs(jiffies -
|
||||||
|
orig_node->last_valid) % 1000;
|
||||||
|
|
||||||
tmp_len = sprintf(buff + bytes_written,
|
seq_printf(seq, "%-17s %4i.%03is (%3i) %17s [%10s]:",
|
||||||
"%-17s (%3i) %17s [%10s]:",
|
orig_str, last_seen_secs, last_seen_msecs,
|
||||||
orig_str, orig_node->router->tq_avg,
|
orig_node->router->tq_avg, router_str,
|
||||||
router_str,
|
|
||||||
orig_node->router->if_incoming->dev);
|
orig_node->router->if_incoming->dev);
|
||||||
|
|
||||||
list_for_each_entry(neigh_node, &orig_node->neigh_list, list) {
|
list_for_each_entry(neigh_node, &orig_node->neigh_list, list) {
|
||||||
addr_to_string(orig_str, neigh_node->addr);
|
addr_to_string(orig_str, neigh_node->addr);
|
||||||
tmp_len += sprintf(buff + bytes_written + tmp_len,
|
seq_printf(seq, " %17s (%3i)", orig_str,
|
||||||
" %17s (%3i)", orig_str,
|
|
||||||
neigh_node->tq_avg);
|
neigh_node->tq_avg);
|
||||||
}
|
}
|
||||||
|
|
||||||
tmp_len += sprintf(buff + bytes_written + tmp_len, "\n");
|
seq_printf(seq, "\n");
|
||||||
|
|
||||||
batman_count++;
|
batman_count++;
|
||||||
hdr_len += tmp_len;
|
|
||||||
|
|
||||||
if (off >= hdr_len)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
bytes_written += tmp_len;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
spin_unlock_irqrestore(&orig_hash_lock, flags);
|
spin_unlock_irqrestore(&orig_hash_lock, flags);
|
||||||
|
|
||||||
if ((batman_count == 0) && (off == 0))
|
if ((batman_count == 0))
|
||||||
bytes_written += sprintf(buff + bytes_written,
|
seq_printf(seq, "No batman nodes in range ...\n");
|
||||||
"No batman nodes in range ...\n");
|
|
||||||
|
|
||||||
return bytes_written;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int orig_node_add_if(struct orig_node *orig_node, int max_if_num)
|
static int orig_node_add_if(struct orig_node *orig_node, int max_if_num)
|
||||||
|
@ -373,8 +365,7 @@ static int orig_node_add_if(struct orig_node *orig_node, int max_if_num)
|
||||||
data_ptr = kmalloc(max_if_num * sizeof(TYPE_OF_WORD) * NUM_WORDS,
|
data_ptr = kmalloc(max_if_num * sizeof(TYPE_OF_WORD) * NUM_WORDS,
|
||||||
GFP_ATOMIC);
|
GFP_ATOMIC);
|
||||||
if (!data_ptr) {
|
if (!data_ptr) {
|
||||||
printk(KERN_ERR
|
pr_err("Can't resize orig: out of memory\n");
|
||||||
"batman-adv:Can't resize orig: out of memory\n");
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -385,8 +376,7 @@ static int orig_node_add_if(struct orig_node *orig_node, int max_if_num)
|
||||||
|
|
||||||
data_ptr = kmalloc(max_if_num * sizeof(uint8_t), GFP_ATOMIC);
|
data_ptr = kmalloc(max_if_num * sizeof(uint8_t), GFP_ATOMIC);
|
||||||
if (!data_ptr) {
|
if (!data_ptr) {
|
||||||
printk(KERN_ERR
|
pr_err("Can't resize orig: out of memory\n");
|
||||||
"batman-adv:Can't resize orig: out of memory\n");
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -435,8 +425,7 @@ static int orig_node_del_if(struct orig_node *orig_node,
|
||||||
chunk_size = sizeof(TYPE_OF_WORD) * NUM_WORDS;
|
chunk_size = sizeof(TYPE_OF_WORD) * NUM_WORDS;
|
||||||
data_ptr = kmalloc(max_if_num * chunk_size, GFP_ATOMIC);
|
data_ptr = kmalloc(max_if_num * chunk_size, GFP_ATOMIC);
|
||||||
if (!data_ptr) {
|
if (!data_ptr) {
|
||||||
printk(KERN_ERR
|
pr_err("Can't resize orig: out of memory\n");
|
||||||
"batman-adv:Can't resize orig: out of memory\n");
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -457,8 +446,7 @@ free_bcast_own:
|
||||||
|
|
||||||
data_ptr = kmalloc(max_if_num * sizeof(uint8_t), GFP_ATOMIC);
|
data_ptr = kmalloc(max_if_num * sizeof(uint8_t), GFP_ATOMIC);
|
||||||
if (!data_ptr) {
|
if (!data_ptr) {
|
||||||
printk(KERN_ERR
|
pr_err("Can't resize orig: out of memory\n");
|
||||||
"batman-adv:Can't resize orig: out of memory\n");
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,16 +19,18 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#ifndef _NET_BATMAN_ADV_ORIGINATOR_H_
|
||||||
|
#define _NET_BATMAN_ADV_ORIGINATOR_H_
|
||||||
|
|
||||||
int originator_init(void);
|
int originator_init(void);
|
||||||
void free_orig_node(void *data);
|
|
||||||
void originator_free(void);
|
void originator_free(void);
|
||||||
void purge_orig(struct work_struct *work);
|
void purge_orig(struct work_struct *work);
|
||||||
struct orig_node *orig_find(char *mac);
|
|
||||||
struct orig_node *get_orig_node(uint8_t *addr);
|
struct orig_node *get_orig_node(uint8_t *addr);
|
||||||
struct neigh_node *
|
struct neigh_node *
|
||||||
create_neighbor(struct orig_node *orig_node, struct orig_node *orig_neigh_node,
|
create_neighbor(struct orig_node *orig_node, struct orig_node *orig_neigh_node,
|
||||||
uint8_t *neigh, struct batman_if *if_incoming);
|
uint8_t *neigh, struct batman_if *if_incoming);
|
||||||
ssize_t orig_fill_buffer_text(struct net_device *net_dev, char *buff,
|
int orig_seq_print_text(struct seq_file *seq, void *offset);
|
||||||
size_t count, loff_t off);
|
|
||||||
int orig_hash_add_if(struct batman_if *batman_if, int max_if_num);
|
int orig_hash_add_if(struct batman_if *batman_if, int max_if_num);
|
||||||
int orig_hash_del_if(struct batman_if *batman_if, int max_if_num);
|
int orig_hash_del_if(struct batman_if *batman_if, int max_if_num);
|
||||||
|
|
||||||
|
#endif /* _NET_BATMAN_ADV_ORIGINATOR_H_ */
|
||||||
|
|
|
@ -19,6 +19,9 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#ifndef _NET_BATMAN_ADV_PACKET_H_
|
||||||
|
#define _NET_BATMAN_ADV_PACKET_H_
|
||||||
|
|
||||||
#define ETH_P_BATMAN 0x4305 /* unofficial/not registered Ethertype */
|
#define ETH_P_BATMAN 0x4305 /* unofficial/not registered Ethertype */
|
||||||
|
|
||||||
#define BAT_PACKET 0x01
|
#define BAT_PACKET 0x01
|
||||||
|
@ -28,9 +31,10 @@
|
||||||
#define BAT_VIS 0x05
|
#define BAT_VIS 0x05
|
||||||
|
|
||||||
/* this file is included by batctl which needs these defines */
|
/* this file is included by batctl which needs these defines */
|
||||||
#define COMPAT_VERSION 8
|
#define COMPAT_VERSION 11
|
||||||
#define DIRECTLINK 0x40
|
#define DIRECTLINK 0x40
|
||||||
#define VIS_SERVER 0x20
|
#define VIS_SERVER 0x20
|
||||||
|
#define PRIMARIES_FIRST_HOP 0x10
|
||||||
|
|
||||||
/* ICMP message types */
|
/* ICMP message types */
|
||||||
#define ECHO_REPLY 0
|
#define ECHO_REPLY 0
|
||||||
|
@ -48,7 +52,7 @@ struct batman_packet {
|
||||||
uint8_t version; /* batman version field */
|
uint8_t version; /* batman version field */
|
||||||
uint8_t flags; /* 0x40: DIRECTLINK flag, 0x20 VIS_SERVER flag... */
|
uint8_t flags; /* 0x40: DIRECTLINK flag, 0x20 VIS_SERVER flag... */
|
||||||
uint8_t tq;
|
uint8_t tq;
|
||||||
uint16_t seqno;
|
uint32_t seqno;
|
||||||
uint8_t orig[6];
|
uint8_t orig[6];
|
||||||
uint8_t prev_sender[6];
|
uint8_t prev_sender[6];
|
||||||
uint8_t ttl;
|
uint8_t ttl;
|
||||||
|
@ -68,6 +72,23 @@ struct icmp_packet {
|
||||||
uint8_t uid;
|
uint8_t uid;
|
||||||
} __attribute__((packed));
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
#define BAT_RR_LEN 16
|
||||||
|
|
||||||
|
/* icmp_packet_rr must start with all fields from imcp_packet
|
||||||
|
as this is assumed by code that handles ICMP packets */
|
||||||
|
struct icmp_packet_rr {
|
||||||
|
uint8_t packet_type;
|
||||||
|
uint8_t version; /* batman version field */
|
||||||
|
uint8_t msg_type; /* see ICMP message types above */
|
||||||
|
uint8_t ttl;
|
||||||
|
uint8_t dst[6];
|
||||||
|
uint8_t orig[6];
|
||||||
|
uint16_t seqno;
|
||||||
|
uint8_t uid;
|
||||||
|
uint8_t rr_cur;
|
||||||
|
uint8_t rr[BAT_RR_LEN][ETH_ALEN];
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
struct unicast_packet {
|
struct unicast_packet {
|
||||||
uint8_t packet_type;
|
uint8_t packet_type;
|
||||||
uint8_t version; /* batman version field */
|
uint8_t version; /* batman version field */
|
||||||
|
@ -79,18 +100,21 @@ struct bcast_packet {
|
||||||
uint8_t packet_type;
|
uint8_t packet_type;
|
||||||
uint8_t version; /* batman version field */
|
uint8_t version; /* batman version field */
|
||||||
uint8_t orig[6];
|
uint8_t orig[6];
|
||||||
uint16_t seqno;
|
uint8_t ttl;
|
||||||
|
uint32_t seqno;
|
||||||
} __attribute__((packed));
|
} __attribute__((packed));
|
||||||
|
|
||||||
struct vis_packet {
|
struct vis_packet {
|
||||||
uint8_t packet_type;
|
uint8_t packet_type;
|
||||||
uint8_t version; /* batman version field */
|
uint8_t version; /* batman version field */
|
||||||
uint8_t vis_type; /* which type of vis-participant sent this? */
|
uint8_t vis_type; /* which type of vis-participant sent this? */
|
||||||
uint8_t seqno; /* sequence number */
|
|
||||||
uint8_t entries; /* number of entries behind this struct */
|
uint8_t entries; /* number of entries behind this struct */
|
||||||
|
uint32_t seqno; /* sequence number */
|
||||||
uint8_t ttl; /* TTL */
|
uint8_t ttl; /* TTL */
|
||||||
uint8_t vis_orig[6]; /* originator that informs about its
|
uint8_t vis_orig[6]; /* originator that informs about its
|
||||||
* neighbors */
|
* neighbors */
|
||||||
uint8_t target_orig[6]; /* who should receive this packet */
|
uint8_t target_orig[6]; /* who should receive this packet */
|
||||||
uint8_t sender_orig[6]; /* who sent or rebroadcasted this packet */
|
uint8_t sender_orig[6]; /* who sent or rebroadcasted this packet */
|
||||||
} __attribute__((packed));
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
#endif /* _NET_BATMAN_ADV_PACKET_H_ */
|
||||||
|
|
|
@ -19,5 +19,10 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#ifndef _NET_BATMAN_ADV_RING_BUFFER_H_
|
||||||
|
#define _NET_BATMAN_ADV_RING_BUFFER_H_
|
||||||
|
|
||||||
void ring_buffer_set(uint8_t lq_recv[], uint8_t *lq_index, uint8_t value);
|
void ring_buffer_set(uint8_t lq_recv[], uint8_t *lq_index, uint8_t value);
|
||||||
uint8_t ring_buffer_avg(uint8_t lq_recv[]);
|
uint8_t ring_buffer_avg(uint8_t lq_recv[]);
|
||||||
|
|
||||||
|
#endif /* _NET_BATMAN_ADV_RING_BUFFER_H_ */
|
||||||
|
|
|
@ -25,7 +25,7 @@
|
||||||
#include "hash.h"
|
#include "hash.h"
|
||||||
#include "soft-interface.h"
|
#include "soft-interface.h"
|
||||||
#include "hard-interface.h"
|
#include "hard-interface.h"
|
||||||
#include "device.h"
|
#include "icmp_socket.h"
|
||||||
#include "translation-table.h"
|
#include "translation-table.h"
|
||||||
#include "originator.h"
|
#include "originator.h"
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
|
@ -33,7 +33,7 @@
|
||||||
#include "vis.h"
|
#include "vis.h"
|
||||||
#include "aggregation.h"
|
#include "aggregation.h"
|
||||||
|
|
||||||
DECLARE_WAIT_QUEUE_HEAD(thread_wait);
|
static DECLARE_WAIT_QUEUE_HEAD(thread_wait);
|
||||||
|
|
||||||
void slide_own_bcast_window(struct batman_if *batman_if)
|
void slide_own_bcast_window(struct batman_if *batman_if)
|
||||||
{
|
{
|
||||||
|
@ -77,24 +77,27 @@ static void update_route(struct orig_node *orig_node,
|
||||||
struct neigh_node *neigh_node,
|
struct neigh_node *neigh_node,
|
||||||
unsigned char *hna_buff, int hna_buff_len)
|
unsigned char *hna_buff, int hna_buff_len)
|
||||||
{
|
{
|
||||||
|
/* FIXME: each orig_node->batman_if will be attached to a softif */
|
||||||
|
struct bat_priv *bat_priv = netdev_priv(soft_device);
|
||||||
|
|
||||||
/* route deleted */
|
/* route deleted */
|
||||||
if ((orig_node->router != NULL) && (neigh_node == NULL)) {
|
if ((orig_node->router != NULL) && (neigh_node == NULL)) {
|
||||||
|
|
||||||
bat_dbg(DBG_ROUTES, "Deleting route towards: %pM\n",
|
bat_dbg(DBG_ROUTES, bat_priv, "Deleting route towards: %pM\n",
|
||||||
orig_node->orig);
|
orig_node->orig);
|
||||||
hna_global_del_orig(orig_node, "originator timed out");
|
hna_global_del_orig(orig_node, "originator timed out");
|
||||||
|
|
||||||
/* route added */
|
/* route added */
|
||||||
} else if ((orig_node->router == NULL) && (neigh_node != NULL)) {
|
} else if ((orig_node->router == NULL) && (neigh_node != NULL)) {
|
||||||
|
|
||||||
bat_dbg(DBG_ROUTES,
|
bat_dbg(DBG_ROUTES, bat_priv,
|
||||||
"Adding route towards: %pM (via %pM)\n",
|
"Adding route towards: %pM (via %pM)\n",
|
||||||
orig_node->orig, neigh_node->addr);
|
orig_node->orig, neigh_node->addr);
|
||||||
hna_global_add_orig(orig_node, hna_buff, hna_buff_len);
|
hna_global_add_orig(orig_node, hna_buff, hna_buff_len);
|
||||||
|
|
||||||
/* route changed */
|
/* route changed */
|
||||||
} else {
|
} else {
|
||||||
bat_dbg(DBG_ROUTES,
|
bat_dbg(DBG_ROUTES, bat_priv,
|
||||||
"Changing route towards: %pM "
|
"Changing route towards: %pM "
|
||||||
"(now via %pM - was via %pM)\n",
|
"(now via %pM - was via %pM)\n",
|
||||||
orig_node->orig, neigh_node->addr,
|
orig_node->orig, neigh_node->addr,
|
||||||
|
@ -120,11 +123,13 @@ void update_routes(struct orig_node *orig_node,
|
||||||
update_HNA(orig_node, hna_buff, hna_buff_len);
|
update_HNA(orig_node, hna_buff, hna_buff_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int isBidirectionalNeigh(struct orig_node *orig_node,
|
static int is_bidirectional_neigh(struct orig_node *orig_node,
|
||||||
struct orig_node *orig_neigh_node,
|
struct orig_node *orig_neigh_node,
|
||||||
struct batman_packet *batman_packet,
|
struct batman_packet *batman_packet,
|
||||||
struct batman_if *if_incoming)
|
struct batman_if *if_incoming)
|
||||||
{
|
{
|
||||||
|
/* FIXME: each orig_node->batman_if will be attached to a softif */
|
||||||
|
struct bat_priv *bat_priv = netdev_priv(soft_device);
|
||||||
struct neigh_node *neigh_node = NULL, *tmp_neigh_node = NULL;
|
struct neigh_node *neigh_node = NULL, *tmp_neigh_node = NULL;
|
||||||
unsigned char total_count;
|
unsigned char total_count;
|
||||||
|
|
||||||
|
@ -211,7 +216,7 @@ static int isBidirectionalNeigh(struct orig_node *orig_node,
|
||||||
orig_neigh_node->tq_asym_penalty) /
|
orig_neigh_node->tq_asym_penalty) /
|
||||||
(TQ_MAX_VALUE * TQ_MAX_VALUE));
|
(TQ_MAX_VALUE * TQ_MAX_VALUE));
|
||||||
|
|
||||||
bat_dbg(DBG_BATMAN,
|
bat_dbg(DBG_BATMAN, bat_priv,
|
||||||
"bidirectional: "
|
"bidirectional: "
|
||||||
"orig = %-15pM neigh = %-15pM => own_bcast = %2i, "
|
"orig = %-15pM neigh = %-15pM => own_bcast = %2i, "
|
||||||
"real recv = %2i, local tq: %3i, asym_penalty: %3i, "
|
"real recv = %2i, local tq: %3i, asym_penalty: %3i, "
|
||||||
|
@ -234,10 +239,12 @@ static void update_orig(struct orig_node *orig_node, struct ethhdr *ethhdr,
|
||||||
unsigned char *hna_buff, int hna_buff_len,
|
unsigned char *hna_buff, int hna_buff_len,
|
||||||
char is_duplicate)
|
char is_duplicate)
|
||||||
{
|
{
|
||||||
|
/* FIXME: get bat_priv */
|
||||||
|
struct bat_priv *bat_priv = netdev_priv(soft_device);
|
||||||
struct neigh_node *neigh_node = NULL, *tmp_neigh_node = NULL;
|
struct neigh_node *neigh_node = NULL, *tmp_neigh_node = NULL;
|
||||||
int tmp_hna_buff_len;
|
int tmp_hna_buff_len;
|
||||||
|
|
||||||
bat_dbg(DBG_BATMAN, "update_originator(): "
|
bat_dbg(DBG_BATMAN, bat_priv, "update_originator(): "
|
||||||
"Searching and updating originator entry of received packet\n");
|
"Searching and updating originator entry of received packet\n");
|
||||||
|
|
||||||
list_for_each_entry(tmp_neigh_node, &orig_node->neigh_list, list) {
|
list_for_each_entry(tmp_neigh_node, &orig_node->neigh_list, list) {
|
||||||
|
@ -269,7 +276,7 @@ static void update_orig(struct orig_node *orig_node, struct ethhdr *ethhdr,
|
||||||
if (!neigh_node)
|
if (!neigh_node)
|
||||||
return;
|
return;
|
||||||
} else
|
} else
|
||||||
bat_dbg(DBG_BATMAN,
|
bat_dbg(DBG_BATMAN, bat_priv,
|
||||||
"Updating existing last-hop neighbor of originator\n");
|
"Updating existing last-hop neighbor of originator\n");
|
||||||
|
|
||||||
orig_node->flags = batman_packet->flags;
|
orig_node->flags = batman_packet->flags;
|
||||||
|
@ -318,16 +325,19 @@ update_hna:
|
||||||
* 0 if the packet is to be accepted
|
* 0 if the packet is to be accepted
|
||||||
* 1 if the packet is to be ignored.
|
* 1 if the packet is to be ignored.
|
||||||
*/
|
*/
|
||||||
static int window_protected(int16_t seq_num_diff,
|
static int window_protected(int32_t seq_num_diff,
|
||||||
unsigned long *last_reset)
|
unsigned long *last_reset)
|
||||||
{
|
{
|
||||||
|
/* FIXME: each orig_node->batman_if will be attached to a softif */
|
||||||
|
struct bat_priv *bat_priv = netdev_priv(soft_device);
|
||||||
|
|
||||||
if ((seq_num_diff <= -TQ_LOCAL_WINDOW_SIZE)
|
if ((seq_num_diff <= -TQ_LOCAL_WINDOW_SIZE)
|
||||||
|| (seq_num_diff >= EXPECTED_SEQNO_RANGE)) {
|
|| (seq_num_diff >= EXPECTED_SEQNO_RANGE)) {
|
||||||
if (time_after(jiffies, *last_reset +
|
if (time_after(jiffies, *last_reset +
|
||||||
msecs_to_jiffies(RESET_PROTECTION_MS))) {
|
msecs_to_jiffies(RESET_PROTECTION_MS))) {
|
||||||
|
|
||||||
*last_reset = jiffies;
|
*last_reset = jiffies;
|
||||||
bat_dbg(DBG_BATMAN,
|
bat_dbg(DBG_BATMAN, bat_priv,
|
||||||
"old packet received, start protection\n");
|
"old packet received, start protection\n");
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -349,10 +359,12 @@ static char count_real_packets(struct ethhdr *ethhdr,
|
||||||
struct batman_packet *batman_packet,
|
struct batman_packet *batman_packet,
|
||||||
struct batman_if *if_incoming)
|
struct batman_if *if_incoming)
|
||||||
{
|
{
|
||||||
|
/* FIXME: each orig_node->batman_if will be attached to a softif */
|
||||||
|
struct bat_priv *bat_priv = netdev_priv(soft_device);
|
||||||
struct orig_node *orig_node;
|
struct orig_node *orig_node;
|
||||||
struct neigh_node *tmp_neigh_node;
|
struct neigh_node *tmp_neigh_node;
|
||||||
char is_duplicate = 0;
|
char is_duplicate = 0;
|
||||||
int16_t seq_diff;
|
int32_t seq_diff;
|
||||||
int need_update = 0;
|
int need_update = 0;
|
||||||
int set_mark;
|
int set_mark;
|
||||||
|
|
||||||
|
@ -387,7 +399,8 @@ static char count_real_packets(struct ethhdr *ethhdr,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (need_update) {
|
if (need_update) {
|
||||||
bat_dbg(DBG_BATMAN, "updating last_seqno: old %d, new %d\n",
|
bat_dbg(DBG_BATMAN, bat_priv,
|
||||||
|
"updating last_seqno: old %d, new %d\n",
|
||||||
orig_node->last_real_seqno, batman_packet->seqno);
|
orig_node->last_real_seqno, batman_packet->seqno);
|
||||||
orig_node->last_real_seqno = batman_packet->seqno;
|
orig_node->last_real_seqno = batman_packet->seqno;
|
||||||
}
|
}
|
||||||
|
@ -395,18 +408,127 @@ static char count_real_packets(struct ethhdr *ethhdr,
|
||||||
return is_duplicate;
|
return is_duplicate;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* copy primary address for bonding */
|
||||||
|
static void mark_bonding_address(struct bat_priv *bat_priv,
|
||||||
|
struct orig_node *orig_node,
|
||||||
|
struct orig_node *orig_neigh_node,
|
||||||
|
struct batman_packet *batman_packet)
|
||||||
|
|
||||||
|
{
|
||||||
|
if (batman_packet->flags & PRIMARIES_FIRST_HOP)
|
||||||
|
memcpy(orig_neigh_node->primary_addr,
|
||||||
|
orig_node->orig, ETH_ALEN);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* mark possible bond.candidates in the neighbor list */
|
||||||
|
void update_bonding_candidates(struct bat_priv *bat_priv,
|
||||||
|
struct orig_node *orig_node)
|
||||||
|
{
|
||||||
|
int candidates;
|
||||||
|
int interference_candidate;
|
||||||
|
int best_tq;
|
||||||
|
struct neigh_node *tmp_neigh_node, *tmp_neigh_node2;
|
||||||
|
struct neigh_node *first_candidate, *last_candidate;
|
||||||
|
|
||||||
|
/* update the candidates for this originator */
|
||||||
|
if (!orig_node->router) {
|
||||||
|
orig_node->bond.candidates = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
best_tq = orig_node->router->tq_avg;
|
||||||
|
|
||||||
|
/* update bond.candidates */
|
||||||
|
|
||||||
|
candidates = 0;
|
||||||
|
|
||||||
|
/* mark other nodes which also received "PRIMARIES FIRST HOP" packets
|
||||||
|
* as "bonding partner" */
|
||||||
|
|
||||||
|
/* first, zero the list */
|
||||||
|
list_for_each_entry(tmp_neigh_node, &orig_node->neigh_list, list) {
|
||||||
|
tmp_neigh_node->next_bond_candidate = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
first_candidate = NULL;
|
||||||
|
last_candidate = NULL;
|
||||||
|
list_for_each_entry(tmp_neigh_node, &orig_node->neigh_list, list) {
|
||||||
|
|
||||||
|
/* only consider if it has the same primary address ... */
|
||||||
|
if (memcmp(orig_node->orig,
|
||||||
|
tmp_neigh_node->orig_node->primary_addr,
|
||||||
|
ETH_ALEN) != 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* ... and is good enough to be considered */
|
||||||
|
if (tmp_neigh_node->tq_avg < best_tq - BONDING_TQ_THRESHOLD)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* check if we have another candidate with the same
|
||||||
|
* mac address or interface. If we do, we won't
|
||||||
|
* select this candidate because of possible interference. */
|
||||||
|
|
||||||
|
interference_candidate = 0;
|
||||||
|
list_for_each_entry(tmp_neigh_node2,
|
||||||
|
&orig_node->neigh_list, list) {
|
||||||
|
|
||||||
|
if (tmp_neigh_node2 == tmp_neigh_node)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* we only care if the other candidate is even
|
||||||
|
* considered as candidate. */
|
||||||
|
if (tmp_neigh_node2->next_bond_candidate == NULL)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
|
||||||
|
if ((tmp_neigh_node->if_incoming ==
|
||||||
|
tmp_neigh_node2->if_incoming)
|
||||||
|
|| (memcmp(tmp_neigh_node->addr,
|
||||||
|
tmp_neigh_node2->addr, ETH_ALEN) == 0)) {
|
||||||
|
|
||||||
|
interference_candidate = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* don't care further if it is an interference candidate */
|
||||||
|
if (interference_candidate)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (first_candidate == NULL) {
|
||||||
|
first_candidate = tmp_neigh_node;
|
||||||
|
tmp_neigh_node->next_bond_candidate = first_candidate;
|
||||||
|
} else
|
||||||
|
tmp_neigh_node->next_bond_candidate = last_candidate;
|
||||||
|
|
||||||
|
last_candidate = tmp_neigh_node;
|
||||||
|
|
||||||
|
candidates++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (candidates > 0) {
|
||||||
|
first_candidate->next_bond_candidate = last_candidate;
|
||||||
|
orig_node->bond.selected = first_candidate;
|
||||||
|
}
|
||||||
|
|
||||||
|
orig_node->bond.candidates = candidates;
|
||||||
|
}
|
||||||
|
|
||||||
void receive_bat_packet(struct ethhdr *ethhdr,
|
void receive_bat_packet(struct ethhdr *ethhdr,
|
||||||
struct batman_packet *batman_packet,
|
struct batman_packet *batman_packet,
|
||||||
unsigned char *hna_buff, int hna_buff_len,
|
unsigned char *hna_buff, int hna_buff_len,
|
||||||
struct batman_if *if_incoming)
|
struct batman_if *if_incoming)
|
||||||
{
|
{
|
||||||
|
/* FIXME: each orig_node->batman_if will be attached to a softif */
|
||||||
|
struct bat_priv *bat_priv = netdev_priv(soft_device);
|
||||||
struct batman_if *batman_if;
|
struct batman_if *batman_if;
|
||||||
struct orig_node *orig_neigh_node, *orig_node;
|
struct orig_node *orig_neigh_node, *orig_node;
|
||||||
char has_directlink_flag;
|
char has_directlink_flag;
|
||||||
char is_my_addr = 0, is_my_orig = 0, is_my_oldorig = 0;
|
char is_my_addr = 0, is_my_orig = 0, is_my_oldorig = 0;
|
||||||
char is_broadcast = 0, is_bidirectional, is_single_hop_neigh;
|
char is_broadcast = 0, is_bidirectional, is_single_hop_neigh;
|
||||||
char is_duplicate;
|
char is_duplicate;
|
||||||
unsigned short if_incoming_seqno;
|
uint32_t if_incoming_seqno;
|
||||||
|
|
||||||
/* Silently drop when the batman packet is actually not a
|
/* Silently drop when the batman packet is actually not a
|
||||||
* correct packet.
|
* correct packet.
|
||||||
|
@ -431,7 +553,8 @@ void receive_bat_packet(struct ethhdr *ethhdr,
|
||||||
is_single_hop_neigh = (compare_orig(ethhdr->h_source,
|
is_single_hop_neigh = (compare_orig(ethhdr->h_source,
|
||||||
batman_packet->orig) ? 1 : 0);
|
batman_packet->orig) ? 1 : 0);
|
||||||
|
|
||||||
bat_dbg(DBG_BATMAN, "Received BATMAN packet via NB: %pM, IF: %s [%s] "
|
bat_dbg(DBG_BATMAN, bat_priv,
|
||||||
|
"Received BATMAN packet via NB: %pM, IF: %s [%s] "
|
||||||
"(from OG: %pM, via prev OG: %pM, seqno %d, tq %d, "
|
"(from OG: %pM, via prev OG: %pM, seqno %d, tq %d, "
|
||||||
"TTL %d, V %d, IDF %d)\n",
|
"TTL %d, V %d, IDF %d)\n",
|
||||||
ethhdr->h_source, if_incoming->dev, if_incoming->addr_str,
|
ethhdr->h_source, if_incoming->dev, if_incoming->addr_str,
|
||||||
|
@ -455,19 +578,19 @@ void receive_bat_packet(struct ethhdr *ethhdr,
|
||||||
batman_if->net_dev->dev_addr))
|
batman_if->net_dev->dev_addr))
|
||||||
is_my_oldorig = 1;
|
is_my_oldorig = 1;
|
||||||
|
|
||||||
if (compare_orig(ethhdr->h_source, broadcastAddr))
|
if (compare_orig(ethhdr->h_source, broadcast_addr))
|
||||||
is_broadcast = 1;
|
is_broadcast = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (batman_packet->version != COMPAT_VERSION) {
|
if (batman_packet->version != COMPAT_VERSION) {
|
||||||
bat_dbg(DBG_BATMAN,
|
bat_dbg(DBG_BATMAN, bat_priv,
|
||||||
"Drop packet: incompatible batman version (%i)\n",
|
"Drop packet: incompatible batman version (%i)\n",
|
||||||
batman_packet->version);
|
batman_packet->version);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_my_addr) {
|
if (is_my_addr) {
|
||||||
bat_dbg(DBG_BATMAN,
|
bat_dbg(DBG_BATMAN, bat_priv,
|
||||||
"Drop packet: received my own broadcast (sender: %pM"
|
"Drop packet: received my own broadcast (sender: %pM"
|
||||||
")\n",
|
")\n",
|
||||||
ethhdr->h_source);
|
ethhdr->h_source);
|
||||||
|
@ -475,7 +598,7 @@ void receive_bat_packet(struct ethhdr *ethhdr,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_broadcast) {
|
if (is_broadcast) {
|
||||||
bat_dbg(DBG_BATMAN, "Drop packet: "
|
bat_dbg(DBG_BATMAN, bat_priv, "Drop packet: "
|
||||||
"ignoring all packets with broadcast source addr (sender: %pM"
|
"ignoring all packets with broadcast source addr (sender: %pM"
|
||||||
")\n", ethhdr->h_source);
|
")\n", ethhdr->h_source);
|
||||||
return;
|
return;
|
||||||
|
@ -505,13 +628,13 @@ void receive_bat_packet(struct ethhdr *ethhdr,
|
||||||
bit_packet_count(word);
|
bit_packet_count(word);
|
||||||
}
|
}
|
||||||
|
|
||||||
bat_dbg(DBG_BATMAN, "Drop packet: "
|
bat_dbg(DBG_BATMAN, bat_priv, "Drop packet: "
|
||||||
"originator packet from myself (via neighbor)\n");
|
"originator packet from myself (via neighbor)\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_my_oldorig) {
|
if (is_my_oldorig) {
|
||||||
bat_dbg(DBG_BATMAN,
|
bat_dbg(DBG_BATMAN, bat_priv,
|
||||||
"Drop packet: ignoring all rebroadcast echos (sender: "
|
"Drop packet: ignoring all rebroadcast echos (sender: "
|
||||||
"%pM)\n", ethhdr->h_source);
|
"%pM)\n", ethhdr->h_source);
|
||||||
return;
|
return;
|
||||||
|
@ -524,14 +647,14 @@ void receive_bat_packet(struct ethhdr *ethhdr,
|
||||||
is_duplicate = count_real_packets(ethhdr, batman_packet, if_incoming);
|
is_duplicate = count_real_packets(ethhdr, batman_packet, if_incoming);
|
||||||
|
|
||||||
if (is_duplicate == -1) {
|
if (is_duplicate == -1) {
|
||||||
bat_dbg(DBG_BATMAN,
|
bat_dbg(DBG_BATMAN, bat_priv,
|
||||||
"Drop packet: packet within seqno protection time "
|
"Drop packet: packet within seqno protection time "
|
||||||
"(sender: %pM)\n", ethhdr->h_source);
|
"(sender: %pM)\n", ethhdr->h_source);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (batman_packet->tq == 0) {
|
if (batman_packet->tq == 0) {
|
||||||
bat_dbg(DBG_BATMAN,
|
bat_dbg(DBG_BATMAN, bat_priv,
|
||||||
"Drop packet: originator packet with tq equal 0\n");
|
"Drop packet: originator packet with tq equal 0\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -544,7 +667,7 @@ void receive_bat_packet(struct ethhdr *ethhdr,
|
||||||
!(compare_orig(batman_packet->orig, batman_packet->prev_sender)) &&
|
!(compare_orig(batman_packet->orig, batman_packet->prev_sender)) &&
|
||||||
(compare_orig(orig_node->router->addr,
|
(compare_orig(orig_node->router->addr,
|
||||||
orig_node->router->orig_node->router->addr))) {
|
orig_node->router->orig_node->router->addr))) {
|
||||||
bat_dbg(DBG_BATMAN,
|
bat_dbg(DBG_BATMAN, bat_priv,
|
||||||
"Drop packet: ignoring all rebroadcast packets that "
|
"Drop packet: ignoring all rebroadcast packets that "
|
||||||
"may make me loop (sender: %pM)\n", ethhdr->h_source);
|
"may make me loop (sender: %pM)\n", ethhdr->h_source);
|
||||||
return;
|
return;
|
||||||
|
@ -561,11 +684,12 @@ void receive_bat_packet(struct ethhdr *ethhdr,
|
||||||
* don't route towards it */
|
* don't route towards it */
|
||||||
if (!is_single_hop_neigh &&
|
if (!is_single_hop_neigh &&
|
||||||
(orig_neigh_node->router == NULL)) {
|
(orig_neigh_node->router == NULL)) {
|
||||||
bat_dbg(DBG_BATMAN, "Drop packet: OGM via unknown neighbor!\n");
|
bat_dbg(DBG_BATMAN, bat_priv,
|
||||||
|
"Drop packet: OGM via unknown neighbor!\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
is_bidirectional = isBidirectionalNeigh(orig_node, orig_neigh_node,
|
is_bidirectional = is_bidirectional_neigh(orig_node, orig_neigh_node,
|
||||||
batman_packet, if_incoming);
|
batman_packet, if_incoming);
|
||||||
|
|
||||||
/* update ranking if it is not a duplicate or has the same
|
/* update ranking if it is not a duplicate or has the same
|
||||||
|
@ -577,6 +701,10 @@ void receive_bat_packet(struct ethhdr *ethhdr,
|
||||||
update_orig(orig_node, ethhdr, batman_packet,
|
update_orig(orig_node, ethhdr, batman_packet,
|
||||||
if_incoming, hna_buff, hna_buff_len, is_duplicate);
|
if_incoming, hna_buff, hna_buff_len, is_duplicate);
|
||||||
|
|
||||||
|
mark_bonding_address(bat_priv, orig_node,
|
||||||
|
orig_neigh_node, batman_packet);
|
||||||
|
update_bonding_candidates(bat_priv, orig_node);
|
||||||
|
|
||||||
/* is single hop (direct) neighbor */
|
/* is single hop (direct) neighbor */
|
||||||
if (is_single_hop_neigh) {
|
if (is_single_hop_neigh) {
|
||||||
|
|
||||||
|
@ -584,24 +712,25 @@ void receive_bat_packet(struct ethhdr *ethhdr,
|
||||||
schedule_forward_packet(orig_node, ethhdr, batman_packet,
|
schedule_forward_packet(orig_node, ethhdr, batman_packet,
|
||||||
1, hna_buff_len, if_incoming);
|
1, hna_buff_len, if_incoming);
|
||||||
|
|
||||||
bat_dbg(DBG_BATMAN, "Forwarding packet: "
|
bat_dbg(DBG_BATMAN, bat_priv, "Forwarding packet: "
|
||||||
"rebroadcast neighbor packet with direct link flag\n");
|
"rebroadcast neighbor packet with direct link flag\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* multihop originator */
|
/* multihop originator */
|
||||||
if (!is_bidirectional) {
|
if (!is_bidirectional) {
|
||||||
bat_dbg(DBG_BATMAN,
|
bat_dbg(DBG_BATMAN, bat_priv,
|
||||||
"Drop packet: not received via bidirectional link\n");
|
"Drop packet: not received via bidirectional link\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_duplicate) {
|
if (is_duplicate) {
|
||||||
bat_dbg(DBG_BATMAN, "Drop packet: duplicate packet received\n");
|
bat_dbg(DBG_BATMAN, bat_priv,
|
||||||
|
"Drop packet: duplicate packet received\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
bat_dbg(DBG_BATMAN,
|
bat_dbg(DBG_BATMAN, bat_priv,
|
||||||
"Forwarding packet: rebroadcast originator packet\n");
|
"Forwarding packet: rebroadcast originator packet\n");
|
||||||
schedule_forward_packet(orig_node, ethhdr, batman_packet,
|
schedule_forward_packet(orig_node, ethhdr, batman_packet,
|
||||||
0, hna_buff_len, if_incoming);
|
0, hna_buff_len, if_incoming);
|
||||||
|
@ -652,10 +781,10 @@ int recv_bat_packet(struct sk_buff *skb,
|
||||||
return NET_RX_SUCCESS;
|
return NET_RX_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int recv_my_icmp_packet(struct sk_buff *skb)
|
static int recv_my_icmp_packet(struct sk_buff *skb, size_t icmp_len)
|
||||||
{
|
{
|
||||||
struct orig_node *orig_node;
|
struct orig_node *orig_node;
|
||||||
struct icmp_packet *icmp_packet;
|
struct icmp_packet_rr *icmp_packet;
|
||||||
struct ethhdr *ethhdr;
|
struct ethhdr *ethhdr;
|
||||||
struct sk_buff *skb_old;
|
struct sk_buff *skb_old;
|
||||||
struct batman_if *batman_if;
|
struct batman_if *batman_if;
|
||||||
|
@ -663,12 +792,12 @@ static int recv_my_icmp_packet(struct sk_buff *skb)
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
uint8_t dstaddr[ETH_ALEN];
|
uint8_t dstaddr[ETH_ALEN];
|
||||||
|
|
||||||
icmp_packet = (struct icmp_packet *)skb->data;
|
icmp_packet = (struct icmp_packet_rr *)skb->data;
|
||||||
ethhdr = (struct ethhdr *)skb_mac_header(skb);
|
ethhdr = (struct ethhdr *)skb_mac_header(skb);
|
||||||
|
|
||||||
/* add data to device queue */
|
/* add data to device queue */
|
||||||
if (icmp_packet->msg_type != ECHO_REQUEST) {
|
if (icmp_packet->msg_type != ECHO_REQUEST) {
|
||||||
bat_device_receive_packet(icmp_packet);
|
bat_socket_receive_packet(icmp_packet, icmp_len);
|
||||||
return NET_RX_DROP;
|
return NET_RX_DROP;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -690,13 +819,12 @@ static int recv_my_icmp_packet(struct sk_buff *skb)
|
||||||
|
|
||||||
/* create a copy of the skb, if needed, to modify it. */
|
/* create a copy of the skb, if needed, to modify it. */
|
||||||
skb_old = NULL;
|
skb_old = NULL;
|
||||||
if (!skb_clone_writable(skb, sizeof(struct icmp_packet))) {
|
if (!skb_clone_writable(skb, icmp_len)) {
|
||||||
skb_old = skb;
|
skb_old = skb;
|
||||||
skb = skb_copy(skb, GFP_ATOMIC);
|
skb = skb_copy(skb, GFP_ATOMIC);
|
||||||
if (!skb)
|
if (!skb)
|
||||||
return NET_RX_DROP;
|
return NET_RX_DROP;
|
||||||
|
icmp_packet = (struct icmp_packet_rr *)skb->data;
|
||||||
icmp_packet = (struct icmp_packet *)skb->data;
|
|
||||||
ethhdr = (struct ethhdr *)skb_mac_header(skb);
|
ethhdr = (struct ethhdr *)skb_mac_header(skb);
|
||||||
kfree_skb(skb_old);
|
kfree_skb(skb_old);
|
||||||
}
|
}
|
||||||
|
@ -715,7 +843,7 @@ static int recv_my_icmp_packet(struct sk_buff *skb)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int recv_icmp_ttl_exceeded(struct sk_buff *skb)
|
static int recv_icmp_ttl_exceeded(struct sk_buff *skb, size_t icmp_len)
|
||||||
{
|
{
|
||||||
struct orig_node *orig_node;
|
struct orig_node *orig_node;
|
||||||
struct icmp_packet *icmp_packet;
|
struct icmp_packet *icmp_packet;
|
||||||
|
@ -731,10 +859,9 @@ static int recv_icmp_ttl_exceeded(struct sk_buff *skb)
|
||||||
|
|
||||||
/* send TTL exceeded if packet is an echo request (traceroute) */
|
/* send TTL exceeded if packet is an echo request (traceroute) */
|
||||||
if (icmp_packet->msg_type != ECHO_REQUEST) {
|
if (icmp_packet->msg_type != ECHO_REQUEST) {
|
||||||
printk(KERN_WARNING "batman-adv:"
|
pr_warning("Warning - can't forward icmp packet from %pM to "
|
||||||
"Warning - can't forward icmp packet from %pM to %pM: "
|
"%pM: ttl exceeded\n", icmp_packet->orig,
|
||||||
"ttl exceeded\n",
|
icmp_packet->dst);
|
||||||
icmp_packet->orig, icmp_packet->dst);
|
|
||||||
return NET_RX_DROP;
|
return NET_RX_DROP;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -754,7 +881,7 @@ static int recv_icmp_ttl_exceeded(struct sk_buff *skb)
|
||||||
spin_unlock_irqrestore(&orig_hash_lock, flags);
|
spin_unlock_irqrestore(&orig_hash_lock, flags);
|
||||||
|
|
||||||
/* create a copy of the skb, if needed, to modify it. */
|
/* create a copy of the skb, if needed, to modify it. */
|
||||||
if (!skb_clone_writable(skb, sizeof(struct icmp_packet))) {
|
if (!skb_clone_writable(skb, icmp_len)) {
|
||||||
skb_old = skb;
|
skb_old = skb;
|
||||||
skb = skb_copy(skb, GFP_ATOMIC);
|
skb = skb_copy(skb, GFP_ATOMIC);
|
||||||
if (!skb)
|
if (!skb)
|
||||||
|
@ -781,7 +908,7 @@ static int recv_icmp_ttl_exceeded(struct sk_buff *skb)
|
||||||
|
|
||||||
int recv_icmp_packet(struct sk_buff *skb)
|
int recv_icmp_packet(struct sk_buff *skb)
|
||||||
{
|
{
|
||||||
struct icmp_packet *icmp_packet;
|
struct icmp_packet_rr *icmp_packet;
|
||||||
struct ethhdr *ethhdr;
|
struct ethhdr *ethhdr;
|
||||||
struct orig_node *orig_node;
|
struct orig_node *orig_node;
|
||||||
struct sk_buff *skb_old;
|
struct sk_buff *skb_old;
|
||||||
|
@ -791,6 +918,12 @@ int recv_icmp_packet(struct sk_buff *skb)
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
uint8_t dstaddr[ETH_ALEN];
|
uint8_t dstaddr[ETH_ALEN];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* we truncate all incoming icmp packets if they don't match our size
|
||||||
|
*/
|
||||||
|
if (skb_headlen(skb) >= sizeof(struct icmp_packet_rr))
|
||||||
|
hdr_size = sizeof(struct icmp_packet_rr);
|
||||||
|
|
||||||
/* drop packet if it has not necessary minimum size */
|
/* drop packet if it has not necessary minimum size */
|
||||||
if (skb_headlen(skb) < hdr_size)
|
if (skb_headlen(skb) < hdr_size)
|
||||||
return NET_RX_DROP;
|
return NET_RX_DROP;
|
||||||
|
@ -809,15 +942,23 @@ int recv_icmp_packet(struct sk_buff *skb)
|
||||||
if (!is_my_mac(ethhdr->h_dest))
|
if (!is_my_mac(ethhdr->h_dest))
|
||||||
return NET_RX_DROP;
|
return NET_RX_DROP;
|
||||||
|
|
||||||
icmp_packet = (struct icmp_packet *)skb->data;
|
icmp_packet = (struct icmp_packet_rr *)skb->data;
|
||||||
|
|
||||||
|
/* add record route information if not full */
|
||||||
|
if ((hdr_size == sizeof(struct icmp_packet_rr)) &&
|
||||||
|
(icmp_packet->rr_cur < BAT_RR_LEN)) {
|
||||||
|
memcpy(&(icmp_packet->rr[icmp_packet->rr_cur]),
|
||||||
|
ethhdr->h_dest, ETH_ALEN);
|
||||||
|
icmp_packet->rr_cur++;
|
||||||
|
}
|
||||||
|
|
||||||
/* packet for me */
|
/* packet for me */
|
||||||
if (is_my_mac(icmp_packet->dst))
|
if (is_my_mac(icmp_packet->dst))
|
||||||
return recv_my_icmp_packet(skb);
|
return recv_my_icmp_packet(skb, hdr_size);
|
||||||
|
|
||||||
/* TTL exceeded */
|
/* TTL exceeded */
|
||||||
if (icmp_packet->ttl < 2)
|
if (icmp_packet->ttl < 2)
|
||||||
return recv_icmp_ttl_exceeded(skb);
|
return recv_icmp_ttl_exceeded(skb, hdr_size);
|
||||||
|
|
||||||
ret = NET_RX_DROP;
|
ret = NET_RX_DROP;
|
||||||
|
|
||||||
|
@ -836,12 +977,12 @@ int recv_icmp_packet(struct sk_buff *skb)
|
||||||
spin_unlock_irqrestore(&orig_hash_lock, flags);
|
spin_unlock_irqrestore(&orig_hash_lock, flags);
|
||||||
|
|
||||||
/* create a copy of the skb, if needed, to modify it. */
|
/* create a copy of the skb, if needed, to modify it. */
|
||||||
if (!skb_clone_writable(skb, sizeof(struct icmp_packet))) {
|
if (!skb_clone_writable(skb, hdr_size)) {
|
||||||
skb_old = skb;
|
skb_old = skb;
|
||||||
skb = skb_copy(skb, GFP_ATOMIC);
|
skb = skb_copy(skb, GFP_ATOMIC);
|
||||||
if (!skb)
|
if (!skb)
|
||||||
return NET_RX_DROP;
|
return NET_RX_DROP;
|
||||||
icmp_packet = (struct icmp_packet *)skb->data;
|
icmp_packet = (struct icmp_packet_rr *)skb->data;
|
||||||
ethhdr = (struct ethhdr *)skb_mac_header(skb);
|
ethhdr = (struct ethhdr *)skb_mac_header(skb);
|
||||||
kfree_skb(skb_old);
|
kfree_skb(skb_old);
|
||||||
}
|
}
|
||||||
|
@ -859,16 +1000,109 @@ int recv_icmp_packet(struct sk_buff *skb)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int recv_unicast_packet(struct sk_buff *skb)
|
/* find a suitable router for this originator, and use
|
||||||
|
* bonding if possible. */
|
||||||
|
struct neigh_node *find_router(struct orig_node *orig_node,
|
||||||
|
struct batman_if *recv_if)
|
||||||
|
{
|
||||||
|
/* FIXME: each orig_node->batman_if will be attached to a softif */
|
||||||
|
struct bat_priv *bat_priv = netdev_priv(soft_device);
|
||||||
|
struct orig_node *primary_orig_node;
|
||||||
|
struct orig_node *router_orig;
|
||||||
|
struct neigh_node *router, *first_candidate, *best_router;
|
||||||
|
static uint8_t zero_mac[ETH_ALEN] = {0, 0, 0, 0, 0, 0};
|
||||||
|
int bonding_enabled;
|
||||||
|
|
||||||
|
if (!orig_node)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (!orig_node->router)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
/* without bonding, the first node should
|
||||||
|
* always choose the default router. */
|
||||||
|
|
||||||
|
bonding_enabled = atomic_read(&bat_priv->bonding_enabled);
|
||||||
|
if (!bonding_enabled && (recv_if == NULL))
|
||||||
|
return orig_node->router;
|
||||||
|
|
||||||
|
router_orig = orig_node->router->orig_node;
|
||||||
|
|
||||||
|
/* if we have something in the primary_addr, we can search
|
||||||
|
* for a potential bonding candidate. */
|
||||||
|
if (memcmp(router_orig->primary_addr, zero_mac, ETH_ALEN) == 0)
|
||||||
|
return orig_node->router;
|
||||||
|
|
||||||
|
/* find the orig_node which has the primary interface. might
|
||||||
|
* even be the same as our router_orig in many cases */
|
||||||
|
|
||||||
|
if (memcmp(router_orig->primary_addr,
|
||||||
|
router_orig->orig, ETH_ALEN) == 0) {
|
||||||
|
primary_orig_node = router_orig;
|
||||||
|
} else {
|
||||||
|
primary_orig_node = hash_find(orig_hash,
|
||||||
|
router_orig->primary_addr);
|
||||||
|
if (!primary_orig_node)
|
||||||
|
return orig_node->router;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* with less than 2 candidates, we can't do any
|
||||||
|
* bonding and prefer the original router. */
|
||||||
|
|
||||||
|
if (primary_orig_node->bond.candidates < 2)
|
||||||
|
return orig_node->router;
|
||||||
|
|
||||||
|
|
||||||
|
/* all nodes between should choose a candidate which
|
||||||
|
* is is not on the interface where the packet came
|
||||||
|
* in. */
|
||||||
|
first_candidate = primary_orig_node->bond.selected;
|
||||||
|
router = first_candidate;
|
||||||
|
|
||||||
|
if (bonding_enabled) {
|
||||||
|
/* in the bonding case, send the packets in a round
|
||||||
|
* robin fashion over the remaining interfaces. */
|
||||||
|
do {
|
||||||
|
/* recv_if == NULL on the first node. */
|
||||||
|
if (router->if_incoming != recv_if)
|
||||||
|
break;
|
||||||
|
|
||||||
|
router = router->next_bond_candidate;
|
||||||
|
} while (router != first_candidate);
|
||||||
|
|
||||||
|
primary_orig_node->bond.selected = router->next_bond_candidate;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
/* if bonding is disabled, use the best of the
|
||||||
|
* remaining candidates which are not using
|
||||||
|
* this interface. */
|
||||||
|
best_router = first_candidate;
|
||||||
|
|
||||||
|
do {
|
||||||
|
/* recv_if == NULL on the first node. */
|
||||||
|
if ((router->if_incoming != recv_if) &&
|
||||||
|
(router->tq_avg > best_router->tq_avg))
|
||||||
|
best_router = router;
|
||||||
|
|
||||||
|
router = router->next_bond_candidate;
|
||||||
|
} while (router != first_candidate);
|
||||||
|
|
||||||
|
router = best_router;
|
||||||
|
}
|
||||||
|
|
||||||
|
return router;
|
||||||
|
}
|
||||||
|
|
||||||
|
int recv_unicast_packet(struct sk_buff *skb, struct batman_if *recv_if)
|
||||||
{
|
{
|
||||||
struct unicast_packet *unicast_packet;
|
struct unicast_packet *unicast_packet;
|
||||||
struct orig_node *orig_node;
|
struct orig_node *orig_node;
|
||||||
|
struct neigh_node *router;
|
||||||
struct ethhdr *ethhdr;
|
struct ethhdr *ethhdr;
|
||||||
struct batman_if *batman_if;
|
struct batman_if *batman_if;
|
||||||
struct sk_buff *skb_old;
|
struct sk_buff *skb_old;
|
||||||
uint8_t dstaddr[ETH_ALEN];
|
uint8_t dstaddr[ETH_ALEN];
|
||||||
int hdr_size = sizeof(struct unicast_packet);
|
int hdr_size = sizeof(struct unicast_packet);
|
||||||
int ret;
|
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
/* drop packet if it has not necessary minimum size */
|
/* drop packet if it has not necessary minimum size */
|
||||||
|
@ -899,26 +1133,30 @@ int recv_unicast_packet(struct sk_buff *skb)
|
||||||
|
|
||||||
/* TTL exceeded */
|
/* TTL exceeded */
|
||||||
if (unicast_packet->ttl < 2) {
|
if (unicast_packet->ttl < 2) {
|
||||||
printk(KERN_WARNING "batman-adv:Warning - "
|
pr_warning("Warning - can't forward unicast packet from %pM to "
|
||||||
"can't forward unicast packet from %pM to %pM: "
|
"%pM: ttl exceeded\n", ethhdr->h_source,
|
||||||
"ttl exceeded\n",
|
unicast_packet->dest);
|
||||||
ethhdr->h_source, unicast_packet->dest);
|
|
||||||
return NET_RX_DROP;
|
return NET_RX_DROP;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = NET_RX_DROP;
|
|
||||||
/* get routing information */
|
/* get routing information */
|
||||||
spin_lock_irqsave(&orig_hash_lock, flags);
|
spin_lock_irqsave(&orig_hash_lock, flags);
|
||||||
orig_node = ((struct orig_node *)
|
orig_node = ((struct orig_node *)
|
||||||
hash_find(orig_hash, unicast_packet->dest));
|
hash_find(orig_hash, unicast_packet->dest));
|
||||||
|
|
||||||
if ((orig_node != NULL) &&
|
router = find_router(orig_node, recv_if);
|
||||||
(orig_node->router != NULL)) {
|
|
||||||
|
if (!router) {
|
||||||
|
spin_unlock_irqrestore(&orig_hash_lock, flags);
|
||||||
|
return NET_RX_DROP;
|
||||||
|
}
|
||||||
|
|
||||||
/* don't lock while sending the packets ... we therefore
|
/* don't lock while sending the packets ... we therefore
|
||||||
* copy the required data before sending */
|
* copy the required data before sending */
|
||||||
batman_if = orig_node->router->if_incoming;
|
|
||||||
memcpy(dstaddr, orig_node->router->addr, ETH_ALEN);
|
batman_if = router->if_incoming;
|
||||||
|
memcpy(dstaddr, router->addr, ETH_ALEN);
|
||||||
|
|
||||||
spin_unlock_irqrestore(&orig_hash_lock, flags);
|
spin_unlock_irqrestore(&orig_hash_lock, flags);
|
||||||
|
|
||||||
/* create a copy of the skb, if needed, to modify it. */
|
/* create a copy of the skb, if needed, to modify it. */
|
||||||
|
@ -927,21 +1165,18 @@ int recv_unicast_packet(struct sk_buff *skb)
|
||||||
skb = skb_copy(skb, GFP_ATOMIC);
|
skb = skb_copy(skb, GFP_ATOMIC);
|
||||||
if (!skb)
|
if (!skb)
|
||||||
return NET_RX_DROP;
|
return NET_RX_DROP;
|
||||||
unicast_packet = (struct unicast_packet *)skb->data;
|
unicast_packet = (struct unicast_packet *) skb->data;
|
||||||
ethhdr = (struct ethhdr *)skb_mac_header(skb);
|
ethhdr = (struct ethhdr *)skb_mac_header(skb);
|
||||||
kfree_skb(skb_old);
|
kfree_skb(skb_old);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* decrement ttl */
|
/* decrement ttl */
|
||||||
unicast_packet->ttl--;
|
unicast_packet->ttl--;
|
||||||
|
|
||||||
/* route it */
|
/* route it */
|
||||||
send_skb_packet(skb, batman_if, dstaddr);
|
send_skb_packet(skb, batman_if, dstaddr);
|
||||||
ret = NET_RX_SUCCESS;
|
|
||||||
|
|
||||||
} else
|
return NET_RX_SUCCESS;
|
||||||
spin_unlock_irqrestore(&orig_hash_lock, flags);
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int recv_bcast_packet(struct sk_buff *skb)
|
int recv_bcast_packet(struct sk_buff *skb)
|
||||||
|
@ -950,7 +1185,7 @@ int recv_bcast_packet(struct sk_buff *skb)
|
||||||
struct bcast_packet *bcast_packet;
|
struct bcast_packet *bcast_packet;
|
||||||
struct ethhdr *ethhdr;
|
struct ethhdr *ethhdr;
|
||||||
int hdr_size = sizeof(struct bcast_packet);
|
int hdr_size = sizeof(struct bcast_packet);
|
||||||
int16_t seq_diff;
|
int32_t seq_diff;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
/* drop packet if it has not necessary minimum size */
|
/* drop packet if it has not necessary minimum size */
|
||||||
|
@ -977,6 +1212,9 @@ int recv_bcast_packet(struct sk_buff *skb)
|
||||||
if (is_my_mac(bcast_packet->orig))
|
if (is_my_mac(bcast_packet->orig))
|
||||||
return NET_RX_DROP;
|
return NET_RX_DROP;
|
||||||
|
|
||||||
|
if (bcast_packet->ttl < 2)
|
||||||
|
return NET_RX_DROP;
|
||||||
|
|
||||||
spin_lock_irqsave(&orig_hash_lock, flags);
|
spin_lock_irqsave(&orig_hash_lock, flags);
|
||||||
orig_node = ((struct orig_node *)
|
orig_node = ((struct orig_node *)
|
||||||
hash_find(orig_hash, bcast_packet->orig));
|
hash_find(orig_hash, bcast_packet->orig));
|
||||||
|
@ -989,12 +1227,12 @@ int recv_bcast_packet(struct sk_buff *skb)
|
||||||
/* check whether the packet is a duplicate */
|
/* check whether the packet is a duplicate */
|
||||||
if (get_bit_status(orig_node->bcast_bits,
|
if (get_bit_status(orig_node->bcast_bits,
|
||||||
orig_node->last_bcast_seqno,
|
orig_node->last_bcast_seqno,
|
||||||
ntohs(bcast_packet->seqno))) {
|
ntohl(bcast_packet->seqno))) {
|
||||||
spin_unlock_irqrestore(&orig_hash_lock, flags);
|
spin_unlock_irqrestore(&orig_hash_lock, flags);
|
||||||
return NET_RX_DROP;
|
return NET_RX_DROP;
|
||||||
}
|
}
|
||||||
|
|
||||||
seq_diff = ntohs(bcast_packet->seqno) - orig_node->last_bcast_seqno;
|
seq_diff = ntohl(bcast_packet->seqno) - orig_node->last_bcast_seqno;
|
||||||
|
|
||||||
/* check whether the packet is old and the host just restarted. */
|
/* check whether the packet is old and the host just restarted. */
|
||||||
if (window_protected(seq_diff, &orig_node->bcast_seqno_reset)) {
|
if (window_protected(seq_diff, &orig_node->bcast_seqno_reset)) {
|
||||||
|
@ -1005,7 +1243,7 @@ int recv_bcast_packet(struct sk_buff *skb)
|
||||||
/* mark broadcast in flood history, update window position
|
/* mark broadcast in flood history, update window position
|
||||||
* if required. */
|
* if required. */
|
||||||
if (bit_get_packet(orig_node->bcast_bits, seq_diff, 1))
|
if (bit_get_packet(orig_node->bcast_bits, seq_diff, 1))
|
||||||
orig_node->last_bcast_seqno = ntohs(bcast_packet->seqno);
|
orig_node->last_bcast_seqno = ntohl(bcast_packet->seqno);
|
||||||
|
|
||||||
spin_unlock_irqrestore(&orig_hash_lock, flags);
|
spin_unlock_irqrestore(&orig_hash_lock, flags);
|
||||||
/* rebroadcast packet */
|
/* rebroadcast packet */
|
||||||
|
|
|
@ -19,9 +19,10 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "types.h"
|
#ifndef _NET_BATMAN_ADV_ROUTING_H_
|
||||||
|
#define _NET_BATMAN_ADV_ROUTING_H_
|
||||||
|
|
||||||
extern wait_queue_head_t thread_wait;
|
#include "types.h"
|
||||||
|
|
||||||
void slide_own_bcast_window(struct batman_if *batman_if);
|
void slide_own_bcast_window(struct batman_if *batman_if);
|
||||||
void receive_bat_packet(struct ethhdr *ethhdr,
|
void receive_bat_packet(struct ethhdr *ethhdr,
|
||||||
|
@ -32,8 +33,14 @@ void update_routes(struct orig_node *orig_node,
|
||||||
struct neigh_node *neigh_node,
|
struct neigh_node *neigh_node,
|
||||||
unsigned char *hna_buff, int hna_buff_len);
|
unsigned char *hna_buff, int hna_buff_len);
|
||||||
int recv_icmp_packet(struct sk_buff *skb);
|
int recv_icmp_packet(struct sk_buff *skb);
|
||||||
int recv_unicast_packet(struct sk_buff *skb);
|
int recv_unicast_packet(struct sk_buff *skb, struct batman_if *recv_if);
|
||||||
int recv_bcast_packet(struct sk_buff *skb);
|
int recv_bcast_packet(struct sk_buff *skb);
|
||||||
int recv_vis_packet(struct sk_buff *skb);
|
int recv_vis_packet(struct sk_buff *skb);
|
||||||
int recv_bat_packet(struct sk_buff *skb,
|
int recv_bat_packet(struct sk_buff *skb,
|
||||||
struct batman_if *batman_if);
|
struct batman_if *batman_if);
|
||||||
|
struct neigh_node *find_router(struct orig_node *orig_node,
|
||||||
|
struct batman_if *recv_if);
|
||||||
|
void update_bonding_candidates(struct bat_priv *bat_priv,
|
||||||
|
struct orig_node *orig_node);
|
||||||
|
|
||||||
|
#endif /* _NET_BATMAN_ADV_ROUTING_H_ */
|
||||||
|
|
|
@ -29,6 +29,10 @@
|
||||||
#include "vis.h"
|
#include "vis.h"
|
||||||
#include "aggregation.h"
|
#include "aggregation.h"
|
||||||
|
|
||||||
|
#include <linux/netfilter_bridge.h>
|
||||||
|
|
||||||
|
static void send_outstanding_bcast_packet(struct work_struct *work);
|
||||||
|
|
||||||
/* apply hop penalty for a normal link */
|
/* apply hop penalty for a normal link */
|
||||||
static uint8_t hop_penalty(const uint8_t tq)
|
static uint8_t hop_penalty(const uint8_t tq)
|
||||||
{
|
{
|
||||||
|
@ -38,15 +42,15 @@ static uint8_t hop_penalty(const uint8_t tq)
|
||||||
/* when do we schedule our own packet to be sent */
|
/* when do we schedule our own packet to be sent */
|
||||||
static unsigned long own_send_time(struct bat_priv *bat_priv)
|
static unsigned long own_send_time(struct bat_priv *bat_priv)
|
||||||
{
|
{
|
||||||
return jiffies +
|
return jiffies + msecs_to_jiffies(
|
||||||
(((atomic_read(&bat_priv->orig_interval) - JITTER +
|
atomic_read(&bat_priv->orig_interval) -
|
||||||
(random32() % 2*JITTER)) * HZ) / 1000);
|
JITTER + (random32() % 2*JITTER));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* when do we schedule a forwarded packet to be sent */
|
/* when do we schedule a forwarded packet to be sent */
|
||||||
static unsigned long forward_send_time(struct bat_priv *bat_priv)
|
static unsigned long forward_send_time(struct bat_priv *bat_priv)
|
||||||
{
|
{
|
||||||
return jiffies + (((random32() % (JITTER/2)) * HZ) / 1000);
|
return jiffies + msecs_to_jiffies(random32() % (JITTER/2));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* send out an already prepared packet to the given address via the
|
/* send out an already prepared packet to the given address via the
|
||||||
|
@ -64,10 +68,8 @@ int send_skb_packet(struct sk_buff *skb,
|
||||||
goto send_skb_err;
|
goto send_skb_err;
|
||||||
|
|
||||||
if (!(batman_if->net_dev->flags & IFF_UP)) {
|
if (!(batman_if->net_dev->flags & IFF_UP)) {
|
||||||
printk(KERN_WARNING
|
pr_warning("Interface %s is not up - can't send packet via "
|
||||||
"batman-adv:Interface %s "
|
"that interface!\n", batman_if->dev);
|
||||||
"is not up - can't send packet via that interface!\n",
|
|
||||||
batman_if->dev);
|
|
||||||
goto send_skb_err;
|
goto send_skb_err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -90,9 +92,12 @@ int send_skb_packet(struct sk_buff *skb,
|
||||||
|
|
||||||
/* dev_queue_xmit() returns a negative result on error. However on
|
/* dev_queue_xmit() returns a negative result on error. However on
|
||||||
* congestion and traffic shaping, it drops and returns NET_XMIT_DROP
|
* congestion and traffic shaping, it drops and returns NET_XMIT_DROP
|
||||||
* (which is > 0). This will not be treated as an error. */
|
* (which is > 0). This will not be treated as an error.
|
||||||
|
* Also, if netfilter/ebtables wants to block outgoing batman
|
||||||
|
* packets then giving them a chance to do so here */
|
||||||
|
|
||||||
return dev_queue_xmit(skb);
|
return NF_HOOK(PF_BRIDGE, NF_BR_LOCAL_OUT, skb, NULL, skb->dev,
|
||||||
|
dev_queue_xmit);
|
||||||
send_skb_err:
|
send_skb_err:
|
||||||
kfree_skb(skb);
|
kfree_skb(skb);
|
||||||
return NET_XMIT_DROP;
|
return NET_XMIT_DROP;
|
||||||
|
@ -119,6 +124,8 @@ void send_raw_packet(unsigned char *pack_buff, int pack_buff_len,
|
||||||
static void send_packet_to_if(struct forw_packet *forw_packet,
|
static void send_packet_to_if(struct forw_packet *forw_packet,
|
||||||
struct batman_if *batman_if)
|
struct batman_if *batman_if)
|
||||||
{
|
{
|
||||||
|
/* FIXME: each batman_if will be attached to a softif */
|
||||||
|
struct bat_priv *bat_priv = netdev_priv(soft_device);
|
||||||
char *fwd_str;
|
char *fwd_str;
|
||||||
uint8_t packet_num;
|
uint8_t packet_num;
|
||||||
int16_t buff_pos;
|
int16_t buff_pos;
|
||||||
|
@ -148,11 +155,11 @@ static void send_packet_to_if(struct forw_packet *forw_packet,
|
||||||
fwd_str = (packet_num > 0 ? "Forwarding" : (forw_packet->own ?
|
fwd_str = (packet_num > 0 ? "Forwarding" : (forw_packet->own ?
|
||||||
"Sending own" :
|
"Sending own" :
|
||||||
"Forwarding"));
|
"Forwarding"));
|
||||||
bat_dbg(DBG_BATMAN,
|
bat_dbg(DBG_BATMAN, bat_priv,
|
||||||
"%s %spacket (originator %pM, seqno %d, TQ %d, TTL %d,"
|
"%s %spacket (originator %pM, seqno %d, TQ %d, TTL %d,"
|
||||||
" IDF %s) on interface %s [%s]\n",
|
" IDF %s) on interface %s [%s]\n",
|
||||||
fwd_str, (packet_num > 0 ? "aggregated " : ""),
|
fwd_str, (packet_num > 0 ? "aggregated " : ""),
|
||||||
batman_packet->orig, ntohs(batman_packet->seqno),
|
batman_packet->orig, ntohl(batman_packet->seqno),
|
||||||
batman_packet->tq, batman_packet->ttl,
|
batman_packet->tq, batman_packet->ttl,
|
||||||
(batman_packet->flags & DIRECTLINK ?
|
(batman_packet->flags & DIRECTLINK ?
|
||||||
"on" : "off"),
|
"on" : "off"),
|
||||||
|
@ -167,20 +174,22 @@ static void send_packet_to_if(struct forw_packet *forw_packet,
|
||||||
|
|
||||||
send_raw_packet(forw_packet->packet_buff,
|
send_raw_packet(forw_packet->packet_buff,
|
||||||
forw_packet->packet_len,
|
forw_packet->packet_len,
|
||||||
batman_if, broadcastAddr);
|
batman_if, broadcast_addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* send a batman packet */
|
/* send a batman packet */
|
||||||
static void send_packet(struct forw_packet *forw_packet)
|
static void send_packet(struct forw_packet *forw_packet)
|
||||||
{
|
{
|
||||||
|
/* FIXME: each batman_if will be attached to a softif */
|
||||||
|
struct bat_priv *bat_priv = netdev_priv(soft_device);
|
||||||
struct batman_if *batman_if;
|
struct batman_if *batman_if;
|
||||||
struct batman_packet *batman_packet =
|
struct batman_packet *batman_packet =
|
||||||
(struct batman_packet *)(forw_packet->packet_buff);
|
(struct batman_packet *)(forw_packet->packet_buff);
|
||||||
unsigned char directlink = (batman_packet->flags & DIRECTLINK ? 1 : 0);
|
unsigned char directlink = (batman_packet->flags & DIRECTLINK ? 1 : 0);
|
||||||
|
|
||||||
if (!forw_packet->if_incoming) {
|
if (!forw_packet->if_incoming) {
|
||||||
printk(KERN_ERR "batman-adv: Error - can't forward packet: "
|
pr_err("Error - can't forward packet: incoming iface not "
|
||||||
"incoming iface not specified\n");
|
"specified\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -193,18 +202,18 @@ static void send_packet(struct forw_packet *forw_packet)
|
||||||
(forw_packet->own && (forw_packet->if_incoming->if_num > 0))) {
|
(forw_packet->own && (forw_packet->if_incoming->if_num > 0))) {
|
||||||
|
|
||||||
/* FIXME: what about aggregated packets ? */
|
/* FIXME: what about aggregated packets ? */
|
||||||
bat_dbg(DBG_BATMAN,
|
bat_dbg(DBG_BATMAN, bat_priv,
|
||||||
"%s packet (originator %pM, seqno %d, TTL %d) "
|
"%s packet (originator %pM, seqno %d, TTL %d) "
|
||||||
"on interface %s [%s]\n",
|
"on interface %s [%s]\n",
|
||||||
(forw_packet->own ? "Sending own" : "Forwarding"),
|
(forw_packet->own ? "Sending own" : "Forwarding"),
|
||||||
batman_packet->orig, ntohs(batman_packet->seqno),
|
batman_packet->orig, ntohl(batman_packet->seqno),
|
||||||
batman_packet->ttl, forw_packet->if_incoming->dev,
|
batman_packet->ttl, forw_packet->if_incoming->dev,
|
||||||
forw_packet->if_incoming->addr_str);
|
forw_packet->if_incoming->addr_str);
|
||||||
|
|
||||||
send_raw_packet(forw_packet->packet_buff,
|
send_raw_packet(forw_packet->packet_buff,
|
||||||
forw_packet->packet_len,
|
forw_packet->packet_len,
|
||||||
forw_packet->if_incoming,
|
forw_packet->if_incoming,
|
||||||
broadcastAddr);
|
broadcast_addr);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -276,14 +285,14 @@ void schedule_own_packet(struct batman_if *batman_if)
|
||||||
batman_packet = (struct batman_packet *)batman_if->packet_buff;
|
batman_packet = (struct batman_packet *)batman_if->packet_buff;
|
||||||
|
|
||||||
/* change sequence number to network order */
|
/* change sequence number to network order */
|
||||||
batman_packet->seqno = htons((uint16_t)atomic_read(&batman_if->seqno));
|
batman_packet->seqno =
|
||||||
|
htonl((uint32_t)atomic_read(&batman_if->seqno));
|
||||||
|
|
||||||
if (vis_server == VIS_TYPE_SERVER_SYNC)
|
if (vis_server == VIS_TYPE_SERVER_SYNC)
|
||||||
batman_packet->flags = VIS_SERVER;
|
batman_packet->flags |= VIS_SERVER;
|
||||||
else
|
else
|
||||||
batman_packet->flags &= ~VIS_SERVER;
|
batman_packet->flags &= ~VIS_SERVER;
|
||||||
|
|
||||||
/* could be read by receive_bat_packet() */
|
|
||||||
atomic_inc(&batman_if->seqno);
|
atomic_inc(&batman_if->seqno);
|
||||||
|
|
||||||
slide_own_bcast_window(batman_if);
|
slide_own_bcast_window(batman_if);
|
||||||
|
@ -306,7 +315,7 @@ void schedule_forward_packet(struct orig_node *orig_node,
|
||||||
unsigned long send_time;
|
unsigned long send_time;
|
||||||
|
|
||||||
if (batman_packet->ttl <= 1) {
|
if (batman_packet->ttl <= 1) {
|
||||||
bat_dbg(DBG_BATMAN, "ttl exceeded\n");
|
bat_dbg(DBG_BATMAN, bat_priv, "ttl exceeded\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -335,13 +344,16 @@ void schedule_forward_packet(struct orig_node *orig_node,
|
||||||
/* apply hop penalty */
|
/* apply hop penalty */
|
||||||
batman_packet->tq = hop_penalty(batman_packet->tq);
|
batman_packet->tq = hop_penalty(batman_packet->tq);
|
||||||
|
|
||||||
bat_dbg(DBG_BATMAN, "Forwarding packet: tq_orig: %i, tq_avg: %i, "
|
bat_dbg(DBG_BATMAN, bat_priv,
|
||||||
|
"Forwarding packet: tq_orig: %i, tq_avg: %i, "
|
||||||
"tq_forw: %i, ttl_orig: %i, ttl_forw: %i\n",
|
"tq_forw: %i, ttl_orig: %i, ttl_forw: %i\n",
|
||||||
in_tq, tq_avg, batman_packet->tq, in_ttl - 1,
|
in_tq, tq_avg, batman_packet->tq, in_ttl - 1,
|
||||||
batman_packet->ttl);
|
batman_packet->ttl);
|
||||||
|
|
||||||
batman_packet->seqno = htons(batman_packet->seqno);
|
batman_packet->seqno = htonl(batman_packet->seqno);
|
||||||
|
|
||||||
|
/* switch of primaries first hop flag when forwarding */
|
||||||
|
batman_packet->flags &= ~PRIMARIES_FIRST_HOP;
|
||||||
if (directlink)
|
if (directlink)
|
||||||
batman_packet->flags |= DIRECTLINK;
|
batman_packet->flags |= DIRECTLINK;
|
||||||
else
|
else
|
||||||
|
@ -392,9 +404,12 @@ static void _add_bcast_packet_to_list(struct forw_packet *forw_packet,
|
||||||
int add_bcast_packet_to_list(struct sk_buff *skb)
|
int add_bcast_packet_to_list(struct sk_buff *skb)
|
||||||
{
|
{
|
||||||
struct forw_packet *forw_packet;
|
struct forw_packet *forw_packet;
|
||||||
|
struct bcast_packet *bcast_packet;
|
||||||
|
/* FIXME: each batman_if will be attached to a softif */
|
||||||
|
struct bat_priv *bat_priv = netdev_priv(soft_device);
|
||||||
|
|
||||||
if (!atomic_dec_not_zero(&bcast_queue_left)) {
|
if (!atomic_dec_not_zero(&bcast_queue_left)) {
|
||||||
bat_dbg(DBG_BATMAN, "bcast packet queue full\n");
|
bat_dbg(DBG_BATMAN, bat_priv, "bcast packet queue full\n");
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -407,6 +422,10 @@ int add_bcast_packet_to_list(struct sk_buff *skb)
|
||||||
if (!skb)
|
if (!skb)
|
||||||
goto packet_free;
|
goto packet_free;
|
||||||
|
|
||||||
|
/* as we have a copy now, it is safe to decrease the TTL */
|
||||||
|
bcast_packet = (struct bcast_packet *)skb->data;
|
||||||
|
bcast_packet->ttl--;
|
||||||
|
|
||||||
skb_reset_mac_header(skb);
|
skb_reset_mac_header(skb);
|
||||||
|
|
||||||
forw_packet->skb = skb;
|
forw_packet->skb = skb;
|
||||||
|
@ -426,7 +445,7 @@ out:
|
||||||
return NETDEV_TX_BUSY;
|
return NETDEV_TX_BUSY;
|
||||||
}
|
}
|
||||||
|
|
||||||
void send_outstanding_bcast_packet(struct work_struct *work)
|
static void send_outstanding_bcast_packet(struct work_struct *work)
|
||||||
{
|
{
|
||||||
struct batman_if *batman_if;
|
struct batman_if *batman_if;
|
||||||
struct delayed_work *delayed_work =
|
struct delayed_work *delayed_work =
|
||||||
|
@ -450,7 +469,7 @@ void send_outstanding_bcast_packet(struct work_struct *work)
|
||||||
skb1 = skb_copy(forw_packet->skb, GFP_ATOMIC);
|
skb1 = skb_copy(forw_packet->skb, GFP_ATOMIC);
|
||||||
if (skb1)
|
if (skb1)
|
||||||
send_skb_packet(skb1,
|
send_skb_packet(skb1,
|
||||||
batman_if, broadcastAddr);
|
batman_if, broadcast_addr);
|
||||||
}
|
}
|
||||||
rcu_read_unlock();
|
rcu_read_unlock();
|
||||||
|
|
||||||
|
@ -502,15 +521,19 @@ out:
|
||||||
|
|
||||||
void purge_outstanding_packets(struct batman_if *batman_if)
|
void purge_outstanding_packets(struct batman_if *batman_if)
|
||||||
{
|
{
|
||||||
|
/* FIXME: each batman_if will be attached to a softif */
|
||||||
|
struct bat_priv *bat_priv = netdev_priv(soft_device);
|
||||||
struct forw_packet *forw_packet;
|
struct forw_packet *forw_packet;
|
||||||
struct hlist_node *tmp_node, *safe_tmp_node;
|
struct hlist_node *tmp_node, *safe_tmp_node;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
if (batman_if)
|
if (batman_if)
|
||||||
bat_dbg(DBG_BATMAN, "purge_outstanding_packets(): %s\n",
|
bat_dbg(DBG_BATMAN, bat_priv,
|
||||||
|
"purge_outstanding_packets(): %s\n",
|
||||||
batman_if->dev);
|
batman_if->dev);
|
||||||
else
|
else
|
||||||
bat_dbg(DBG_BATMAN, "purge_outstanding_packets()\n");
|
bat_dbg(DBG_BATMAN, bat_priv,
|
||||||
|
"purge_outstanding_packets()\n");
|
||||||
|
|
||||||
/* free bcast list */
|
/* free bcast list */
|
||||||
spin_lock_irqsave(&forw_bcast_list_lock, flags);
|
spin_lock_irqsave(&forw_bcast_list_lock, flags);
|
||||||
|
|
|
@ -19,9 +19,11 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#ifndef _NET_BATMAN_ADV_SEND_H_
|
||||||
|
#define _NET_BATMAN_ADV_SEND_H_
|
||||||
|
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
|
|
||||||
void send_own_packet_work(struct work_struct *work);
|
|
||||||
int send_skb_packet(struct sk_buff *skb,
|
int send_skb_packet(struct sk_buff *skb,
|
||||||
struct batman_if *batman_if,
|
struct batman_if *batman_if,
|
||||||
uint8_t *dst_addr);
|
uint8_t *dst_addr);
|
||||||
|
@ -34,6 +36,7 @@ void schedule_forward_packet(struct orig_node *orig_node,
|
||||||
uint8_t directlink, int hna_buff_len,
|
uint8_t directlink, int hna_buff_len,
|
||||||
struct batman_if *if_outgoing);
|
struct batman_if *if_outgoing);
|
||||||
int add_bcast_packet_to_list(struct sk_buff *skb);
|
int add_bcast_packet_to_list(struct sk_buff *skb);
|
||||||
void send_outstanding_bcast_packet(struct work_struct *work);
|
|
||||||
void send_outstanding_bat_packet(struct work_struct *work);
|
void send_outstanding_bat_packet(struct work_struct *work);
|
||||||
void purge_outstanding_packets(struct batman_if *batman_if);
|
void purge_outstanding_packets(struct batman_if *batman_if);
|
||||||
|
|
||||||
|
#endif /* _NET_BATMAN_ADV_SEND_H_ */
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
#include "soft-interface.h"
|
#include "soft-interface.h"
|
||||||
#include "hard-interface.h"
|
#include "hard-interface.h"
|
||||||
|
#include "routing.h"
|
||||||
#include "send.h"
|
#include "send.h"
|
||||||
#include "translation-table.h"
|
#include "translation-table.h"
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
|
@ -30,13 +31,12 @@
|
||||||
#include <linux/ethtool.h>
|
#include <linux/ethtool.h>
|
||||||
#include <linux/etherdevice.h>
|
#include <linux/etherdevice.h>
|
||||||
|
|
||||||
static uint16_t bcast_seqno = 1; /* give own bcast messages seq numbers to avoid
|
static uint32_t bcast_seqno = 1; /* give own bcast messages seq numbers to avoid
|
||||||
* broadcast storms */
|
* broadcast storms */
|
||||||
static int32_t skb_packets;
|
static int32_t skb_packets;
|
||||||
static int32_t skb_bad_packets;
|
static int32_t skb_bad_packets;
|
||||||
|
|
||||||
unsigned char mainIfAddr[ETH_ALEN];
|
unsigned char main_if_addr[ETH_ALEN];
|
||||||
static unsigned char mainIfAddr_default[ETH_ALEN];
|
|
||||||
static int bat_get_settings(struct net_device *dev, struct ethtool_cmd *cmd);
|
static int bat_get_settings(struct net_device *dev, struct ethtool_cmd *cmd);
|
||||||
static void bat_get_drvinfo(struct net_device *dev,
|
static void bat_get_drvinfo(struct net_device *dev,
|
||||||
struct ethtool_drvinfo *info);
|
struct ethtool_drvinfo *info);
|
||||||
|
@ -58,12 +58,7 @@ static const struct ethtool_ops bat_ethtool_ops = {
|
||||||
|
|
||||||
void set_main_if_addr(uint8_t *addr)
|
void set_main_if_addr(uint8_t *addr)
|
||||||
{
|
{
|
||||||
memcpy(mainIfAddr, addr, ETH_ALEN);
|
memcpy(main_if_addr, addr, ETH_ALEN);
|
||||||
}
|
|
||||||
|
|
||||||
int main_if_was_up(void)
|
|
||||||
{
|
|
||||||
return (memcmp(mainIfAddr, mainIfAddr_default, ETH_ALEN) != 0 ? 1 : 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int my_skb_push(struct sk_buff *skb, unsigned int len)
|
int my_skb_push(struct sk_buff *skb, unsigned int len)
|
||||||
|
@ -83,69 +78,25 @@ int my_skb_push(struct sk_buff *skb, unsigned int len)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_NET_DEVICE_OPS
|
static int interface_open(struct net_device *dev)
|
||||||
static const struct net_device_ops bat_netdev_ops = {
|
|
||||||
.ndo_open = interface_open,
|
|
||||||
.ndo_stop = interface_release,
|
|
||||||
.ndo_get_stats = interface_stats,
|
|
||||||
.ndo_set_mac_address = interface_set_mac_addr,
|
|
||||||
.ndo_change_mtu = interface_change_mtu,
|
|
||||||
.ndo_start_xmit = interface_tx,
|
|
||||||
.ndo_validate_addr = eth_validate_addr
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void interface_setup(struct net_device *dev)
|
|
||||||
{
|
|
||||||
struct bat_priv *priv = netdev_priv(dev);
|
|
||||||
char dev_addr[ETH_ALEN];
|
|
||||||
|
|
||||||
ether_setup(dev);
|
|
||||||
|
|
||||||
#ifdef HAVE_NET_DEVICE_OPS
|
|
||||||
dev->netdev_ops = &bat_netdev_ops;
|
|
||||||
#else
|
|
||||||
dev->open = interface_open;
|
|
||||||
dev->stop = interface_release;
|
|
||||||
dev->get_stats = interface_stats;
|
|
||||||
dev->set_mac_address = interface_set_mac_addr;
|
|
||||||
dev->change_mtu = interface_change_mtu;
|
|
||||||
dev->hard_start_xmit = interface_tx;
|
|
||||||
#endif
|
|
||||||
dev->destructor = free_netdev;
|
|
||||||
|
|
||||||
dev->mtu = hardif_min_mtu();
|
|
||||||
dev->hard_header_len = BAT_HEADER_LEN; /* reserve more space in the
|
|
||||||
* skbuff for our header */
|
|
||||||
|
|
||||||
/* generate random address */
|
|
||||||
random_ether_addr(dev_addr);
|
|
||||||
memcpy(dev->dev_addr, dev_addr, ETH_ALEN);
|
|
||||||
|
|
||||||
SET_ETHTOOL_OPS(dev, &bat_ethtool_ops);
|
|
||||||
|
|
||||||
memset(priv, 0, sizeof(struct bat_priv));
|
|
||||||
}
|
|
||||||
|
|
||||||
int interface_open(struct net_device *dev)
|
|
||||||
{
|
{
|
||||||
netif_start_queue(dev);
|
netif_start_queue(dev);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int interface_release(struct net_device *dev)
|
static int interface_release(struct net_device *dev)
|
||||||
{
|
{
|
||||||
netif_stop_queue(dev);
|
netif_stop_queue(dev);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct net_device_stats *interface_stats(struct net_device *dev)
|
static struct net_device_stats *interface_stats(struct net_device *dev)
|
||||||
{
|
{
|
||||||
struct bat_priv *priv = netdev_priv(dev);
|
struct bat_priv *priv = netdev_priv(dev);
|
||||||
return &priv->stats;
|
return &priv->stats;
|
||||||
}
|
}
|
||||||
|
|
||||||
int interface_set_mac_addr(struct net_device *dev, void *p)
|
static int interface_set_mac_addr(struct net_device *dev, void *p)
|
||||||
{
|
{
|
||||||
struct sockaddr *addr = p;
|
struct sockaddr *addr = p;
|
||||||
|
|
||||||
|
@ -163,7 +114,7 @@ int interface_set_mac_addr(struct net_device *dev, void *p)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int interface_change_mtu(struct net_device *dev, int new_mtu)
|
static int interface_change_mtu(struct net_device *dev, int new_mtu)
|
||||||
{
|
{
|
||||||
/* check ranges */
|
/* check ranges */
|
||||||
if ((new_mtu < 68) || (new_mtu > hardif_min_mtu()))
|
if ((new_mtu < 68) || (new_mtu > hardif_min_mtu()))
|
||||||
|
@ -179,6 +130,7 @@ int interface_tx(struct sk_buff *skb, struct net_device *dev)
|
||||||
struct unicast_packet *unicast_packet;
|
struct unicast_packet *unicast_packet;
|
||||||
struct bcast_packet *bcast_packet;
|
struct bcast_packet *bcast_packet;
|
||||||
struct orig_node *orig_node;
|
struct orig_node *orig_node;
|
||||||
|
struct neigh_node *router;
|
||||||
struct ethhdr *ethhdr = (struct ethhdr *)skb->data;
|
struct ethhdr *ethhdr = (struct ethhdr *)skb->data;
|
||||||
struct bat_priv *priv = netdev_priv(dev);
|
struct bat_priv *priv = netdev_priv(dev);
|
||||||
struct batman_if *batman_if;
|
struct batman_if *batman_if;
|
||||||
|
@ -205,16 +157,17 @@ int interface_tx(struct sk_buff *skb, struct net_device *dev)
|
||||||
|
|
||||||
bcast_packet = (struct bcast_packet *)skb->data;
|
bcast_packet = (struct bcast_packet *)skb->data;
|
||||||
bcast_packet->version = COMPAT_VERSION;
|
bcast_packet->version = COMPAT_VERSION;
|
||||||
|
bcast_packet->ttl = TTL;
|
||||||
|
|
||||||
/* batman packet type: broadcast */
|
/* batman packet type: broadcast */
|
||||||
bcast_packet->packet_type = BAT_BCAST;
|
bcast_packet->packet_type = BAT_BCAST;
|
||||||
|
|
||||||
/* hw address of first interface is the orig mac because only
|
/* hw address of first interface is the orig mac because only
|
||||||
* this mac is known throughout the mesh */
|
* this mac is known throughout the mesh */
|
||||||
memcpy(bcast_packet->orig, mainIfAddr, ETH_ALEN);
|
memcpy(bcast_packet->orig, main_if_addr, ETH_ALEN);
|
||||||
|
|
||||||
/* set broadcast sequence number */
|
/* set broadcast sequence number */
|
||||||
bcast_packet->seqno = htons(bcast_seqno);
|
bcast_packet->seqno = htonl(bcast_seqno);
|
||||||
|
|
||||||
/* broadcast packet. on success, increase seqno. */
|
/* broadcast packet. on success, increase seqno. */
|
||||||
if (add_bcast_packet_to_list(skb) == NETDEV_TX_OK)
|
if (add_bcast_packet_to_list(skb) == NETDEV_TX_OK)
|
||||||
|
@ -235,12 +188,24 @@ int interface_tx(struct sk_buff *skb, struct net_device *dev)
|
||||||
if (!orig_node)
|
if (!orig_node)
|
||||||
orig_node = transtable_search(ethhdr->h_dest);
|
orig_node = transtable_search(ethhdr->h_dest);
|
||||||
|
|
||||||
if ((orig_node) &&
|
router = find_router(orig_node, NULL);
|
||||||
(orig_node->router)) {
|
|
||||||
struct neigh_node *router = orig_node->router;
|
if (!router)
|
||||||
|
goto unlock;
|
||||||
|
|
||||||
|
/* don't lock while sending the packets ... we therefore
|
||||||
|
* copy the required data before sending */
|
||||||
|
|
||||||
|
batman_if = router->if_incoming;
|
||||||
|
memcpy(dstaddr, router->addr, ETH_ALEN);
|
||||||
|
|
||||||
|
spin_unlock_irqrestore(&orig_hash_lock, flags);
|
||||||
|
|
||||||
|
if (batman_if->if_status != IF_ACTIVE)
|
||||||
|
goto dropped;
|
||||||
|
|
||||||
if (my_skb_push(skb, sizeof(struct unicast_packet)) < 0)
|
if (my_skb_push(skb, sizeof(struct unicast_packet)) < 0)
|
||||||
goto unlock;
|
goto dropped;
|
||||||
|
|
||||||
unicast_packet = (struct unicast_packet *)skb->data;
|
unicast_packet = (struct unicast_packet *)skb->data;
|
||||||
|
|
||||||
|
@ -252,21 +217,7 @@ int interface_tx(struct sk_buff *skb, struct net_device *dev)
|
||||||
/* copy the destination for faster routing */
|
/* copy the destination for faster routing */
|
||||||
memcpy(unicast_packet->dest, orig_node->orig, ETH_ALEN);
|
memcpy(unicast_packet->dest, orig_node->orig, ETH_ALEN);
|
||||||
|
|
||||||
/* net_dev won't be available when not active */
|
|
||||||
if (router->if_incoming->if_status != IF_ACTIVE)
|
|
||||||
goto unlock;
|
|
||||||
|
|
||||||
/* don't lock while sending the packets ... we therefore
|
|
||||||
* copy the required data before sending */
|
|
||||||
|
|
||||||
batman_if = router->if_incoming;
|
|
||||||
memcpy(dstaddr, router->addr, ETH_ALEN);
|
|
||||||
spin_unlock_irqrestore(&orig_hash_lock, flags);
|
|
||||||
|
|
||||||
send_skb_packet(skb, batman_if, dstaddr);
|
send_skb_packet(skb, batman_if, dstaddr);
|
||||||
} else {
|
|
||||||
goto unlock;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
priv->stats.tx_packets++;
|
priv->stats.tx_packets++;
|
||||||
|
@ -315,6 +266,50 @@ void interface_rx(struct sk_buff *skb, int hdr_size)
|
||||||
netif_rx(skb);
|
netif_rx(skb);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_NET_DEVICE_OPS
|
||||||
|
static const struct net_device_ops bat_netdev_ops = {
|
||||||
|
.ndo_open = interface_open,
|
||||||
|
.ndo_stop = interface_release,
|
||||||
|
.ndo_get_stats = interface_stats,
|
||||||
|
.ndo_set_mac_address = interface_set_mac_addr,
|
||||||
|
.ndo_change_mtu = interface_change_mtu,
|
||||||
|
.ndo_start_xmit = interface_tx,
|
||||||
|
.ndo_validate_addr = eth_validate_addr
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void interface_setup(struct net_device *dev)
|
||||||
|
{
|
||||||
|
struct bat_priv *priv = netdev_priv(dev);
|
||||||
|
char dev_addr[ETH_ALEN];
|
||||||
|
|
||||||
|
ether_setup(dev);
|
||||||
|
|
||||||
|
#ifdef HAVE_NET_DEVICE_OPS
|
||||||
|
dev->netdev_ops = &bat_netdev_ops;
|
||||||
|
#else
|
||||||
|
dev->open = interface_open;
|
||||||
|
dev->stop = interface_release;
|
||||||
|
dev->get_stats = interface_stats;
|
||||||
|
dev->set_mac_address = interface_set_mac_addr;
|
||||||
|
dev->change_mtu = interface_change_mtu;
|
||||||
|
dev->hard_start_xmit = interface_tx;
|
||||||
|
#endif
|
||||||
|
dev->destructor = free_netdev;
|
||||||
|
|
||||||
|
dev->mtu = hardif_min_mtu();
|
||||||
|
dev->hard_header_len = BAT_HEADER_LEN; /* reserve more space in the
|
||||||
|
* skbuff for our header */
|
||||||
|
|
||||||
|
/* generate random address */
|
||||||
|
random_ether_addr(dev_addr);
|
||||||
|
memcpy(dev->dev_addr, dev_addr, ETH_ALEN);
|
||||||
|
|
||||||
|
SET_ETHTOOL_OPS(dev, &bat_ethtool_ops);
|
||||||
|
|
||||||
|
memset(priv, 0, sizeof(struct bat_priv));
|
||||||
|
}
|
||||||
|
|
||||||
/* ethtool */
|
/* ethtool */
|
||||||
static int bat_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
|
static int bat_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
|
||||||
{
|
{
|
||||||
|
|
|
@ -19,16 +19,15 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#ifndef _NET_BATMAN_ADV_SOFT_INTERFACE_H_
|
||||||
|
#define _NET_BATMAN_ADV_SOFT_INTERFACE_H_
|
||||||
|
|
||||||
void set_main_if_addr(uint8_t *addr);
|
void set_main_if_addr(uint8_t *addr);
|
||||||
int main_if_was_up(void);
|
|
||||||
void interface_setup(struct net_device *dev);
|
void interface_setup(struct net_device *dev);
|
||||||
int interface_open(struct net_device *dev);
|
|
||||||
int interface_release(struct net_device *dev);
|
|
||||||
struct net_device_stats *interface_stats(struct net_device *dev);
|
|
||||||
int interface_set_mac_addr(struct net_device *dev, void *addr);
|
|
||||||
int interface_change_mtu(struct net_device *dev, int new_mtu);
|
|
||||||
int interface_tx(struct sk_buff *skb, struct net_device *dev);
|
int interface_tx(struct sk_buff *skb, struct net_device *dev);
|
||||||
void interface_rx(struct sk_buff *skb, int hdr_size);
|
void interface_rx(struct sk_buff *skb, int hdr_size);
|
||||||
int my_skb_push(struct sk_buff *skb, unsigned int len);
|
int my_skb_push(struct sk_buff *skb, unsigned int len);
|
||||||
|
|
||||||
extern unsigned char mainIfAddr[];
|
extern unsigned char main_if_addr[];
|
||||||
|
|
||||||
|
#endif /* _NET_BATMAN_ADV_SOFT_INTERFACE_H_ */
|
||||||
|
|
|
@ -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.
|
|
@ -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);
|
DEFINE_SPINLOCK(hna_local_hash_lock);
|
||||||
static DEFINE_SPINLOCK(hna_global_hash_lock);
|
static DEFINE_SPINLOCK(hna_global_hash_lock);
|
||||||
|
|
||||||
|
static void hna_local_purge(struct work_struct *work);
|
||||||
static DECLARE_DELAYED_WORK(hna_local_purge_wq, hna_local_purge);
|
static DECLARE_DELAYED_WORK(hna_local_purge_wq, hna_local_purge);
|
||||||
|
static void _hna_global_del_orig(struct hna_global_entry *hna_global_entry,
|
||||||
|
char *message);
|
||||||
|
|
||||||
static void hna_local_start_timer(void)
|
static void hna_local_start_timer(void)
|
||||||
{
|
{
|
||||||
|
@ -57,6 +60,8 @@ int hna_local_init(void)
|
||||||
|
|
||||||
void hna_local_add(uint8_t *addr)
|
void hna_local_add(uint8_t *addr)
|
||||||
{
|
{
|
||||||
|
/* FIXME: each orig_node->batman_if will be attached to a softif */
|
||||||
|
struct bat_priv *bat_priv = netdev_priv(soft_device);
|
||||||
struct hna_local_entry *hna_local_entry;
|
struct hna_local_entry *hna_local_entry;
|
||||||
struct hna_global_entry *hna_global_entry;
|
struct hna_global_entry *hna_global_entry;
|
||||||
struct hashtable_t *swaphash;
|
struct hashtable_t *swaphash;
|
||||||
|
@ -77,15 +82,15 @@ void hna_local_add(uint8_t *addr)
|
||||||
MAC-flooding. */
|
MAC-flooding. */
|
||||||
if ((num_hna + 1 > (ETH_DATA_LEN - BAT_PACKET_LEN) / ETH_ALEN) ||
|
if ((num_hna + 1 > (ETH_DATA_LEN - BAT_PACKET_LEN) / ETH_ALEN) ||
|
||||||
(num_hna + 1 > 255)) {
|
(num_hna + 1 > 255)) {
|
||||||
bat_dbg(DBG_ROUTES,
|
bat_dbg(DBG_ROUTES, bat_priv,
|
||||||
"Can't add new local hna entry (%pM): "
|
"Can't add new local hna entry (%pM): "
|
||||||
"number of local hna entries exceeds packet size\n",
|
"number of local hna entries exceeds packet size\n",
|
||||||
addr);
|
addr);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
bat_dbg(DBG_ROUTES, "Creating new local hna entry: %pM\n",
|
bat_dbg(DBG_ROUTES, bat_priv,
|
||||||
addr);
|
"Creating new local hna entry: %pM\n", addr);
|
||||||
|
|
||||||
hna_local_entry = kmalloc(sizeof(struct hna_local_entry), GFP_ATOMIC);
|
hna_local_entry = kmalloc(sizeof(struct hna_local_entry), GFP_ATOMIC);
|
||||||
if (!hna_local_entry)
|
if (!hna_local_entry)
|
||||||
|
@ -111,8 +116,7 @@ void hna_local_add(uint8_t *addr)
|
||||||
hna_local_hash->size * 2);
|
hna_local_hash->size * 2);
|
||||||
|
|
||||||
if (swaphash == NULL)
|
if (swaphash == NULL)
|
||||||
printk(KERN_ERR "batman-adv:"
|
pr_err("Couldn't resize local hna hash table\n");
|
||||||
"Couldn't resize local hna hash table\n");
|
|
||||||
else
|
else
|
||||||
hna_local_hash = swaphash;
|
hna_local_hash = swaphash;
|
||||||
}
|
}
|
||||||
|
@ -160,59 +164,54 @@ int hna_local_fill_buffer(unsigned char *buff, int buff_len)
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
int hna_local_fill_buffer_text(struct net_device *net_dev, char *buff,
|
int hna_local_seq_print_text(struct seq_file *seq, void *offset)
|
||||||
size_t count, loff_t off)
|
|
||||||
{
|
{
|
||||||
|
struct net_device *net_dev = (struct net_device *)seq->private;
|
||||||
struct bat_priv *bat_priv = netdev_priv(net_dev);
|
struct bat_priv *bat_priv = netdev_priv(net_dev);
|
||||||
struct hna_local_entry *hna_local_entry;
|
struct hna_local_entry *hna_local_entry;
|
||||||
HASHIT(hashit);
|
HASHIT(hashit);
|
||||||
int bytes_written = 0;
|
HASHIT(hashit_count);
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
size_t hdr_len;
|
size_t buf_size, pos;
|
||||||
|
char *buff;
|
||||||
|
|
||||||
if (!bat_priv->primary_if) {
|
if (!bat_priv->primary_if) {
|
||||||
if (off == 0)
|
return seq_printf(seq, "BATMAN mesh %s disabled - "
|
||||||
return sprintf(buff,
|
|
||||||
"BATMAN mesh %s disabled - "
|
|
||||||
"please specify interfaces to enable it\n",
|
"please specify interfaces to enable it\n",
|
||||||
net_dev->name);
|
net_dev->name);
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
hdr_len = sprintf(buff,
|
seq_printf(seq, "Locally retrieved addresses (from %s) "
|
||||||
"Locally retrieved addresses (from %s) "
|
|
||||||
"announced via HNA:\n",
|
"announced via HNA:\n",
|
||||||
net_dev->name);
|
net_dev->name);
|
||||||
|
|
||||||
if (off < hdr_len)
|
|
||||||
bytes_written = hdr_len;
|
|
||||||
|
|
||||||
spin_lock_irqsave(&hna_local_hash_lock, flags);
|
spin_lock_irqsave(&hna_local_hash_lock, flags);
|
||||||
|
|
||||||
|
buf_size = 1;
|
||||||
|
/* Estimate length for: " * xx:xx:xx:xx:xx:xx\n" */
|
||||||
|
while (hash_iterate(hna_local_hash, &hashit_count))
|
||||||
|
buf_size += 21;
|
||||||
|
|
||||||
|
buff = kmalloc(buf_size, GFP_ATOMIC);
|
||||||
|
if (!buff) {
|
||||||
|
spin_unlock_irqrestore(&hna_local_hash_lock, flags);
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
buff[0] = '\0';
|
||||||
|
pos = 0;
|
||||||
|
|
||||||
while (hash_iterate(hna_local_hash, &hashit)) {
|
while (hash_iterate(hna_local_hash, &hashit)) {
|
||||||
hdr_len += 21;
|
|
||||||
|
|
||||||
if (count < bytes_written + 22)
|
|
||||||
break;
|
|
||||||
|
|
||||||
if (off >= hdr_len)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
hna_local_entry = hashit.bucket->data;
|
hna_local_entry = hashit.bucket->data;
|
||||||
|
|
||||||
bytes_written += snprintf(buff + bytes_written, 22,
|
pos += snprintf(buff + pos, 22, " * %pM\n",
|
||||||
" * " MAC_FMT "\n",
|
hna_local_entry->addr);
|
||||||
hna_local_entry->addr[0],
|
|
||||||
hna_local_entry->addr[1],
|
|
||||||
hna_local_entry->addr[2],
|
|
||||||
hna_local_entry->addr[3],
|
|
||||||
hna_local_entry->addr[4],
|
|
||||||
hna_local_entry->addr[5]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
spin_unlock_irqrestore(&hna_local_hash_lock, flags);
|
spin_unlock_irqrestore(&hna_local_hash_lock, flags);
|
||||||
return bytes_written;
|
|
||||||
|
seq_printf(seq, "%s", buff);
|
||||||
|
kfree(buff);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _hna_local_del(void *data)
|
static void _hna_local_del(void *data)
|
||||||
|
@ -225,7 +224,9 @@ static void _hna_local_del(void *data)
|
||||||
static void hna_local_del(struct hna_local_entry *hna_local_entry,
|
static void hna_local_del(struct hna_local_entry *hna_local_entry,
|
||||||
char *message)
|
char *message)
|
||||||
{
|
{
|
||||||
bat_dbg(DBG_ROUTES, "Deleting local hna entry (%pM): %s\n",
|
/* FIXME: each orig_node->batman_if will be attached to a softif */
|
||||||
|
struct bat_priv *bat_priv = netdev_priv(soft_device);
|
||||||
|
bat_dbg(DBG_ROUTES, bat_priv, "Deleting local hna entry (%pM): %s\n",
|
||||||
hna_local_entry->addr, message);
|
hna_local_entry->addr, message);
|
||||||
|
|
||||||
hash_remove(hna_local_hash, hna_local_entry->addr);
|
hash_remove(hna_local_hash, hna_local_entry->addr);
|
||||||
|
@ -247,7 +248,7 @@ void hna_local_remove(uint8_t *addr, char *message)
|
||||||
spin_unlock_irqrestore(&hna_local_hash_lock, flags);
|
spin_unlock_irqrestore(&hna_local_hash_lock, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
void hna_local_purge(struct work_struct *work)
|
static void hna_local_purge(struct work_struct *work)
|
||||||
{
|
{
|
||||||
struct hna_local_entry *hna_local_entry;
|
struct hna_local_entry *hna_local_entry;
|
||||||
HASHIT(hashit);
|
HASHIT(hashit);
|
||||||
|
@ -259,8 +260,7 @@ void hna_local_purge(struct work_struct *work)
|
||||||
while (hash_iterate(hna_local_hash, &hashit)) {
|
while (hash_iterate(hna_local_hash, &hashit)) {
|
||||||
hna_local_entry = hashit.bucket->data;
|
hna_local_entry = hashit.bucket->data;
|
||||||
|
|
||||||
timeout = hna_local_entry->last_seen +
|
timeout = hna_local_entry->last_seen + LOCAL_HNA_TIMEOUT * HZ;
|
||||||
((LOCAL_HNA_TIMEOUT / 1000) * HZ);
|
|
||||||
if ((!hna_local_entry->never_purge) &&
|
if ((!hna_local_entry->never_purge) &&
|
||||||
time_after(jiffies, timeout))
|
time_after(jiffies, timeout))
|
||||||
hna_local_del(hna_local_entry, "address timed out");
|
hna_local_del(hna_local_entry, "address timed out");
|
||||||
|
@ -296,6 +296,8 @@ int hna_global_init(void)
|
||||||
void hna_global_add_orig(struct orig_node *orig_node,
|
void hna_global_add_orig(struct orig_node *orig_node,
|
||||||
unsigned char *hna_buff, int hna_buff_len)
|
unsigned char *hna_buff, int hna_buff_len)
|
||||||
{
|
{
|
||||||
|
/* FIXME: each orig_node->batman_if will be attached to a softif */
|
||||||
|
struct bat_priv *bat_priv = netdev_priv(soft_device);
|
||||||
struct hna_global_entry *hna_global_entry;
|
struct hna_global_entry *hna_global_entry;
|
||||||
struct hna_local_entry *hna_local_entry;
|
struct hna_local_entry *hna_local_entry;
|
||||||
struct hashtable_t *swaphash;
|
struct hashtable_t *swaphash;
|
||||||
|
@ -322,7 +324,7 @@ void hna_global_add_orig(struct orig_node *orig_node,
|
||||||
|
|
||||||
memcpy(hna_global_entry->addr, hna_ptr, ETH_ALEN);
|
memcpy(hna_global_entry->addr, hna_ptr, ETH_ALEN);
|
||||||
|
|
||||||
bat_dbg(DBG_ROUTES,
|
bat_dbg(DBG_ROUTES, bat_priv,
|
||||||
"Creating new global hna entry: "
|
"Creating new global hna entry: "
|
||||||
"%pM (via %pM)\n",
|
"%pM (via %pM)\n",
|
||||||
hna_global_entry->addr, orig_node->orig);
|
hna_global_entry->addr, orig_node->orig);
|
||||||
|
@ -369,8 +371,7 @@ void hna_global_add_orig(struct orig_node *orig_node,
|
||||||
hna_global_hash->size * 2);
|
hna_global_hash->size * 2);
|
||||||
|
|
||||||
if (swaphash == NULL)
|
if (swaphash == NULL)
|
||||||
printk(KERN_ERR "batman-adv:"
|
pr_err("Couldn't resize global hna hash table\n");
|
||||||
"Couldn't resize global hna hash table\n");
|
|
||||||
else
|
else
|
||||||
hna_global_hash = swaphash;
|
hna_global_hash = swaphash;
|
||||||
}
|
}
|
||||||
|
@ -378,71 +379,63 @@ void hna_global_add_orig(struct orig_node *orig_node,
|
||||||
spin_unlock_irqrestore(&hna_global_hash_lock, flags);
|
spin_unlock_irqrestore(&hna_global_hash_lock, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
int hna_global_fill_buffer_text(struct net_device *net_dev, char *buff,
|
int hna_global_seq_print_text(struct seq_file *seq, void *offset)
|
||||||
size_t count, loff_t off)
|
|
||||||
{
|
{
|
||||||
|
struct net_device *net_dev = (struct net_device *)seq->private;
|
||||||
struct bat_priv *bat_priv = netdev_priv(net_dev);
|
struct bat_priv *bat_priv = netdev_priv(net_dev);
|
||||||
struct hna_global_entry *hna_global_entry;
|
struct hna_global_entry *hna_global_entry;
|
||||||
HASHIT(hashit);
|
HASHIT(hashit);
|
||||||
int bytes_written = 0;
|
HASHIT(hashit_count);
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
size_t hdr_len;
|
size_t buf_size, pos;
|
||||||
|
char *buff;
|
||||||
|
|
||||||
if (!bat_priv->primary_if) {
|
if (!bat_priv->primary_if) {
|
||||||
if (off == 0)
|
return seq_printf(seq, "BATMAN mesh %s disabled - "
|
||||||
return sprintf(buff,
|
|
||||||
"BATMAN mesh %s disabled - "
|
|
||||||
"please specify interfaces to enable it\n",
|
"please specify interfaces to enable it\n",
|
||||||
net_dev->name);
|
net_dev->name);
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
hdr_len = sprintf(buff,
|
seq_printf(seq, "Globally announced HNAs received via the mesh %s\n",
|
||||||
"Globally announced HNAs received via the mesh %s "
|
|
||||||
"(translation table):\n",
|
|
||||||
net_dev->name);
|
net_dev->name);
|
||||||
|
|
||||||
if (off < hdr_len)
|
|
||||||
bytes_written = hdr_len;
|
|
||||||
|
|
||||||
spin_lock_irqsave(&hna_global_hash_lock, flags);
|
spin_lock_irqsave(&hna_global_hash_lock, flags);
|
||||||
|
|
||||||
|
buf_size = 1;
|
||||||
|
/* Estimate length for: " * xx:xx:xx:xx:xx:xx via xx:xx:xx:xx:xx:xx\n"*/
|
||||||
|
while (hash_iterate(hna_global_hash, &hashit_count))
|
||||||
|
buf_size += 43;
|
||||||
|
|
||||||
|
buff = kmalloc(buf_size, GFP_ATOMIC);
|
||||||
|
if (!buff) {
|
||||||
|
spin_unlock_irqrestore(&hna_global_hash_lock, flags);
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
buff[0] = '\0';
|
||||||
|
pos = 0;
|
||||||
|
|
||||||
while (hash_iterate(hna_global_hash, &hashit)) {
|
while (hash_iterate(hna_global_hash, &hashit)) {
|
||||||
hdr_len += 43;
|
|
||||||
|
|
||||||
if (count < bytes_written + 44)
|
|
||||||
break;
|
|
||||||
|
|
||||||
if (off >= hdr_len)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
hna_global_entry = hashit.bucket->data;
|
hna_global_entry = hashit.bucket->data;
|
||||||
|
|
||||||
bytes_written += snprintf(buff + bytes_written, 44,
|
pos += snprintf(buff + pos, 44,
|
||||||
" * " MAC_FMT " via " MAC_FMT "\n",
|
" * %pM via %pM\n", hna_global_entry->addr,
|
||||||
hna_global_entry->addr[0],
|
hna_global_entry->orig_node->orig);
|
||||||
hna_global_entry->addr[1],
|
|
||||||
hna_global_entry->addr[2],
|
|
||||||
hna_global_entry->addr[3],
|
|
||||||
hna_global_entry->addr[4],
|
|
||||||
hna_global_entry->addr[5],
|
|
||||||
hna_global_entry->orig_node->orig[0],
|
|
||||||
hna_global_entry->orig_node->orig[1],
|
|
||||||
hna_global_entry->orig_node->orig[2],
|
|
||||||
hna_global_entry->orig_node->orig[3],
|
|
||||||
hna_global_entry->orig_node->orig[4],
|
|
||||||
hna_global_entry->orig_node->orig[5]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
spin_unlock_irqrestore(&hna_global_hash_lock, flags);
|
spin_unlock_irqrestore(&hna_global_hash_lock, flags);
|
||||||
return bytes_written;
|
|
||||||
|
seq_printf(seq, "%s", buff);
|
||||||
|
kfree(buff);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _hna_global_del_orig(struct hna_global_entry *hna_global_entry,
|
static void _hna_global_del_orig(struct hna_global_entry *hna_global_entry,
|
||||||
char *message)
|
char *message)
|
||||||
{
|
{
|
||||||
bat_dbg(DBG_ROUTES, "Deleting global hna entry %pM (via %pM): %s\n",
|
/* FIXME: each orig_node->batman_if will be attached to a softif */
|
||||||
|
struct bat_priv *bat_priv = netdev_priv(soft_device);
|
||||||
|
bat_dbg(DBG_ROUTES, bat_priv,
|
||||||
|
"Deleting global hna entry %pM (via %pM): %s\n",
|
||||||
hna_global_entry->addr, hna_global_entry->orig_node->orig,
|
hna_global_entry->addr, hna_global_entry->orig_node->orig,
|
||||||
message);
|
message);
|
||||||
|
|
||||||
|
|
|
@ -19,23 +19,21 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#ifndef _NET_BATMAN_ADV_TRANSLATION_TABLE_H_
|
||||||
|
#define _NET_BATMAN_ADV_TRANSLATION_TABLE_H_
|
||||||
|
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
|
|
||||||
int hna_local_init(void);
|
int hna_local_init(void);
|
||||||
void hna_local_add(uint8_t *addr);
|
void hna_local_add(uint8_t *addr);
|
||||||
void hna_local_remove(uint8_t *addr, char *message);
|
void hna_local_remove(uint8_t *addr, char *message);
|
||||||
int hna_local_fill_buffer(unsigned char *buff, int buff_len);
|
int hna_local_fill_buffer(unsigned char *buff, int buff_len);
|
||||||
int hna_local_fill_buffer_text(struct net_device *net_dev, char *buff,
|
int hna_local_seq_print_text(struct seq_file *seq, void *offset);
|
||||||
size_t count, loff_t off);
|
|
||||||
void hna_local_purge(struct work_struct *work);
|
|
||||||
void hna_local_free(void);
|
void hna_local_free(void);
|
||||||
int hna_global_init(void);
|
int hna_global_init(void);
|
||||||
void hna_global_add_orig(struct orig_node *orig_node, unsigned char *hna_buff,
|
void hna_global_add_orig(struct orig_node *orig_node, unsigned char *hna_buff,
|
||||||
int hna_buff_len);
|
int hna_buff_len);
|
||||||
int hna_global_fill_buffer_text(struct net_device *net_dev, char *buff,
|
int hna_global_seq_print_text(struct seq_file *seq, void *offset);
|
||||||
size_t count, loff_t off);
|
|
||||||
void _hna_global_del_orig(struct hna_global_entry *hna_global_entry,
|
|
||||||
char *orig_str);
|
|
||||||
void hna_global_del_orig(struct orig_node *orig_node, char *message);
|
void hna_global_del_orig(struct orig_node *orig_node, char *message);
|
||||||
void hna_global_free(void);
|
void hna_global_free(void);
|
||||||
struct orig_node *transtable_search(uint8_t *addr);
|
struct orig_node *transtable_search(uint8_t *addr);
|
||||||
|
@ -43,3 +41,5 @@ struct orig_node *transtable_search(uint8_t *addr);
|
||||||
extern spinlock_t hna_local_hash_lock;
|
extern spinlock_t hna_local_hash_lock;
|
||||||
extern struct hashtable_t *hna_local_hash;
|
extern struct hashtable_t *hna_local_hash;
|
||||||
extern atomic_t hna_local_changed;
|
extern atomic_t hna_local_changed;
|
||||||
|
|
||||||
|
#endif /* _NET_BATMAN_ADV_TRANSLATION_TABLE_H_ */
|
||||||
|
|
|
@ -21,10 +21,8 @@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef _NET_BATMAN_ADV_TYPES_H_
|
||||||
|
#define _NET_BATMAN_ADV_TYPES_H_
|
||||||
#ifndef TYPES_H
|
|
||||||
#define TYPES_H
|
|
||||||
|
|
||||||
#include "packet.h"
|
#include "packet.h"
|
||||||
#include "bitarray.h"
|
#include "bitarray.h"
|
||||||
|
@ -52,6 +50,7 @@ struct batman_if {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* orig_node - structure for orig_list maintaining nodes of mesh
|
* orig_node - structure for orig_list maintaining nodes of mesh
|
||||||
|
* @primary_addr: hosts primary interface address
|
||||||
* @last_valid: when last packet from this node was received
|
* @last_valid: when last packet from this node was received
|
||||||
* @bcast_seqno_reset: time when the broadcast seqno window was reset
|
* @bcast_seqno_reset: time when the broadcast seqno window was reset
|
||||||
* @batman_seqno_reset: time when the batman seqno window was reset
|
* @batman_seqno_reset: time when the batman seqno window was reset
|
||||||
|
@ -59,9 +58,13 @@ struct batman_if {
|
||||||
* @last_real_seqno: last and best known squence number
|
* @last_real_seqno: last and best known squence number
|
||||||
* @last_ttl: ttl of last received packet
|
* @last_ttl: ttl of last received packet
|
||||||
* @last_bcast_seqno: last broadcast sequence number received by this host
|
* @last_bcast_seqno: last broadcast sequence number received by this host
|
||||||
|
*
|
||||||
|
* @candidates: how many candidates are available
|
||||||
|
* @selected: next bonding candidate
|
||||||
*/
|
*/
|
||||||
struct orig_node {
|
struct orig_node {
|
||||||
uint8_t orig[ETH_ALEN];
|
uint8_t orig[ETH_ALEN];
|
||||||
|
uint8_t primary_addr[ETH_ALEN];
|
||||||
struct neigh_node *router;
|
struct neigh_node *router;
|
||||||
TYPE_OF_WORD *bcast_own;
|
TYPE_OF_WORD *bcast_own;
|
||||||
uint8_t *bcast_own_sum;
|
uint8_t *bcast_own_sum;
|
||||||
|
@ -73,11 +76,15 @@ struct orig_node {
|
||||||
uint8_t flags;
|
uint8_t flags;
|
||||||
unsigned char *hna_buff;
|
unsigned char *hna_buff;
|
||||||
int16_t hna_buff_len;
|
int16_t hna_buff_len;
|
||||||
uint16_t last_real_seqno;
|
uint32_t last_real_seqno;
|
||||||
uint8_t last_ttl;
|
uint8_t last_ttl;
|
||||||
TYPE_OF_WORD bcast_bits[NUM_WORDS];
|
TYPE_OF_WORD bcast_bits[NUM_WORDS];
|
||||||
uint16_t last_bcast_seqno;
|
uint32_t last_bcast_seqno;
|
||||||
struct list_head neigh_list;
|
struct list_head neigh_list;
|
||||||
|
struct {
|
||||||
|
uint8_t candidates;
|
||||||
|
struct neigh_node *selected;
|
||||||
|
} bond;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -92,6 +99,7 @@ struct neigh_node {
|
||||||
uint8_t tq_index;
|
uint8_t tq_index;
|
||||||
uint8_t tq_avg;
|
uint8_t tq_avg;
|
||||||
uint8_t last_ttl;
|
uint8_t last_ttl;
|
||||||
|
struct neigh_node *next_bond_candidate;
|
||||||
unsigned long last_valid;
|
unsigned long last_valid;
|
||||||
TYPE_OF_WORD real_bits[NUM_WORDS];
|
TYPE_OF_WORD real_bits[NUM_WORDS];
|
||||||
struct orig_node *orig_node;
|
struct orig_node *orig_node;
|
||||||
|
@ -101,14 +109,18 @@ struct neigh_node {
|
||||||
struct bat_priv {
|
struct bat_priv {
|
||||||
struct net_device_stats stats;
|
struct net_device_stats stats;
|
||||||
atomic_t aggregation_enabled;
|
atomic_t aggregation_enabled;
|
||||||
|
atomic_t bonding_enabled;
|
||||||
atomic_t vis_mode;
|
atomic_t vis_mode;
|
||||||
atomic_t orig_interval;
|
atomic_t orig_interval;
|
||||||
|
atomic_t log_level;
|
||||||
char num_ifaces;
|
char num_ifaces;
|
||||||
|
struct debug_log *debug_log;
|
||||||
struct batman_if *primary_if;
|
struct batman_if *primary_if;
|
||||||
struct kobject *mesh_obj;
|
struct kobject *mesh_obj;
|
||||||
|
struct dentry *debug_dir;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct device_client {
|
struct socket_client {
|
||||||
struct list_head queue_list;
|
struct list_head queue_list;
|
||||||
unsigned int queue_len;
|
unsigned int queue_len;
|
||||||
unsigned char index;
|
unsigned char index;
|
||||||
|
@ -116,9 +128,10 @@ struct device_client {
|
||||||
wait_queue_head_t queue_wait;
|
wait_queue_head_t queue_wait;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct device_packet {
|
struct socket_packet {
|
||||||
struct list_head list;
|
struct list_head list;
|
||||||
struct icmp_packet icmp_packet;
|
size_t icmp_len;
|
||||||
|
struct icmp_packet_rr icmp_packet;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct hna_local_entry {
|
struct hna_local_entry {
|
||||||
|
@ -159,4 +172,12 @@ struct if_list_entry {
|
||||||
struct hlist_node list;
|
struct hlist_node list;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
struct debug_log {
|
||||||
|
char log_buff[LOG_BUF_LEN];
|
||||||
|
unsigned long log_start;
|
||||||
|
unsigned long log_end;
|
||||||
|
spinlock_t lock;
|
||||||
|
wait_queue_head_t queue_wait;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* _NET_BATMAN_ADV_TYPES_H_ */
|
||||||
|
|
|
@ -43,8 +43,8 @@
|
||||||
_dummy > smallest_signed_int(_dummy); })
|
_dummy > smallest_signed_int(_dummy); })
|
||||||
#define seq_after(x, y) seq_before(y, x)
|
#define seq_after(x, y) seq_before(y, x)
|
||||||
|
|
||||||
struct hashtable_t *vis_hash;
|
static struct hashtable_t *vis_hash;
|
||||||
DEFINE_SPINLOCK(vis_hash_lock);
|
static DEFINE_SPINLOCK(vis_hash_lock);
|
||||||
static DEFINE_SPINLOCK(recv_list_lock);
|
static DEFINE_SPINLOCK(recv_list_lock);
|
||||||
static struct vis_info *my_vis_info;
|
static struct vis_info *my_vis_info;
|
||||||
static struct list_head send_list; /* always locked with vis_hash_lock */
|
static struct list_head send_list; /* always locked with vis_hash_lock */
|
||||||
|
@ -115,7 +115,7 @@ static void vis_data_insert_interface(const uint8_t *interface,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* its a new address, add it to the list */
|
/* its a new address, add it to the list */
|
||||||
entry = kmalloc(sizeof(*entry), GFP_KERNEL);
|
entry = kmalloc(sizeof(*entry), GFP_ATOMIC);
|
||||||
if (!entry)
|
if (!entry)
|
||||||
return;
|
return;
|
||||||
memcpy(entry->addr, interface, ETH_ALEN);
|
memcpy(entry->addr, interface, ETH_ALEN);
|
||||||
|
@ -142,12 +142,29 @@ static ssize_t vis_data_read_prim_sec(char *buff, struct hlist_head *if_list)
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static size_t vis_data_count_prim_sec(struct hlist_head *if_list)
|
||||||
|
{
|
||||||
|
struct if_list_entry *entry;
|
||||||
|
struct hlist_node *pos;
|
||||||
|
size_t count = 0;
|
||||||
|
|
||||||
|
hlist_for_each_entry(entry, pos, if_list, list) {
|
||||||
|
if (entry->primary)
|
||||||
|
count += 9;
|
||||||
|
else
|
||||||
|
count += 23;
|
||||||
|
}
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
/* read an entry */
|
/* read an entry */
|
||||||
static ssize_t vis_data_read_entry(char *buff, struct vis_info_entry *entry,
|
static ssize_t vis_data_read_entry(char *buff, struct vis_info_entry *entry,
|
||||||
uint8_t *src, bool primary)
|
uint8_t *src, bool primary)
|
||||||
{
|
{
|
||||||
char to[40];
|
char to[18];
|
||||||
|
|
||||||
|
/* maximal length: max(4+17+2, 3+17+1+3+2) == 26 */
|
||||||
addr_to_string(to, entry->dest);
|
addr_to_string(to, entry->dest);
|
||||||
if (primary && entry->quality == 0)
|
if (primary && entry->quality == 0)
|
||||||
return sprintf(buff, "HNA %s, ", to);
|
return sprintf(buff, "HNA %s, ", to);
|
||||||
|
@ -157,38 +174,74 @@ static ssize_t vis_data_read_entry(char *buff, struct vis_info_entry *entry,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
ssize_t vis_fill_buffer_text(struct net_device *net_dev, char *buff,
|
int vis_seq_print_text(struct seq_file *seq, void *offset)
|
||||||
size_t count, loff_t off)
|
|
||||||
{
|
{
|
||||||
HASHIT(hashit);
|
HASHIT(hashit);
|
||||||
|
HASHIT(hashit_count);
|
||||||
struct vis_info *info;
|
struct vis_info *info;
|
||||||
struct vis_info_entry *entries;
|
struct vis_info_entry *entries;
|
||||||
|
struct net_device *net_dev = (struct net_device *)seq->private;
|
||||||
struct bat_priv *bat_priv = netdev_priv(net_dev);
|
struct bat_priv *bat_priv = netdev_priv(net_dev);
|
||||||
HLIST_HEAD(vis_if_list);
|
HLIST_HEAD(vis_if_list);
|
||||||
struct if_list_entry *entry;
|
struct if_list_entry *entry;
|
||||||
struct hlist_node *pos, *n;
|
struct hlist_node *pos, *n;
|
||||||
size_t hdr_len, tmp_len;
|
int i;
|
||||||
int i, bytes_written = 0;
|
|
||||||
char tmp_addr_str[ETH_STR_LEN];
|
char tmp_addr_str[ETH_STR_LEN];
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
int vis_server = atomic_read(&bat_priv->vis_mode);
|
int vis_server = atomic_read(&bat_priv->vis_mode);
|
||||||
|
size_t buff_pos, buf_size;
|
||||||
|
char *buff;
|
||||||
|
|
||||||
if ((!bat_priv->primary_if) ||
|
if ((!bat_priv->primary_if) ||
|
||||||
(vis_server == VIS_TYPE_CLIENT_UPDATE))
|
(vis_server == VIS_TYPE_CLIENT_UPDATE))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
hdr_len = 0;
|
buf_size = 1;
|
||||||
|
/* Estimate length */
|
||||||
spin_lock_irqsave(&vis_hash_lock, flags);
|
spin_lock_irqsave(&vis_hash_lock, flags);
|
||||||
|
while (hash_iterate(vis_hash, &hashit_count)) {
|
||||||
|
info = hashit_count.bucket->data;
|
||||||
|
entries = (struct vis_info_entry *)
|
||||||
|
((char *)info + sizeof(struct vis_info));
|
||||||
|
|
||||||
|
for (i = 0; i < info->packet.entries; i++) {
|
||||||
|
if (entries[i].quality == 0)
|
||||||
|
continue;
|
||||||
|
vis_data_insert_interface(entries[i].src, &vis_if_list,
|
||||||
|
compare_orig(entries[i].src,
|
||||||
|
info->packet.vis_orig));
|
||||||
|
}
|
||||||
|
|
||||||
|
hlist_for_each_entry(entry, pos, &vis_if_list, list) {
|
||||||
|
buf_size += 18 + 26 * info->packet.entries;
|
||||||
|
|
||||||
|
/* add primary/secondary records */
|
||||||
|
if (compare_orig(entry->addr, info->packet.vis_orig))
|
||||||
|
buf_size +=
|
||||||
|
vis_data_count_prim_sec(&vis_if_list);
|
||||||
|
|
||||||
|
buf_size += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
hlist_for_each_entry_safe(entry, pos, n, &vis_if_list, list) {
|
||||||
|
hlist_del(&entry->list);
|
||||||
|
kfree(entry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
buff = kmalloc(buf_size, GFP_ATOMIC);
|
||||||
|
if (!buff) {
|
||||||
|
spin_unlock_irqrestore(&vis_hash_lock, flags);
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
buff[0] = '\0';
|
||||||
|
buff_pos = 0;
|
||||||
|
|
||||||
while (hash_iterate(vis_hash, &hashit)) {
|
while (hash_iterate(vis_hash, &hashit)) {
|
||||||
info = hashit.bucket->data;
|
info = hashit.bucket->data;
|
||||||
entries = (struct vis_info_entry *)
|
entries = (struct vis_info_entry *)
|
||||||
((char *)info + sizeof(struct vis_info));
|
((char *)info + sizeof(struct vis_info));
|
||||||
|
|
||||||
/* estimated line length */
|
|
||||||
if (count < bytes_written + 200)
|
|
||||||
break;
|
|
||||||
|
|
||||||
for (i = 0; i < info->packet.entries; i++) {
|
for (i = 0; i < info->packet.entries; i++) {
|
||||||
if (entries[i].quality == 0)
|
if (entries[i].quality == 0)
|
||||||
continue;
|
continue;
|
||||||
|
@ -199,30 +252,22 @@ ssize_t vis_fill_buffer_text(struct net_device *net_dev, char *buff,
|
||||||
|
|
||||||
hlist_for_each_entry(entry, pos, &vis_if_list, list) {
|
hlist_for_each_entry(entry, pos, &vis_if_list, list) {
|
||||||
addr_to_string(tmp_addr_str, entry->addr);
|
addr_to_string(tmp_addr_str, entry->addr);
|
||||||
tmp_len = sprintf(buff + bytes_written,
|
buff_pos += sprintf(buff + buff_pos, "%s,",
|
||||||
"%s,", tmp_addr_str);
|
tmp_addr_str);
|
||||||
|
|
||||||
for (i = 0; i < info->packet.entries; i++)
|
for (i = 0; i < info->packet.entries; i++)
|
||||||
tmp_len += vis_data_read_entry(
|
buff_pos += vis_data_read_entry(buff + buff_pos,
|
||||||
buff + bytes_written + tmp_len,
|
&entries[i],
|
||||||
&entries[i], entry->addr,
|
entry->addr,
|
||||||
entry->primary);
|
entry->primary);
|
||||||
|
|
||||||
/* add primary/secondary records */
|
/* add primary/secondary records */
|
||||||
if (compare_orig(entry->addr, info->packet.vis_orig))
|
if (compare_orig(entry->addr, info->packet.vis_orig))
|
||||||
tmp_len += vis_data_read_prim_sec(
|
buff_pos +=
|
||||||
buff + bytes_written + tmp_len,
|
vis_data_read_prim_sec(buff + buff_pos,
|
||||||
&vis_if_list);
|
&vis_if_list);
|
||||||
|
|
||||||
tmp_len += sprintf(buff + bytes_written + tmp_len,
|
buff_pos += sprintf(buff + buff_pos, "\n");
|
||||||
"\n");
|
|
||||||
|
|
||||||
hdr_len += tmp_len;
|
|
||||||
|
|
||||||
if (off >= hdr_len)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
bytes_written += tmp_len;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
hlist_for_each_entry_safe(entry, pos, n, &vis_if_list, list) {
|
hlist_for_each_entry_safe(entry, pos, n, &vis_if_list, list) {
|
||||||
|
@ -230,9 +275,13 @@ ssize_t vis_fill_buffer_text(struct net_device *net_dev, char *buff,
|
||||||
kfree(entry);
|
kfree(entry);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
spin_unlock_irqrestore(&vis_hash_lock, flags);
|
spin_unlock_irqrestore(&vis_hash_lock, flags);
|
||||||
|
|
||||||
return bytes_written;
|
seq_printf(seq, "%s", buff);
|
||||||
|
kfree(buff);
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* add the info packet to the send list, if it was not
|
/* add the info packet to the send list, if it was not
|
||||||
|
@ -308,7 +357,8 @@ static struct vis_info *add_packet(struct vis_packet *vis_packet,
|
||||||
old_info = hash_find(vis_hash, &search_elem);
|
old_info = hash_find(vis_hash, &search_elem);
|
||||||
|
|
||||||
if (old_info != NULL) {
|
if (old_info != NULL) {
|
||||||
if (!seq_after(vis_packet->seqno, old_info->packet.seqno)) {
|
if (!seq_after(ntohl(vis_packet->seqno),
|
||||||
|
ntohl(old_info->packet.seqno))) {
|
||||||
if (old_info->packet.seqno == vis_packet->seqno) {
|
if (old_info->packet.seqno == vis_packet->seqno) {
|
||||||
recv_list_add(&old_info->recv_list,
|
recv_list_add(&old_info->recv_list,
|
||||||
vis_packet->sender_orig);
|
vis_packet->sender_orig);
|
||||||
|
@ -340,7 +390,7 @@ static struct vis_info *add_packet(struct vis_packet *vis_packet,
|
||||||
|
|
||||||
/* Make it a broadcast packet, if required */
|
/* Make it a broadcast packet, if required */
|
||||||
if (make_broadcast)
|
if (make_broadcast)
|
||||||
memcpy(info->packet.target_orig, broadcastAddr, ETH_ALEN);
|
memcpy(info->packet.target_orig, broadcast_addr, ETH_ALEN);
|
||||||
|
|
||||||
/* repair if entries is longer than packet. */
|
/* repair if entries is longer than packet. */
|
||||||
if (info->packet.entries * sizeof(struct vis_info_entry) > vis_info_len)
|
if (info->packet.entries * sizeof(struct vis_info_entry) > vis_info_len)
|
||||||
|
@ -474,9 +524,9 @@ static int generate_vis_packet(struct bat_priv *bat_priv)
|
||||||
info->packet.vis_type = atomic_read(&bat_priv->vis_mode);
|
info->packet.vis_type = atomic_read(&bat_priv->vis_mode);
|
||||||
|
|
||||||
spin_lock_irqsave(&orig_hash_lock, flags);
|
spin_lock_irqsave(&orig_hash_lock, flags);
|
||||||
memcpy(info->packet.target_orig, broadcastAddr, ETH_ALEN);
|
memcpy(info->packet.target_orig, broadcast_addr, ETH_ALEN);
|
||||||
info->packet.ttl = TTL;
|
info->packet.ttl = TTL;
|
||||||
info->packet.seqno++;
|
info->packet.seqno = htonl(ntohl(info->packet.seqno) + 1);
|
||||||
info->packet.entries = 0;
|
info->packet.entries = 0;
|
||||||
|
|
||||||
if (info->packet.vis_type == VIS_TYPE_CLIENT_UPDATE) {
|
if (info->packet.vis_type == VIS_TYPE_CLIENT_UPDATE) {
|
||||||
|
@ -547,7 +597,7 @@ static void purge_vis_packets(void)
|
||||||
if (info == my_vis_info) /* never purge own data. */
|
if (info == my_vis_info) /* never purge own data. */
|
||||||
continue;
|
continue;
|
||||||
if (time_after(jiffies,
|
if (time_after(jiffies,
|
||||||
info->first_seen + (VIS_TIMEOUT*HZ)/1000)) {
|
info->first_seen + VIS_TIMEOUT * HZ)) {
|
||||||
hash_remove_bucket(vis_hash, &hashit);
|
hash_remove_bucket(vis_hash, &hashit);
|
||||||
send_list_del(info);
|
send_list_del(info);
|
||||||
kref_put(&info->refcount, free_info);
|
kref_put(&info->refcount, free_info);
|
||||||
|
@ -591,7 +641,7 @@ static void broadcast_vis_packet(struct vis_info *info, int packet_length)
|
||||||
|
|
||||||
}
|
}
|
||||||
spin_unlock_irqrestore(&orig_hash_lock, flags);
|
spin_unlock_irqrestore(&orig_hash_lock, flags);
|
||||||
memcpy(info->packet.target_orig, broadcastAddr, ETH_ALEN);
|
memcpy(info->packet.target_orig, broadcast_addr, ETH_ALEN);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void unicast_vis_packet(struct vis_info *info, int packet_length)
|
static void unicast_vis_packet(struct vis_info *info, int packet_length)
|
||||||
|
@ -628,11 +678,11 @@ static void send_vis_packet(struct vis_info *info)
|
||||||
int packet_length;
|
int packet_length;
|
||||||
|
|
||||||
if (info->packet.ttl < 2) {
|
if (info->packet.ttl < 2) {
|
||||||
printk(KERN_WARNING "batman-adv: Error - can't send vis packet: ttl exceeded\n");
|
pr_warning("Error - can't send vis packet: ttl exceeded\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(info->packet.sender_orig, mainIfAddr, ETH_ALEN);
|
memcpy(info->packet.sender_orig, main_if_addr, ETH_ALEN);
|
||||||
info->packet.ttl--;
|
info->packet.ttl--;
|
||||||
|
|
||||||
packet_length = sizeof(struct vis_packet) +
|
packet_length = sizeof(struct vis_packet) +
|
||||||
|
@ -690,18 +740,18 @@ int vis_init(void)
|
||||||
|
|
||||||
vis_hash = hash_new(256, vis_info_cmp, vis_info_choose);
|
vis_hash = hash_new(256, vis_info_cmp, vis_info_choose);
|
||||||
if (!vis_hash) {
|
if (!vis_hash) {
|
||||||
printk(KERN_ERR "batman-adv:Can't initialize vis_hash\n");
|
pr_err("Can't initialize vis_hash\n");
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
my_vis_info = kmalloc(1000, GFP_ATOMIC);
|
my_vis_info = kmalloc(1000, GFP_ATOMIC);
|
||||||
if (!my_vis_info) {
|
if (!my_vis_info) {
|
||||||
printk(KERN_ERR "batman-adv:Can't initialize vis packet\n");
|
pr_err("Can't initialize vis packet\n");
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* prefill the vis info */
|
/* prefill the vis info */
|
||||||
my_vis_info->first_seen = jiffies - atomic_read(&vis_interval);
|
my_vis_info->first_seen = jiffies - msecs_to_jiffies(VIS_INTERVAL);
|
||||||
INIT_LIST_HEAD(&my_vis_info->recv_list);
|
INIT_LIST_HEAD(&my_vis_info->recv_list);
|
||||||
INIT_LIST_HEAD(&my_vis_info->send_list);
|
INIT_LIST_HEAD(&my_vis_info->send_list);
|
||||||
kref_init(&my_vis_info->refcount);
|
kref_init(&my_vis_info->refcount);
|
||||||
|
@ -713,12 +763,11 @@ int vis_init(void)
|
||||||
|
|
||||||
INIT_LIST_HEAD(&send_list);
|
INIT_LIST_HEAD(&send_list);
|
||||||
|
|
||||||
memcpy(my_vis_info->packet.vis_orig, mainIfAddr, ETH_ALEN);
|
memcpy(my_vis_info->packet.vis_orig, main_if_addr, ETH_ALEN);
|
||||||
memcpy(my_vis_info->packet.sender_orig, mainIfAddr, ETH_ALEN);
|
memcpy(my_vis_info->packet.sender_orig, main_if_addr, ETH_ALEN);
|
||||||
|
|
||||||
if (hash_add(vis_hash, my_vis_info) < 0) {
|
if (hash_add(vis_hash, my_vis_info) < 0) {
|
||||||
printk(KERN_ERR
|
pr_err("Can't add own vis packet into hash\n");
|
||||||
"batman-adv:Can't add own vis packet into hash\n");
|
|
||||||
/* not in hash, need to remove it manually. */
|
/* not in hash, need to remove it manually. */
|
||||||
kref_put(&my_vis_info->refcount, free_info);
|
kref_put(&my_vis_info->refcount, free_info);
|
||||||
goto err;
|
goto err;
|
||||||
|
@ -764,5 +813,5 @@ void vis_quit(void)
|
||||||
static void start_vis_timer(void)
|
static void start_vis_timer(void)
|
||||||
{
|
{
|
||||||
queue_delayed_work(bat_event_workqueue, &vis_timer_wq,
|
queue_delayed_work(bat_event_workqueue, &vis_timer_wq,
|
||||||
(atomic_read(&vis_interval) * HZ) / 1000);
|
(VIS_INTERVAL * HZ) / 1000);
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,7 +19,10 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define VIS_TIMEOUT 200000
|
#ifndef _NET_BATMAN_ADV_VIS_H_
|
||||||
|
#define _NET_BATMAN_ADV_VIS_H_
|
||||||
|
|
||||||
|
#define VIS_TIMEOUT 200 /* timeout of vis packets in seconds */
|
||||||
|
|
||||||
struct vis_info {
|
struct vis_info {
|
||||||
unsigned long first_seen;
|
unsigned long first_seen;
|
||||||
|
@ -44,11 +47,7 @@ struct recvlist_node {
|
||||||
uint8_t mac[ETH_ALEN];
|
uint8_t mac[ETH_ALEN];
|
||||||
};
|
};
|
||||||
|
|
||||||
extern struct hashtable_t *vis_hash;
|
int vis_seq_print_text(struct seq_file *seq, void *offset);
|
||||||
extern spinlock_t vis_hash_lock;
|
|
||||||
|
|
||||||
ssize_t vis_fill_buffer_text(struct net_device *net_dev, char *buff,
|
|
||||||
size_t count, loff_t off);
|
|
||||||
void receive_server_sync_packet(struct bat_priv *bat_priv,
|
void receive_server_sync_packet(struct bat_priv *bat_priv,
|
||||||
struct vis_packet *vis_packet,
|
struct vis_packet *vis_packet,
|
||||||
int vis_info_len);
|
int vis_info_len);
|
||||||
|
@ -57,3 +56,5 @@ void receive_client_update_packet(struct bat_priv *bat_priv,
|
||||||
int vis_info_len);
|
int vis_info_len);
|
||||||
int vis_init(void);
|
int vis_init(void);
|
||||||
void vis_quit(void);
|
void vis_quit(void);
|
||||||
|
|
||||||
|
#endif /* _NET_BATMAN_ADV_VIS_H_ */
|
||||||
|
|
|
@ -2,7 +2,6 @@ TODO:
|
||||||
- checkpatch.pl cleanups
|
- checkpatch.pl cleanups
|
||||||
- Lindent
|
- Lindent
|
||||||
- remove all wrappers
|
- remove all wrappers
|
||||||
- remove typedefs
|
|
||||||
- audit userspace interface
|
- audit userspace interface
|
||||||
- reserve major number
|
- reserve major number
|
||||||
- cleanup the individual comedi drivers as well
|
- cleanup the individual comedi drivers as well
|
||||||
|
|
|
@ -1845,8 +1845,15 @@ ok:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dev->attached && dev->use_count == 0 && dev->open)
|
if (dev->attached && dev->use_count == 0 && dev->open) {
|
||||||
dev->open(dev);
|
int rc = dev->open(dev);
|
||||||
|
if (rc < 0) {
|
||||||
|
module_put(dev->driver->module);
|
||||||
|
module_put(THIS_MODULE);
|
||||||
|
mutex_unlock(&dev->mutex);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
dev->use_count++;
|
dev->use_count++;
|
||||||
|
|
||||||
|
|
|
@ -53,62 +53,6 @@
|
||||||
COMEDI_MINORVERSION, COMEDI_MICROVERSION)
|
COMEDI_MINORVERSION, COMEDI_MICROVERSION)
|
||||||
#define COMEDI_RELEASE VERSION
|
#define COMEDI_RELEASE VERSION
|
||||||
|
|
||||||
#define COMEDI_INITCLEANUP_NOMODULE(x) \
|
|
||||||
static int __init x ## _init_module(void) \
|
|
||||||
{return comedi_driver_register(&(x)); } \
|
|
||||||
static void __exit x ## _cleanup_module(void) \
|
|
||||||
{comedi_driver_unregister(&(x)); } \
|
|
||||||
module_init(x ## _init_module); \
|
|
||||||
module_exit(x ## _cleanup_module);
|
|
||||||
|
|
||||||
#define COMEDI_MODULE_MACROS \
|
|
||||||
MODULE_AUTHOR("Comedi http://www.comedi.org"); \
|
|
||||||
MODULE_DESCRIPTION("Comedi low-level driver"); \
|
|
||||||
MODULE_LICENSE("GPL");
|
|
||||||
|
|
||||||
#define COMEDI_INITCLEANUP(x) \
|
|
||||||
COMEDI_MODULE_MACROS \
|
|
||||||
COMEDI_INITCLEANUP_NOMODULE(x)
|
|
||||||
|
|
||||||
#define COMEDI_PCI_INITCLEANUP_NOMODULE(comedi_driver, pci_id_table) \
|
|
||||||
static int __devinit comedi_driver ## _pci_probe(struct pci_dev *dev, \
|
|
||||||
const struct pci_device_id *ent) \
|
|
||||||
{ \
|
|
||||||
return comedi_pci_auto_config(dev, comedi_driver.driver_name); \
|
|
||||||
} \
|
|
||||||
static void __devexit comedi_driver ## _pci_remove(\
|
|
||||||
struct pci_dev *dev) \
|
|
||||||
{ \
|
|
||||||
comedi_pci_auto_unconfig(dev); \
|
|
||||||
} \
|
|
||||||
static struct pci_driver comedi_driver ## _pci_driver = \
|
|
||||||
{ \
|
|
||||||
.id_table = pci_id_table, \
|
|
||||||
.probe = &comedi_driver ## _pci_probe, \
|
|
||||||
.remove = __devexit_p(&comedi_driver ## _pci_remove) \
|
|
||||||
}; \
|
|
||||||
static int __init comedi_driver ## _init_module(void) \
|
|
||||||
{ \
|
|
||||||
int retval; \
|
|
||||||
retval = comedi_driver_register(&comedi_driver); \
|
|
||||||
if (retval < 0) \
|
|
||||||
return retval; \
|
|
||||||
comedi_driver ## _pci_driver.name = \
|
|
||||||
(char *)comedi_driver.driver_name; \
|
|
||||||
return pci_register_driver(&comedi_driver ## _pci_driver); \
|
|
||||||
} \
|
|
||||||
static void __exit comedi_driver ## _cleanup_module(void) \
|
|
||||||
{ \
|
|
||||||
pci_unregister_driver(&comedi_driver ## _pci_driver); \
|
|
||||||
comedi_driver_unregister(&comedi_driver); \
|
|
||||||
} \
|
|
||||||
module_init(comedi_driver ## _init_module); \
|
|
||||||
module_exit(comedi_driver ## _cleanup_module);
|
|
||||||
|
|
||||||
#define COMEDI_PCI_INITCLEANUP(comedi_driver, pci_id_table) \
|
|
||||||
COMEDI_MODULE_MACROS \
|
|
||||||
COMEDI_PCI_INITCLEANUP_NOMODULE(comedi_driver, pci_id_table)
|
|
||||||
|
|
||||||
#define PCI_VENDOR_ID_ADLINK 0x144a
|
#define PCI_VENDOR_ID_ADLINK 0x144a
|
||||||
#define PCI_VENDOR_ID_ICP 0x104c
|
#define PCI_VENDOR_ID_ICP 0x104c
|
||||||
#define PCI_VENDOR_ID_CONTEC 0x1221
|
#define PCI_VENDOR_ID_CONTEC 0x1221
|
||||||
|
@ -285,7 +229,7 @@ struct comedi_device {
|
||||||
|
|
||||||
struct fasync_struct *async_queue;
|
struct fasync_struct *async_queue;
|
||||||
|
|
||||||
void (*open) (struct comedi_device *dev);
|
int (*open) (struct comedi_device *dev);
|
||||||
void (*close) (struct comedi_device *dev);
|
void (*close) (struct comedi_device *dev);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -117,7 +117,18 @@ static struct comedi_driver driver_8255 = {
|
||||||
.detach = dev_8255_detach,
|
.detach = dev_8255_detach,
|
||||||
};
|
};
|
||||||
|
|
||||||
COMEDI_INITCLEANUP(driver_8255);
|
static int __init driver_8255_init_module(void)
|
||||||
|
{
|
||||||
|
return comedi_driver_register(&driver_8255);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __exit driver_8255_cleanup_module(void)
|
||||||
|
{
|
||||||
|
comedi_driver_unregister(&driver_8255);
|
||||||
|
}
|
||||||
|
|
||||||
|
module_init(driver_8255_init_module);
|
||||||
|
module_exit(driver_8255_cleanup_module);
|
||||||
|
|
||||||
static void do_config(struct comedi_device *dev, struct comedi_subdevice *s);
|
static void do_config(struct comedi_device *dev, struct comedi_subdevice *s);
|
||||||
|
|
||||||
|
@ -457,3 +468,7 @@ static int dev_8255_detach(struct comedi_device *dev)
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MODULE_AUTHOR("Comedi http://www.comedi.org");
|
||||||
|
MODULE_DESCRIPTION("Comedi low-level driver");
|
||||||
|
MODULE_LICENSE("GPL");
|
||||||
|
|
|
@ -49,7 +49,18 @@ static struct comedi_driver driver_acl7225b = {
|
||||||
.offset = sizeof(struct boardtype),
|
.offset = sizeof(struct boardtype),
|
||||||
};
|
};
|
||||||
|
|
||||||
COMEDI_INITCLEANUP(driver_acl7225b);
|
static int __init driver_acl7225b_init_module(void)
|
||||||
|
{
|
||||||
|
return comedi_driver_register(&driver_acl7225b);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __exit driver_acl7225b_cleanup_module(void)
|
||||||
|
{
|
||||||
|
comedi_driver_unregister(&driver_acl7225b);
|
||||||
|
}
|
||||||
|
|
||||||
|
module_init(driver_acl7225b_init_module);
|
||||||
|
module_exit(driver_acl7225b_cleanup_module);
|
||||||
|
|
||||||
static int acl7225b_do_insn(struct comedi_device *dev,
|
static int acl7225b_do_insn(struct comedi_device *dev,
|
||||||
struct comedi_subdevice *s,
|
struct comedi_subdevice *s,
|
||||||
|
@ -150,3 +161,7 @@ static int acl7225b_detach(struct comedi_device *dev)
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MODULE_AUTHOR("Comedi http://www.comedi.org");
|
||||||
|
MODULE_DESCRIPTION("Comedi low-level driver");
|
||||||
|
MODULE_LICENSE("GPL");
|
||||||
|
|
|
@ -247,16 +247,14 @@ int i_pci_card_data(struct pcilst_struct *amcc,
|
||||||
/* build list of amcc cards in this system */
|
/* build list of amcc cards in this system */
|
||||||
void v_pci_card_list_init(unsigned short pci_vendor, char display)
|
void v_pci_card_list_init(unsigned short pci_vendor, char display)
|
||||||
{
|
{
|
||||||
struct pci_dev *pcidev;
|
struct pci_dev *pcidev = NULL;
|
||||||
struct pcilst_struct *amcc, *last;
|
struct pcilst_struct *amcc, *last;
|
||||||
int i;
|
int i;
|
||||||
int i_Count = 0;
|
int i_Count = 0;
|
||||||
amcc_devices = NULL;
|
amcc_devices = NULL;
|
||||||
last = NULL;
|
last = NULL;
|
||||||
|
|
||||||
for (pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, NULL);
|
for_each_pci_dev(pcidev) {
|
||||||
pcidev != NULL;
|
|
||||||
pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pcidev)) {
|
|
||||||
for (i_Count = 0; i_Count < 2; i_Count++) {
|
for (i_Count = 0; i_Count < 2; i_Count++) {
|
||||||
pci_vendor = i_ADDIDATADeviceID[i_Count];
|
pci_vendor = i_ADDIDATADeviceID[i_Count];
|
||||||
if (pcidev->vendor == pci_vendor) {
|
if (pcidev->vendor == pci_vendor) {
|
||||||
|
|
|
@ -2541,7 +2541,43 @@ static struct comedi_driver driver_addi = {
|
||||||
.offset = sizeof(struct addi_board),
|
.offset = sizeof(struct addi_board),
|
||||||
};
|
};
|
||||||
|
|
||||||
COMEDI_PCI_INITCLEANUP(driver_addi, addi_apci_tbl);
|
static int __devinit driver_addi_pci_probe(struct pci_dev *dev,
|
||||||
|
const struct pci_device_id *ent)
|
||||||
|
{
|
||||||
|
return comedi_pci_auto_config(dev, driver_addi.driver_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __devexit driver_addi_pci_remove(struct pci_dev *dev)
|
||||||
|
{
|
||||||
|
comedi_pci_auto_unconfig(dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct pci_driver driver_addi_pci_driver = {
|
||||||
|
.id_table = addi_apci_tbl,
|
||||||
|
.probe = &driver_addi_pci_probe,
|
||||||
|
.remove = __devexit_p(&driver_addi_pci_remove)
|
||||||
|
};
|
||||||
|
|
||||||
|
static int __init driver_addi_init_module(void)
|
||||||
|
{
|
||||||
|
int retval;
|
||||||
|
|
||||||
|
retval = comedi_driver_register(&driver_addi);
|
||||||
|
if (retval < 0)
|
||||||
|
return retval;
|
||||||
|
|
||||||
|
driver_addi_pci_driver.name = (char *)driver_addi.driver_name;
|
||||||
|
return pci_register_driver(&driver_addi_pci_driver);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __exit driver_addi_cleanup_module(void)
|
||||||
|
{
|
||||||
|
pci_unregister_driver(&driver_addi_pci_driver);
|
||||||
|
comedi_driver_unregister(&driver_addi);
|
||||||
|
}
|
||||||
|
|
||||||
|
module_init(driver_addi_init_module);
|
||||||
|
module_exit(driver_addi_cleanup_module);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
+----------------------------------------------------------------------------+
|
+----------------------------------------------------------------------------+
|
||||||
|
|
|
@ -101,10 +101,10 @@ struct str_TimerMainHeader {
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
typedef struct {
|
struct str_AnalogOutputHeader {
|
||||||
unsigned short w_Nchannel;
|
unsigned short w_Nchannel;
|
||||||
unsigned char b_Resolution;
|
unsigned char b_Resolution;
|
||||||
} str_AnalogOutputHeader;
|
};
|
||||||
|
|
||||||
struct str_AnalogInputHeader {
|
struct str_AnalogInputHeader {
|
||||||
unsigned short w_Nchannel;
|
unsigned short w_Nchannel;
|
||||||
|
@ -136,7 +136,7 @@ int i_EepromReadTimerHeader(unsigned short w_PCIBoardEepromAddress,
|
||||||
|
|
||||||
int i_EepromReadAnlogOutputHeader(unsigned short w_PCIBoardEepromAddress,
|
int i_EepromReadAnlogOutputHeader(unsigned short w_PCIBoardEepromAddress,
|
||||||
char *pc_PCIChipInformation, unsigned short w_Address,
|
char *pc_PCIChipInformation, unsigned short w_Address,
|
||||||
str_AnalogOutputHeader *s_Header);
|
struct str_AnalogOutputHeader *s_Header);
|
||||||
|
|
||||||
int i_EepromReadAnlogInputHeader(unsigned short w_PCIBoardEepromAddress,
|
int i_EepromReadAnlogInputHeader(unsigned short w_PCIBoardEepromAddress,
|
||||||
char *pc_PCIChipInformation, unsigned short w_Address,
|
char *pc_PCIChipInformation, unsigned short w_Address,
|
||||||
|
@ -635,7 +635,7 @@ void v_EepromSendCommand76(unsigned int dw_Address, unsigned int dw_EepromComman
|
||||||
|
|
||||||
| Input Parameters : unsigned int dw_Address : PCI eeprom base address |
|
| Input Parameters : unsigned int dw_Address : PCI eeprom base address |
|
||||||
|
|
||||||
| unsigned short w_offset : Offset of the adress to read |
|
| unsigned short w_offset : Offset of the address to read |
|
||||||
|
|
||||||
| unsigned short * pw_Value : PCI eeprom 16 bit read value. |
|
| unsigned short * pw_Value : PCI eeprom 16 bit read value. |
|
||||||
|
|
||||||
|
@ -811,7 +811,7 @@ int i_EepromReadMainHeader(unsigned short w_PCIBoardEepromAddress,
|
||||||
struct str_DigitalInputHeader s_DigitalInputHeader;
|
struct str_DigitalInputHeader s_DigitalInputHeader;
|
||||||
struct str_DigitalOutputHeader s_DigitalOutputHeader;
|
struct str_DigitalOutputHeader s_DigitalOutputHeader;
|
||||||
/* struct str_TimerMainHeader s_TimerMainHeader,s_WatchdogMainHeader; */
|
/* struct str_TimerMainHeader s_TimerMainHeader,s_WatchdogMainHeader; */
|
||||||
str_AnalogOutputHeader s_AnalogOutputHeader;
|
struct str_AnalogOutputHeader s_AnalogOutputHeader;
|
||||||
struct str_AnalogInputHeader s_AnalogInputHeader;
|
struct str_AnalogInputHeader s_AnalogInputHeader;
|
||||||
|
|
||||||
/* Read size */
|
/* Read size */
|
||||||
|
@ -1081,7 +1081,7 @@ int i_EepromReadTimerHeader(unsigned short w_PCIBoardEepromAddress,
|
||||||
|
|
||||||
int i_EepromReadAnlogOutputHeader(unsigned short w_PCIBoardEepromAddress,
|
int i_EepromReadAnlogOutputHeader(unsigned short w_PCIBoardEepromAddress,
|
||||||
char *pc_PCIChipInformation, unsigned short w_Address,
|
char *pc_PCIChipInformation, unsigned short w_Address,
|
||||||
str_AnalogOutputHeader *s_Header)
|
struct str_AnalogOutputHeader *s_Header)
|
||||||
{
|
{
|
||||||
unsigned short w_Temp;
|
unsigned short w_Temp;
|
||||||
/* No of channels for 1st hard component */
|
/* No of channels for 1st hard component */
|
||||||
|
|
|
@ -1090,13 +1090,13 @@ int i_APCI3120_CyclicAnalogInput(int mode, struct comedi_device *dev,
|
||||||
* and put into into an array array used may be for differnet pages
|
* and put into into an array array used may be for differnet pages
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* DMA Start Adress Low */
|
/* DMA Start Address Low */
|
||||||
outw(APCI3120_ADD_ON_MWAR_LOW, devpriv->i_IobaseAddon + 0);
|
outw(APCI3120_ADD_ON_MWAR_LOW, devpriv->i_IobaseAddon + 0);
|
||||||
outw((devpriv->ul_DmaBufferHw[0] & 0xFFFF),
|
outw((devpriv->ul_DmaBufferHw[0] & 0xFFFF),
|
||||||
devpriv->i_IobaseAddon + 2);
|
devpriv->i_IobaseAddon + 2);
|
||||||
|
|
||||||
/*************************/
|
/*************************/
|
||||||
/* DMA Start Adress High */
|
/* DMA Start Address High */
|
||||||
/*************************/
|
/*************************/
|
||||||
outw(APCI3120_ADD_ON_MWAR_HIGH, devpriv->i_IobaseAddon + 0);
|
outw(APCI3120_ADD_ON_MWAR_HIGH, devpriv->i_IobaseAddon + 0);
|
||||||
outw((devpriv->ul_DmaBufferHw[0] / 65536),
|
outw((devpriv->ul_DmaBufferHw[0] / 65536),
|
||||||
|
@ -1733,11 +1733,11 @@ void v_APCI3120_InterruptDma(int irq, void *d)
|
||||||
var = devpriv->ul_DmaBufferHw[next_dma_buf];
|
var = devpriv->ul_DmaBufferHw[next_dma_buf];
|
||||||
high_word = var / 65536;
|
high_word = var / 65536;
|
||||||
|
|
||||||
/* DMA Start Adress Low */
|
/* DMA Start Address Low */
|
||||||
outw(APCI3120_ADD_ON_MWAR_LOW, devpriv->i_IobaseAddon + 0);
|
outw(APCI3120_ADD_ON_MWAR_LOW, devpriv->i_IobaseAddon + 0);
|
||||||
outw(low_word, devpriv->i_IobaseAddon + 2);
|
outw(low_word, devpriv->i_IobaseAddon + 2);
|
||||||
|
|
||||||
/* DMA Start Adress High */
|
/* DMA Start Address High */
|
||||||
outw(APCI3120_ADD_ON_MWAR_HIGH, devpriv->i_IobaseAddon + 0);
|
outw(APCI3120_ADD_ON_MWAR_HIGH, devpriv->i_IobaseAddon + 0);
|
||||||
outw(high_word, devpriv->i_IobaseAddon + 2);
|
outw(high_word, devpriv->i_IobaseAddon + 2);
|
||||||
|
|
||||||
|
|
|
@ -5,3 +5,7 @@
|
||||||
#define ADDIDATA_DRIVER_NAME "addi_apci_035"
|
#define ADDIDATA_DRIVER_NAME "addi_apci_035"
|
||||||
|
|
||||||
#include "addi-data/addi_common.c"
|
#include "addi-data/addi_common.c"
|
||||||
|
|
||||||
|
MODULE_AUTHOR("Comedi http://www.comedi.org");
|
||||||
|
MODULE_DESCRIPTION("Comedi low-level driver");
|
||||||
|
MODULE_LICENSE("GPL");
|
||||||
|
|
|
@ -3,3 +3,7 @@
|
||||||
#define ADDIDATA_DRIVER_NAME "addi_apci_1032"
|
#define ADDIDATA_DRIVER_NAME "addi_apci_1032"
|
||||||
|
|
||||||
#include "addi-data/addi_common.c"
|
#include "addi-data/addi_common.c"
|
||||||
|
|
||||||
|
MODULE_AUTHOR("Comedi http://www.comedi.org");
|
||||||
|
MODULE_DESCRIPTION("Comedi low-level driver");
|
||||||
|
MODULE_LICENSE("GPL");
|
||||||
|
|
|
@ -3,3 +3,7 @@
|
||||||
#define ADDIDATA_DRIVER_NAME "addi_apci_1500"
|
#define ADDIDATA_DRIVER_NAME "addi_apci_1500"
|
||||||
|
|
||||||
#include "addi-data/addi_common.c"
|
#include "addi-data/addi_common.c"
|
||||||
|
|
||||||
|
MODULE_AUTHOR("Comedi http://www.comedi.org");
|
||||||
|
MODULE_DESCRIPTION("Comedi low-level driver");
|
||||||
|
MODULE_LICENSE("GPL");
|
||||||
|
|
|
@ -3,3 +3,7 @@
|
||||||
#define ADDIDATA_DRIVER_NAME "addi_apci_1516"
|
#define ADDIDATA_DRIVER_NAME "addi_apci_1516"
|
||||||
|
|
||||||
#include "addi-data/addi_common.c"
|
#include "addi-data/addi_common.c"
|
||||||
|
|
||||||
|
MODULE_AUTHOR("Comedi http://www.comedi.org");
|
||||||
|
MODULE_DESCRIPTION("Comedi low-level driver");
|
||||||
|
MODULE_LICENSE("GPL");
|
||||||
|
|
|
@ -3,3 +3,7 @@
|
||||||
#define ADDIDATA_DRIVER_NAME "addi_apci_1564"
|
#define ADDIDATA_DRIVER_NAME "addi_apci_1564"
|
||||||
|
|
||||||
#include "addi-data/addi_common.c"
|
#include "addi-data/addi_common.c"
|
||||||
|
|
||||||
|
MODULE_AUTHOR("Comedi http://www.comedi.org");
|
||||||
|
MODULE_DESCRIPTION("Comedi low-level driver");
|
||||||
|
MODULE_LICENSE("GPL");
|
||||||
|
|
|
@ -3,3 +3,7 @@
|
||||||
#define ADDIDATA_DRIVER_NAME "addi_apci_16xx"
|
#define ADDIDATA_DRIVER_NAME "addi_apci_16xx"
|
||||||
|
|
||||||
#include "addi-data/addi_common.c"
|
#include "addi-data/addi_common.c"
|
||||||
|
|
||||||
|
MODULE_AUTHOR("Comedi http://www.comedi.org");
|
||||||
|
MODULE_DESCRIPTION("Comedi low-level driver");
|
||||||
|
MODULE_LICENSE("GPL");
|
||||||
|
|
|
@ -3,3 +3,7 @@
|
||||||
#define ADDIDATA_DRIVER_NAME "addi_apci_2016"
|
#define ADDIDATA_DRIVER_NAME "addi_apci_2016"
|
||||||
|
|
||||||
#include "addi-data/addi_common.c"
|
#include "addi-data/addi_common.c"
|
||||||
|
|
||||||
|
MODULE_AUTHOR("Comedi http://www.comedi.org");
|
||||||
|
MODULE_DESCRIPTION("Comedi low-level driver");
|
||||||
|
MODULE_LICENSE("GPL");
|
||||||
|
|
|
@ -3,3 +3,7 @@
|
||||||
#define ADDIDATA_DRIVER_NAME "addi_apci_2032"
|
#define ADDIDATA_DRIVER_NAME "addi_apci_2032"
|
||||||
|
|
||||||
#include "addi-data/addi_common.c"
|
#include "addi-data/addi_common.c"
|
||||||
|
|
||||||
|
MODULE_AUTHOR("Comedi http://www.comedi.org");
|
||||||
|
MODULE_DESCRIPTION("Comedi low-level driver");
|
||||||
|
MODULE_LICENSE("GPL");
|
||||||
|
|
|
@ -3,3 +3,7 @@
|
||||||
#define ADDIDATA_DRIVER_NAME "addi_apci_2200"
|
#define ADDIDATA_DRIVER_NAME "addi_apci_2200"
|
||||||
|
|
||||||
#include "addi-data/addi_common.c"
|
#include "addi-data/addi_common.c"
|
||||||
|
|
||||||
|
MODULE_AUTHOR("Comedi http://www.comedi.org");
|
||||||
|
MODULE_DESCRIPTION("Comedi low-level driver");
|
||||||
|
MODULE_LICENSE("GPL");
|
||||||
|
|
|
@ -3,3 +3,7 @@
|
||||||
#define ADDIDATA_DRIVER_NAME "addi_apci_3001"
|
#define ADDIDATA_DRIVER_NAME "addi_apci_3001"
|
||||||
|
|
||||||
#include "addi-data/addi_common.c"
|
#include "addi-data/addi_common.c"
|
||||||
|
|
||||||
|
MODULE_AUTHOR("Comedi http://www.comedi.org");
|
||||||
|
MODULE_DESCRIPTION("Comedi low-level driver");
|
||||||
|
MODULE_LICENSE("GPL");
|
||||||
|
|
|
@ -3,3 +3,7 @@
|
||||||
#define ADDIDATA_DRIVER_NAME "addi_apci_3120"
|
#define ADDIDATA_DRIVER_NAME "addi_apci_3120"
|
||||||
|
|
||||||
#include "addi-data/addi_common.c"
|
#include "addi-data/addi_common.c"
|
||||||
|
|
||||||
|
MODULE_AUTHOR("Comedi http://www.comedi.org");
|
||||||
|
MODULE_DESCRIPTION("Comedi low-level driver");
|
||||||
|
MODULE_LICENSE("GPL");
|
||||||
|
|
|
@ -3,3 +3,7 @@
|
||||||
#define ADDIDATA_DRIVER_NAME "addi_apci_3501"
|
#define ADDIDATA_DRIVER_NAME "addi_apci_3501"
|
||||||
|
|
||||||
#include "addi-data/addi_common.c"
|
#include "addi-data/addi_common.c"
|
||||||
|
|
||||||
|
MODULE_AUTHOR("Comedi http://www.comedi.org");
|
||||||
|
MODULE_DESCRIPTION("Comedi low-level driver");
|
||||||
|
MODULE_LICENSE("GPL");
|
||||||
|
|
|
@ -3,3 +3,7 @@
|
||||||
#define ADDIDATA_DRIVER_NAME "addi_apci_3xxx"
|
#define ADDIDATA_DRIVER_NAME "addi_apci_3xxx"
|
||||||
|
|
||||||
#include "addi-data/addi_common.c"
|
#include "addi-data/addi_common.c"
|
||||||
|
|
||||||
|
MODULE_AUTHOR("Comedi http://www.comedi.org");
|
||||||
|
MODULE_DESCRIPTION("Comedi low-level driver");
|
||||||
|
MODULE_LICENSE("GPL");
|
||||||
|
|
|
@ -119,7 +119,43 @@ static struct comedi_driver driver_pci6208 = {
|
||||||
.detach = pci6208_detach,
|
.detach = pci6208_detach,
|
||||||
};
|
};
|
||||||
|
|
||||||
COMEDI_PCI_INITCLEANUP(driver_pci6208, pci6208_pci_table);
|
static int __devinit driver_pci6208_pci_probe(struct pci_dev *dev,
|
||||||
|
const struct pci_device_id *ent)
|
||||||
|
{
|
||||||
|
return comedi_pci_auto_config(dev, driver_pci6208.driver_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __devexit driver_pci6208_pci_remove(struct pci_dev *dev)
|
||||||
|
{
|
||||||
|
comedi_pci_auto_unconfig(dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct pci_driver driver_pci6208_pci_driver = {
|
||||||
|
.id_table = pci6208_pci_table,
|
||||||
|
.probe = &driver_pci6208_pci_probe,
|
||||||
|
.remove = __devexit_p(&driver_pci6208_pci_remove)
|
||||||
|
};
|
||||||
|
|
||||||
|
static int __init driver_pci6208_init_module(void)
|
||||||
|
{
|
||||||
|
int retval;
|
||||||
|
|
||||||
|
retval = comedi_driver_register(&driver_pci6208);
|
||||||
|
if (retval < 0)
|
||||||
|
return retval;
|
||||||
|
|
||||||
|
driver_pci6208_pci_driver.name = (char *)driver_pci6208.driver_name;
|
||||||
|
return pci_register_driver(&driver_pci6208_pci_driver);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __exit driver_pci6208_cleanup_module(void)
|
||||||
|
{
|
||||||
|
pci_unregister_driver(&driver_pci6208_pci_driver);
|
||||||
|
comedi_driver_unregister(&driver_pci6208);
|
||||||
|
}
|
||||||
|
|
||||||
|
module_init(driver_pci6208_init_module);
|
||||||
|
module_exit(driver_pci6208_cleanup_module);
|
||||||
|
|
||||||
static int pci6208_find_device(struct comedi_device *dev, int bus, int slot);
|
static int pci6208_find_device(struct comedi_device *dev, int bus, int slot);
|
||||||
static int
|
static int
|
||||||
|
@ -315,12 +351,10 @@ static int pci6208_ao_rinsn(struct comedi_device *dev,
|
||||||
|
|
||||||
static int pci6208_find_device(struct comedi_device *dev, int bus, int slot)
|
static int pci6208_find_device(struct comedi_device *dev, int bus, int slot)
|
||||||
{
|
{
|
||||||
struct pci_dev *pci_dev;
|
struct pci_dev *pci_dev = NULL;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (pci_dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, NULL);
|
for_each_pci_dev(pci_dev) {
|
||||||
pci_dev != NULL;
|
|
||||||
pci_dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pci_dev)) {
|
|
||||||
if (pci_dev->vendor == PCI_VENDOR_ID_ADLINK) {
|
if (pci_dev->vendor == PCI_VENDOR_ID_ADLINK) {
|
||||||
for (i = 0; i < ARRAY_SIZE(pci6208_boards); i++) {
|
for (i = 0; i < ARRAY_SIZE(pci6208_boards); i++) {
|
||||||
if (pci6208_boards[i].dev_id ==
|
if (pci6208_boards[i].dev_id ==
|
||||||
|
@ -408,3 +442,7 @@ pci6208_pci_setup(struct pci_dev *pci_dev, unsigned long *io_base_ptr,
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MODULE_AUTHOR("Comedi http://www.comedi.org");
|
||||||
|
MODULE_DESCRIPTION("Comedi low-level driver");
|
||||||
|
MODULE_LICENSE("GPL");
|
||||||
|
|
|
@ -90,7 +90,7 @@ static int adl_pci7230_do_insn_bits(struct comedi_device *dev,
|
||||||
static int adl_pci7230_attach(struct comedi_device *dev,
|
static int adl_pci7230_attach(struct comedi_device *dev,
|
||||||
struct comedi_devconfig *it)
|
struct comedi_devconfig *it)
|
||||||
{
|
{
|
||||||
struct pci_dev *pcidev;
|
struct pci_dev *pcidev = NULL;
|
||||||
struct comedi_subdevice *s;
|
struct comedi_subdevice *s;
|
||||||
int bus, slot;
|
int bus, slot;
|
||||||
|
|
||||||
|
@ -106,10 +106,7 @@ static int adl_pci7230_attach(struct comedi_device *dev,
|
||||||
if (alloc_subdevices(dev, 2) < 0)
|
if (alloc_subdevices(dev, 2) < 0)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
for (pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, NULL);
|
for_each_pci_dev(pcidev) {
|
||||||
pcidev != NULL;
|
|
||||||
pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pcidev)) {
|
|
||||||
|
|
||||||
if (pcidev->vendor == PCI_VENDOR_ID_ADLINK &&
|
if (pcidev->vendor == PCI_VENDOR_ID_ADLINK &&
|
||||||
pcidev->device == PCI_DEVICE_ID_PCI7230) {
|
pcidev->device == PCI_DEVICE_ID_PCI7230) {
|
||||||
if (bus || slot) {
|
if (bus || slot) {
|
||||||
|
@ -203,4 +200,46 @@ static int adl_pci7230_di_insn_bits(struct comedi_device *dev,
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
COMEDI_PCI_INITCLEANUP(driver_adl_pci7230, adl_pci7230_pci_table);
|
static int __devinit driver_adl_pci7230_pci_probe(struct pci_dev *dev,
|
||||||
|
const struct pci_device_id
|
||||||
|
*ent)
|
||||||
|
{
|
||||||
|
return comedi_pci_auto_config(dev, driver_adl_pci7230.driver_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __devexit driver_adl_pci7230_pci_remove(struct pci_dev *dev)
|
||||||
|
{
|
||||||
|
comedi_pci_auto_unconfig(dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct pci_driver driver_adl_pci7230_pci_driver = {
|
||||||
|
.id_table = adl_pci7230_pci_table,
|
||||||
|
.probe = &driver_adl_pci7230_pci_probe,
|
||||||
|
.remove = __devexit_p(&driver_adl_pci7230_pci_remove)
|
||||||
|
};
|
||||||
|
|
||||||
|
static int __init driver_adl_pci7230_init_module(void)
|
||||||
|
{
|
||||||
|
int retval;
|
||||||
|
|
||||||
|
retval = comedi_driver_register(&driver_adl_pci7230);
|
||||||
|
if (retval < 0)
|
||||||
|
return retval;
|
||||||
|
|
||||||
|
driver_adl_pci7230_pci_driver.name =
|
||||||
|
(char *)driver_adl_pci7230.driver_name;
|
||||||
|
return pci_register_driver(&driver_adl_pci7230_pci_driver);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __exit driver_adl_pci7230_cleanup_module(void)
|
||||||
|
{
|
||||||
|
pci_unregister_driver(&driver_adl_pci7230_pci_driver);
|
||||||
|
comedi_driver_unregister(&driver_adl_pci7230);
|
||||||
|
}
|
||||||
|
|
||||||
|
module_init(driver_adl_pci7230_init_module);
|
||||||
|
module_exit(driver_adl_pci7230_cleanup_module);
|
||||||
|
|
||||||
|
MODULE_AUTHOR("Comedi http://www.comedi.org");
|
||||||
|
MODULE_DESCRIPTION("Comedi low-level driver");
|
||||||
|
MODULE_LICENSE("GPL");
|
||||||
|
|
|
@ -77,7 +77,7 @@ static struct comedi_driver driver_adl_pci7296 = {
|
||||||
static int adl_pci7296_attach(struct comedi_device *dev,
|
static int adl_pci7296_attach(struct comedi_device *dev,
|
||||||
struct comedi_devconfig *it)
|
struct comedi_devconfig *it)
|
||||||
{
|
{
|
||||||
struct pci_dev *pcidev;
|
struct pci_dev *pcidev = NULL;
|
||||||
struct comedi_subdevice *s;
|
struct comedi_subdevice *s;
|
||||||
int bus, slot;
|
int bus, slot;
|
||||||
int ret;
|
int ret;
|
||||||
|
@ -94,10 +94,7 @@ static int adl_pci7296_attach(struct comedi_device *dev,
|
||||||
if (alloc_subdevices(dev, 4) < 0)
|
if (alloc_subdevices(dev, 4) < 0)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
for (pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, NULL);
|
for_each_pci_dev(pcidev) {
|
||||||
pcidev != NULL;
|
|
||||||
pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pcidev)) {
|
|
||||||
|
|
||||||
if (pcidev->vendor == PCI_VENDOR_ID_ADLINK &&
|
if (pcidev->vendor == PCI_VENDOR_ID_ADLINK &&
|
||||||
pcidev->device == PCI_DEVICE_ID_PCI7296) {
|
pcidev->device == PCI_DEVICE_ID_PCI7296) {
|
||||||
if (bus || slot) {
|
if (bus || slot) {
|
||||||
|
@ -177,4 +174,46 @@ static int adl_pci7296_detach(struct comedi_device *dev)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
COMEDI_PCI_INITCLEANUP(driver_adl_pci7296, adl_pci7296_pci_table);
|
static int __devinit driver_adl_pci7296_pci_probe(struct pci_dev *dev,
|
||||||
|
const struct pci_device_id
|
||||||
|
*ent)
|
||||||
|
{
|
||||||
|
return comedi_pci_auto_config(dev, driver_adl_pci7296.driver_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __devexit driver_adl_pci7296_pci_remove(struct pci_dev *dev)
|
||||||
|
{
|
||||||
|
comedi_pci_auto_unconfig(dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct pci_driver driver_adl_pci7296_pci_driver = {
|
||||||
|
.id_table = adl_pci7296_pci_table,
|
||||||
|
.probe = &driver_adl_pci7296_pci_probe,
|
||||||
|
.remove = __devexit_p(&driver_adl_pci7296_pci_remove)
|
||||||
|
};
|
||||||
|
|
||||||
|
static int __init driver_adl_pci7296_init_module(void)
|
||||||
|
{
|
||||||
|
int retval;
|
||||||
|
|
||||||
|
retval = comedi_driver_register(&driver_adl_pci7296);
|
||||||
|
if (retval < 0)
|
||||||
|
return retval;
|
||||||
|
|
||||||
|
driver_adl_pci7296_pci_driver.name =
|
||||||
|
(char *)driver_adl_pci7296.driver_name;
|
||||||
|
return pci_register_driver(&driver_adl_pci7296_pci_driver);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __exit driver_adl_pci7296_cleanup_module(void)
|
||||||
|
{
|
||||||
|
pci_unregister_driver(&driver_adl_pci7296_pci_driver);
|
||||||
|
comedi_driver_unregister(&driver_adl_pci7296);
|
||||||
|
}
|
||||||
|
|
||||||
|
module_init(driver_adl_pci7296_init_module);
|
||||||
|
module_exit(driver_adl_pci7296_cleanup_module);
|
||||||
|
|
||||||
|
MODULE_AUTHOR("Comedi http://www.comedi.org");
|
||||||
|
MODULE_DESCRIPTION("Comedi low-level driver");
|
||||||
|
MODULE_LICENSE("GPL");
|
||||||
|
|
|
@ -86,7 +86,7 @@ static int adl_pci7432_do_insn_bits(struct comedi_device *dev,
|
||||||
static int adl_pci7432_attach(struct comedi_device *dev,
|
static int adl_pci7432_attach(struct comedi_device *dev,
|
||||||
struct comedi_devconfig *it)
|
struct comedi_devconfig *it)
|
||||||
{
|
{
|
||||||
struct pci_dev *pcidev;
|
struct pci_dev *pcidev = NULL;
|
||||||
struct comedi_subdevice *s;
|
struct comedi_subdevice *s;
|
||||||
int bus, slot;
|
int bus, slot;
|
||||||
|
|
||||||
|
@ -102,10 +102,7 @@ static int adl_pci7432_attach(struct comedi_device *dev,
|
||||||
if (alloc_subdevices(dev, 2) < 0)
|
if (alloc_subdevices(dev, 2) < 0)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
for (pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, NULL);
|
for_each_pci_dev(pcidev) {
|
||||||
pcidev != NULL;
|
|
||||||
pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pcidev)) {
|
|
||||||
|
|
||||||
if (pcidev->vendor == PCI_VENDOR_ID_ADLINK &&
|
if (pcidev->vendor == PCI_VENDOR_ID_ADLINK &&
|
||||||
pcidev->device == PCI_DEVICE_ID_PCI7432) {
|
pcidev->device == PCI_DEVICE_ID_PCI7432) {
|
||||||
if (bus || slot) {
|
if (bus || slot) {
|
||||||
|
@ -210,4 +207,46 @@ static int adl_pci7432_di_insn_bits(struct comedi_device *dev,
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
COMEDI_PCI_INITCLEANUP(driver_adl_pci7432, adl_pci7432_pci_table);
|
static int __devinit driver_adl_pci7432_pci_probe(struct pci_dev *dev,
|
||||||
|
const struct pci_device_id
|
||||||
|
*ent)
|
||||||
|
{
|
||||||
|
return comedi_pci_auto_config(dev, driver_adl_pci7432.driver_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __devexit driver_adl_pci7432_pci_remove(struct pci_dev *dev)
|
||||||
|
{
|
||||||
|
comedi_pci_auto_unconfig(dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct pci_driver driver_adl_pci7432_pci_driver = {
|
||||||
|
.id_table = adl_pci7432_pci_table,
|
||||||
|
.probe = &driver_adl_pci7432_pci_probe,
|
||||||
|
.remove = __devexit_p(&driver_adl_pci7432_pci_remove)
|
||||||
|
};
|
||||||
|
|
||||||
|
static int __init driver_adl_pci7432_init_module(void)
|
||||||
|
{
|
||||||
|
int retval;
|
||||||
|
|
||||||
|
retval = comedi_driver_register(&driver_adl_pci7432);
|
||||||
|
if (retval < 0)
|
||||||
|
return retval;
|
||||||
|
|
||||||
|
driver_adl_pci7432_pci_driver.name =
|
||||||
|
(char *)driver_adl_pci7432.driver_name;
|
||||||
|
return pci_register_driver(&driver_adl_pci7432_pci_driver);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __exit driver_adl_pci7432_cleanup_module(void)
|
||||||
|
{
|
||||||
|
pci_unregister_driver(&driver_adl_pci7432_pci_driver);
|
||||||
|
comedi_driver_unregister(&driver_adl_pci7432);
|
||||||
|
}
|
||||||
|
|
||||||
|
module_init(driver_adl_pci7432_init_module);
|
||||||
|
module_exit(driver_adl_pci7432_cleanup_module);
|
||||||
|
|
||||||
|
MODULE_AUTHOR("Comedi http://www.comedi.org");
|
||||||
|
MODULE_DESCRIPTION("Comedi low-level driver");
|
||||||
|
MODULE_LICENSE("GPL");
|
||||||
|
|
|
@ -125,7 +125,7 @@ static int adl_pci8164_insn_write_buf1(struct comedi_device *dev,
|
||||||
static int adl_pci8164_attach(struct comedi_device *dev,
|
static int adl_pci8164_attach(struct comedi_device *dev,
|
||||||
struct comedi_devconfig *it)
|
struct comedi_devconfig *it)
|
||||||
{
|
{
|
||||||
struct pci_dev *pcidev;
|
struct pci_dev *pcidev = NULL;
|
||||||
struct comedi_subdevice *s;
|
struct comedi_subdevice *s;
|
||||||
int bus, slot;
|
int bus, slot;
|
||||||
|
|
||||||
|
@ -142,10 +142,7 @@ static int adl_pci8164_attach(struct comedi_device *dev,
|
||||||
if (alloc_subdevices(dev, 4) < 0)
|
if (alloc_subdevices(dev, 4) < 0)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
for (pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, NULL);
|
for_each_pci_dev(pcidev) {
|
||||||
pcidev != NULL;
|
|
||||||
pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pcidev)) {
|
|
||||||
|
|
||||||
if (pcidev->vendor == PCI_VENDOR_ID_ADLINK &&
|
if (pcidev->vendor == PCI_VENDOR_ID_ADLINK &&
|
||||||
pcidev->device == PCI_DEVICE_ID_PCI8164) {
|
pcidev->device == PCI_DEVICE_ID_PCI8164) {
|
||||||
if (bus || slot) {
|
if (bus || slot) {
|
||||||
|
@ -389,4 +386,46 @@ static int adl_pci8164_insn_write_buf1(struct comedi_device *dev,
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
COMEDI_PCI_INITCLEANUP(driver_adl_pci8164, adl_pci8164_pci_table);
|
static int __devinit driver_adl_pci8164_pci_probe(struct pci_dev *dev,
|
||||||
|
const struct pci_device_id
|
||||||
|
*ent)
|
||||||
|
{
|
||||||
|
return comedi_pci_auto_config(dev, driver_adl_pci8164.driver_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __devexit driver_adl_pci8164_pci_remove(struct pci_dev *dev)
|
||||||
|
{
|
||||||
|
comedi_pci_auto_unconfig(dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct pci_driver driver_adl_pci8164_pci_driver = {
|
||||||
|
.id_table = adl_pci8164_pci_table,
|
||||||
|
.probe = &driver_adl_pci8164_pci_probe,
|
||||||
|
.remove = __devexit_p(&driver_adl_pci8164_pci_remove)
|
||||||
|
};
|
||||||
|
|
||||||
|
static int __init driver_adl_pci8164_init_module(void)
|
||||||
|
{
|
||||||
|
int retval;
|
||||||
|
|
||||||
|
retval = comedi_driver_register(&driver_adl_pci8164);
|
||||||
|
if (retval < 0)
|
||||||
|
return retval;
|
||||||
|
|
||||||
|
driver_adl_pci8164_pci_driver.name =
|
||||||
|
(char *)driver_adl_pci8164.driver_name;
|
||||||
|
return pci_register_driver(&driver_adl_pci8164_pci_driver);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __exit driver_adl_pci8164_cleanup_module(void)
|
||||||
|
{
|
||||||
|
pci_unregister_driver(&driver_adl_pci8164_pci_driver);
|
||||||
|
comedi_driver_unregister(&driver_adl_pci8164);
|
||||||
|
}
|
||||||
|
|
||||||
|
module_init(driver_adl_pci8164_init_module);
|
||||||
|
module_exit(driver_adl_pci8164_cleanup_module);
|
||||||
|
|
||||||
|
MODULE_AUTHOR("Comedi http://www.comedi.org");
|
||||||
|
MODULE_DESCRIPTION("Comedi low-level driver");
|
||||||
|
MODULE_LICENSE("GPL");
|
||||||
|
|
|
@ -68,8 +68,9 @@ CHANGELOG:
|
||||||
TODO:
|
TODO:
|
||||||
|
|
||||||
- Really test implemented functionality.
|
- Really test implemented functionality.
|
||||||
- Add support for the PCI-9111DG with a probe routine to identify the card type
|
- Add support for the PCI-9111DG with a probe routine to identify the card
|
||||||
(perhaps with the help of the channel number readback of the A/D Data register).
|
type (perhaps with the help of the channel number readback of the A/D Data
|
||||||
|
register).
|
||||||
- Add external multiplexer support.
|
- Add external multiplexer support.
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
@ -134,11 +135,13 @@ TODO:
|
||||||
|
|
||||||
/* IO address map */
|
/* IO address map */
|
||||||
|
|
||||||
#define PCI9111_REGISTER_AD_FIFO_VALUE 0x00 /* AD Data stored in FIFO */
|
#define PCI9111_REGISTER_AD_FIFO_VALUE 0x00 /* AD Data stored
|
||||||
|
in FIFO */
|
||||||
#define PCI9111_REGISTER_DA_OUTPUT 0x00
|
#define PCI9111_REGISTER_DA_OUTPUT 0x00
|
||||||
#define PCI9111_REGISTER_DIGITAL_IO 0x02
|
#define PCI9111_REGISTER_DIGITAL_IO 0x02
|
||||||
#define PCI9111_REGISTER_EXTENDED_IO_PORTS 0x04
|
#define PCI9111_REGISTER_EXTENDED_IO_PORTS 0x04
|
||||||
#define PCI9111_REGISTER_AD_CHANNEL_CONTROL 0x06 /* Channel selection */
|
#define PCI9111_REGISTER_AD_CHANNEL_CONTROL 0x06 /* Channel
|
||||||
|
selection */
|
||||||
#define PCI9111_REGISTER_AD_CHANNEL_READBACK 0x06
|
#define PCI9111_REGISTER_AD_CHANNEL_READBACK 0x06
|
||||||
#define PCI9111_REGISTER_INPUT_SIGNAL_RANGE 0x08
|
#define PCI9111_REGISTER_INPUT_SIGNAL_RANGE 0x08
|
||||||
#define PCI9111_REGISTER_RANGE_STATUS_READBACK 0x08
|
#define PCI9111_REGISTER_RANGE_STATUS_READBACK 0x08
|
||||||
|
@ -177,7 +180,7 @@ TODO:
|
||||||
#define PCI9111_FIFO_FULL_MASK 0x40
|
#define PCI9111_FIFO_FULL_MASK 0x40
|
||||||
#define PCI9111_AD_BUSY_MASK 0x80
|
#define PCI9111_AD_BUSY_MASK 0x80
|
||||||
|
|
||||||
#define PCI9111_IO_BASE dev->iobase
|
#define PCI9111_IO_BASE (dev->iobase)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Define inlined function
|
* Define inlined function
|
||||||
|
@ -190,7 +193,8 @@ TODO:
|
||||||
outb(flags, PCI9111_IO_BASE+PCI9111_REGISTER_TRIGGER_MODE_CONTROL)
|
outb(flags, PCI9111_IO_BASE+PCI9111_REGISTER_TRIGGER_MODE_CONTROL)
|
||||||
|
|
||||||
#define pci9111_interrupt_and_fifo_get() \
|
#define pci9111_interrupt_and_fifo_get() \
|
||||||
((inb(PCI9111_IO_BASE+PCI9111_REGISTER_AD_MODE_INTERRUPT_READBACK) >> 4) &0x03)
|
((inb(PCI9111_IO_BASE+PCI9111_REGISTER_AD_MODE_INTERRUPT_READBACK) >> 4) \
|
||||||
|
&0x03)
|
||||||
|
|
||||||
#define pci9111_interrupt_and_fifo_set(flags) \
|
#define pci9111_interrupt_and_fifo_set(flags) \
|
||||||
outb(flags, PCI9111_IO_BASE+PCI9111_REGISTER_INTERRUPT_CONTROL)
|
outb(flags, PCI9111_IO_BASE+PCI9111_REGISTER_INTERRUPT_CONTROL)
|
||||||
|
@ -201,45 +205,56 @@ TODO:
|
||||||
#define pci9111_software_trigger() \
|
#define pci9111_software_trigger() \
|
||||||
outb(0, PCI9111_IO_BASE+PCI9111_REGISTER_SOFTWARE_TRIGGER)
|
outb(0, PCI9111_IO_BASE+PCI9111_REGISTER_SOFTWARE_TRIGGER)
|
||||||
|
|
||||||
#define pci9111_fifo_reset() \
|
#define pci9111_fifo_reset() do { \
|
||||||
outb(PCI9111_FFEN_SET_FIFO_ENABLE, PCI9111_IO_BASE+PCI9111_REGISTER_INTERRUPT_CONTROL); \
|
outb(PCI9111_FFEN_SET_FIFO_ENABLE, \
|
||||||
outb(PCI9111_FFEN_SET_FIFO_DISABLE, PCI9111_IO_BASE+PCI9111_REGISTER_INTERRUPT_CONTROL); \
|
PCI9111_IO_BASE+PCI9111_REGISTER_INTERRUPT_CONTROL); \
|
||||||
outb(PCI9111_FFEN_SET_FIFO_ENABLE, PCI9111_IO_BASE+PCI9111_REGISTER_INTERRUPT_CONTROL)
|
outb(PCI9111_FFEN_SET_FIFO_DISABLE, \
|
||||||
|
PCI9111_IO_BASE+PCI9111_REGISTER_INTERRUPT_CONTROL); \
|
||||||
|
outb(PCI9111_FFEN_SET_FIFO_ENABLE, \
|
||||||
|
PCI9111_IO_BASE+PCI9111_REGISTER_INTERRUPT_CONTROL); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
#define pci9111_is_fifo_full() \
|
#define pci9111_is_fifo_full() \
|
||||||
((inb(PCI9111_IO_BASE+PCI9111_REGISTER_RANGE_STATUS_READBACK)& \
|
((inb(PCI9111_IO_BASE+PCI9111_REGISTER_RANGE_STATUS_READBACK)& \
|
||||||
PCI9111_FIFO_FULL_MASK)==0)
|
PCI9111_FIFO_FULL_MASK) == 0)
|
||||||
|
|
||||||
#define pci9111_is_fifo_half_full() \
|
#define pci9111_is_fifo_half_full() \
|
||||||
((inb(PCI9111_IO_BASE+PCI9111_REGISTER_RANGE_STATUS_READBACK)& \
|
((inb(PCI9111_IO_BASE+PCI9111_REGISTER_RANGE_STATUS_READBACK)& \
|
||||||
PCI9111_FIFO_HALF_FULL_MASK)==0)
|
PCI9111_FIFO_HALF_FULL_MASK) == 0)
|
||||||
|
|
||||||
#define pci9111_is_fifo_empty() \
|
#define pci9111_is_fifo_empty() \
|
||||||
((inb(PCI9111_IO_BASE+PCI9111_REGISTER_RANGE_STATUS_READBACK)& \
|
((inb(PCI9111_IO_BASE+PCI9111_REGISTER_RANGE_STATUS_READBACK)& \
|
||||||
PCI9111_FIFO_EMPTY_MASK)==0)
|
PCI9111_FIFO_EMPTY_MASK) == 0)
|
||||||
|
|
||||||
#define pci9111_ai_channel_set(channel) \
|
#define pci9111_ai_channel_set(channel) \
|
||||||
outb((channel)&PCI9111_CHANNEL_MASK, PCI9111_IO_BASE+PCI9111_REGISTER_AD_CHANNEL_CONTROL)
|
outb((channel)&PCI9111_CHANNEL_MASK, \
|
||||||
|
PCI9111_IO_BASE+PCI9111_REGISTER_AD_CHANNEL_CONTROL)
|
||||||
|
|
||||||
#define pci9111_ai_channel_get() \
|
#define pci9111_ai_channel_get() \
|
||||||
inb(PCI9111_IO_BASE+PCI9111_REGISTER_AD_CHANNEL_READBACK)&PCI9111_CHANNEL_MASK
|
(inb(PCI9111_IO_BASE+PCI9111_REGISTER_AD_CHANNEL_READBACK) \
|
||||||
|
&PCI9111_CHANNEL_MASK)
|
||||||
|
|
||||||
#define pci9111_ai_range_set(range) \
|
#define pci9111_ai_range_set(range) \
|
||||||
outb((range)&PCI9111_RANGE_MASK, PCI9111_IO_BASE+PCI9111_REGISTER_INPUT_SIGNAL_RANGE)
|
outb((range)&PCI9111_RANGE_MASK, \
|
||||||
|
PCI9111_IO_BASE+PCI9111_REGISTER_INPUT_SIGNAL_RANGE)
|
||||||
|
|
||||||
#define pci9111_ai_range_get() \
|
#define pci9111_ai_range_get() \
|
||||||
inb(PCI9111_IO_BASE+PCI9111_REGISTER_RANGE_STATUS_READBACK)&PCI9111_RANGE_MASK
|
(inb(PCI9111_IO_BASE+PCI9111_REGISTER_RANGE_STATUS_READBACK) \
|
||||||
|
&PCI9111_RANGE_MASK)
|
||||||
|
|
||||||
#define pci9111_ai_get_data() \
|
#define pci9111_ai_get_data() \
|
||||||
((inw(PCI9111_IO_BASE+PCI9111_REGISTER_AD_FIFO_VALUE)>>4)&PCI9111_AI_RESOLUTION_MASK) \
|
(((inw(PCI9111_IO_BASE+PCI9111_REGISTER_AD_FIFO_VALUE)>>4) \
|
||||||
^ PCI9111_AI_RESOLUTION_2_CMP_BIT
|
&PCI9111_AI_RESOLUTION_MASK) \
|
||||||
|
^ PCI9111_AI_RESOLUTION_2_CMP_BIT)
|
||||||
|
|
||||||
#define pci9111_hr_ai_get_data() \
|
#define pci9111_hr_ai_get_data() \
|
||||||
(inw(PCI9111_IO_BASE+PCI9111_REGISTER_AD_FIFO_VALUE) & PCI9111_HR_AI_RESOLUTION_MASK) \
|
((inw(PCI9111_IO_BASE+PCI9111_REGISTER_AD_FIFO_VALUE) \
|
||||||
^ PCI9111_HR_AI_RESOLUTION_2_CMP_BIT
|
& PCI9111_HR_AI_RESOLUTION_MASK) \
|
||||||
|
^ PCI9111_HR_AI_RESOLUTION_2_CMP_BIT)
|
||||||
|
|
||||||
#define pci9111_ao_set_data(data) \
|
#define pci9111_ao_set_data(data) \
|
||||||
outw(data&PCI9111_AO_RESOLUTION_MASK, PCI9111_IO_BASE+PCI9111_REGISTER_DA_OUTPUT)
|
outw(data&PCI9111_AO_RESOLUTION_MASK, \
|
||||||
|
PCI9111_IO_BASE+PCI9111_REGISTER_DA_OUTPUT)
|
||||||
|
|
||||||
#define pci9111_di_get_bits() \
|
#define pci9111_di_get_bits() \
|
||||||
inw(PCI9111_IO_BASE+PCI9111_REGISTER_DIGITAL_IO)
|
inw(PCI9111_IO_BASE+PCI9111_REGISTER_DIGITAL_IO)
|
||||||
|
@ -284,12 +299,11 @@ static const struct comedi_lrange pci9111_hr_ai_range = {
|
||||||
};
|
};
|
||||||
|
|
||||||
static DEFINE_PCI_DEVICE_TABLE(pci9111_pci_table) = {
|
static DEFINE_PCI_DEVICE_TABLE(pci9111_pci_table) = {
|
||||||
{
|
{ PCI_VENDOR_ID_ADLINK, PCI9111_HR_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,
|
||||||
PCI_VENDOR_ID_ADLINK, PCI9111_HR_DEVICE_ID, PCI_ANY_ID,
|
0, 0, 0 },
|
||||||
PCI_ANY_ID, 0, 0, 0},
|
/* { PCI_VENDOR_ID_ADLINK, PCI9111_HG_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,
|
||||||
/* { PCI_VENDOR_ID_ADLINK, PCI9111_HG_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, */
|
* 0, 0, 0 }, */
|
||||||
{
|
{ 0 }
|
||||||
0}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
MODULE_DEVICE_TABLE(pci, pci9111_pci_table);
|
MODULE_DEVICE_TABLE(pci, pci9111_pci_table);
|
||||||
|
@ -337,7 +351,43 @@ static struct comedi_driver pci9111_driver = {
|
||||||
.detach = pci9111_detach,
|
.detach = pci9111_detach,
|
||||||
};
|
};
|
||||||
|
|
||||||
COMEDI_PCI_INITCLEANUP(pci9111_driver, pci9111_pci_table);
|
static int __devinit pci9111_driver_pci_probe(struct pci_dev *dev,
|
||||||
|
const struct pci_device_id *ent)
|
||||||
|
{
|
||||||
|
return comedi_pci_auto_config(dev, pci9111_driver.driver_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __devexit pci9111_driver_pci_remove(struct pci_dev *dev)
|
||||||
|
{
|
||||||
|
comedi_pci_auto_unconfig(dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct pci_driver pci9111_driver_pci_driver = {
|
||||||
|
.id_table = pci9111_pci_table,
|
||||||
|
.probe = &pci9111_driver_pci_probe,
|
||||||
|
.remove = __devexit_p(&pci9111_driver_pci_remove)
|
||||||
|
};
|
||||||
|
|
||||||
|
static int __init pci9111_driver_init_module(void)
|
||||||
|
{
|
||||||
|
int retval;
|
||||||
|
|
||||||
|
retval = comedi_driver_register(&pci9111_driver);
|
||||||
|
if (retval < 0)
|
||||||
|
return retval;
|
||||||
|
|
||||||
|
pci9111_driver_pci_driver.name = (char *)pci9111_driver.driver_name;
|
||||||
|
return pci_register_driver(&pci9111_driver_pci_driver);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __exit pci9111_driver_cleanup_module(void)
|
||||||
|
{
|
||||||
|
pci_unregister_driver(&pci9111_driver_pci_driver);
|
||||||
|
comedi_driver_unregister(&pci9111_driver);
|
||||||
|
}
|
||||||
|
|
||||||
|
module_init(pci9111_driver_init_module);
|
||||||
|
module_exit(pci9111_driver_cleanup_module);
|
||||||
|
|
||||||
/* Private data structure */
|
/* Private data structure */
|
||||||
|
|
||||||
|
@ -345,7 +395,8 @@ struct pci9111_private_data {
|
||||||
struct pci_dev *pci_device;
|
struct pci_dev *pci_device;
|
||||||
unsigned long io_range; /* PCI6503 io range */
|
unsigned long io_range; /* PCI6503 io range */
|
||||||
|
|
||||||
unsigned long lcr_io_base; /* Local configuration register base address */
|
unsigned long lcr_io_base; /* Local configuration register base
|
||||||
|
* address */
|
||||||
unsigned long lcr_io_range;
|
unsigned long lcr_io_range;
|
||||||
|
|
||||||
int stop_counter;
|
int stop_counter;
|
||||||
|
@ -358,7 +409,8 @@ struct pci9111_private_data {
|
||||||
|
|
||||||
int ao_readback; /* Last written analog output data */
|
int ao_readback; /* Last written analog output data */
|
||||||
|
|
||||||
unsigned int timer_divisor_1; /* Divisor values for the 8254 timer pacer */
|
unsigned int timer_divisor_1; /* Divisor values for the 8254 timer
|
||||||
|
* pacer */
|
||||||
unsigned int timer_divisor_2;
|
unsigned int timer_divisor_2;
|
||||||
|
|
||||||
int is_valid; /* Is device valid */
|
int is_valid; /* Is device valid */
|
||||||
|
@ -548,10 +600,12 @@ static int pci9111_ai_cancel(struct comedi_device *dev,
|
||||||
|
|
||||||
/* Test analog input command */
|
/* Test analog input command */
|
||||||
|
|
||||||
#define pci9111_check_trigger_src(src, flags) \
|
#define pci9111_check_trigger_src(src, flags) do { \
|
||||||
tmp = src; \
|
tmp = src; \
|
||||||
src &= flags; \
|
src &= flags; \
|
||||||
if (!src || tmp != src) error++
|
if (!src || tmp != src) \
|
||||||
|
error++; \
|
||||||
|
} while (false);
|
||||||
|
|
||||||
static int
|
static int
|
||||||
pci9111_ai_do_cmd_test(struct comedi_device *dev,
|
pci9111_ai_do_cmd_test(struct comedi_device *dev,
|
||||||
|
@ -575,7 +629,8 @@ pci9111_ai_do_cmd_test(struct comedi_device *dev,
|
||||||
if (error)
|
if (error)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
/* step 2 : make sure trigger sources are unique and mutually compatible */
|
/* step 2 : make sure trigger sources are unique and mutually
|
||||||
|
* compatible */
|
||||||
|
|
||||||
if (cmd->start_src != TRIG_NOW)
|
if (cmd->start_src != TRIG_NOW)
|
||||||
error++;
|
error++;
|
||||||
|
@ -637,7 +692,8 @@ pci9111_ai_do_cmd_test(struct comedi_device *dev,
|
||||||
cmd->scan_begin_arg = board->ai_acquisition_period_min_ns;
|
cmd->scan_begin_arg = board->ai_acquisition_period_min_ns;
|
||||||
error++;
|
error++;
|
||||||
}
|
}
|
||||||
if ((cmd->scan_begin_src == TRIG_FOLLOW) && (cmd->scan_begin_arg != 0)) {
|
if ((cmd->scan_begin_src == TRIG_FOLLOW)
|
||||||
|
&& (cmd->scan_begin_arg != 0)) {
|
||||||
cmd->scan_begin_arg = 0;
|
cmd->scan_begin_arg = 0;
|
||||||
error++;
|
error++;
|
||||||
}
|
}
|
||||||
|
@ -1216,7 +1272,7 @@ static int pci9111_attach(struct comedi_device *dev,
|
||||||
{
|
{
|
||||||
struct comedi_subdevice *subdevice;
|
struct comedi_subdevice *subdevice;
|
||||||
unsigned long io_base, io_range, lcr_io_base, lcr_io_range;
|
unsigned long io_base, io_range, lcr_io_base, lcr_io_range;
|
||||||
struct pci_dev *pci_device;
|
struct pci_dev *pci_device = NULL;
|
||||||
int error, i;
|
int error, i;
|
||||||
const struct pci9111_board *board;
|
const struct pci9111_board *board;
|
||||||
|
|
||||||
|
@ -1226,17 +1282,17 @@ static int pci9111_attach(struct comedi_device *dev,
|
||||||
|
|
||||||
printk("comedi%d: " PCI9111_DRIVER_NAME " driver\n", dev->minor);
|
printk("comedi%d: " PCI9111_DRIVER_NAME " driver\n", dev->minor);
|
||||||
|
|
||||||
for (pci_device = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, NULL);
|
for_each_pci_dev(pci_device) {
|
||||||
pci_device != NULL;
|
|
||||||
pci_device = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pci_device)) {
|
|
||||||
if (pci_device->vendor == PCI_VENDOR_ID_ADLINK) {
|
if (pci_device->vendor == PCI_VENDOR_ID_ADLINK) {
|
||||||
for (i = 0; i < pci9111_board_nbr; i++) {
|
for (i = 0; i < pci9111_board_nbr; i++) {
|
||||||
if (pci9111_boards[i].device_id ==
|
if (pci9111_boards[i].device_id ==
|
||||||
pci_device->device) {
|
pci_device->device) {
|
||||||
/* was a particular bus/slot requested? */
|
/* was a particular bus/slot
|
||||||
|
* requested? */
|
||||||
if ((it->options[0] != 0)
|
if ((it->options[0] != 0)
|
||||||
|| (it->options[1] != 0)) {
|
|| (it->options[1] != 0)) {
|
||||||
/* are we on the wrong bus/slot? */
|
/* are we on the wrong
|
||||||
|
* bus/slot? */
|
||||||
if (pci_device->bus->number !=
|
if (pci_device->bus->number !=
|
||||||
it->options[0]
|
it->options[0]
|
||||||
||
|
||
|
||||||
|
@ -1272,7 +1328,8 @@ found:
|
||||||
|
|
||||||
/* TODO: Warn about non-tested boards. */
|
/* TODO: Warn about non-tested boards. */
|
||||||
|
|
||||||
/* Read local configuration register base address [PCI_BASE_ADDRESS #1]. */
|
/* Read local configuration register base address
|
||||||
|
* [PCI_BASE_ADDRESS #1]. */
|
||||||
|
|
||||||
lcr_io_base = pci_resource_start(pci_device, 1);
|
lcr_io_base = pci_resource_start(pci_device, 1);
|
||||||
lcr_io_range = pci_resource_len(pci_device, 1);
|
lcr_io_range = pci_resource_len(pci_device, 1);
|
||||||
|
@ -1399,3 +1456,7 @@ static int pci9111_detach(struct comedi_device *dev)
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MODULE_AUTHOR("Comedi http://www.comedi.org");
|
||||||
|
MODULE_DESCRIPTION("Comedi low-level driver");
|
||||||
|
MODULE_LICENSE("GPL");
|
||||||
|
|
|
@ -289,7 +289,43 @@ static struct comedi_driver driver_pci9118 = {
|
||||||
.offset = sizeof(struct boardtype),
|
.offset = sizeof(struct boardtype),
|
||||||
};
|
};
|
||||||
|
|
||||||
COMEDI_PCI_INITCLEANUP(driver_pci9118, pci9118_pci_table);
|
static int __devinit driver_pci9118_pci_probe(struct pci_dev *dev,
|
||||||
|
const struct pci_device_id *ent)
|
||||||
|
{
|
||||||
|
return comedi_pci_auto_config(dev, driver_pci9118.driver_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __devexit driver_pci9118_pci_remove(struct pci_dev *dev)
|
||||||
|
{
|
||||||
|
comedi_pci_auto_unconfig(dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct pci_driver driver_pci9118_pci_driver = {
|
||||||
|
.id_table = pci9118_pci_table,
|
||||||
|
.probe = &driver_pci9118_pci_probe,
|
||||||
|
.remove = __devexit_p(&driver_pci9118_pci_remove)
|
||||||
|
};
|
||||||
|
|
||||||
|
static int __init driver_pci9118_init_module(void)
|
||||||
|
{
|
||||||
|
int retval;
|
||||||
|
|
||||||
|
retval = comedi_driver_register(&driver_pci9118);
|
||||||
|
if (retval < 0)
|
||||||
|
return retval;
|
||||||
|
|
||||||
|
driver_pci9118_pci_driver.name = (char *)driver_pci9118.driver_name;
|
||||||
|
return pci_register_driver(&driver_pci9118_pci_driver);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __exit driver_pci9118_cleanup_module(void)
|
||||||
|
{
|
||||||
|
pci_unregister_driver(&driver_pci9118_pci_driver);
|
||||||
|
comedi_driver_unregister(&driver_pci9118);
|
||||||
|
}
|
||||||
|
|
||||||
|
module_init(driver_pci9118_init_module);
|
||||||
|
module_exit(driver_pci9118_cleanup_module);
|
||||||
|
|
||||||
struct pci9118_private {
|
struct pci9118_private {
|
||||||
unsigned long iobase_a; /* base+size for AMCC chip */
|
unsigned long iobase_a; /* base+size for AMCC chip */
|
||||||
|
@ -2432,3 +2468,7 @@ static int pci9118_detach(struct comedi_device *dev)
|
||||||
/*
|
/*
|
||||||
==============================================================================
|
==============================================================================
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
MODULE_AUTHOR("Comedi http://www.comedi.org");
|
||||||
|
MODULE_DESCRIPTION("Comedi low-level driver");
|
||||||
|
MODULE_LICENSE("GPL");
|
||||||
|
|
|
@ -402,4 +402,19 @@ static int adq12b_do_insn_bits(struct comedi_device *dev,
|
||||||
* A convenient macro that defines init_module() and cleanup_module(),
|
* A convenient macro that defines init_module() and cleanup_module(),
|
||||||
* as necessary.
|
* as necessary.
|
||||||
*/
|
*/
|
||||||
COMEDI_INITCLEANUP(driver_adq12b);
|
static int __init driver_adq12b_init_module(void)
|
||||||
|
{
|
||||||
|
return comedi_driver_register(&driver_adq12b);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __exit driver_adq12b_cleanup_module(void)
|
||||||
|
{
|
||||||
|
comedi_driver_unregister(&driver_adq12b);
|
||||||
|
}
|
||||||
|
|
||||||
|
module_init(driver_adq12b_init_module);
|
||||||
|
module_exit(driver_adq12b_cleanup_module);
|
||||||
|
|
||||||
|
MODULE_AUTHOR("Comedi http://www.comedi.org");
|
||||||
|
MODULE_DESCRIPTION("Comedi low-level driver");
|
||||||
|
MODULE_LICENSE("GPL");
|
||||||
|
|
|
@ -50,7 +50,9 @@ Configuration options:
|
||||||
#include "8253.h"
|
#include "8253.h"
|
||||||
#include "amcc_s5933.h"
|
#include "amcc_s5933.h"
|
||||||
|
|
||||||
#define PCI171x_PARANOIDCHECK /* if defined, then is used code which control correct channel number on every 12 bit sample */
|
#define PCI171x_PARANOIDCHECK /* if defined, then is used code which control
|
||||||
|
* correct channel number on every 12 bit
|
||||||
|
* sample */
|
||||||
|
|
||||||
#undef PCI171X_EXTDEBUG
|
#undef PCI171X_EXTDEBUG
|
||||||
|
|
||||||
|
@ -91,13 +93,15 @@ Configuration options:
|
||||||
#define PCI171x_CNT2 28 /* R/W: 8254 counter 2 */
|
#define PCI171x_CNT2 28 /* R/W: 8254 counter 2 */
|
||||||
#define PCI171x_CNTCTRL 30 /* W: 8254 counter control */
|
#define PCI171x_CNTCTRL 30 /* W: 8254 counter control */
|
||||||
|
|
||||||
/* upper bits from status register (PCI171x_STATUS) (lower is same woth control reg) */
|
/* upper bits from status register (PCI171x_STATUS) (lower is same with control
|
||||||
|
* reg) */
|
||||||
#define Status_FE 0x0100 /* 1=FIFO is empty */
|
#define Status_FE 0x0100 /* 1=FIFO is empty */
|
||||||
#define Status_FH 0x0200 /* 1=FIFO is half full */
|
#define Status_FH 0x0200 /* 1=FIFO is half full */
|
||||||
#define Status_FF 0x0400 /* 1=FIFO is full, fatal error */
|
#define Status_FF 0x0400 /* 1=FIFO is full, fatal error */
|
||||||
#define Status_IRQ 0x0800 /* 1=IRQ occured */
|
#define Status_IRQ 0x0800 /* 1=IRQ occured */
|
||||||
/* bits from control register (PCI171x_CONTROL) */
|
/* bits from control register (PCI171x_CONTROL) */
|
||||||
#define Control_CNT0 0x0040 /* 1=CNT0 have external source, 0=have internal 100kHz source */
|
#define Control_CNT0 0x0040 /* 1=CNT0 have external source,
|
||||||
|
* 0=have internal 100kHz source */
|
||||||
#define Control_ONEFH 0x0020 /* 1=IRQ on FIFO is half full, 0=every sample */
|
#define Control_ONEFH 0x0020 /* 1=IRQ on FIFO is half full, 0=every sample */
|
||||||
#define Control_IRQEN 0x0010 /* 1=enable IRQ */
|
#define Control_IRQEN 0x0010 /* 1=enable IRQ */
|
||||||
#define Control_GATE 0x0008 /* 1=enable external trigger GATE (8254?) */
|
#define Control_GATE 0x0008 /* 1=enable external trigger GATE (8254?) */
|
||||||
|
@ -112,7 +116,8 @@ Configuration options:
|
||||||
#define Counter_RW0 0x0010 /* RW0/RW1 select read/write mode */
|
#define Counter_RW0 0x0010 /* RW0/RW1 select read/write mode */
|
||||||
#define Counter_RW1 0x0020
|
#define Counter_RW1 0x0020
|
||||||
#define Counter_SC0 0x0040 /* Select Counter. Only 00 or 11 may */
|
#define Counter_SC0 0x0040 /* Select Counter. Only 00 or 11 may */
|
||||||
#define Counter_SC1 0x0080 /* be used, 00 for CNT0, 11 for read-back command */
|
#define Counter_SC1 0x0080 /* be used, 00 for CNT0,
|
||||||
|
* 11 for read-back command */
|
||||||
|
|
||||||
#define PCI1720_DA0 0 /* W: D/A register 0 */
|
#define PCI1720_DA0 0 /* W: D/A register 0 */
|
||||||
#define PCI1720_DA1 2 /* W: D/A register 1 */
|
#define PCI1720_DA1 2 /* W: D/A register 1 */
|
||||||
|
@ -138,8 +143,8 @@ static const struct comedi_lrange range_pci1710_3 = { 9, {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
static const char range_codes_pci1710_3[] =
|
static const char range_codes_pci1710_3[] = { 0x00, 0x01, 0x02, 0x03, 0x04,
|
||||||
{ 0x00, 0x01, 0x02, 0x03, 0x04, 0x10, 0x11, 0x12, 0x13 };
|
0x10, 0x11, 0x12, 0x13 };
|
||||||
|
|
||||||
static const struct comedi_lrange range_pci1710hg = { 12, {
|
static const struct comedi_lrange range_pci1710hg = { 12, {
|
||||||
BIP_RANGE(5),
|
BIP_RANGE(5),
|
||||||
|
@ -157,10 +162,9 @@ static const struct comedi_lrange range_pci1710hg = { 12, {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
static const char range_codes_pci1710hg[] =
|
static const char range_codes_pci1710hg[] = { 0x00, 0x01, 0x02, 0x03, 0x04,
|
||||||
{ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x10, 0x11, 0x12,
|
0x05, 0x06, 0x07, 0x10, 0x11,
|
||||||
0x13
|
0x12, 0x13 };
|
||||||
};
|
|
||||||
|
|
||||||
static const struct comedi_lrange range_pci17x1 = { 5, {
|
static const struct comedi_lrange range_pci17x1 = { 5, {
|
||||||
BIP_RANGE(10),
|
BIP_RANGE(10),
|
||||||
|
@ -301,7 +305,8 @@ struct pci1710_private {
|
||||||
unsigned int ai_timer1; /* timers */
|
unsigned int ai_timer1; /* timers */
|
||||||
unsigned int ai_timer2;
|
unsigned int ai_timer2;
|
||||||
short ao_data[4]; /* data output buffer */
|
short ao_data[4]; /* data output buffer */
|
||||||
unsigned int cnt0_write_wait; /* after a write, wait for update of the internal state */
|
unsigned int cnt0_write_wait; /* after a write, wait for update of the
|
||||||
|
* internal state */
|
||||||
};
|
};
|
||||||
|
|
||||||
#define devpriv ((struct pci1710_private *)dev->private)
|
#define devpriv ((struct pci1710_private *)dev->private)
|
||||||
|
@ -324,7 +329,9 @@ static int pci1710_reset(struct comedi_device *dev);
|
||||||
static int pci171x_ai_cancel(struct comedi_device *dev,
|
static int pci171x_ai_cancel(struct comedi_device *dev,
|
||||||
struct comedi_subdevice *s);
|
struct comedi_subdevice *s);
|
||||||
|
|
||||||
static const unsigned int muxonechan[] = { 0x0000, 0x0101, 0x0202, 0x0303, 0x0404, 0x0505, 0x0606, 0x0707, /* used for gain list programming */
|
/* used for gain list programming */
|
||||||
|
static const unsigned int muxonechan[] = {
|
||||||
|
0x0000, 0x0101, 0x0202, 0x0303, 0x0404, 0x0505, 0x0606, 0x0707,
|
||||||
0x0808, 0x0909, 0x0a0a, 0x0b0b, 0x0c0c, 0x0d0d, 0x0e0e, 0x0f0f,
|
0x0808, 0x0909, 0x0a0a, 0x0b0b, 0x0c0c, 0x0d0d, 0x0e0e, 0x0f0f,
|
||||||
0x1010, 0x1111, 0x1212, 0x1313, 0x1414, 0x1515, 0x1616, 0x1717,
|
0x1010, 0x1111, 0x1212, 0x1313, 0x1414, 0x1515, 0x1616, 0x1717,
|
||||||
0x1818, 0x1919, 0x1a1a, 0x1b1b, 0x1c1c, 0x1d1d, 0x1e1e, 0x1f1f
|
0x1818, 0x1919, 0x1a1a, 0x1b1b, 0x1c1c, 0x1d1d, 0x1e1e, 0x1f1f
|
||||||
|
@ -774,7 +781,8 @@ static void interrupt_pci1710_half_fifo(void *d)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!devpriv->neverending_ai)
|
if (!devpriv->neverending_ai)
|
||||||
if (devpriv->ai_act_scan >= devpriv->ai_scans) { /* all data sampled */
|
if (devpriv->ai_act_scan >= devpriv->ai_scans) { /* all data
|
||||||
|
sampled */
|
||||||
pci171x_ai_cancel(dev, s);
|
pci171x_ai_cancel(dev, s);
|
||||||
s->async->events |= COMEDI_CB_EOA;
|
s->async->events |= COMEDI_CB_EOA;
|
||||||
comedi_event(dev, s);
|
comedi_event(dev, s);
|
||||||
|
@ -1559,7 +1567,8 @@ static int pci1710_attach(struct comedi_device *dev,
|
||||||
s->maxdata = 1;
|
s->maxdata = 1;
|
||||||
s->len_chanlist = this_board->n_dochan;
|
s->len_chanlist = this_board->n_dochan;
|
||||||
s->range_table = &range_digital;
|
s->range_table = &range_digital;
|
||||||
s->io_bits = (1 << this_board->n_dochan) - 1; /* all bits output */
|
/* all bits output */
|
||||||
|
s->io_bits = (1 << this_board->n_dochan) - 1;
|
||||||
s->state = 0;
|
s->state = 0;
|
||||||
s->insn_bits = pci171x_insn_bits_do;
|
s->insn_bits = pci171x_insn_bits_do;
|
||||||
subdev++;
|
subdev++;
|
||||||
|
@ -1609,7 +1618,47 @@ static int pci1710_detach(struct comedi_device *dev)
|
||||||
/*
|
/*
|
||||||
==============================================================================
|
==============================================================================
|
||||||
*/
|
*/
|
||||||
COMEDI_PCI_INITCLEANUP(driver_pci1710, pci1710_pci_table);
|
static int __devinit driver_pci1710_pci_probe(struct pci_dev *dev,
|
||||||
|
const struct pci_device_id *ent)
|
||||||
|
{
|
||||||
|
return comedi_pci_auto_config(dev, driver_pci1710.driver_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __devexit driver_pci1710_pci_remove(struct pci_dev *dev)
|
||||||
|
{
|
||||||
|
comedi_pci_auto_unconfig(dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct pci_driver driver_pci1710_pci_driver = {
|
||||||
|
.id_table = pci1710_pci_table,
|
||||||
|
.probe = &driver_pci1710_pci_probe,
|
||||||
|
.remove = __devexit_p(&driver_pci1710_pci_remove)
|
||||||
|
};
|
||||||
|
|
||||||
|
static int __init driver_pci1710_init_module(void)
|
||||||
|
{
|
||||||
|
int retval;
|
||||||
|
|
||||||
|
retval = comedi_driver_register(&driver_pci1710);
|
||||||
|
if (retval < 0)
|
||||||
|
return retval;
|
||||||
|
|
||||||
|
driver_pci1710_pci_driver.name = (char *)driver_pci1710.driver_name;
|
||||||
|
return pci_register_driver(&driver_pci1710_pci_driver);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __exit driver_pci1710_cleanup_module(void)
|
||||||
|
{
|
||||||
|
pci_unregister_driver(&driver_pci1710_pci_driver);
|
||||||
|
comedi_driver_unregister(&driver_pci1710);
|
||||||
|
}
|
||||||
|
|
||||||
|
module_init(driver_pci1710_init_module);
|
||||||
|
module_exit(driver_pci1710_cleanup_module);
|
||||||
/*
|
/*
|
||||||
==============================================================================
|
==============================================================================
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
MODULE_AUTHOR("Comedi http://www.comedi.org");
|
||||||
|
MODULE_DESCRIPTION("Comedi low-level driver");
|
||||||
|
MODULE_LICENSE("GPL");
|
||||||
|
|
|
@ -496,4 +496,44 @@ static int pci1723_detach(struct comedi_device *dev)
|
||||||
* A convenient macro that defines init_module() and cleanup_module(),
|
* A convenient macro that defines init_module() and cleanup_module(),
|
||||||
* as necessary.
|
* as necessary.
|
||||||
*/
|
*/
|
||||||
COMEDI_PCI_INITCLEANUP(driver_pci1723, pci1723_pci_table);
|
static int __devinit driver_pci1723_pci_probe(struct pci_dev *dev,
|
||||||
|
const struct pci_device_id *ent)
|
||||||
|
{
|
||||||
|
return comedi_pci_auto_config(dev, driver_pci1723.driver_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __devexit driver_pci1723_pci_remove(struct pci_dev *dev)
|
||||||
|
{
|
||||||
|
comedi_pci_auto_unconfig(dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct pci_driver driver_pci1723_pci_driver = {
|
||||||
|
.id_table = pci1723_pci_table,
|
||||||
|
.probe = &driver_pci1723_pci_probe,
|
||||||
|
.remove = __devexit_p(&driver_pci1723_pci_remove)
|
||||||
|
};
|
||||||
|
|
||||||
|
static int __init driver_pci1723_init_module(void)
|
||||||
|
{
|
||||||
|
int retval;
|
||||||
|
|
||||||
|
retval = comedi_driver_register(&driver_pci1723);
|
||||||
|
if (retval < 0)
|
||||||
|
return retval;
|
||||||
|
|
||||||
|
driver_pci1723_pci_driver.name = (char *)driver_pci1723.driver_name;
|
||||||
|
return pci_register_driver(&driver_pci1723_pci_driver);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __exit driver_pci1723_cleanup_module(void)
|
||||||
|
{
|
||||||
|
pci_unregister_driver(&driver_pci1723_pci_driver);
|
||||||
|
comedi_driver_unregister(&driver_pci1723);
|
||||||
|
}
|
||||||
|
|
||||||
|
module_init(driver_pci1723_init_module);
|
||||||
|
module_exit(driver_pci1723_cleanup_module);
|
||||||
|
|
||||||
|
MODULE_AUTHOR("Comedi http://www.comedi.org");
|
||||||
|
MODULE_DESCRIPTION("Comedi low-level driver");
|
||||||
|
MODULE_LICENSE("GPL");
|
||||||
|
|
|
@ -67,9 +67,12 @@ enum hw_io_access {
|
||||||
|
|
||||||
#define MAX_DI_SUBDEVS 2 /* max number of DI subdevices per card */
|
#define MAX_DI_SUBDEVS 2 /* max number of DI subdevices per card */
|
||||||
#define MAX_DO_SUBDEVS 2 /* max number of DO subdevices per card */
|
#define MAX_DO_SUBDEVS 2 /* max number of DO subdevices per card */
|
||||||
#define MAX_DIO_SUBDEVG 2 /* max number of DIO subdevices group per card */
|
#define MAX_DIO_SUBDEVG 2 /* max number of DIO subdevices group per
|
||||||
#define MAX_8254_SUBDEVS 1 /* max number of 8254 counter subdevs per card */
|
* card */
|
||||||
/* (could be more than one 8254 per subdevice) */
|
#define MAX_8254_SUBDEVS 1 /* max number of 8254 counter subdevs per
|
||||||
|
* card */
|
||||||
|
/* (could be more than one 8254 per
|
||||||
|
* subdevice) */
|
||||||
|
|
||||||
#define SIZE_8254 4 /* 8254 IO space length */
|
#define SIZE_8254 4 /* 8254 IO space length */
|
||||||
#define SIZE_8255 4 /* 8255 IO space length */
|
#define SIZE_8255 4 /* 8255 IO space length */
|
||||||
|
@ -84,7 +87,8 @@ enum hw_io_access {
|
||||||
#define PCI1730_DO 2 /* W: Digital output 0-15 */
|
#define PCI1730_DO 2 /* W: Digital output 0-15 */
|
||||||
#define PCI1733_IDI 0 /* R: Isolated digital input 0-31 */
|
#define PCI1733_IDI 0 /* R: Isolated digital input 0-31 */
|
||||||
#define PCI1730_3_INT_EN 0x08 /* R/W: enable/disable interrupts */
|
#define PCI1730_3_INT_EN 0x08 /* R/W: enable/disable interrupts */
|
||||||
#define PCI1730_3_INT_RF 0x0c /* R/W: set falling/raising edge for interrupts */
|
#define PCI1730_3_INT_RF 0x0c /* R/W: set falling/raising edge for
|
||||||
|
* interrupts */
|
||||||
#define PCI1730_3_INT_CLR 0x10 /* R/W: clear interrupts */
|
#define PCI1730_3_INT_CLR 0x10 /* R/W: clear interrupts */
|
||||||
#define PCI1734_IDO 0 /* W: Isolated digital output 0-31 */
|
#define PCI1734_IDO 0 /* W: Isolated digital output 0-31 */
|
||||||
#define PCI173x_BOARDID 4 /* R: Board I/D switch for 1730/3/4 */
|
#define PCI173x_BOARDID 4 /* R: Board I/D switch for 1730/3/4 */
|
||||||
|
@ -99,7 +103,8 @@ enum hw_io_access {
|
||||||
#define PCI1736_IDI 0 /* R: Isolated digital input 0-15 */
|
#define PCI1736_IDI 0 /* R: Isolated digital input 0-15 */
|
||||||
#define PCI1736_IDO 0 /* W: Isolated digital output 0-15 */
|
#define PCI1736_IDO 0 /* W: Isolated digital output 0-15 */
|
||||||
#define PCI1736_3_INT_EN 0x08 /* R/W: enable/disable interrupts */
|
#define PCI1736_3_INT_EN 0x08 /* R/W: enable/disable interrupts */
|
||||||
#define PCI1736_3_INT_RF 0x0c /* R/W: set falling/raising edge for interrupts */
|
#define PCI1736_3_INT_RF 0x0c /* R/W: set falling/raising edge for
|
||||||
|
* interrupts */
|
||||||
#define PCI1736_3_INT_CLR 0x10 /* R/W: clear interrupts */
|
#define PCI1736_3_INT_CLR 0x10 /* R/W: clear interrupts */
|
||||||
#define PCI1736_BOARDID 4 /* R: Board I/D switch for 1736UP */
|
#define PCI1736_BOARDID 4 /* R: Board I/D switch for 1736UP */
|
||||||
#define PCI1736_MAINREG 0 /* Normal register (2) doesn't work */
|
#define PCI1736_MAINREG 0 /* Normal register (2) doesn't work */
|
||||||
|
@ -161,37 +166,66 @@ enum hw_io_access {
|
||||||
#define INTCSR3 0x3b
|
#define INTCSR3 0x3b
|
||||||
|
|
||||||
/* PCI-1760 mailbox commands */
|
/* PCI-1760 mailbox commands */
|
||||||
#define CMD_ClearIMB2 0x00 /* Clear IMB2 status and return actaul DI status in IMB3 */
|
#define CMD_ClearIMB2 0x00 /* Clear IMB2 status and return actual
|
||||||
|
* DI status in IMB3 */
|
||||||
#define CMD_SetRelaysOutput 0x01 /* Set relay output from OMB0 */
|
#define CMD_SetRelaysOutput 0x01 /* Set relay output from OMB0 */
|
||||||
#define CMD_GetRelaysStatus 0x02 /* Get relay status to IMB0 */
|
#define CMD_GetRelaysStatus 0x02 /* Get relay status to IMB0 */
|
||||||
#define CMD_ReadCurrentStatus 0x07 /* Read the current status of the register in OMB0, result in IMB0 */
|
#define CMD_ReadCurrentStatus 0x07 /* Read the current status of the
|
||||||
#define CMD_ReadFirmwareVersion 0x0e /* Read the firmware ver., result in IMB1.IMB0 */
|
* register in OMB0, result in IMB0 */
|
||||||
#define CMD_ReadHardwareVersion 0x0f /* Read the hardware ver., result in IMB1.IMB0 */
|
#define CMD_ReadFirmwareVersion 0x0e /* Read the firmware ver., result in
|
||||||
#define CMD_EnableIDIFilters 0x20 /* Enable IDI filters based on bits in OMB0 */
|
* IMB1.IMB0 */
|
||||||
#define CMD_EnableIDIPatternMatch 0x21 /* Enable IDI pattern match based on bits in OMB0 */
|
#define CMD_ReadHardwareVersion 0x0f /* Read the hardware ver., result in
|
||||||
#define CMD_SetIDIPatternMatch 0x22 /* Enable IDI pattern match based on bits in OMB0 */
|
* IMB1.IMB0 */
|
||||||
#define CMD_EnableIDICounters 0x28 /* Enable IDI counters based on bits in OMB0 */
|
#define CMD_EnableIDIFilters 0x20 /* Enable IDI filters based on bits in
|
||||||
#define CMD_ResetIDICounters 0x29 /* Reset IDI counters based on bits in OMB0 to its reset values */
|
* OMB0 */
|
||||||
#define CMD_OverflowIDICounters 0x2a /* Enable IDI counters overflow interrupts based on bits in OMB0 */
|
#define CMD_EnableIDIPatternMatch 0x21 /* Enable IDI pattern match based on
|
||||||
#define CMD_MatchIntIDICounters 0x2b /* Enable IDI counters match value interrupts based on bits in OMB0 */
|
* bits in OMB0 */
|
||||||
#define CMD_EdgeIDICounters 0x2c /* Set IDI up counters count edge (bit=0 - rising, =1 - falling) */
|
#define CMD_SetIDIPatternMatch 0x22 /* Enable IDI pattern match based on
|
||||||
#define CMD_GetIDICntCurValue 0x2f /* Read IDI{OMB0} up counter current value */
|
* bits in OMB0 */
|
||||||
#define CMD_SetIDI0CntResetValue 0x40 /* Set IDI0 Counter Reset Value 256*OMB1+OMB0 */
|
#define CMD_EnableIDICounters 0x28 /* Enable IDI counters based on bits in
|
||||||
#define CMD_SetIDI1CntResetValue 0x41 /* Set IDI1 Counter Reset Value 256*OMB1+OMB0 */
|
* OMB0 */
|
||||||
#define CMD_SetIDI2CntResetValue 0x42 /* Set IDI2 Counter Reset Value 256*OMB1+OMB0 */
|
#define CMD_ResetIDICounters 0x29 /* Reset IDI counters based on bits in
|
||||||
#define CMD_SetIDI3CntResetValue 0x43 /* Set IDI3 Counter Reset Value 256*OMB1+OMB0 */
|
* OMB0 to its reset values */
|
||||||
#define CMD_SetIDI4CntResetValue 0x44 /* Set IDI4 Counter Reset Value 256*OMB1+OMB0 */
|
#define CMD_OverflowIDICounters 0x2a /* Enable IDI counters overflow
|
||||||
#define CMD_SetIDI5CntResetValue 0x45 /* Set IDI5 Counter Reset Value 256*OMB1+OMB0 */
|
* interrupts based on bits in OMB0 */
|
||||||
#define CMD_SetIDI6CntResetValue 0x46 /* Set IDI6 Counter Reset Value 256*OMB1+OMB0 */
|
#define CMD_MatchIntIDICounters 0x2b /* Enable IDI counters match value
|
||||||
#define CMD_SetIDI7CntResetValue 0x47 /* Set IDI7 Counter Reset Value 256*OMB1+OMB0 */
|
* interrupts based on bits in OMB0 */
|
||||||
#define CMD_SetIDI0CntMatchValue 0x48 /* Set IDI0 Counter Match Value 256*OMB1+OMB0 */
|
#define CMD_EdgeIDICounters 0x2c /* Set IDI up counters count edge (bit=0
|
||||||
#define CMD_SetIDI1CntMatchValue 0x49 /* Set IDI1 Counter Match Value 256*OMB1+OMB0 */
|
* - rising, =1 - falling) */
|
||||||
#define CMD_SetIDI2CntMatchValue 0x4a /* Set IDI2 Counter Match Value 256*OMB1+OMB0 */
|
#define CMD_GetIDICntCurValue 0x2f /* Read IDI{OMB0} up counter current
|
||||||
#define CMD_SetIDI3CntMatchValue 0x4b /* Set IDI3 Counter Match Value 256*OMB1+OMB0 */
|
* value */
|
||||||
#define CMD_SetIDI4CntMatchValue 0x4c /* Set IDI4 Counter Match Value 256*OMB1+OMB0 */
|
#define CMD_SetIDI0CntResetValue 0x40 /* Set IDI0 Counter Reset Value
|
||||||
#define CMD_SetIDI5CntMatchValue 0x4d /* Set IDI5 Counter Match Value 256*OMB1+OMB0 */
|
* 256*OMB1+OMB0 */
|
||||||
#define CMD_SetIDI6CntMatchValue 0x4e /* Set IDI6 Counter Match Value 256*OMB1+OMB0 */
|
#define CMD_SetIDI1CntResetValue 0x41 /* Set IDI1 Counter Reset Value
|
||||||
#define CMD_SetIDI7CntMatchValue 0x4f /* Set IDI7 Counter Match Value 256*OMB1+OMB0 */
|
* 256*OMB1+OMB0 */
|
||||||
|
#define CMD_SetIDI2CntResetValue 0x42 /* Set IDI2 Counter Reset Value
|
||||||
|
* 256*OMB1+OMB0 */
|
||||||
|
#define CMD_SetIDI3CntResetValue 0x43 /* Set IDI3 Counter Reset Value
|
||||||
|
* 256*OMB1+OMB0 */
|
||||||
|
#define CMD_SetIDI4CntResetValue 0x44 /* Set IDI4 Counter Reset Value
|
||||||
|
* 256*OMB1+OMB0 */
|
||||||
|
#define CMD_SetIDI5CntResetValue 0x45 /* Set IDI5 Counter Reset Value
|
||||||
|
* 256*OMB1+OMB0 */
|
||||||
|
#define CMD_SetIDI6CntResetValue 0x46 /* Set IDI6 Counter Reset Value
|
||||||
|
* 256*OMB1+OMB0 */
|
||||||
|
#define CMD_SetIDI7CntResetValue 0x47 /* Set IDI7 Counter Reset Value
|
||||||
|
* 256*OMB1+OMB0 */
|
||||||
|
#define CMD_SetIDI0CntMatchValue 0x48 /* Set IDI0 Counter Match Value
|
||||||
|
* 256*OMB1+OMB0 */
|
||||||
|
#define CMD_SetIDI1CntMatchValue 0x49 /* Set IDI1 Counter Match Value
|
||||||
|
* 256*OMB1+OMB0 */
|
||||||
|
#define CMD_SetIDI2CntMatchValue 0x4a /* Set IDI2 Counter Match Value
|
||||||
|
* 256*OMB1+OMB0 */
|
||||||
|
#define CMD_SetIDI3CntMatchValue 0x4b /* Set IDI3 Counter Match Value
|
||||||
|
* 256*OMB1+OMB0 */
|
||||||
|
#define CMD_SetIDI4CntMatchValue 0x4c /* Set IDI4 Counter Match Value
|
||||||
|
* 256*OMB1+OMB0 */
|
||||||
|
#define CMD_SetIDI5CntMatchValue 0x4d /* Set IDI5 Counter Match Value
|
||||||
|
* 256*OMB1+OMB0 */
|
||||||
|
#define CMD_SetIDI6CntMatchValue 0x4e /* Set IDI6 Counter Match Value
|
||||||
|
* 256*OMB1+OMB0 */
|
||||||
|
#define CMD_SetIDI7CntMatchValue 0x4f /* Set IDI7 Counter Match Value
|
||||||
|
* 256*OMB1+OMB0 */
|
||||||
|
|
||||||
#define OMBCMD_RETRY 0x03 /* 3 times try request before error */
|
#define OMBCMD_RETRY 0x03 /* 3 times try request before error */
|
||||||
|
|
||||||
|
@ -244,115 +278,115 @@ MODULE_DEVICE_TABLE(pci, pci_dio_pci_table);
|
||||||
static const struct dio_boardtype boardtypes[] = {
|
static const struct dio_boardtype boardtypes[] = {
|
||||||
{"pci1730", PCI_VENDOR_ID_ADVANTECH, 0x1730, PCIDIO_MAINREG,
|
{"pci1730", PCI_VENDOR_ID_ADVANTECH, 0x1730, PCIDIO_MAINREG,
|
||||||
TYPE_PCI1730,
|
TYPE_PCI1730,
|
||||||
{{16, PCI1730_DI, 2, 0}, {16, PCI1730_IDI, 2, 0}},
|
{ {16, PCI1730_DI, 2, 0}, {16, PCI1730_IDI, 2, 0} },
|
||||||
{{16, PCI1730_DO, 2, 0}, {16, PCI1730_IDO, 2, 0}},
|
{ {16, PCI1730_DO, 2, 0}, {16, PCI1730_IDO, 2, 0} },
|
||||||
{{0, 0, 0, 0}, {0, 0, 0, 0}},
|
{ {0, 0, 0, 0}, {0, 0, 0, 0} },
|
||||||
{4, PCI173x_BOARDID, 1, SDF_INTERNAL},
|
{4, PCI173x_BOARDID, 1, SDF_INTERNAL},
|
||||||
{{0, 0, 0, 0}},
|
{ {0, 0, 0, 0} },
|
||||||
IO_8b},
|
IO_8b},
|
||||||
{"pci1733", PCI_VENDOR_ID_ADVANTECH, 0x1733, PCIDIO_MAINREG,
|
{"pci1733", PCI_VENDOR_ID_ADVANTECH, 0x1733, PCIDIO_MAINREG,
|
||||||
TYPE_PCI1733,
|
TYPE_PCI1733,
|
||||||
{{0, 0, 0, 0}, {32, PCI1733_IDI, 4, 0}},
|
{ {0, 0, 0, 0}, {32, PCI1733_IDI, 4, 0} },
|
||||||
{{0, 0, 0, 0}, {0, 0, 0, 0}},
|
{ {0, 0, 0, 0}, {0, 0, 0, 0} },
|
||||||
{{0, 0, 0, 0}, {0, 0, 0, 0}},
|
{ {0, 0, 0, 0}, {0, 0, 0, 0} },
|
||||||
{4, PCI173x_BOARDID, 1, SDF_INTERNAL},
|
{4, PCI173x_BOARDID, 1, SDF_INTERNAL},
|
||||||
{{0, 0, 0, 0}},
|
{ {0, 0, 0, 0} },
|
||||||
IO_8b},
|
IO_8b},
|
||||||
{"pci1734", PCI_VENDOR_ID_ADVANTECH, 0x1734, PCIDIO_MAINREG,
|
{"pci1734", PCI_VENDOR_ID_ADVANTECH, 0x1734, PCIDIO_MAINREG,
|
||||||
TYPE_PCI1734,
|
TYPE_PCI1734,
|
||||||
{{0, 0, 0, 0}, {0, 0, 0, 0}},
|
{ {0, 0, 0, 0}, {0, 0, 0, 0} },
|
||||||
{{0, 0, 0, 0}, {32, PCI1734_IDO, 4, 0}},
|
{ {0, 0, 0, 0}, {32, PCI1734_IDO, 4, 0} },
|
||||||
{{0, 0, 0, 0}, {0, 0, 0, 0}},
|
{ {0, 0, 0, 0}, {0, 0, 0, 0} },
|
||||||
{4, PCI173x_BOARDID, 1, SDF_INTERNAL},
|
{4, PCI173x_BOARDID, 1, SDF_INTERNAL},
|
||||||
{{0, 0, 0, 0}},
|
{ {0, 0, 0, 0} },
|
||||||
IO_8b},
|
IO_8b},
|
||||||
{"pci1735", PCI_VENDOR_ID_ADVANTECH, 0x1735, PCIDIO_MAINREG,
|
{"pci1735", PCI_VENDOR_ID_ADVANTECH, 0x1735, PCIDIO_MAINREG,
|
||||||
TYPE_PCI1735,
|
TYPE_PCI1735,
|
||||||
{{32, PCI1735_DI, 4, 0}, {0, 0, 0, 0}},
|
{ {32, PCI1735_DI, 4, 0}, {0, 0, 0, 0} },
|
||||||
{{32, PCI1735_DO, 4, 0}, {0, 0, 0, 0}},
|
{ {32, PCI1735_DO, 4, 0}, {0, 0, 0, 0} },
|
||||||
{{0, 0, 0, 0}, {0, 0, 0, 0}},
|
{ {0, 0, 0, 0}, {0, 0, 0, 0} },
|
||||||
{ 4, PCI1735_BOARDID, 1, SDF_INTERNAL},
|
{ 4, PCI1735_BOARDID, 1, SDF_INTERNAL},
|
||||||
{{3, PCI1735_C8254, 1, 0}},
|
{ {3, PCI1735_C8254, 1, 0} },
|
||||||
IO_8b},
|
IO_8b},
|
||||||
{"pci1736", PCI_VENDOR_ID_ADVANTECH, 0x1736, PCI1736_MAINREG,
|
{"pci1736", PCI_VENDOR_ID_ADVANTECH, 0x1736, PCI1736_MAINREG,
|
||||||
TYPE_PCI1736,
|
TYPE_PCI1736,
|
||||||
{{0, 0, 0, 0}, {16, PCI1736_IDI, 2, 0}},
|
{ {0, 0, 0, 0}, {16, PCI1736_IDI, 2, 0} },
|
||||||
{{0, 0, 0, 0}, {16, PCI1736_IDO, 2, 0}},
|
{ {0, 0, 0, 0}, {16, PCI1736_IDO, 2, 0} },
|
||||||
{{0, 0, 0, 0}, {0, 0, 0, 0}},
|
{ {0, 0, 0, 0}, {0, 0, 0, 0} },
|
||||||
{4, PCI1736_BOARDID, 1, SDF_INTERNAL},
|
{4, PCI1736_BOARDID, 1, SDF_INTERNAL},
|
||||||
{{0, 0, 0, 0}},
|
{ {0, 0, 0, 0} },
|
||||||
IO_8b},
|
IO_8b},
|
||||||
{"pci1750", PCI_VENDOR_ID_ADVANTECH, 0x1750, PCIDIO_MAINREG,
|
{"pci1750", PCI_VENDOR_ID_ADVANTECH, 0x1750, PCIDIO_MAINREG,
|
||||||
TYPE_PCI1750,
|
TYPE_PCI1750,
|
||||||
{{0, 0, 0, 0}, {16, PCI1750_IDI, 2, 0}},
|
{ {0, 0, 0, 0}, {16, PCI1750_IDI, 2, 0} },
|
||||||
{{0, 0, 0, 0}, {16, PCI1750_IDO, 2, 0}},
|
{ {0, 0, 0, 0}, {16, PCI1750_IDO, 2, 0} },
|
||||||
{{0, 0, 0, 0}, {0, 0, 0, 0}},
|
{ {0, 0, 0, 0}, {0, 0, 0, 0} },
|
||||||
{0, 0, 0, 0},
|
{0, 0, 0, 0},
|
||||||
{{0, 0, 0, 0}},
|
{ {0, 0, 0, 0} },
|
||||||
IO_8b},
|
IO_8b},
|
||||||
{"pci1751", PCI_VENDOR_ID_ADVANTECH, 0x1751, PCIDIO_MAINREG,
|
{"pci1751", PCI_VENDOR_ID_ADVANTECH, 0x1751, PCIDIO_MAINREG,
|
||||||
TYPE_PCI1751,
|
TYPE_PCI1751,
|
||||||
{{0, 0, 0, 0}, {0, 0, 0, 0}},
|
{ {0, 0, 0, 0}, {0, 0, 0, 0} },
|
||||||
{{0, 0, 0, 0}, {0, 0, 0, 0}},
|
{ {0, 0, 0, 0}, {0, 0, 0, 0} },
|
||||||
{{48, PCI1751_DIO, 2, 0}, {0, 0, 0, 0}},
|
{ {48, PCI1751_DIO, 2, 0}, {0, 0, 0, 0} },
|
||||||
{0, 0, 0, 0},
|
{0, 0, 0, 0},
|
||||||
{{0, 0, 0, 0}},
|
{ {0, 0, 0, 0} },
|
||||||
IO_8b},
|
IO_8b},
|
||||||
{"pci1752", PCI_VENDOR_ID_ADVANTECH, 0x1752, PCIDIO_MAINREG,
|
{"pci1752", PCI_VENDOR_ID_ADVANTECH, 0x1752, PCIDIO_MAINREG,
|
||||||
TYPE_PCI1752,
|
TYPE_PCI1752,
|
||||||
{{0, 0, 0, 0}, {0, 0, 0, 0}},
|
{ {0, 0, 0, 0}, {0, 0, 0, 0} },
|
||||||
{{32, PCI1752_IDO, 2, 0}, {32, PCI1752_IDO2, 2, 0}},
|
{ {32, PCI1752_IDO, 2, 0}, {32, PCI1752_IDO2, 2, 0} },
|
||||||
{{0, 0, 0, 0}, {0, 0, 0, 0}},
|
{ {0, 0, 0, 0}, {0, 0, 0, 0} },
|
||||||
{4, PCI175x_BOARDID, 1, SDF_INTERNAL},
|
{4, PCI175x_BOARDID, 1, SDF_INTERNAL},
|
||||||
{{0, 0, 0, 0}},
|
{ {0, 0, 0, 0} },
|
||||||
IO_16b},
|
IO_16b},
|
||||||
{"pci1753", PCI_VENDOR_ID_ADVANTECH, 0x1753, PCIDIO_MAINREG,
|
{"pci1753", PCI_VENDOR_ID_ADVANTECH, 0x1753, PCIDIO_MAINREG,
|
||||||
TYPE_PCI1753,
|
TYPE_PCI1753,
|
||||||
{{0, 0, 0, 0}, {0, 0, 0, 0}},
|
{ {0, 0, 0, 0}, {0, 0, 0, 0} },
|
||||||
{{0, 0, 0, 0}, {0, 0, 0, 0}},
|
{ {0, 0, 0, 0}, {0, 0, 0, 0} },
|
||||||
{{96, PCI1753_DIO, 4, 0}, {0, 0, 0, 0}},
|
{ {96, PCI1753_DIO, 4, 0}, {0, 0, 0, 0} },
|
||||||
{0, 0, 0, 0},
|
{0, 0, 0, 0},
|
||||||
{{0, 0, 0, 0}},
|
{ {0, 0, 0, 0} },
|
||||||
IO_8b},
|
IO_8b},
|
||||||
{"pci1753e", PCI_VENDOR_ID_ADVANTECH, 0x1753, PCIDIO_MAINREG,
|
{"pci1753e", PCI_VENDOR_ID_ADVANTECH, 0x1753, PCIDIO_MAINREG,
|
||||||
TYPE_PCI1753E,
|
TYPE_PCI1753E,
|
||||||
{{0, 0, 0, 0}, {0, 0, 0, 0}},
|
{ {0, 0, 0, 0}, {0, 0, 0, 0} },
|
||||||
{{0, 0, 0, 0}, {0, 0, 0, 0}},
|
{ {0, 0, 0, 0}, {0, 0, 0, 0} },
|
||||||
{{96, PCI1753_DIO, 4, 0}, {96, PCI1753E_DIO, 4, 0}},
|
{ {96, PCI1753_DIO, 4, 0}, {96, PCI1753E_DIO, 4, 0} },
|
||||||
{0, 0, 0, 0},
|
{0, 0, 0, 0},
|
||||||
{{0, 0, 0, 0}},
|
{ {0, 0, 0, 0} },
|
||||||
IO_8b},
|
IO_8b},
|
||||||
{"pci1754", PCI_VENDOR_ID_ADVANTECH, 0x1754, PCIDIO_MAINREG,
|
{"pci1754", PCI_VENDOR_ID_ADVANTECH, 0x1754, PCIDIO_MAINREG,
|
||||||
TYPE_PCI1754,
|
TYPE_PCI1754,
|
||||||
{{32, PCI1754_IDI, 2, 0}, {32, PCI1754_IDI2, 2, 0}},
|
{ {32, PCI1754_IDI, 2, 0}, {32, PCI1754_IDI2, 2, 0} },
|
||||||
{{0, 0, 0, 0}, {0, 0, 0, 0}},
|
{ {0, 0, 0, 0}, {0, 0, 0, 0} },
|
||||||
{{0, 0, 0, 0}, {0, 0, 0, 0}},
|
{ {0, 0, 0, 0}, {0, 0, 0, 0} },
|
||||||
{4, PCI175x_BOARDID, 1, SDF_INTERNAL},
|
{4, PCI175x_BOARDID, 1, SDF_INTERNAL},
|
||||||
{{0, 0, 0, 0}},
|
{ {0, 0, 0, 0} },
|
||||||
IO_16b},
|
IO_16b},
|
||||||
{"pci1756", PCI_VENDOR_ID_ADVANTECH, 0x1756, PCIDIO_MAINREG,
|
{"pci1756", PCI_VENDOR_ID_ADVANTECH, 0x1756, PCIDIO_MAINREG,
|
||||||
TYPE_PCI1756,
|
TYPE_PCI1756,
|
||||||
{{0, 0, 0, 0}, {32, PCI1756_IDI, 2, 0}},
|
{ {0, 0, 0, 0}, {32, PCI1756_IDI, 2, 0} },
|
||||||
{{0, 0, 0, 0}, {32, PCI1756_IDO, 2, 0}},
|
{ {0, 0, 0, 0}, {32, PCI1756_IDO, 2, 0} },
|
||||||
{{0, 0, 0, 0}, {0, 0, 0, 0}},
|
{ {0, 0, 0, 0}, {0, 0, 0, 0} },
|
||||||
{4, PCI175x_BOARDID, 1, SDF_INTERNAL},
|
{4, PCI175x_BOARDID, 1, SDF_INTERNAL},
|
||||||
{{0, 0, 0, 0}},
|
{ {0, 0, 0, 0} },
|
||||||
IO_16b},
|
IO_16b},
|
||||||
{"pci1760", PCI_VENDOR_ID_ADVANTECH, 0x1760, 0,
|
{"pci1760", PCI_VENDOR_ID_ADVANTECH, 0x1760, 0,
|
||||||
TYPE_PCI1760,
|
TYPE_PCI1760,
|
||||||
{{0, 0, 0, 0}, {0, 0, 0, 0}}, /* This card have own setup work */
|
{ {0, 0, 0, 0}, {0, 0, 0, 0} }, /* This card have own setup work */
|
||||||
{{0, 0, 0, 0}, {0, 0, 0, 0}},
|
{ {0, 0, 0, 0}, {0, 0, 0, 0} },
|
||||||
{{0, 0, 0, 0}, {0, 0, 0, 0}},
|
{ {0, 0, 0, 0}, {0, 0, 0, 0} },
|
||||||
{0, 0, 0, 0},
|
{0, 0, 0, 0},
|
||||||
{{0, 0, 0, 0}},
|
{ {0, 0, 0, 0} },
|
||||||
IO_8b},
|
IO_8b},
|
||||||
{"pci1762", PCI_VENDOR_ID_ADVANTECH, 0x1762, PCIDIO_MAINREG,
|
{"pci1762", PCI_VENDOR_ID_ADVANTECH, 0x1762, PCIDIO_MAINREG,
|
||||||
TYPE_PCI1762,
|
TYPE_PCI1762,
|
||||||
{{0, 0, 0, 0}, {16, PCI1762_IDI, 1, 0}},
|
{ {0, 0, 0, 0}, {16, PCI1762_IDI, 1, 0} },
|
||||||
{{0, 0, 0, 0}, {16, PCI1762_RO, 1, 0}},
|
{ {0, 0, 0, 0}, {16, PCI1762_RO, 1, 0} },
|
||||||
{{0, 0, 0, 0}, {0, 0, 0, 0}},
|
{ {0, 0, 0, 0}, {0, 0, 0, 0} },
|
||||||
{4, PCI1762_BOARDID, 1, SDF_INTERNAL},
|
{4, PCI1762_BOARDID, 1, SDF_INTERNAL},
|
||||||
{{0, 0, 0, 0}},
|
{ {0, 0, 0, 0} },
|
||||||
IO_16b}
|
IO_16b}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -373,9 +407,12 @@ struct pci_dio_private {
|
||||||
char GlobalIrqEnabled; /* 1= any IRQ source is enabled */
|
char GlobalIrqEnabled; /* 1= any IRQ source is enabled */
|
||||||
/* PCI-1760 specific data */
|
/* PCI-1760 specific data */
|
||||||
unsigned char IDICntEnable; /* counter's counting enable status */
|
unsigned char IDICntEnable; /* counter's counting enable status */
|
||||||
unsigned char IDICntOverEnable; /* counter's overflow interrupts enable status */
|
unsigned char IDICntOverEnable; /* counter's overflow interrupts enable
|
||||||
unsigned char IDICntMatchEnable; /* counter's match interrupts enable status */
|
* status */
|
||||||
unsigned char IDICntEdge; /* counter's count edge value (bit=0 - rising, =1 - falling) */
|
unsigned char IDICntMatchEnable; /* counter's match interrupts
|
||||||
|
* enable status */
|
||||||
|
unsigned char IDICntEdge; /* counter's count edge value
|
||||||
|
* (bit=0 - rising, =1 - falling) */
|
||||||
unsigned short CntResValue[8]; /* counters' reset value */
|
unsigned short CntResValue[8]; /* counters' reset value */
|
||||||
unsigned short CntMatchValue[8]; /* counters' match interrupt value */
|
unsigned short CntMatchValue[8]; /* counters' match interrupt value */
|
||||||
unsigned char IDIFiltersEn; /* IDI's digital filters enable status */
|
unsigned char IDIFiltersEn; /* IDI's digital filters enable status */
|
||||||
|
@ -691,7 +728,8 @@ static int pci1760_insn_cnt_write(struct comedi_device *dev,
|
||||||
};
|
};
|
||||||
unsigned char imb[4];
|
unsigned char imb[4];
|
||||||
|
|
||||||
if (devpriv->CntResValue[chan] != (data[0] & 0xffff)) { /* Set reset value if different */
|
/* Set reset value if different */
|
||||||
|
if (devpriv->CntResValue[chan] != (data[0] & 0xffff)) {
|
||||||
ret = pci1760_mbxrequest(dev, omb, imb);
|
ret = pci1760_mbxrequest(dev, omb, imb);
|
||||||
if (!ret)
|
if (!ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -704,7 +742,8 @@ static int pci1760_insn_cnt_write(struct comedi_device *dev,
|
||||||
if (!ret)
|
if (!ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
if (!(bitmask & devpriv->IDICntEnable)) { /* start counter if it don't run */
|
/* start counter if it don't run */
|
||||||
|
if (!(bitmask & devpriv->IDICntEnable)) {
|
||||||
omb[0] = bitmask;
|
omb[0] = bitmask;
|
||||||
omb[2] = CMD_EnableIDICounters;
|
omb[2] = CMD_EnableIDICounters;
|
||||||
ret = pci1760_mbxrequest(dev, omb, imb);
|
ret = pci1760_mbxrequest(dev, omb, imb);
|
||||||
|
@ -740,12 +779,14 @@ static int pci1760_reset(struct comedi_device *dev)
|
||||||
devpriv->IDICntEnable = 0;
|
devpriv->IDICntEnable = 0;
|
||||||
|
|
||||||
omb[0] = 0x00;
|
omb[0] = 0x00;
|
||||||
omb[2] = CMD_OverflowIDICounters; /* disable counters overflow interrupts */
|
omb[2] = CMD_OverflowIDICounters; /* disable counters overflow
|
||||||
|
* interrupts */
|
||||||
pci1760_mbxrequest(dev, omb, imb);
|
pci1760_mbxrequest(dev, omb, imb);
|
||||||
devpriv->IDICntOverEnable = 0;
|
devpriv->IDICntOverEnable = 0;
|
||||||
|
|
||||||
omb[0] = 0x00;
|
omb[0] = 0x00;
|
||||||
omb[2] = CMD_MatchIntIDICounters; /* disable counters match value interrupts */
|
omb[2] = CMD_MatchIntIDICounters; /* disable counters match value
|
||||||
|
* interrupts */
|
||||||
pci1760_mbxrequest(dev, omb, imb);
|
pci1760_mbxrequest(dev, omb, imb);
|
||||||
devpriv->IDICntMatchEnable = 0;
|
devpriv->IDICntMatchEnable = 0;
|
||||||
|
|
||||||
|
@ -766,7 +807,8 @@ static int pci1760_reset(struct comedi_device *dev)
|
||||||
}
|
}
|
||||||
|
|
||||||
omb[0] = 0xff;
|
omb[0] = 0xff;
|
||||||
omb[2] = CMD_ResetIDICounters; /* reset IDI up counters to reset values */
|
omb[2] = CMD_ResetIDICounters; /* reset IDI up counters to reset
|
||||||
|
* values */
|
||||||
pci1760_mbxrequest(dev, omb, imb);
|
pci1760_mbxrequest(dev, omb, imb);
|
||||||
|
|
||||||
omb[0] = 0x00;
|
omb[0] = 0x00;
|
||||||
|
@ -807,9 +849,12 @@ static int pci_dio_reset(struct comedi_device *dev)
|
||||||
outb(0, dev->iobase + PCI1730_IDO + 1);
|
outb(0, dev->iobase + PCI1730_IDO + 1);
|
||||||
/* NO break there! */
|
/* NO break there! */
|
||||||
case TYPE_PCI1733:
|
case TYPE_PCI1733:
|
||||||
outb(0, dev->iobase + PCI1730_3_INT_EN); /* disable interrupts */
|
/* disable interrupts */
|
||||||
outb(0x0f, dev->iobase + PCI1730_3_INT_CLR); /* clear interrupts */
|
outb(0, dev->iobase + PCI1730_3_INT_EN);
|
||||||
outb(0, dev->iobase + PCI1730_3_INT_RF); /* set rising edge trigger */
|
/* clear interrupts */
|
||||||
|
outb(0x0f, dev->iobase + PCI1730_3_INT_CLR);
|
||||||
|
/* set rising edge trigger */
|
||||||
|
outb(0, dev->iobase + PCI1730_3_INT_RF);
|
||||||
break;
|
break;
|
||||||
case TYPE_PCI1734:
|
case TYPE_PCI1734:
|
||||||
outb(0, dev->iobase + PCI1734_IDO); /* clear outputs */
|
outb(0, dev->iobase + PCI1734_IDO); /* clear outputs */
|
||||||
|
@ -830,43 +875,53 @@ static int pci_dio_reset(struct comedi_device *dev)
|
||||||
case TYPE_PCI1736:
|
case TYPE_PCI1736:
|
||||||
outb(0, dev->iobase + PCI1736_IDO);
|
outb(0, dev->iobase + PCI1736_IDO);
|
||||||
outb(0, dev->iobase + PCI1736_IDO + 1);
|
outb(0, dev->iobase + PCI1736_IDO + 1);
|
||||||
outb(0, dev->iobase + PCI1736_3_INT_EN); /* disable interrupts */
|
/* disable interrupts */
|
||||||
outb(0x0f, dev->iobase + PCI1736_3_INT_CLR); /* clear interrupts */
|
outb(0, dev->iobase + PCI1736_3_INT_EN);
|
||||||
outb(0, dev->iobase + PCI1736_3_INT_RF); /* set rising edge trigger */
|
/* clear interrupts */
|
||||||
|
outb(0x0f, dev->iobase + PCI1736_3_INT_CLR);
|
||||||
|
/* set rising edge trigger */
|
||||||
|
outb(0, dev->iobase + PCI1736_3_INT_RF);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TYPE_PCI1750:
|
case TYPE_PCI1750:
|
||||||
case TYPE_PCI1751:
|
case TYPE_PCI1751:
|
||||||
outb(0x88, dev->iobase + PCI1750_ICR); /* disable & clear interrupts */
|
/* disable & clear interrupts */
|
||||||
|
outb(0x88, dev->iobase + PCI1750_ICR);
|
||||||
break;
|
break;
|
||||||
case TYPE_PCI1752:
|
case TYPE_PCI1752:
|
||||||
outw(0, dev->iobase + PCI1752_6_CFC); /* disable channel freeze function */
|
outw(0, dev->iobase + PCI1752_6_CFC); /* disable channel freeze
|
||||||
|
* function */
|
||||||
outw(0, dev->iobase + PCI1752_IDO); /* clear outputs */
|
outw(0, dev->iobase + PCI1752_IDO); /* clear outputs */
|
||||||
outw(0, dev->iobase + PCI1752_IDO + 2);
|
outw(0, dev->iobase + PCI1752_IDO + 2);
|
||||||
outw(0, dev->iobase + PCI1752_IDO2);
|
outw(0, dev->iobase + PCI1752_IDO2);
|
||||||
outw(0, dev->iobase + PCI1752_IDO2 + 2);
|
outw(0, dev->iobase + PCI1752_IDO2 + 2);
|
||||||
break;
|
break;
|
||||||
case TYPE_PCI1753E:
|
case TYPE_PCI1753E:
|
||||||
outb(0x88, dev->iobase + PCI1753E_ICR0); /* disable & clear interrupts */
|
outb(0x88, dev->iobase + PCI1753E_ICR0); /* disable & clear
|
||||||
|
* interrupts */
|
||||||
outb(0x80, dev->iobase + PCI1753E_ICR1);
|
outb(0x80, dev->iobase + PCI1753E_ICR1);
|
||||||
outb(0x80, dev->iobase + PCI1753E_ICR2);
|
outb(0x80, dev->iobase + PCI1753E_ICR2);
|
||||||
outb(0x80, dev->iobase + PCI1753E_ICR3);
|
outb(0x80, dev->iobase + PCI1753E_ICR3);
|
||||||
/* NO break there! */
|
/* NO break there! */
|
||||||
case TYPE_PCI1753:
|
case TYPE_PCI1753:
|
||||||
outb(0x88, dev->iobase + PCI1753_ICR0); /* disable & clear interrupts */
|
outb(0x88, dev->iobase + PCI1753_ICR0); /* disable & clear
|
||||||
|
* interrupts */
|
||||||
outb(0x80, dev->iobase + PCI1753_ICR1);
|
outb(0x80, dev->iobase + PCI1753_ICR1);
|
||||||
outb(0x80, dev->iobase + PCI1753_ICR2);
|
outb(0x80, dev->iobase + PCI1753_ICR2);
|
||||||
outb(0x80, dev->iobase + PCI1753_ICR3);
|
outb(0x80, dev->iobase + PCI1753_ICR3);
|
||||||
break;
|
break;
|
||||||
case TYPE_PCI1754:
|
case TYPE_PCI1754:
|
||||||
outw(0x08, dev->iobase + PCI1754_6_ICR0); /* disable and clear interrupts */
|
outw(0x08, dev->iobase + PCI1754_6_ICR0); /* disable and clear
|
||||||
|
* interrupts */
|
||||||
outw(0x08, dev->iobase + PCI1754_6_ICR1);
|
outw(0x08, dev->iobase + PCI1754_6_ICR1);
|
||||||
outw(0x08, dev->iobase + PCI1754_ICR2);
|
outw(0x08, dev->iobase + PCI1754_ICR2);
|
||||||
outw(0x08, dev->iobase + PCI1754_ICR3);
|
outw(0x08, dev->iobase + PCI1754_ICR3);
|
||||||
break;
|
break;
|
||||||
case TYPE_PCI1756:
|
case TYPE_PCI1756:
|
||||||
outw(0, dev->iobase + PCI1752_6_CFC); /* disable channel freeze function */
|
outw(0, dev->iobase + PCI1752_6_CFC); /* disable channel freeze
|
||||||
outw(0x08, dev->iobase + PCI1754_6_ICR0); /* disable and clear interrupts */
|
* function */
|
||||||
|
outw(0x08, dev->iobase + PCI1754_6_ICR0); /* disable and clear
|
||||||
|
* interrupts */
|
||||||
outw(0x08, dev->iobase + PCI1754_6_ICR1);
|
outw(0x08, dev->iobase + PCI1754_6_ICR1);
|
||||||
outw(0, dev->iobase + PCI1756_IDO); /* clear outputs */
|
outw(0, dev->iobase + PCI1756_IDO); /* clear outputs */
|
||||||
outw(0, dev->iobase + PCI1756_IDO + 2);
|
outw(0, dev->iobase + PCI1756_IDO + 2);
|
||||||
|
@ -875,7 +930,8 @@ static int pci_dio_reset(struct comedi_device *dev)
|
||||||
pci1760_reset(dev);
|
pci1760_reset(dev);
|
||||||
break;
|
break;
|
||||||
case TYPE_PCI1762:
|
case TYPE_PCI1762:
|
||||||
outw(0x0101, dev->iobase + PCI1762_ICR); /* disable & clear interrupts */
|
outw(0x0101, dev->iobase + PCI1762_ICR); /* disable & clear
|
||||||
|
* interrupts */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -996,7 +1052,7 @@ static int pci_dio_add_do(struct comedi_device *dev, struct comedi_subdevice *s,
|
||||||
==============================================================================
|
==============================================================================
|
||||||
*/
|
*/
|
||||||
static int pci_dio_add_8254(struct comedi_device *dev,
|
static int pci_dio_add_8254(struct comedi_device *dev,
|
||||||
struct comedi_subdevice * s,
|
struct comedi_subdevice *s,
|
||||||
const struct diosubd_data *d, int subdev)
|
const struct diosubd_data *d, int subdev)
|
||||||
{
|
{
|
||||||
s->type = COMEDI_SUBD_COUNTER;
|
s->type = COMEDI_SUBD_COUNTER;
|
||||||
|
@ -1048,7 +1104,7 @@ static int pci_dio_attach(struct comedi_device *dev,
|
||||||
struct comedi_subdevice *s;
|
struct comedi_subdevice *s;
|
||||||
int ret, subdev, n_subdevices, i, j;
|
int ret, subdev, n_subdevices, i, j;
|
||||||
unsigned long iobase;
|
unsigned long iobase;
|
||||||
struct pci_dev *pcidev;
|
struct pci_dev *pcidev = NULL;
|
||||||
|
|
||||||
printk("comedi%d: adv_pci_dio: ", dev->minor);
|
printk("comedi%d: adv_pci_dio: ", dev->minor);
|
||||||
|
|
||||||
|
@ -1058,9 +1114,7 @@ static int pci_dio_attach(struct comedi_device *dev,
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, NULL);
|
for_each_pci_dev(pcidev) {
|
||||||
pcidev != NULL;
|
|
||||||
pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pcidev)) {
|
|
||||||
/* loop through cards supported by this driver */
|
/* loop through cards supported by this driver */
|
||||||
for (i = 0; i < n_boardtypes; ++i) {
|
for (i = 0; i < n_boardtypes; ++i) {
|
||||||
if (boardtypes[i].vendor_id != pcidev->vendor)
|
if (boardtypes[i].vendor_id != pcidev->vendor)
|
||||||
|
@ -1215,15 +1269,12 @@ static int pci_dio_detach(struct comedi_device *dev)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this_board->boardid.chans) {
|
if (this_board->boardid.chans)
|
||||||
subdev++;
|
subdev++;
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < MAX_8254_SUBDEVS; i++) {
|
for (i = 0; i < MAX_8254_SUBDEVS; i++)
|
||||||
if (this_board->s8254[i].chans) {
|
if (this_board->s8254[i].chans)
|
||||||
subdev++;
|
subdev++;
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < dev->n_subdevices; i++) {
|
for (i = 0; i < dev->n_subdevices; i++) {
|
||||||
s = dev->subdevices + i;
|
s = dev->subdevices + i;
|
||||||
|
@ -1253,7 +1304,47 @@ static int pci_dio_detach(struct comedi_device *dev)
|
||||||
/*
|
/*
|
||||||
==============================================================================
|
==============================================================================
|
||||||
*/
|
*/
|
||||||
COMEDI_PCI_INITCLEANUP(driver_pci_dio, pci_dio_pci_table);
|
static int __devinit driver_pci_dio_pci_probe(struct pci_dev *dev,
|
||||||
|
const struct pci_device_id *ent)
|
||||||
|
{
|
||||||
|
return comedi_pci_auto_config(dev, driver_pci_dio.driver_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __devexit driver_pci_dio_pci_remove(struct pci_dev *dev)
|
||||||
|
{
|
||||||
|
comedi_pci_auto_unconfig(dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct pci_driver driver_pci_dio_pci_driver = {
|
||||||
|
.id_table = pci_dio_pci_table,
|
||||||
|
.probe = &driver_pci_dio_pci_probe,
|
||||||
|
.remove = __devexit_p(&driver_pci_dio_pci_remove)
|
||||||
|
};
|
||||||
|
|
||||||
|
static int __init driver_pci_dio_init_module(void)
|
||||||
|
{
|
||||||
|
int retval;
|
||||||
|
|
||||||
|
retval = comedi_driver_register(&driver_pci_dio);
|
||||||
|
if (retval < 0)
|
||||||
|
return retval;
|
||||||
|
|
||||||
|
driver_pci_dio_pci_driver.name = (char *)driver_pci_dio.driver_name;
|
||||||
|
return pci_register_driver(&driver_pci_dio_pci_driver);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __exit driver_pci_dio_cleanup_module(void)
|
||||||
|
{
|
||||||
|
pci_unregister_driver(&driver_pci_dio_pci_driver);
|
||||||
|
comedi_driver_unregister(&driver_pci_dio);
|
||||||
|
}
|
||||||
|
|
||||||
|
module_init(driver_pci_dio_init_module);
|
||||||
|
module_exit(driver_pci_dio_cleanup_module);
|
||||||
/*
|
/*
|
||||||
==============================================================================
|
==============================================================================
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
MODULE_AUTHOR("Comedi http://www.comedi.org");
|
||||||
|
MODULE_DESCRIPTION("Comedi low-level driver");
|
||||||
|
MODULE_LICENSE("GPL");
|
||||||
|
|
|
@ -227,4 +227,19 @@ static struct comedi_driver driver_aio_aio12_8 = {
|
||||||
.offset = sizeof(struct aio12_8_boardtype),
|
.offset = sizeof(struct aio12_8_boardtype),
|
||||||
};
|
};
|
||||||
|
|
||||||
COMEDI_INITCLEANUP(driver_aio_aio12_8);
|
static int __init driver_aio_aio12_8_init_module(void)
|
||||||
|
{
|
||||||
|
return comedi_driver_register(&driver_aio_aio12_8);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __exit driver_aio_aio12_8_cleanup_module(void)
|
||||||
|
{
|
||||||
|
comedi_driver_unregister(&driver_aio_aio12_8);
|
||||||
|
}
|
||||||
|
|
||||||
|
module_init(driver_aio_aio12_8_init_module);
|
||||||
|
module_exit(driver_aio_aio12_8_cleanup_module);
|
||||||
|
|
||||||
|
MODULE_AUTHOR("Comedi http://www.comedi.org");
|
||||||
|
MODULE_DESCRIPTION("Comedi low-level driver");
|
||||||
|
MODULE_LICENSE("GPL");
|
||||||
|
|
|
@ -184,4 +184,19 @@ static int aio_iiro_16_dio_insn_bits_read(struct comedi_device *dev,
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
COMEDI_INITCLEANUP(driver_aio_iiro_16);
|
static int __init driver_aio_iiro_16_init_module(void)
|
||||||
|
{
|
||||||
|
return comedi_driver_register(&driver_aio_iiro_16);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __exit driver_aio_iiro_16_cleanup_module(void)
|
||||||
|
{
|
||||||
|
comedi_driver_unregister(&driver_aio_iiro_16);
|
||||||
|
}
|
||||||
|
|
||||||
|
module_init(driver_aio_iiro_16_init_module);
|
||||||
|
module_exit(driver_aio_iiro_16_cleanup_module);
|
||||||
|
|
||||||
|
MODULE_AUTHOR("Comedi http://www.comedi.org");
|
||||||
|
MODULE_DESCRIPTION("Comedi low-level driver");
|
||||||
|
MODULE_LICENSE("GPL");
|
||||||
|
|
|
@ -47,32 +47,32 @@
|
||||||
#ifdef Am9513_8BITBUS
|
#ifdef Am9513_8BITBUS
|
||||||
|
|
||||||
#define Am9513_write_register(reg, val) \
|
#define Am9513_write_register(reg, val) \
|
||||||
do{ \
|
do { \
|
||||||
Am9513_output_control(reg); \
|
Am9513_output_control(reg); \
|
||||||
Am9513_output_data(val>>8); \
|
Am9513_output_data(val>>8); \
|
||||||
Am9513_output_data(val&0xff); \
|
Am9513_output_data(val&0xff); \
|
||||||
}while (0)
|
} while (0)
|
||||||
|
|
||||||
#define Am9513_read_register(reg, val) \
|
#define Am9513_read_register(reg, val) \
|
||||||
do{ \
|
do { \
|
||||||
Am9513_output_control(reg); \
|
Am9513_output_control(reg); \
|
||||||
val=Am9513_input_data()<<8; \
|
val = Am9513_input_data()<<8; \
|
||||||
val|=Am9513_input_data(); \
|
val |= Am9513_input_data(); \
|
||||||
}while (0)
|
} while (0)
|
||||||
|
|
||||||
#else /* Am9513_16BITBUS */
|
#else /* Am9513_16BITBUS */
|
||||||
|
|
||||||
#define Am9513_write_register(reg, val) \
|
#define Am9513_write_register(reg, val) \
|
||||||
do{ \
|
do { \
|
||||||
Am9513_output_control(reg); \
|
Am9513_output_control(reg); \
|
||||||
Am9513_output_data(val); \
|
Am9513_output_data(val); \
|
||||||
}while (0)
|
} while (0)
|
||||||
|
|
||||||
#define Am9513_read_register(reg, val) \
|
#define Am9513_read_register(reg, val) \
|
||||||
do{ \
|
do { \
|
||||||
Am9513_output_control(reg); \
|
Am9513_output_control(reg); \
|
||||||
val=Am9513_input_data(); \
|
val = Am9513_input_data(); \
|
||||||
}while (0)
|
} while (0)
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -494,9 +494,58 @@ static struct comedi_driver driver_amplc_dio200 = {
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef CONFIG_COMEDI_PCI
|
#ifdef CONFIG_COMEDI_PCI
|
||||||
COMEDI_PCI_INITCLEANUP(driver_amplc_dio200, dio200_pci_table);
|
static int __devinit driver_amplc_dio200_pci_probe(struct pci_dev *dev,
|
||||||
|
const struct pci_device_id
|
||||||
|
*ent)
|
||||||
|
{
|
||||||
|
return comedi_pci_auto_config(dev, driver_amplc_dio200.driver_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __devexit driver_amplc_dio200_pci_remove(struct pci_dev *dev)
|
||||||
|
{
|
||||||
|
comedi_pci_auto_unconfig(dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct pci_driver driver_amplc_dio200_pci_driver = {
|
||||||
|
.id_table = dio200_pci_table,
|
||||||
|
.probe = &driver_amplc_dio200_pci_probe,
|
||||||
|
.remove = __devexit_p(&driver_amplc_dio200_pci_remove)
|
||||||
|
};
|
||||||
|
|
||||||
|
static int __init driver_amplc_dio200_init_module(void)
|
||||||
|
{
|
||||||
|
int retval;
|
||||||
|
|
||||||
|
retval = comedi_driver_register(&driver_amplc_dio200);
|
||||||
|
if (retval < 0)
|
||||||
|
return retval;
|
||||||
|
|
||||||
|
driver_amplc_dio200_pci_driver.name =
|
||||||
|
(char *)driver_amplc_dio200.driver_name;
|
||||||
|
return pci_register_driver(&driver_amplc_dio200_pci_driver);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __exit driver_amplc_dio200_cleanup_module(void)
|
||||||
|
{
|
||||||
|
pci_unregister_driver(&driver_amplc_dio200_pci_driver);
|
||||||
|
comedi_driver_unregister(&driver_amplc_dio200);
|
||||||
|
}
|
||||||
|
|
||||||
|
module_init(driver_amplc_dio200_init_module);
|
||||||
|
module_exit(driver_amplc_dio200_cleanup_module);
|
||||||
#else
|
#else
|
||||||
COMEDI_INITCLEANUP(driver_amplc_dio200);
|
static int __init driver_amplc_dio200_init_module(void)
|
||||||
|
{
|
||||||
|
return comedi_driver_register(&driver_amplc_dio200);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __exit driver_amplc_dio200_cleanup_module(void)
|
||||||
|
{
|
||||||
|
comedi_driver_unregister(&driver_amplc_dio200);
|
||||||
|
}
|
||||||
|
|
||||||
|
module_init(driver_amplc_dio200_init_module);
|
||||||
|
module_exit(driver_amplc_dio200_cleanup_module);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1501,3 +1550,7 @@ static int dio200_detach(struct comedi_device *dev)
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MODULE_AUTHOR("Comedi http://www.comedi.org");
|
||||||
|
MODULE_DESCRIPTION("Comedi low-level driver");
|
||||||
|
MODULE_LICENSE("GPL");
|
||||||
|
|
|
@ -182,9 +182,58 @@ static struct comedi_driver driver_amplc_pc236 = {
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef CONFIG_COMEDI_PCI
|
#ifdef CONFIG_COMEDI_PCI
|
||||||
COMEDI_PCI_INITCLEANUP(driver_amplc_pc236, pc236_pci_table);
|
static int __devinit driver_amplc_pc236_pci_probe(struct pci_dev *dev,
|
||||||
|
const struct pci_device_id
|
||||||
|
*ent)
|
||||||
|
{
|
||||||
|
return comedi_pci_auto_config(dev, driver_amplc_pc236.driver_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __devexit driver_amplc_pc236_pci_remove(struct pci_dev *dev)
|
||||||
|
{
|
||||||
|
comedi_pci_auto_unconfig(dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct pci_driver driver_amplc_pc236_pci_driver = {
|
||||||
|
.id_table = pc236_pci_table,
|
||||||
|
.probe = &driver_amplc_pc236_pci_probe,
|
||||||
|
.remove = __devexit_p(&driver_amplc_pc236_pci_remove)
|
||||||
|
};
|
||||||
|
|
||||||
|
static int __init driver_amplc_pc236_init_module(void)
|
||||||
|
{
|
||||||
|
int retval;
|
||||||
|
|
||||||
|
retval = comedi_driver_register(&driver_amplc_pc236);
|
||||||
|
if (retval < 0)
|
||||||
|
return retval;
|
||||||
|
|
||||||
|
driver_amplc_pc236_pci_driver.name =
|
||||||
|
(char *)driver_amplc_pc236.driver_name;
|
||||||
|
return pci_register_driver(&driver_amplc_pc236_pci_driver);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __exit driver_amplc_pc236_cleanup_module(void)
|
||||||
|
{
|
||||||
|
pci_unregister_driver(&driver_amplc_pc236_pci_driver);
|
||||||
|
comedi_driver_unregister(&driver_amplc_pc236);
|
||||||
|
}
|
||||||
|
|
||||||
|
module_init(driver_amplc_pc236_init_module);
|
||||||
|
module_exit(driver_amplc_pc236_cleanup_module);
|
||||||
#else
|
#else
|
||||||
COMEDI_INITCLEANUP(driver_amplc_pc236);
|
static int __init driver_amplc_pc236_init_module(void)
|
||||||
|
{
|
||||||
|
return comedi_driver_register(&driver_amplc_pc236);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __exit driver_amplc_pc236_cleanup_module(void)
|
||||||
|
{
|
||||||
|
comedi_driver_unregister(&driver_amplc_pc236);
|
||||||
|
}
|
||||||
|
|
||||||
|
module_init(driver_amplc_pc236_init_module);
|
||||||
|
module_exit(driver_amplc_pc236_cleanup_module);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static int pc236_request_region(unsigned minor, unsigned long from,
|
static int pc236_request_region(unsigned minor, unsigned long from,
|
||||||
|
@ -664,3 +713,7 @@ static irqreturn_t pc236_interrupt(int irq, void *d)
|
||||||
}
|
}
|
||||||
return IRQ_RETVAL(handled);
|
return IRQ_RETVAL(handled);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MODULE_AUTHOR("Comedi http://www.comedi.org");
|
||||||
|
MODULE_DESCRIPTION("Comedi low-level driver");
|
||||||
|
MODULE_LICENSE("GPL");
|
||||||
|
|
|
@ -432,7 +432,60 @@ static int pc263_dio_insn_config(struct comedi_device *dev,
|
||||||
* as necessary.
|
* as necessary.
|
||||||
*/
|
*/
|
||||||
#ifdef CONFIG_COMEDI_PCI
|
#ifdef CONFIG_COMEDI_PCI
|
||||||
COMEDI_PCI_INITCLEANUP(driver_amplc_pc263, pc263_pci_table);
|
static int __devinit driver_amplc_pc263_pci_probe(struct pci_dev *dev,
|
||||||
|
const struct pci_device_id
|
||||||
|
*ent)
|
||||||
|
{
|
||||||
|
return comedi_pci_auto_config(dev, driver_amplc_pc263.driver_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __devexit driver_amplc_pc263_pci_remove(struct pci_dev *dev)
|
||||||
|
{
|
||||||
|
comedi_pci_auto_unconfig(dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct pci_driver driver_amplc_pc263_pci_driver = {
|
||||||
|
.id_table = pc263_pci_table,
|
||||||
|
.probe = &driver_amplc_pc263_pci_probe,
|
||||||
|
.remove = __devexit_p(&driver_amplc_pc263_pci_remove)
|
||||||
|
};
|
||||||
|
|
||||||
|
static int __init driver_amplc_pc263_init_module(void)
|
||||||
|
{
|
||||||
|
int retval;
|
||||||
|
|
||||||
|
retval = comedi_driver_register(&driver_amplc_pc263);
|
||||||
|
if (retval < 0)
|
||||||
|
return retval;
|
||||||
|
|
||||||
|
driver_amplc_pc263_pci_driver.name =
|
||||||
|
(char *)driver_amplc_pc263.driver_name;
|
||||||
|
return pci_register_driver(&driver_amplc_pc263_pci_driver);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __exit driver_amplc_pc263_cleanup_module(void)
|
||||||
|
{
|
||||||
|
pci_unregister_driver(&driver_amplc_pc263_pci_driver);
|
||||||
|
comedi_driver_unregister(&driver_amplc_pc263);
|
||||||
|
}
|
||||||
|
|
||||||
|
module_init(driver_amplc_pc263_init_module);
|
||||||
|
module_exit(driver_amplc_pc263_cleanup_module);
|
||||||
#else
|
#else
|
||||||
COMEDI_INITCLEANUP(driver_amplc_pc263);
|
static int __init driver_amplc_pc263_init_module(void)
|
||||||
|
{
|
||||||
|
return comedi_driver_register(&driver_amplc_pc263);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __exit driver_amplc_pc263_cleanup_module(void)
|
||||||
|
{
|
||||||
|
comedi_driver_unregister(&driver_amplc_pc263);
|
||||||
|
}
|
||||||
|
|
||||||
|
module_init(driver_amplc_pc263_init_module);
|
||||||
|
module_exit(driver_amplc_pc263_cleanup_module);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
MODULE_AUTHOR("Comedi http://www.comedi.org");
|
||||||
|
MODULE_DESCRIPTION("Comedi low-level driver");
|
||||||
|
MODULE_LICENSE("GPL");
|
||||||
|
|
|
@ -443,7 +443,45 @@ static struct comedi_driver driver_amplc_pci224 = {
|
||||||
.num_names = ARRAY_SIZE(pci224_boards),
|
.num_names = ARRAY_SIZE(pci224_boards),
|
||||||
};
|
};
|
||||||
|
|
||||||
COMEDI_PCI_INITCLEANUP(driver_amplc_pci224, pci224_pci_table);
|
static int __devinit driver_amplc_pci224_pci_probe(struct pci_dev *dev,
|
||||||
|
const struct pci_device_id
|
||||||
|
*ent)
|
||||||
|
{
|
||||||
|
return comedi_pci_auto_config(dev, driver_amplc_pci224.driver_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __devexit driver_amplc_pci224_pci_remove(struct pci_dev *dev)
|
||||||
|
{
|
||||||
|
comedi_pci_auto_unconfig(dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct pci_driver driver_amplc_pci224_pci_driver = {
|
||||||
|
.id_table = pci224_pci_table,
|
||||||
|
.probe = &driver_amplc_pci224_pci_probe,
|
||||||
|
.remove = __devexit_p(&driver_amplc_pci224_pci_remove)
|
||||||
|
};
|
||||||
|
|
||||||
|
static int __init driver_amplc_pci224_init_module(void)
|
||||||
|
{
|
||||||
|
int retval;
|
||||||
|
|
||||||
|
retval = comedi_driver_register(&driver_amplc_pci224);
|
||||||
|
if (retval < 0)
|
||||||
|
return retval;
|
||||||
|
|
||||||
|
driver_amplc_pci224_pci_driver.name =
|
||||||
|
(char *)driver_amplc_pci224.driver_name;
|
||||||
|
return pci_register_driver(&driver_amplc_pci224_pci_driver);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __exit driver_amplc_pci224_cleanup_module(void)
|
||||||
|
{
|
||||||
|
pci_unregister_driver(&driver_amplc_pci224_pci_driver);
|
||||||
|
comedi_driver_unregister(&driver_amplc_pci224);
|
||||||
|
}
|
||||||
|
|
||||||
|
module_init(driver_amplc_pci224_init_module);
|
||||||
|
module_exit(driver_amplc_pci224_cleanup_module);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Called from the 'insn_write' function to perform a single write.
|
* Called from the 'insn_write' function to perform a single write.
|
||||||
|
@ -1557,3 +1595,7 @@ static int pci224_detach(struct comedi_device *dev)
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MODULE_AUTHOR("Comedi http://www.comedi.org");
|
||||||
|
MODULE_DESCRIPTION("Comedi low-level driver");
|
||||||
|
MODULE_LICENSE("GPL");
|
||||||
|
|
|
@ -617,7 +617,45 @@ static struct comedi_driver driver_amplc_pci230 = {
|
||||||
.num_names = ARRAY_SIZE(pci230_boards),
|
.num_names = ARRAY_SIZE(pci230_boards),
|
||||||
};
|
};
|
||||||
|
|
||||||
COMEDI_PCI_INITCLEANUP(driver_amplc_pci230, pci230_pci_table);
|
static int __devinit driver_amplc_pci230_pci_probe(struct pci_dev *dev,
|
||||||
|
const struct pci_device_id
|
||||||
|
*ent)
|
||||||
|
{
|
||||||
|
return comedi_pci_auto_config(dev, driver_amplc_pci230.driver_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __devexit driver_amplc_pci230_pci_remove(struct pci_dev *dev)
|
||||||
|
{
|
||||||
|
comedi_pci_auto_unconfig(dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct pci_driver driver_amplc_pci230_pci_driver = {
|
||||||
|
.id_table = pci230_pci_table,
|
||||||
|
.probe = &driver_amplc_pci230_pci_probe,
|
||||||
|
.remove = __devexit_p(&driver_amplc_pci230_pci_remove)
|
||||||
|
};
|
||||||
|
|
||||||
|
static int __init driver_amplc_pci230_init_module(void)
|
||||||
|
{
|
||||||
|
int retval;
|
||||||
|
|
||||||
|
retval = comedi_driver_register(&driver_amplc_pci230);
|
||||||
|
if (retval < 0)
|
||||||
|
return retval;
|
||||||
|
|
||||||
|
driver_amplc_pci230_pci_driver.name =
|
||||||
|
(char *)driver_amplc_pci230.driver_name;
|
||||||
|
return pci_register_driver(&driver_amplc_pci230_pci_driver);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __exit driver_amplc_pci230_cleanup_module(void)
|
||||||
|
{
|
||||||
|
pci_unregister_driver(&driver_amplc_pci230_pci_driver);
|
||||||
|
comedi_driver_unregister(&driver_amplc_pci230);
|
||||||
|
}
|
||||||
|
|
||||||
|
module_init(driver_amplc_pci230_init_module);
|
||||||
|
module_exit(driver_amplc_pci230_cleanup_module);
|
||||||
|
|
||||||
static int pci230_ai_rinsn(struct comedi_device *dev,
|
static int pci230_ai_rinsn(struct comedi_device *dev,
|
||||||
struct comedi_subdevice *s, struct comedi_insn *insn,
|
struct comedi_subdevice *s, struct comedi_insn *insn,
|
||||||
|
@ -726,7 +764,7 @@ static int pci230_attach(struct comedi_device *dev, struct comedi_devconfig *it)
|
||||||
struct comedi_subdevice *s;
|
struct comedi_subdevice *s;
|
||||||
unsigned long iobase1, iobase2;
|
unsigned long iobase1, iobase2;
|
||||||
/* PCI230's I/O spaces 1 and 2 respectively. */
|
/* PCI230's I/O spaces 1 and 2 respectively. */
|
||||||
struct pci_dev *pci_dev;
|
struct pci_dev *pci_dev = NULL;
|
||||||
int i = 0, irq_hdl, rc;
|
int i = 0, irq_hdl, rc;
|
||||||
|
|
||||||
printk("comedi%d: amplc_pci230: attach %s %d,%d\n", dev->minor,
|
printk("comedi%d: amplc_pci230: attach %s %d,%d\n", dev->minor,
|
||||||
|
@ -742,9 +780,7 @@ static int pci230_attach(struct comedi_device *dev, struct comedi_devconfig *it)
|
||||||
spin_lock_init(&devpriv->ai_stop_spinlock);
|
spin_lock_init(&devpriv->ai_stop_spinlock);
|
||||||
spin_lock_init(&devpriv->ao_stop_spinlock);
|
spin_lock_init(&devpriv->ao_stop_spinlock);
|
||||||
/* Find card */
|
/* Find card */
|
||||||
for (pci_dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, NULL);
|
for_each_pci_dev(pci_dev) {
|
||||||
pci_dev != NULL;
|
|
||||||
pci_dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pci_dev)) {
|
|
||||||
if (it->options[0] || it->options[1]) {
|
if (it->options[0] || it->options[1]) {
|
||||||
/* Match against bus/slot options. */
|
/* Match against bus/slot options. */
|
||||||
if (it->options[0] != pci_dev->bus->number ||
|
if (it->options[0] != pci_dev->bus->number ||
|
||||||
|
@ -3014,3 +3050,7 @@ static int pci230_ai_cancel(struct comedi_device *dev,
|
||||||
pci230_ai_stop(dev, s);
|
pci230_ai_stop(dev, s);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MODULE_AUTHOR("Comedi http://www.comedi.org");
|
||||||
|
MODULE_DESCRIPTION("Comedi low-level driver");
|
||||||
|
MODULE_LICENSE("GPL");
|
||||||
|
|
|
@ -517,4 +517,19 @@ static int c6xdigio_detach(struct comedi_device *dev)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
COMEDI_INITCLEANUP(driver_c6xdigio);
|
static int __init driver_c6xdigio_init_module(void)
|
||||||
|
{
|
||||||
|
return comedi_driver_register(&driver_c6xdigio);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __exit driver_c6xdigio_cleanup_module(void)
|
||||||
|
{
|
||||||
|
comedi_driver_unregister(&driver_c6xdigio);
|
||||||
|
}
|
||||||
|
|
||||||
|
module_init(driver_c6xdigio_init_module);
|
||||||
|
module_exit(driver_c6xdigio_cleanup_module);
|
||||||
|
|
||||||
|
MODULE_AUTHOR("Comedi http://www.comedi.org");
|
||||||
|
MODULE_DESCRIPTION("Comedi low-level driver");
|
||||||
|
MODULE_LICENSE("GPL");
|
||||||
|
|
|
@ -719,7 +719,6 @@ static void das16cs_pcmcia_detach(struct pcmcia_device *link)
|
||||||
((struct local_info_t *)link->priv)->stop = 1;
|
((struct local_info_t *)link->priv)->stop = 1;
|
||||||
das16cs_pcmcia_release(link);
|
das16cs_pcmcia_release(link);
|
||||||
/* This points to the parent struct local_info_t struct */
|
/* This points to the parent struct local_info_t struct */
|
||||||
if (link->priv)
|
|
||||||
kfree(link->priv);
|
kfree(link->priv);
|
||||||
} /* das16cs_pcmcia_detach */
|
} /* das16cs_pcmcia_detach */
|
||||||
|
|
||||||
|
@ -881,5 +880,16 @@ void __exit cleanup_module(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
COMEDI_INITCLEANUP(driver_das16cs);
|
static int __init driver_das16cs_init_module(void)
|
||||||
|
{
|
||||||
|
return comedi_driver_register(&driver_das16cs);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __exit driver_das16cs_cleanup_module(void)
|
||||||
|
{
|
||||||
|
comedi_driver_unregister(&driver_das16cs);
|
||||||
|
}
|
||||||
|
|
||||||
|
module_init(driver_das16cs_init_module);
|
||||||
|
module_exit(driver_das16cs_cleanup_module);
|
||||||
#endif /* CONFIG_PCMCIA */
|
#endif /* CONFIG_PCMCIA */
|
||||||
|
|
|
@ -533,7 +533,7 @@ static int cb_pcidas_attach(struct comedi_device *dev,
|
||||||
struct comedi_devconfig *it)
|
struct comedi_devconfig *it)
|
||||||
{
|
{
|
||||||
struct comedi_subdevice *s;
|
struct comedi_subdevice *s;
|
||||||
struct pci_dev *pcidev;
|
struct pci_dev *pcidev = NULL;
|
||||||
int index;
|
int index;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
@ -550,9 +550,7 @@ static int cb_pcidas_attach(struct comedi_device *dev,
|
||||||
*/
|
*/
|
||||||
printk("\n");
|
printk("\n");
|
||||||
|
|
||||||
for (pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, NULL);
|
for_each_pci_dev(pcidev) {
|
||||||
pcidev != NULL;
|
|
||||||
pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pcidev)) {
|
|
||||||
/* is it not a computer boards card? */
|
/* is it not a computer boards card? */
|
||||||
if (pcidev->vendor != PCI_VENDOR_ID_CB)
|
if (pcidev->vendor != PCI_VENDOR_ID_CB)
|
||||||
continue;
|
continue;
|
||||||
|
@ -1871,4 +1869,44 @@ static int nvram_read(struct comedi_device *dev, unsigned int address,
|
||||||
* A convenient macro that defines init_module() and cleanup_module(),
|
* A convenient macro that defines init_module() and cleanup_module(),
|
||||||
* as necessary.
|
* as necessary.
|
||||||
*/
|
*/
|
||||||
COMEDI_PCI_INITCLEANUP(driver_cb_pcidas, cb_pcidas_pci_table);
|
static int __devinit driver_cb_pcidas_pci_probe(struct pci_dev *dev,
|
||||||
|
const struct pci_device_id *ent)
|
||||||
|
{
|
||||||
|
return comedi_pci_auto_config(dev, driver_cb_pcidas.driver_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __devexit driver_cb_pcidas_pci_remove(struct pci_dev *dev)
|
||||||
|
{
|
||||||
|
comedi_pci_auto_unconfig(dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct pci_driver driver_cb_pcidas_pci_driver = {
|
||||||
|
.id_table = cb_pcidas_pci_table,
|
||||||
|
.probe = &driver_cb_pcidas_pci_probe,
|
||||||
|
.remove = __devexit_p(&driver_cb_pcidas_pci_remove)
|
||||||
|
};
|
||||||
|
|
||||||
|
static int __init driver_cb_pcidas_init_module(void)
|
||||||
|
{
|
||||||
|
int retval;
|
||||||
|
|
||||||
|
retval = comedi_driver_register(&driver_cb_pcidas);
|
||||||
|
if (retval < 0)
|
||||||
|
return retval;
|
||||||
|
|
||||||
|
driver_cb_pcidas_pci_driver.name = (char *)driver_cb_pcidas.driver_name;
|
||||||
|
return pci_register_driver(&driver_cb_pcidas_pci_driver);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __exit driver_cb_pcidas_cleanup_module(void)
|
||||||
|
{
|
||||||
|
pci_unregister_driver(&driver_cb_pcidas_pci_driver);
|
||||||
|
comedi_driver_unregister(&driver_cb_pcidas);
|
||||||
|
}
|
||||||
|
|
||||||
|
module_init(driver_cb_pcidas_init_module);
|
||||||
|
module_exit(driver_cb_pcidas_cleanup_module);
|
||||||
|
|
||||||
|
MODULE_AUTHOR("Comedi http://www.comedi.org");
|
||||||
|
MODULE_DESCRIPTION("Comedi low-level driver");
|
||||||
|
MODULE_LICENSE("GPL");
|
||||||
|
|
|
@ -1237,7 +1237,43 @@ static unsigned int get_ao_divisor(unsigned int ns, unsigned int flags);
|
||||||
static void load_ao_dma(struct comedi_device *dev,
|
static void load_ao_dma(struct comedi_device *dev,
|
||||||
const struct comedi_cmd *cmd);
|
const struct comedi_cmd *cmd);
|
||||||
|
|
||||||
COMEDI_PCI_INITCLEANUP(driver_cb_pcidas, pcidas64_pci_table);
|
static int __devinit driver_cb_pcidas_pci_probe(struct pci_dev *dev,
|
||||||
|
const struct pci_device_id *ent)
|
||||||
|
{
|
||||||
|
return comedi_pci_auto_config(dev, driver_cb_pcidas.driver_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __devexit driver_cb_pcidas_pci_remove(struct pci_dev *dev)
|
||||||
|
{
|
||||||
|
comedi_pci_auto_unconfig(dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct pci_driver driver_cb_pcidas_pci_driver = {
|
||||||
|
.id_table = pcidas64_pci_table,
|
||||||
|
.probe = &driver_cb_pcidas_pci_probe,
|
||||||
|
.remove = __devexit_p(&driver_cb_pcidas_pci_remove)
|
||||||
|
};
|
||||||
|
|
||||||
|
static int __init driver_cb_pcidas_init_module(void)
|
||||||
|
{
|
||||||
|
int retval;
|
||||||
|
|
||||||
|
retval = comedi_driver_register(&driver_cb_pcidas);
|
||||||
|
if (retval < 0)
|
||||||
|
return retval;
|
||||||
|
|
||||||
|
driver_cb_pcidas_pci_driver.name = (char *)driver_cb_pcidas.driver_name;
|
||||||
|
return pci_register_driver(&driver_cb_pcidas_pci_driver);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __exit driver_cb_pcidas_cleanup_module(void)
|
||||||
|
{
|
||||||
|
pci_unregister_driver(&driver_cb_pcidas_pci_driver);
|
||||||
|
comedi_driver_unregister(&driver_cb_pcidas);
|
||||||
|
}
|
||||||
|
|
||||||
|
module_init(driver_cb_pcidas_init_module);
|
||||||
|
module_exit(driver_cb_pcidas_cleanup_module);
|
||||||
|
|
||||||
static unsigned int ai_range_bits_6xxx(const struct comedi_device *dev,
|
static unsigned int ai_range_bits_6xxx(const struct comedi_device *dev,
|
||||||
unsigned int range_index)
|
unsigned int range_index)
|
||||||
|
@ -1718,7 +1754,7 @@ static inline void warn_external_queue(struct comedi_device *dev)
|
||||||
*/
|
*/
|
||||||
static int attach(struct comedi_device *dev, struct comedi_devconfig *it)
|
static int attach(struct comedi_device *dev, struct comedi_devconfig *it)
|
||||||
{
|
{
|
||||||
struct pci_dev *pcidev;
|
struct pci_dev *pcidev = NULL;
|
||||||
int index;
|
int index;
|
||||||
uint32_t local_range, local_decode;
|
uint32_t local_range, local_decode;
|
||||||
int retval;
|
int retval;
|
||||||
|
@ -1735,9 +1771,7 @@ static int attach(struct comedi_device *dev, struct comedi_devconfig *it)
|
||||||
* Probe the device to determine what device in the series it is.
|
* Probe the device to determine what device in the series it is.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
for (pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, NULL);
|
for_each_pci_dev(pcidev) {
|
||||||
pcidev != NULL;
|
|
||||||
pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pcidev)) {
|
|
||||||
/* is it not a computer boards card? */
|
/* is it not a computer boards card? */
|
||||||
if (pcidev->vendor != PCI_VENDOR_ID_COMPUTERBOARDS)
|
if (pcidev->vendor != PCI_VENDOR_ID_COMPUTERBOARDS)
|
||||||
continue;
|
continue;
|
||||||
|
@ -4303,3 +4337,7 @@ static void i2c_write(struct comedi_device *dev, unsigned int address,
|
||||||
}
|
}
|
||||||
i2c_stop(dev);
|
i2c_stop(dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MODULE_AUTHOR("Comedi http://www.comedi.org");
|
||||||
|
MODULE_DESCRIPTION("Comedi low-level driver");
|
||||||
|
MODULE_LICENSE("GPL");
|
||||||
|
|
|
@ -280,7 +280,7 @@ static int cb_pcidda_attach(struct comedi_device *dev,
|
||||||
struct comedi_devconfig *it)
|
struct comedi_devconfig *it)
|
||||||
{
|
{
|
||||||
struct comedi_subdevice *s;
|
struct comedi_subdevice *s;
|
||||||
struct pci_dev *pcidev;
|
struct pci_dev *pcidev = NULL;
|
||||||
int index;
|
int index;
|
||||||
|
|
||||||
printk("comedi%d: cb_pcidda: ", dev->minor);
|
printk("comedi%d: cb_pcidda: ", dev->minor);
|
||||||
|
@ -296,9 +296,7 @@ static int cb_pcidda_attach(struct comedi_device *dev,
|
||||||
*/
|
*/
|
||||||
printk("\n");
|
printk("\n");
|
||||||
|
|
||||||
for (pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, NULL);
|
for_each_pci_dev(pcidev) {
|
||||||
pcidev != NULL;
|
|
||||||
pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pcidev)) {
|
|
||||||
if (pcidev->vendor == PCI_VENDOR_ID_CB) {
|
if (pcidev->vendor == PCI_VENDOR_ID_CB) {
|
||||||
if (it->options[0] || it->options[1]) {
|
if (it->options[0] || it->options[1]) {
|
||||||
if (pcidev->bus->number != it->options[0] ||
|
if (pcidev->bus->number != it->options[0] ||
|
||||||
|
@ -856,4 +854,44 @@ static void cb_pcidda_calibrate(struct comedi_device *dev, unsigned int channel,
|
||||||
* A convenient macro that defines init_module() and cleanup_module(),
|
* A convenient macro that defines init_module() and cleanup_module(),
|
||||||
* as necessary.
|
* as necessary.
|
||||||
*/
|
*/
|
||||||
COMEDI_PCI_INITCLEANUP(driver_cb_pcidda, cb_pcidda_pci_table);
|
static int __devinit driver_cb_pcidda_pci_probe(struct pci_dev *dev,
|
||||||
|
const struct pci_device_id *ent)
|
||||||
|
{
|
||||||
|
return comedi_pci_auto_config(dev, driver_cb_pcidda.driver_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __devexit driver_cb_pcidda_pci_remove(struct pci_dev *dev)
|
||||||
|
{
|
||||||
|
comedi_pci_auto_unconfig(dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct pci_driver driver_cb_pcidda_pci_driver = {
|
||||||
|
.id_table = cb_pcidda_pci_table,
|
||||||
|
.probe = &driver_cb_pcidda_pci_probe,
|
||||||
|
.remove = __devexit_p(&driver_cb_pcidda_pci_remove)
|
||||||
|
};
|
||||||
|
|
||||||
|
static int __init driver_cb_pcidda_init_module(void)
|
||||||
|
{
|
||||||
|
int retval;
|
||||||
|
|
||||||
|
retval = comedi_driver_register(&driver_cb_pcidda);
|
||||||
|
if (retval < 0)
|
||||||
|
return retval;
|
||||||
|
|
||||||
|
driver_cb_pcidda_pci_driver.name = (char *)driver_cb_pcidda.driver_name;
|
||||||
|
return pci_register_driver(&driver_cb_pcidda_pci_driver);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __exit driver_cb_pcidda_cleanup_module(void)
|
||||||
|
{
|
||||||
|
pci_unregister_driver(&driver_cb_pcidda_pci_driver);
|
||||||
|
comedi_driver_unregister(&driver_cb_pcidda);
|
||||||
|
}
|
||||||
|
|
||||||
|
module_init(driver_cb_pcidda_init_module);
|
||||||
|
module_exit(driver_cb_pcidda_cleanup_module);
|
||||||
|
|
||||||
|
MODULE_AUTHOR("Comedi http://www.comedi.org");
|
||||||
|
MODULE_DESCRIPTION("Comedi low-level driver");
|
||||||
|
MODULE_LICENSE("GPL");
|
||||||
|
|
|
@ -202,9 +202,7 @@ static int pcidio_attach(struct comedi_device *dev, struct comedi_devconfig *it)
|
||||||
* Probe the device to determine what device in the series it is.
|
* Probe the device to determine what device in the series it is.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
for (pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, NULL);
|
for_each_pci_dev(pcidev) {
|
||||||
pcidev != NULL;
|
|
||||||
pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pcidev)) {
|
|
||||||
/* is it not a computer boards card? */
|
/* is it not a computer boards card? */
|
||||||
if (pcidev->vendor != PCI_VENDOR_ID_CB)
|
if (pcidev->vendor != PCI_VENDOR_ID_CB)
|
||||||
continue;
|
continue;
|
||||||
|
@ -300,4 +298,44 @@ static int pcidio_detach(struct comedi_device *dev)
|
||||||
* A convenient macro that defines init_module() and cleanup_module(),
|
* A convenient macro that defines init_module() and cleanup_module(),
|
||||||
* as necessary.
|
* as necessary.
|
||||||
*/
|
*/
|
||||||
COMEDI_PCI_INITCLEANUP(driver_cb_pcidio, pcidio_pci_table);
|
static int __devinit driver_cb_pcidio_pci_probe(struct pci_dev *dev,
|
||||||
|
const struct pci_device_id *ent)
|
||||||
|
{
|
||||||
|
return comedi_pci_auto_config(dev, driver_cb_pcidio.driver_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __devexit driver_cb_pcidio_pci_remove(struct pci_dev *dev)
|
||||||
|
{
|
||||||
|
comedi_pci_auto_unconfig(dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct pci_driver driver_cb_pcidio_pci_driver = {
|
||||||
|
.id_table = pcidio_pci_table,
|
||||||
|
.probe = &driver_cb_pcidio_pci_probe,
|
||||||
|
.remove = __devexit_p(&driver_cb_pcidio_pci_remove)
|
||||||
|
};
|
||||||
|
|
||||||
|
static int __init driver_cb_pcidio_init_module(void)
|
||||||
|
{
|
||||||
|
int retval;
|
||||||
|
|
||||||
|
retval = comedi_driver_register(&driver_cb_pcidio);
|
||||||
|
if (retval < 0)
|
||||||
|
return retval;
|
||||||
|
|
||||||
|
driver_cb_pcidio_pci_driver.name = (char *)driver_cb_pcidio.driver_name;
|
||||||
|
return pci_register_driver(&driver_cb_pcidio_pci_driver);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __exit driver_cb_pcidio_cleanup_module(void)
|
||||||
|
{
|
||||||
|
pci_unregister_driver(&driver_cb_pcidio_pci_driver);
|
||||||
|
comedi_driver_unregister(&driver_cb_pcidio);
|
||||||
|
}
|
||||||
|
|
||||||
|
module_init(driver_cb_pcidio_init_module);
|
||||||
|
module_exit(driver_cb_pcidio_cleanup_module);
|
||||||
|
|
||||||
|
MODULE_AUTHOR("Comedi http://www.comedi.org");
|
||||||
|
MODULE_DESCRIPTION("Comedi low-level driver");
|
||||||
|
MODULE_LICENSE("GPL");
|
||||||
|
|
|
@ -210,7 +210,7 @@ static int cb_pcimdas_attach(struct comedi_device *dev,
|
||||||
struct comedi_devconfig *it)
|
struct comedi_devconfig *it)
|
||||||
{
|
{
|
||||||
struct comedi_subdevice *s;
|
struct comedi_subdevice *s;
|
||||||
struct pci_dev *pcidev;
|
struct pci_dev *pcidev = NULL;
|
||||||
int index;
|
int index;
|
||||||
/* int i; */
|
/* int i; */
|
||||||
|
|
||||||
|
@ -227,9 +227,7 @@ static int cb_pcimdas_attach(struct comedi_device *dev,
|
||||||
*/
|
*/
|
||||||
printk("\n");
|
printk("\n");
|
||||||
|
|
||||||
for (pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, NULL);
|
for_each_pci_dev(pcidev) {
|
||||||
pcidev != NULL;
|
|
||||||
pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pcidev)) {
|
|
||||||
/* is it not a computer boards card? */
|
/* is it not a computer boards card? */
|
||||||
if (pcidev->vendor != PCI_VENDOR_ID_COMPUTERBOARDS)
|
if (pcidev->vendor != PCI_VENDOR_ID_COMPUTERBOARDS)
|
||||||
continue;
|
continue;
|
||||||
|
@ -491,4 +489,46 @@ static int cb_pcimdas_ao_rinsn(struct comedi_device *dev,
|
||||||
* A convenient macro that defines init_module() and cleanup_module(),
|
* A convenient macro that defines init_module() and cleanup_module(),
|
||||||
* as necessary.
|
* as necessary.
|
||||||
*/
|
*/
|
||||||
COMEDI_PCI_INITCLEANUP(driver_cb_pcimdas, cb_pcimdas_pci_table);
|
static int __devinit driver_cb_pcimdas_pci_probe(struct pci_dev *dev,
|
||||||
|
const struct pci_device_id
|
||||||
|
*ent)
|
||||||
|
{
|
||||||
|
return comedi_pci_auto_config(dev, driver_cb_pcimdas.driver_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __devexit driver_cb_pcimdas_pci_remove(struct pci_dev *dev)
|
||||||
|
{
|
||||||
|
comedi_pci_auto_unconfig(dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct pci_driver driver_cb_pcimdas_pci_driver = {
|
||||||
|
.id_table = cb_pcimdas_pci_table,
|
||||||
|
.probe = &driver_cb_pcimdas_pci_probe,
|
||||||
|
.remove = __devexit_p(&driver_cb_pcimdas_pci_remove)
|
||||||
|
};
|
||||||
|
|
||||||
|
static int __init driver_cb_pcimdas_init_module(void)
|
||||||
|
{
|
||||||
|
int retval;
|
||||||
|
|
||||||
|
retval = comedi_driver_register(&driver_cb_pcimdas);
|
||||||
|
if (retval < 0)
|
||||||
|
return retval;
|
||||||
|
|
||||||
|
driver_cb_pcimdas_pci_driver.name =
|
||||||
|
(char *)driver_cb_pcimdas.driver_name;
|
||||||
|
return pci_register_driver(&driver_cb_pcimdas_pci_driver);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __exit driver_cb_pcimdas_cleanup_module(void)
|
||||||
|
{
|
||||||
|
pci_unregister_driver(&driver_cb_pcimdas_pci_driver);
|
||||||
|
comedi_driver_unregister(&driver_cb_pcimdas);
|
||||||
|
}
|
||||||
|
|
||||||
|
module_init(driver_cb_pcimdas_init_module);
|
||||||
|
module_exit(driver_cb_pcimdas_cleanup_module);
|
||||||
|
|
||||||
|
MODULE_AUTHOR("Comedi http://www.comedi.org");
|
||||||
|
MODULE_DESCRIPTION("Comedi low-level driver");
|
||||||
|
MODULE_LICENSE("GPL");
|
||||||
|
|
|
@ -195,7 +195,45 @@ MODULE_DESCRIPTION("Comedi low-level driver for the Computerboards PCIM-DDA "
|
||||||
"series. Currently only supports PCIM-DDA06-16 (which "
|
"series. Currently only supports PCIM-DDA06-16 (which "
|
||||||
"also happens to be the only board in this series. :) ) ");
|
"also happens to be the only board in this series. :) ) ");
|
||||||
MODULE_LICENSE("GPL");
|
MODULE_LICENSE("GPL");
|
||||||
COMEDI_PCI_INITCLEANUP_NOMODULE(cb_pcimdda_driver, pci_table);
|
static int __devinit cb_pcimdda_driver_pci_probe(struct pci_dev *dev,
|
||||||
|
const struct pci_device_id
|
||||||
|
*ent)
|
||||||
|
{
|
||||||
|
return comedi_pci_auto_config(dev, cb_pcimdda_driver.driver_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __devexit cb_pcimdda_driver_pci_remove(struct pci_dev *dev)
|
||||||
|
{
|
||||||
|
comedi_pci_auto_unconfig(dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct pci_driver cb_pcimdda_driver_pci_driver = {
|
||||||
|
.id_table = pci_table,
|
||||||
|
.probe = &cb_pcimdda_driver_pci_probe,
|
||||||
|
.remove = __devexit_p(&cb_pcimdda_driver_pci_remove)
|
||||||
|
};
|
||||||
|
|
||||||
|
static int __init cb_pcimdda_driver_init_module(void)
|
||||||
|
{
|
||||||
|
int retval;
|
||||||
|
|
||||||
|
retval = comedi_driver_register(&cb_pcimdda_driver);
|
||||||
|
if (retval < 0)
|
||||||
|
return retval;
|
||||||
|
|
||||||
|
cb_pcimdda_driver_pci_driver.name =
|
||||||
|
(char *)cb_pcimdda_driver.driver_name;
|
||||||
|
return pci_register_driver(&cb_pcimdda_driver_pci_driver);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __exit cb_pcimdda_driver_cleanup_module(void)
|
||||||
|
{
|
||||||
|
pci_unregister_driver(&cb_pcimdda_driver_pci_driver);
|
||||||
|
comedi_driver_unregister(&cb_pcimdda_driver);
|
||||||
|
}
|
||||||
|
|
||||||
|
module_init(cb_pcimdda_driver_init_module);
|
||||||
|
module_exit(cb_pcimdda_driver_cleanup_module);
|
||||||
|
|
||||||
static int ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
|
static int ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
|
||||||
struct comedi_insn *insn, unsigned int *data);
|
struct comedi_insn *insn, unsigned int *data);
|
||||||
|
@ -426,13 +464,11 @@ static int ao_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
|
||||||
*/
|
*/
|
||||||
static int probe(struct comedi_device *dev, const struct comedi_devconfig *it)
|
static int probe(struct comedi_device *dev, const struct comedi_devconfig *it)
|
||||||
{
|
{
|
||||||
struct pci_dev *pcidev;
|
struct pci_dev *pcidev = NULL;
|
||||||
int index;
|
int index;
|
||||||
unsigned long registers;
|
unsigned long registers;
|
||||||
|
|
||||||
for (pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, NULL);
|
for_each_pci_dev(pcidev) {
|
||||||
pcidev != NULL;
|
|
||||||
pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pcidev)) {
|
|
||||||
/* is it not a computer boards card? */
|
/* is it not a computer boards card? */
|
||||||
if (pcidev->vendor != PCI_VENDOR_ID_COMPUTERBOARDS)
|
if (pcidev->vendor != PCI_VENDOR_ID_COMPUTERBOARDS)
|
||||||
continue;
|
continue;
|
||||||
|
|
|
@ -50,43 +50,6 @@ Configuration Options:
|
||||||
within each minor will be concatenated together in the order given here.
|
within each minor will be concatenated together in the order given here.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
|
||||||
* The previous block comment is used to automatically generate
|
|
||||||
* documentation in Comedi and Comedilib. The fields:
|
|
||||||
*
|
|
||||||
* Driver: the name of the driver
|
|
||||||
* Description: a short phrase describing the driver. Don't list boards.
|
|
||||||
* Devices: a full list of the boards that attempt to be supported by
|
|
||||||
* the driver. Format is "(manufacturer) board name [comedi name]",
|
|
||||||
* where comedi_name is the name that is used to configure the board.
|
|
||||||
* See the comment near board_name: in the struct comedi_driver structure
|
|
||||||
* below. If (manufacturer) or [comedi name] is missing, the previous
|
|
||||||
* value is used.
|
|
||||||
* Author: you
|
|
||||||
* Updated: date when the _documentation_ was last updated. Use 'date -R'
|
|
||||||
* to get a value for this.
|
|
||||||
* Status: a one-word description of the status. Valid values are:
|
|
||||||
* works - driver works correctly on most boards supported, and
|
|
||||||
* passes comedi_test.
|
|
||||||
* unknown - unknown. Usually put there by ds.
|
|
||||||
* experimental - may not work in any particular release. Author
|
|
||||||
* probably wants assistance testing it.
|
|
||||||
* bitrotten - driver has not been update in a long time, probably
|
|
||||||
* doesn't work, and probably is missing support for significant
|
|
||||||
* Comedi interface features.
|
|
||||||
* untested - author probably wrote it "blind", and is believed to
|
|
||||||
* work, but no confirmation.
|
|
||||||
*
|
|
||||||
* These headers should be followed by a blank line, and any comments
|
|
||||||
* you wish to say about the driver. The comment area is the place
|
|
||||||
* to put any known bugs, limitations, unsupported features, supported
|
|
||||||
* command triggers, whether or not commands are supported on particular
|
|
||||||
* subdevices, etc.
|
|
||||||
*
|
|
||||||
* Somewhere in the comment should be information about configuration
|
|
||||||
* options that are used with comedi_config.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <linux/string.h>
|
#include <linux/string.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
#include "../comedi.h"
|
#include "../comedi.h"
|
||||||
|
|
|
@ -101,7 +101,18 @@ static struct comedi_driver driver_parport = {
|
||||||
.detach = parport_detach,
|
.detach = parport_detach,
|
||||||
};
|
};
|
||||||
|
|
||||||
COMEDI_INITCLEANUP(driver_parport);
|
static int __init driver_parport_init_module(void)
|
||||||
|
{
|
||||||
|
return comedi_driver_register(&driver_parport);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __exit driver_parport_cleanup_module(void)
|
||||||
|
{
|
||||||
|
comedi_driver_unregister(&driver_parport);
|
||||||
|
}
|
||||||
|
|
||||||
|
module_init(driver_parport_init_module);
|
||||||
|
module_exit(driver_parport_cleanup_module);
|
||||||
|
|
||||||
struct parport_private {
|
struct parport_private {
|
||||||
unsigned int a_data;
|
unsigned int a_data;
|
||||||
|
@ -396,3 +407,7 @@ static int parport_detach(struct comedi_device *dev)
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MODULE_AUTHOR("Comedi http://www.comedi.org");
|
||||||
|
MODULE_DESCRIPTION("Comedi low-level driver");
|
||||||
|
MODULE_LICENSE("GPL");
|
||||||
|
|
|
@ -107,7 +107,18 @@ static struct comedi_driver driver_waveform = {
|
||||||
.num_names = ARRAY_SIZE(waveform_boards),
|
.num_names = ARRAY_SIZE(waveform_boards),
|
||||||
};
|
};
|
||||||
|
|
||||||
COMEDI_INITCLEANUP(driver_waveform);
|
static int __init driver_waveform_init_module(void)
|
||||||
|
{
|
||||||
|
return comedi_driver_register(&driver_waveform);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __exit driver_waveform_cleanup_module(void)
|
||||||
|
{
|
||||||
|
comedi_driver_unregister(&driver_waveform);
|
||||||
|
}
|
||||||
|
|
||||||
|
module_init(driver_waveform_init_module);
|
||||||
|
module_exit(driver_waveform_cleanup_module);
|
||||||
|
|
||||||
static int waveform_ai_cmdtest(struct comedi_device *dev,
|
static int waveform_ai_cmdtest(struct comedi_device *dev,
|
||||||
struct comedi_subdevice *s,
|
struct comedi_subdevice *s,
|
||||||
|
@ -549,3 +560,7 @@ static int waveform_ao_insn_write(struct comedi_device *dev,
|
||||||
|
|
||||||
return insn->n;
|
return insn->n;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MODULE_AUTHOR("Comedi http://www.comedi.org");
|
||||||
|
MODULE_DESCRIPTION("Comedi low-level driver");
|
||||||
|
MODULE_LICENSE("GPL");
|
||||||
|
|
|
@ -103,7 +103,7 @@ static int contec_ns_to_timer(unsigned int *ns, int round);
|
||||||
|
|
||||||
static int contec_attach(struct comedi_device *dev, struct comedi_devconfig *it)
|
static int contec_attach(struct comedi_device *dev, struct comedi_devconfig *it)
|
||||||
{
|
{
|
||||||
struct pci_dev *pcidev;
|
struct pci_dev *pcidev = NULL;
|
||||||
struct comedi_subdevice *s;
|
struct comedi_subdevice *s;
|
||||||
|
|
||||||
printk("comedi%d: contec: ", dev->minor);
|
printk("comedi%d: contec: ", dev->minor);
|
||||||
|
@ -116,10 +116,7 @@ static int contec_attach(struct comedi_device *dev, struct comedi_devconfig *it)
|
||||||
if (alloc_subdevices(dev, 2) < 0)
|
if (alloc_subdevices(dev, 2) < 0)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
for (pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, NULL);
|
for_each_pci_dev(pcidev) {
|
||||||
pcidev != NULL;
|
|
||||||
pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pcidev)) {
|
|
||||||
|
|
||||||
if (pcidev->vendor == PCI_VENDOR_ID_CONTEC &&
|
if (pcidev->vendor == PCI_VENDOR_ID_CONTEC &&
|
||||||
pcidev->device == PCI_DEVICE_ID_PIO1616L) {
|
pcidev->device == PCI_DEVICE_ID_PIO1616L) {
|
||||||
if (it->options[0] || it->options[1]) {
|
if (it->options[0] || it->options[1]) {
|
||||||
|
@ -232,4 +229,44 @@ static int contec_di_insn_bits(struct comedi_device *dev,
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
COMEDI_PCI_INITCLEANUP(driver_contec, contec_pci_table);
|
static int __devinit driver_contec_pci_probe(struct pci_dev *dev,
|
||||||
|
const struct pci_device_id *ent)
|
||||||
|
{
|
||||||
|
return comedi_pci_auto_config(dev, driver_contec.driver_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __devexit driver_contec_pci_remove(struct pci_dev *dev)
|
||||||
|
{
|
||||||
|
comedi_pci_auto_unconfig(dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct pci_driver driver_contec_pci_driver = {
|
||||||
|
.id_table = contec_pci_table,
|
||||||
|
.probe = &driver_contec_pci_probe,
|
||||||
|
.remove = __devexit_p(&driver_contec_pci_remove)
|
||||||
|
};
|
||||||
|
|
||||||
|
static int __init driver_contec_init_module(void)
|
||||||
|
{
|
||||||
|
int retval;
|
||||||
|
|
||||||
|
retval = comedi_driver_register(&driver_contec);
|
||||||
|
if (retval < 0)
|
||||||
|
return retval;
|
||||||
|
|
||||||
|
driver_contec_pci_driver.name = (char *)driver_contec.driver_name;
|
||||||
|
return pci_register_driver(&driver_contec_pci_driver);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __exit driver_contec_cleanup_module(void)
|
||||||
|
{
|
||||||
|
pci_unregister_driver(&driver_contec_pci_driver);
|
||||||
|
comedi_driver_unregister(&driver_contec);
|
||||||
|
}
|
||||||
|
|
||||||
|
module_init(driver_contec_init_module);
|
||||||
|
module_exit(driver_contec_cleanup_module);
|
||||||
|
|
||||||
|
MODULE_AUTHOR("Comedi http://www.comedi.org");
|
||||||
|
MODULE_DESCRIPTION("Comedi low-level driver");
|
||||||
|
MODULE_LICENSE("GPL");
|
||||||
|
|
|
@ -887,4 +887,46 @@ static int daqboard2000_detach(struct comedi_device *dev)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
COMEDI_PCI_INITCLEANUP(driver_daqboard2000, daqboard2000_pci_table);
|
static int __devinit driver_daqboard2000_pci_probe(struct pci_dev *dev,
|
||||||
|
const struct pci_device_id
|
||||||
|
*ent)
|
||||||
|
{
|
||||||
|
return comedi_pci_auto_config(dev, driver_daqboard2000.driver_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __devexit driver_daqboard2000_pci_remove(struct pci_dev *dev)
|
||||||
|
{
|
||||||
|
comedi_pci_auto_unconfig(dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct pci_driver driver_daqboard2000_pci_driver = {
|
||||||
|
.id_table = daqboard2000_pci_table,
|
||||||
|
.probe = &driver_daqboard2000_pci_probe,
|
||||||
|
.remove = __devexit_p(&driver_daqboard2000_pci_remove)
|
||||||
|
};
|
||||||
|
|
||||||
|
static int __init driver_daqboard2000_init_module(void)
|
||||||
|
{
|
||||||
|
int retval;
|
||||||
|
|
||||||
|
retval = comedi_driver_register(&driver_daqboard2000);
|
||||||
|
if (retval < 0)
|
||||||
|
return retval;
|
||||||
|
|
||||||
|
driver_daqboard2000_pci_driver.name =
|
||||||
|
(char *)driver_daqboard2000.driver_name;
|
||||||
|
return pci_register_driver(&driver_daqboard2000_pci_driver);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __exit driver_daqboard2000_cleanup_module(void)
|
||||||
|
{
|
||||||
|
pci_unregister_driver(&driver_daqboard2000_pci_driver);
|
||||||
|
comedi_driver_unregister(&driver_daqboard2000);
|
||||||
|
}
|
||||||
|
|
||||||
|
module_init(driver_daqboard2000_init_module);
|
||||||
|
module_exit(driver_daqboard2000_cleanup_module);
|
||||||
|
|
||||||
|
MODULE_AUTHOR("Comedi http://www.comedi.org");
|
||||||
|
MODULE_DESCRIPTION("Comedi low-level driver");
|
||||||
|
MODULE_LICENSE("GPL");
|
||||||
|
|
|
@ -980,7 +980,7 @@ static int das08_attach(struct comedi_device *dev, struct comedi_devconfig *it)
|
||||||
unsigned long iobase;
|
unsigned long iobase;
|
||||||
#ifdef CONFIG_COMEDI_PCI
|
#ifdef CONFIG_COMEDI_PCI
|
||||||
unsigned long pci_iobase = 0;
|
unsigned long pci_iobase = 0;
|
||||||
struct pci_dev *pdev;
|
struct pci_dev *pdev = NULL;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
ret = alloc_private(dev, sizeof(struct das08_private_struct));
|
ret = alloc_private(dev, sizeof(struct das08_private_struct));
|
||||||
|
@ -997,9 +997,7 @@ static int das08_attach(struct comedi_device *dev, struct comedi_devconfig *it)
|
||||||
}
|
}
|
||||||
printk("\n");
|
printk("\n");
|
||||||
/* find card */
|
/* find card */
|
||||||
for (pdev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, NULL);
|
for_each_pci_dev(pdev) {
|
||||||
pdev != NULL;
|
|
||||||
pdev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pdev)) {
|
|
||||||
if (pdev->vendor == PCI_VENDOR_ID_COMPUTERBOARDS
|
if (pdev->vendor == PCI_VENDOR_ID_COMPUTERBOARDS
|
||||||
&& pdev->device == PCI_DEVICE_ID_PCIDAS08) {
|
&& pdev->device == PCI_DEVICE_ID_PCIDAS08) {
|
||||||
if (it->options[0] || it->options[1]) {
|
if (it->options[0] || it->options[1]) {
|
||||||
|
@ -1082,11 +1080,62 @@ int das08_common_detach(struct comedi_device *dev)
|
||||||
EXPORT_SYMBOL_GPL(das08_common_detach);
|
EXPORT_SYMBOL_GPL(das08_common_detach);
|
||||||
|
|
||||||
#ifdef CONFIG_COMEDI_PCI
|
#ifdef CONFIG_COMEDI_PCI
|
||||||
COMEDI_PCI_INITCLEANUP(driver_das08, das08_pci_table);
|
static int __devinit driver_das08_pci_probe(struct pci_dev *dev,
|
||||||
|
const struct pci_device_id *ent)
|
||||||
|
{
|
||||||
|
return comedi_pci_auto_config(dev, driver_das08.driver_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __devexit driver_das08_pci_remove(struct pci_dev *dev)
|
||||||
|
{
|
||||||
|
comedi_pci_auto_unconfig(dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct pci_driver driver_das08_pci_driver = {
|
||||||
|
.id_table = das08_pci_table,
|
||||||
|
.probe = &driver_das08_pci_probe,
|
||||||
|
.remove = __devexit_p(&driver_das08_pci_remove)
|
||||||
|
};
|
||||||
|
|
||||||
|
static int __init driver_das08_init_module(void)
|
||||||
|
{
|
||||||
|
int retval;
|
||||||
|
|
||||||
|
retval = comedi_driver_register(&driver_das08);
|
||||||
|
if (retval < 0)
|
||||||
|
return retval;
|
||||||
|
|
||||||
|
driver_das08_pci_driver.name = (char *)driver_das08.driver_name;
|
||||||
|
return pci_register_driver(&driver_das08_pci_driver);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __exit driver_das08_cleanup_module(void)
|
||||||
|
{
|
||||||
|
pci_unregister_driver(&driver_das08_pci_driver);
|
||||||
|
comedi_driver_unregister(&driver_das08);
|
||||||
|
}
|
||||||
|
|
||||||
|
module_init(driver_das08_init_module);
|
||||||
|
module_exit(driver_das08_cleanup_module);
|
||||||
#else
|
#else
|
||||||
COMEDI_INITCLEANUP(driver_das08);
|
static int __init driver_das08_init_module(void)
|
||||||
|
{
|
||||||
|
return comedi_driver_register(&driver_das08);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __exit driver_das08_cleanup_module(void)
|
||||||
|
{
|
||||||
|
comedi_driver_unregister(&driver_das08);
|
||||||
|
}
|
||||||
|
|
||||||
|
module_init(driver_das08_init_module);
|
||||||
|
module_exit(driver_das08_cleanup_module);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_COMEDI_PCMCIA
|
#ifdef CONFIG_COMEDI_PCMCIA
|
||||||
EXPORT_SYMBOL_GPL(das08_cs_boards);
|
EXPORT_SYMBOL_GPL(das08_cs_boards);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
MODULE_AUTHOR("Comedi http://www.comedi.org");
|
||||||
|
MODULE_DESCRIPTION("Comedi low-level driver");
|
||||||
|
MODULE_LICENSE("GPL");
|
||||||
|
|
|
@ -206,7 +206,6 @@ static void das08_pcmcia_detach(struct pcmcia_device *link)
|
||||||
das08_pcmcia_release(link);
|
das08_pcmcia_release(link);
|
||||||
|
|
||||||
/* This points to the parent struct local_info_t struct */
|
/* This points to the parent struct local_info_t struct */
|
||||||
if (link->priv)
|
|
||||||
kfree(link->priv);
|
kfree(link->priv);
|
||||||
|
|
||||||
} /* das08_pcmcia_detach */
|
} /* das08_pcmcia_detach */
|
||||||
|
|
|
@ -1717,7 +1717,18 @@ static int das16_detach(struct comedi_device *dev)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
COMEDI_INITCLEANUP(driver_das16);
|
static int __init driver_das16_init_module(void)
|
||||||
|
{
|
||||||
|
return comedi_driver_register(&driver_das16);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __exit driver_das16_cleanup_module(void)
|
||||||
|
{
|
||||||
|
comedi_driver_unregister(&driver_das16);
|
||||||
|
}
|
||||||
|
|
||||||
|
module_init(driver_das16_init_module);
|
||||||
|
module_exit(driver_das16_cleanup_module);
|
||||||
|
|
||||||
/* utility function that suggests a dma transfer size in bytes */
|
/* utility function that suggests a dma transfer size in bytes */
|
||||||
static unsigned int das16_suggest_transfer_size(struct comedi_device *dev,
|
static unsigned int das16_suggest_transfer_size(struct comedi_device *dev,
|
||||||
|
@ -1776,3 +1787,7 @@ static void das16_ai_munge(struct comedi_device *dev,
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MODULE_AUTHOR("Comedi http://www.comedi.org");
|
||||||
|
MODULE_DESCRIPTION("Comedi low-level driver");
|
||||||
|
MODULE_LICENSE("GPL");
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue