Merge git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging-2.6

* git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging-2.6: (577 commits)
  Staging: ramzswap: Handler for swap slot free callback
  swap: Add swap slot free callback to block_device_operations
  swap: Add flag to identify block swap devices
  Staging: vt6655: use ETH_FRAME_LEN macro instead of custom one
  Staging: vt6655: use ETH_DATA_LEN macro instead of custom one
  Staging: vt6655: use ETH_FCS_LEN macro instead of custom one
  Staging: vt6656: use ETH_HLEN macro instead of custom one
  Staging: comedi: quatech_daqp_cs.c Replace eos semaphore with a completion.
  Staging: dt3155v4l: remove private memory allocator
  Staging: crystalhd: Remove typedefs from driver
  Staging: winbond: Fix for pointer name format issue in mds.c
  Staging: vt6656: removed custom UCHAR/USHORT/UINT/ULONG/ULONGLONG typedefs
  Staging: vt6656: removed custom CHAR/SHORT/INT/LONG typedefs
  Staging: comedi: Altered the way printk is used in 8255.c
  staging: iio: adis16350 and similar IMU driver
  Staging: iio: max1363 Fix two bugs in single_channel_from_ring
  Staging: iio: adis16220 extract bin_attribute structures from state
  Staging: iio: adis16220 vibration sensor driver
  Staging: comedi: Kconfig dependancy fixes
  Staging: comedi: fix up build error from last Kconfig changes
  ...
This commit is contained in:
Linus Torvalds 2010-05-21 15:26:46 -07:00
commit d79df0b1ed
735 changed files with 55965 additions and 51620 deletions

View file

@ -59,8 +59,6 @@ source "drivers/staging/wlan-ng/Kconfig"
source "drivers/staging/echo/Kconfig"
source "drivers/staging/poch/Kconfig"
source "drivers/staging/otus/Kconfig"
source "drivers/staging/rt2860/Kconfig"
@ -113,6 +111,8 @@ source "drivers/staging/vme/Kconfig"
source "drivers/staging/rar_register/Kconfig"
source "drivers/staging/memrar/Kconfig"
source "drivers/staging/sep/Kconfig"
source "drivers/staging/iio/Kconfig"
@ -127,19 +127,19 @@ source "drivers/staging/batman-adv/Kconfig"
source "drivers/staging/samsung-laptop/Kconfig"
source "drivers/staging/strip/Kconfig"
source "drivers/staging/arlan/Kconfig"
source "drivers/staging/wavelan/Kconfig"
source "drivers/staging/netwave/Kconfig"
source "drivers/staging/sm7xx/Kconfig"
source "drivers/staging/dt3155/Kconfig"
source "drivers/staging/dt3155v4l/Kconfig"
source "drivers/staging/crystalhd/Kconfig"
source "drivers/staging/cxt1e1/Kconfig"
source "drivers/staging/ti-st/Kconfig"
source "drivers/staging/adis16255/Kconfig"
endif # !STAGING_EXCLUDE_BUILD
endif # STAGING

View file

@ -12,7 +12,6 @@ obj-$(CONFIG_USB_IP_COMMON) += usbip/
obj-$(CONFIG_W35UND) += winbond/
obj-$(CONFIG_PRISM2_USB) += wlan-ng/
obj-$(CONFIG_ECHO) += echo/
obj-$(CONFIG_POCH) += poch/
obj-$(CONFIG_OTUS) += otus/
obj-$(CONFIG_RT2860) += rt2860/
obj-$(CONFIG_RT2870) += rt2870/
@ -37,6 +36,7 @@ obj-$(CONFIG_FB_UDL) += udlfb/
obj-$(CONFIG_HYPERV) += hv/
obj-$(CONFIG_VME_BUS) += vme/
obj-$(CONFIG_RAR_REGISTER) += rar_register/
obj-$(CONFIG_MRST_RAR_HANDLER) += memrar/
obj-$(CONFIG_DX_SEP) += sep/
obj-$(CONFIG_IIO) += iio/
obj-$(CONFIG_RAMZSWAP) += ramzswap/
@ -44,11 +44,10 @@ obj-$(CONFIG_WLAGS49_H2) += wlags49_h2/
obj-$(CONFIG_WLAGS49_H25) += wlags49_h25/
obj-$(CONFIG_BATMAN_ADV) += batman-adv/
obj-$(CONFIG_SAMSUNG_LAPTOP) += samsung-laptop/
obj-$(CONFIG_STRIP) += strip/
obj-$(CONFIG_ARLAN) += arlan/
obj-$(CONFIG_WAVELAN) += wavelan/
obj-$(CONFIG_PCMCIA_WAVELAN) += wavelan/
obj-$(CONFIG_PCMCIA_NETWAVE) += netwave/
obj-$(CONFIG_FB_SM7XX) += sm7xx/
obj-$(CONFIG_DT3155) += dt3155/
obj-$(CONFIG_VIDEO_DT3155) += dt3155v4l/
obj-$(CONFIG_CRYSTALHD) += crystalhd/
obj-$(CONFIG_CXT1E1) += cxt1e1/
obj-$(CONFIG_TI_ST) += ti-st/
obj-$(CONFIG_ADIS16255) += adis16255/

View file

@ -0,0 +1,11 @@
config ADIS16255
tristate "Ananlog Devices ADIS16250/16255"
depends on SPI && SYSFS
---help---
If you say yes here you get support for the Analog Devices
ADIS16250/16255 Low Power Gyroscope. The driver exposes
orientation and gyroscope value, as well as sample rate
to the sysfs.
This driver can also be built as a module. If so, the module
will be called adis16255.

View file

@ -0,0 +1 @@
obj-$(CONFIG_ADIS16255) += adis16255.o

View file

@ -0,0 +1,466 @@
/*
* Analog Devices ADIS16250/ADIS16255 Low Power Gyroscope
*
* Written by: Matthias Brugger <m_brugger@web.de>
*
* Copyright (C) 2010 Fraunhofer Institute for Integrated Circuits
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the
* Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/*
* The driver just has a bare interface to the sysfs (sample rate in Hz,
* orientation (x, y, z) and gyroscope data in °/sec.
*
* It should be added to iio subsystem when this has left staging.
*
*/
#include <linux/init.h>
#include <linux/module.h>
#include <linux/device.h>
#include <linux/list.h>
#include <linux/errno.h>
#include <linux/mutex.h>
#include <linux/slab.h>
#include <linux/interrupt.h>
#include <linux/sysfs.h>
#include <linux/stat.h>
#include <linux/delay.h>
#include <linux/gpio.h>
#include <linux/spi/spi.h>
#include <linux/workqueue.h>
#include "adis16255.h"
#define ADIS_STATUS 0x3d
#define ADIS_SMPL_PRD_MSB 0x37
#define ADIS_SMPL_PRD_LSB 0x36
#define ADIS_MSC_CTRL_MSB 0x35
#define ADIS_MSC_CTRL_LSB 0x34
#define ADIS_GPIO_CTRL 0x33
#define ADIS_ALM_SMPL1 0x25
#define ADIS_ALM_MAG1 0x21
#define ADIS_GYRO_SCALE 0x17
#define ADIS_GYRO_OUT 0x05
#define ADIS_SUPPLY_OUT 0x03
#define ADIS_ENDURANCE 0x01
/*
* data structure for every sensor
*
* @dev: Driver model representation of the device.
* @spi: Pointer to the spi device which will manage i/o to spi bus.
* @data: Last read data from device.
* @irq_adis: GPIO Number of IRQ signal
* @irq: irq line manage by kernel
* @negative: indicates if sensor is upside down (negative == 1)
* @direction: indicates axis (x, y, z) the sensor is meassuring
*/
struct spi_adis16255_data {
struct device dev;
struct spi_device *spi;
s16 data;
int irq;
u8 negative;
char direction;
};
/*-------------------------------------------------------------------------*/
static int spi_adis16255_read_data(struct spi_adis16255_data *spiadis,
u8 adr,
u8 *rbuf)
{
struct spi_device *spi = spiadis->spi;
struct spi_message msg;
struct spi_transfer xfer1, xfer2;
u8 *buf, *rx;
int ret;
buf = kzalloc(4, GFP_KERNEL);
if (buf == NULL)
return -ENOMEM;
rx = kzalloc(4, GFP_KERNEL);
if (rx == NULL) {
ret = -ENOMEM;
goto err_buf;
}
buf[0] = adr;
spi_message_init(&msg);
memset(&xfer1, 0, sizeof(xfer1));
memset(&xfer2, 0, sizeof(xfer2));
xfer1.tx_buf = buf;
xfer1.rx_buf = buf + 2;
xfer1.len = 2;
xfer1.delay_usecs = 9;
xfer2.tx_buf = rx + 2;
xfer2.rx_buf = rx;
xfer2.len = 2;
spi_message_add_tail(&xfer1, &msg);
spi_message_add_tail(&xfer2, &msg);
ret = spi_sync(spi, &msg);
if (ret == 0) {
rbuf[0] = rx[0];
rbuf[1] = rx[1];
}
kfree(rx);
err_buf:
kfree(buf);
return ret;
}
static int spi_adis16255_write_data(struct spi_adis16255_data *spiadis,
u8 adr1,
u8 adr2,
u8 *wbuf)
{
struct spi_device *spi = spiadis->spi;
struct spi_message msg;
struct spi_transfer xfer1, xfer2;
u8 *buf, *rx;
int ret;
buf = kmalloc(4, GFP_KERNEL);
if (buf == NULL)
return -ENOMEM;
rx = kzalloc(4, GFP_KERNEL);
if (rx == NULL) {
ret = -ENOMEM;
goto err_buf;
}
spi_message_init(&msg);
memset(&xfer1, 0, sizeof(xfer1));
memset(&xfer2, 0, sizeof(xfer2));
buf[0] = adr1 | 0x80;
buf[1] = *wbuf;
buf[2] = adr2 | 0x80;
buf[3] = *(wbuf + 1);
xfer1.tx_buf = buf;
xfer1.rx_buf = rx;
xfer1.len = 2;
xfer1.delay_usecs = 9;
xfer2.tx_buf = buf+2;
xfer2.rx_buf = rx+2;
xfer2.len = 2;
spi_message_add_tail(&xfer1, &msg);
spi_message_add_tail(&xfer2, &msg);
ret = spi_sync(spi, &msg);
if (ret != 0)
dev_warn(&spi->dev, "write data to %#x %#x failed\n",
buf[0], buf[2]);
kfree(rx);
err_buf:
kfree(buf);
return ret;
}
/*-------------------------------------------------------------------------*/
static irqreturn_t adis_irq_thread(int irq, void *dev_id)
{
struct spi_adis16255_data *spiadis = dev_id;
int status;
u16 value = 0;
status = spi_adis16255_read_data(spiadis, ADIS_GYRO_OUT, (u8 *)&value);
if (status != 0) {
dev_warn(&spiadis->spi->dev, "SPI FAILED\n");
goto exit;
}
/* perform on new data only... */
if (value & 0x8000) {
/* delete error and new data bit */
value = value & 0x3fff;
/* set negative value */
if (value & 0x2000)
value = value | 0xe000;
if (likely(spiadis->negative))
value = -value;
spiadis->data = (s16) value;
}
exit:
return IRQ_HANDLED;
}
/*-------------------------------------------------------------------------*/
ssize_t adis16255_show_data(struct device *device,
struct device_attribute *da,
char *buf)
{
struct spi_adis16255_data *spiadis = dev_get_drvdata(device);
return snprintf(buf, PAGE_SIZE, "%d\n", spiadis->data);
}
DEVICE_ATTR(data, S_IRUGO , adis16255_show_data, NULL);
ssize_t adis16255_show_direction(struct device *device,
struct device_attribute *da,
char *buf)
{
struct spi_adis16255_data *spiadis = dev_get_drvdata(device);
return snprintf(buf, PAGE_SIZE, "%c\n", spiadis->direction);
}
DEVICE_ATTR(direction, S_IRUGO , adis16255_show_direction, NULL);
ssize_t adis16255_show_sample_rate(struct device *device,
struct device_attribute *da,
char *buf)
{
struct spi_adis16255_data *spiadis = dev_get_drvdata(device);
int status = 0;
u16 value = 0;
int ts = 0;
status = spi_adis16255_read_data(spiadis, ADIS_SMPL_PRD_MSB,
(u8 *)&value);
if (status != 0)
return -EINVAL;
if (value & 0x80) {
/* timebase = 60.54 ms */
ts = 60540 * ((0x7f & value) + 1);
} else {
/* timebase = 1.953 ms */
ts = 1953 * ((0x7f & value) + 1);
}
return snprintf(buf, PAGE_SIZE, "%d\n", (1000*1000)/ts);
}
DEVICE_ATTR(sample_rate, S_IRUGO , adis16255_show_sample_rate, NULL);
static struct attribute *adis16255_attributes[] = {
&dev_attr_data.attr,
&dev_attr_direction.attr,
&dev_attr_sample_rate.attr,
NULL
};
static const struct attribute_group adis16255_attr_group = {
.attrs = adis16255_attributes,
};
/*-------------------------------------------------------------------------*/
static int spi_adis16255_shutdown(struct spi_adis16255_data *spiadis)
{
u16 value = 0;
/* turn sensor off */
spi_adis16255_write_data(spiadis,
ADIS_SMPL_PRD_MSB, ADIS_SMPL_PRD_LSB,
(u8 *)&value);
spi_adis16255_write_data(spiadis,
ADIS_MSC_CTRL_MSB, ADIS_MSC_CTRL_LSB,
(u8 *)&value);
return 0;
}
static int spi_adis16255_bringup(struct spi_adis16255_data *spiadis)
{
int status = 0;
u16 value = 0;
status = spi_adis16255_read_data(spiadis, ADIS_GYRO_SCALE,
(u8 *)&value);
if (status != 0)
goto err;
if (value != 0x0800) {
dev_warn(&spiadis->spi->dev, "Scale factor is none default"
"value (%.4x)\n", value);
}
/* timebase = 1.953 ms, Ns = 0 -> 512 Hz sample rate */
value = 0x0001;
status = spi_adis16255_write_data(spiadis,
ADIS_SMPL_PRD_MSB, ADIS_SMPL_PRD_LSB,
(u8 *)&value);
if (status != 0)
goto err;
/* start internal self-test */
value = 0x0400;
status = spi_adis16255_write_data(spiadis,
ADIS_MSC_CTRL_MSB, ADIS_MSC_CTRL_LSB,
(u8 *)&value);
if (status != 0)
goto err;
/* wait 35 ms to finish self-test */
msleep(35);
value = 0x0000;
status = spi_adis16255_read_data(spiadis, ADIS_STATUS,
(u8 *)&value);
if (status != 0)
goto err;
if (value & 0x23) {
if (value & 0x20) {
dev_warn(&spiadis->spi->dev, "self-test error\n");
status = -ENODEV;
goto err;
} else if (value & 0x3) {
dev_warn(&spiadis->spi->dev, "Sensor voltage"
"out of range.\n");
status = -ENODEV;
goto err;
}
}
/* set interrupt to active high on DIO0 when data ready */
value = 0x0006;
status = spi_adis16255_write_data(spiadis,
ADIS_MSC_CTRL_MSB, ADIS_MSC_CTRL_LSB,
(u8 *)&value);
if (status != 0)
goto err;
return status;
err:
spi_adis16255_shutdown(spiadis);
return status;
}
/*-------------------------------------------------------------------------*/
static int spi_adis16255_probe(struct spi_device *spi)
{
struct adis16255_init_data *init_data = spi->dev.platform_data;
struct spi_adis16255_data *spiadis;
int status = 0;
spiadis = kzalloc(sizeof(*spiadis), GFP_KERNEL);
if (!spiadis)
return -ENOMEM;
spiadis->spi = spi;
spiadis->direction = init_data->direction;
if (init_data->negative)
spiadis->negative = 1;
status = gpio_request(init_data->irq, "adis16255");
if (status != 0)
goto err;
status = gpio_direction_input(init_data->irq);
if (status != 0)
goto gpio_err;
spiadis->irq = gpio_to_irq(init_data->irq);
status = request_threaded_irq(spiadis->irq,
NULL, adis_irq_thread,
IRQF_DISABLED, "adis-driver", spiadis);
if (status != 0) {
dev_err(&spi->dev, "IRQ request failed\n");
goto gpio_err;
}
dev_dbg(&spi->dev, "GPIO %d IRQ %d\n", init_data->irq, spiadis->irq);
dev_set_drvdata(&spi->dev, spiadis);
status = sysfs_create_group(&spi->dev.kobj, &adis16255_attr_group);
if (status != 0)
goto irq_err;
status = spi_adis16255_bringup(spiadis);
if (status != 0)
goto irq_err;
dev_info(&spi->dev, "spi_adis16255 driver added!\n");
return status;
irq_err:
free_irq(spiadis->irq, spiadis);
gpio_err:
gpio_free(init_data->irq);
err:
kfree(spiadis);
return status;
}
static int spi_adis16255_remove(struct spi_device *spi)
{
struct spi_adis16255_data *spiadis = dev_get_drvdata(&spi->dev);
spi_adis16255_shutdown(spiadis);
free_irq(spiadis->irq, spiadis);
gpio_free(irq_to_gpio(spiadis->irq));
sysfs_remove_group(&spiadis->spi->dev.kobj, &adis16255_attr_group);
kfree(spiadis);
dev_info(&spi->dev, "spi_adis16255 driver removed!\n");
return 0;
}
static struct spi_driver spi_adis16255_drv = {
.driver = {
.name = "spi_adis16255",
.owner = THIS_MODULE,
},
.probe = spi_adis16255_probe,
.remove = __devexit_p(spi_adis16255_remove),
};
/*-------------------------------------------------------------------------*/
static int __init spi_adis16255_init(void)
{
return spi_register_driver(&spi_adis16255_drv);
}
module_init(spi_adis16255_init);
static void __exit spi_adis16255_exit(void)
{
spi_unregister_driver(&spi_adis16255_drv);
}
module_exit(spi_adis16255_exit);
MODULE_AUTHOR("Matthias Brugger");
MODULE_DESCRIPTION("SPI device driver for ADIS16255 sensor");
MODULE_LICENSE("GPL");

View file

@ -0,0 +1,12 @@
#ifndef ADIS16255_H
#define ADIS16255_H
#include <linux/types.h>
struct adis16255_init_data {
char direction;
u8 negative;
int irq;
};
#endif

View file

@ -1,15 +0,0 @@
config ARLAN
tristate "Aironet Arlan 655 & IC2200 DS support"
depends on ISA && !64BIT && WLAN
select WIRELESS_EXT
---help---
Aironet makes Arlan, a class of wireless LAN adapters. These use the
www.Telxon.com chip, which is also used on several similar cards.
This driver is tested on the 655 and IC2200 series cards. Look at
<http://www.ylenurme.ee/~elmer/655/> for the latest information.
The driver is built as two modules, arlan and arlan-proc. The latter
is the /proc interface and is not needed most of time.
On some computers the card ends up in non-valid state after some
time. Use a ping-reset script to clear it.

View file

@ -1,3 +0,0 @@
obj-$(CONFIG_ARLAN) += arlan.o
arlan-objs := arlan-main.o arlan-proc.o

View file

@ -1,7 +0,0 @@
TODO:
- step up and maintain this driver to ensure that it continues
to work. Having the hardware for this is pretty much a
requirement. If this does not happen, the will be removed in
the 2.6.35 kernel release.
Please send patches to Greg Kroah-Hartman <greg@kroah.com>.

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,535 +0,0 @@
/*
* Copyright (C) 1997 Cullen Jennings
* Copyright (C) 1998 Elmer.Joandi@ut.ee, +37-255-13500
* GNU General Public License applies
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/skbuff.h>
#include <linux/if_ether.h> /* For the statistics structure. */
#include <linux/if_arp.h> /* For ARPHRD_ETHER */
#include <linux/ptrace.h>
#include <linux/ioport.h>
#include <linux/in.h>
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/timer.h>
#include <linux/init.h>
#include <linux/bitops.h>
#include <asm/system.h>
#include <linux/io.h>
#include <linux/errno.h>
#include <linux/delay.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
/* #define ARLAN_DEBUGGING 1 */
#define ARLAN_PROC_INTERFACE
#define MAX_ARLANS 4 /* not more than 4 ! */
#define ARLAN_PROC_SHM_DUMP /* shows all card registers, makes driver way larger */
#define ARLAN_MAX_MULTICAST_ADDRS 16
#define ARLAN_RCV_CLEAN 0
#define ARLAN_RCV_PROMISC 1
#define ARLAN_RCV_CONTROL 2
#ifdef CONFIG_PROC_FS
extern int init_arlan_proc(void);
extern void cleanup_arlan_proc(void);
#else
#define init_arlan_proc() ({ 0; })
#define cleanup_arlan_proc() do { } while (0)
#endif
extern struct net_device *arlan_device[MAX_ARLANS];
extern int arlan_debug;
extern int arlan_entry_debug;
extern int arlan_exit_debug;
extern int testMemory;
extern int arlan_command(struct net_device *dev, int command);
#define SIDUNKNOWN -1
#define radioNodeIdUNKNOWN -1
#define irqUNKNOWN 0
#define debugUNKNOWN 0
#define testMemoryUNKNOWN 1
#define spreadingCodeUNKNOWN 0
#define channelNumberUNKNOWN 0
#define channelSetUNKNOWN 0
#define systemIdUNKNOWN -1
#define registrationModeUNKNOWN -1
#define IFDEBUG(L) if ((L) & arlan_debug)
#define ARLAN_FAKE_HDR_LEN 12
#ifdef ARLAN_DEBUGGING
#define DEBUG 1
#define ARLAN_ENTRY_EXIT_DEBUGGING 1
#define ARLAN_DEBUG(a, b) printk(KERN_DEBUG a, b)
#else
#define ARLAN_DEBUG(a, b)
#endif
#define ARLAN_SHMEM_SIZE 0x2000
struct arlan_shmem {
/* Header Signature */
volatile char textRegion[48];
volatile u_char resetFlag;
volatile u_char diagnosticInfo;
volatile u_short diagnosticOffset;
volatile u_char _1[12];
volatile u_char lanCardNodeId[6];
volatile u_char broadcastAddress[6];
volatile u_char hardwareType;
volatile u_char majorHardwareVersion;
volatile u_char minorHardwareVersion;
volatile u_char radioModule;/* shows EEPROM, can be overridden at 0x111 */
volatile u_char defaultChannelSet; /* shows EEProm, can be overriiden at 0x10A */
volatile u_char _2[47];
/* Control/Status Block - 0x0080 */
volatile u_char interruptInProgress; /* not used by lancpu */
volatile u_char cntrlRegImage; /* not used by lancpu */
volatile u_char _3[13];
volatile u_char dumpByte;
volatile u_char commandByte; /* non-zero = active */
volatile u_char commandParameter[15];
/* Receive Status - 0x00a0 */
volatile u_char rxStatus; /* 1- data, 2-control, 0xff - registr change */
volatile u_char rxFrmType;
volatile u_short rxOffset;
volatile u_short rxLength;
volatile u_char rxSrc[6];
volatile u_char rxBroadcastFlag;
volatile u_char rxQuality;
volatile u_char scrambled;
volatile u_char _4[1];
/* Transmit Status - 0x00b0 */
volatile u_char txStatus;
volatile u_char txAckQuality;
volatile u_char numRetries;
volatile u_char _5[14];
volatile u_char registeredRouter[6];
volatile u_char backboneRouter[6];
volatile u_char registrationStatus;
volatile u_char configuredStatusFlag;
volatile u_char _6[1];
volatile u_char ultimateDestAddress[6];
volatile u_char immedDestAddress[6];
volatile u_char immedSrcAddress[6];
volatile u_short rxSequenceNumber;
volatile u_char assignedLocaltalkAddress;
volatile u_char _7[27];
/* System Parameter Block */
/* - Driver Parameters (Novell Specific) */
volatile u_short txTimeout;
volatile u_short transportTime;
volatile u_char _8[4];
/* - Configuration Parameters */
volatile u_char irqLevel;
volatile u_char spreadingCode;
volatile u_char channelSet;
volatile u_char channelNumber;
volatile u_short radioNodeId;
volatile u_char _9[2];
volatile u_char scramblingDisable;
volatile u_char radioType;
volatile u_short routerId;
volatile u_char _10[9];
volatile u_char txAttenuation;
volatile u_char systemId[4];
volatile u_short globalChecksum;
volatile u_char _11[4];
volatile u_short maxDatagramSize;
volatile u_short maxFrameSize;
volatile u_char maxRetries;
volatile u_char receiveMode;
volatile u_char priority;
volatile u_char rootOrRepeater;
volatile u_char specifiedRouter[6];
volatile u_short fastPollPeriod;
volatile u_char pollDecay;
volatile u_char fastPollDelay[2];
volatile u_char arlThreshold;
volatile u_char arlDecay;
volatile u_char _12[1];
volatile u_short specRouterTimeout;
volatile u_char _13[5];
/* Scrambled Area */
volatile u_char SID[4];
volatile u_char encryptionKey[12];
volatile u_char _14[2];
volatile u_char waitTime[2];
volatile u_char lParameter[2];
volatile u_char _15[3];
volatile u_short headerSize;
volatile u_short sectionChecksum;
volatile u_char registrationMode;
volatile u_char registrationFill;
volatile u_short pollPeriod;
volatile u_short refreshPeriod;
volatile u_char name[16];
volatile u_char NID[6];
volatile u_char localTalkAddress;
volatile u_char codeFormat;
volatile u_char numChannels;
volatile u_char channel1;
volatile u_char channel2;
volatile u_char channel3;
volatile u_char channel4;
volatile u_char SSCode[59];
volatile u_char _16[0xC0];
volatile u_short auxCmd;
volatile u_char dumpPtr[4];
volatile u_char dumpVal;
volatile u_char _17[0x6A];
volatile u_char wireTest;
volatile u_char _18[14];
/* Statistics Block - 0x0300 */
volatile u_char hostcpuLock;
volatile u_char lancpuLock;
volatile u_char resetTime[18];
volatile u_char numDatagramsTransmitted[4];
volatile u_char numReTransmissions[4];
volatile u_char numFramesDiscarded[4];
volatile u_char numDatagramsReceived[4];
volatile u_char numDuplicateReceivedFrames[4];
volatile u_char numDatagramsDiscarded[4];
volatile u_short maxNumReTransmitDatagram;
volatile u_short maxNumReTransmitFrames;
volatile u_short maxNumConsecutiveDuplicateFrames;
/* misaligned here so we have to go to characters */
volatile u_char numBytesTransmitted[4];
volatile u_char numBytesReceived[4];
volatile u_char numCRCErrors[4];
volatile u_char numLengthErrors[4];
volatile u_char numAbortErrors[4];
volatile u_char numTXUnderruns[4];
volatile u_char numRXOverruns[4];
volatile u_char numHoldOffs[4];
volatile u_char numFramesTransmitted[4];
volatile u_char numFramesReceived[4];
volatile u_char numReceiveFramesLost[4];
volatile u_char numRXBufferOverflows[4];
volatile u_char numFramesDiscardedAddrMismatch[4];
volatile u_char numFramesDiscardedSIDMismatch[4];
volatile u_char numPollsTransmistted[4];
volatile u_char numPollAcknowledges[4];
volatile u_char numStatusTimeouts[4];
volatile u_char numNACKReceived[4];
volatile u_char _19[0x86];
volatile u_char txBuffer[0x800];
volatile u_char rxBuffer[0x800];
volatile u_char _20[0x800];
volatile u_char _21[0x3fb];
volatile u_char configStatus;
volatile u_char _22;
volatile u_char progIOCtrl;
volatile u_char shareMBase;
volatile u_char controlRegister;
};
struct arlan_conf_stru {
int spreadingCode;
int channelSet;
int channelNumber;
int scramblingDisable;
int txAttenuation;
int systemId;
int maxDatagramSize;
int maxFrameSize;
int maxRetries;
int receiveMode;
int priority;
int rootOrRepeater;
int SID;
int radioNodeId;
int registrationMode;
int registrationFill;
int localTalkAddress;
int codeFormat;
int numChannels;
int channel1;
int channel2;
int channel3;
int channel4;
int txClear;
int txRetries;
int txRouting;
int txScrambled;
int rxParameter;
int txTimeoutMs;
int txAckTimeoutMs;
int waitCardTimeout;
int waitTime;
int lParameter;
int _15;
int headerSize;
int retries;
int tx_delay_ms;
int waitReTransmitPacketMaxSize;
int ReTransmitPacketMaxSize;
int fastReTransCount;
int driverRetransmissions;
int registrationInterrupts;
int hardwareType;
int radioType;
int writeRadioType;
int writeEEPROM;
char siteName[17];
int measure_rate;
int in_speed;
int out_speed;
int in_speed10;
int out_speed10;
int in_speed_max;
int out_speed_max;
int pre_Command_Wait;
int rx_tweak1;
int rx_tweak2;
int tx_queue_len;
};
extern struct arlan_conf_stru arlan_conf[MAX_ARLANS];
struct TxParam {
volatile short offset;
volatile short length;
volatile u_char dest[6];
volatile unsigned char clear;
volatile unsigned char retries;
volatile unsigned char routing;
volatile unsigned char scrambled;
};
#define TX_RING_SIZE 2
/* Information that need to be kept for each board. */
struct arlan_private {
struct arlan_shmem __iomem *card;
struct arlan_shmem *conf;
struct arlan_conf_stru *Conf;
int bad;
int reset;
unsigned long lastReset;
struct timer_list timer;
struct timer_list tx_delay_timer;
struct timer_list tx_retry_timer;
struct timer_list rx_check_timer;
int registrationLostCount;
int reRegisterExp;
int irq_test_done;
struct TxParam txRing[TX_RING_SIZE];
char reTransmitBuff[0x800];
int txLast;
unsigned ReTransmitRequested;
unsigned long tx_done_delayed;
unsigned long registrationLastSeen;
unsigned long tx_last_sent;
unsigned long tx_last_cleared;
unsigned long retransmissions;
unsigned long interrupt_ack_requested;
spinlock_t lock;
unsigned long waiting_command_mask;
unsigned long card_polling_interval;
unsigned long last_command_buff_free_time;
int under_reset;
int under_config;
int rx_command_given;
int tx_command_given;
unsigned long interrupt_processing_active;
unsigned long last_rx_int_ack_time;
unsigned long in_bytes;
unsigned long out_bytes;
unsigned long in_time;
unsigned long out_time;
unsigned long in_time10;
unsigned long out_time10;
unsigned long in_bytes10;
unsigned long out_bytes10;
int init_etherdev_alloc;
};
#define ARLAN_CLEAR 0x00
#define ARLAN_RESET 0x01
#define ARLAN_CHANNEL_ATTENTION 0x02
#define ARLAN_INTERRUPT_ENABLE 0x04
#define ARLAN_CLEAR_INTERRUPT 0x08
#define ARLAN_POWER 0x40
#define ARLAN_ACCESS 0x80
#define ARLAN_COM_CONF 0x01
#define ARLAN_COM_RX_ENABLE 0x03
#define ARLAN_COM_RX_ABORT 0x04
#define ARLAN_COM_TX_ENABLE 0x05
#define ARLAN_COM_TX_ABORT 0x06
#define ARLAN_COM_NOP 0x07
#define ARLAN_COM_STANDBY 0x08
#define ARLAN_COM_ACTIVATE 0x09
#define ARLAN_COM_GOTO_SLOW_POLL 0x0a
#define ARLAN_COM_INT 0x80
#define TXLAST(dev) (((struct arlan_private *)netdev_priv(dev))->txRing[((struct arlan_private *)netdev_priv(dev))->txLast])
#define TXHEAD(dev) (((struct arlan_private *)netdev_priv(dev))->txRing[0])
#define TXTAIL(dev) (((struct arlan_private *)netdev_priv(dev))->txRing[1])
#define TXBuffStart(dev) offsetof(struct arlan_shmem, txBuffer)
#define TXBuffEnd(dev) offsetof(struct arlan_shmem, xxBuffer)
#define READSHM(to, from, atype) {\
atype tmp;\
memcpy_fromio(&(tmp), &(from), sizeof(atype));\
to = tmp;\
}
#define READSHMEM(from, atype)\
atype from; \
READSHM(from, arlan->from, atype);
#define WRITESHM(to, from, atype) \
{ atype tmpSHM = from;\
memcpy_toio(&(to), &tmpSHM, sizeof(atype));\
}
#define DEBUGSHM(levelSHM, stringSHM, stuff, atype) \
{ atype tmpSHM; \
memcpy_fromio(&tmpSHM, &(stuff), sizeof(atype));\
IFDEBUG(levelSHM) printk(stringSHM, tmpSHM);\
}
#define WRITESHMB(to, val) \
writeb(val, &(to))
#define READSHMB(to) \
readb(&(to))
#define WRITESHMS(to, val) \
writew(val, &(to))
#define READSHMS(to) \
readw(&(to))
#define WRITESHMI(to, val) \
writel(val, &(to))
#define READSHMI(to) \
readl(&(to))
#define registrationBad(dev)\
(( READSHMB(((struct arlan_private *)netdev_priv(dev))->card->registrationMode) > 0) && \
( READSHMB(((struct arlan_private *)netdev_priv(dev))->card->registrationStatus) == 0))
#define readControlRegister(dev)\
READSHMB(((struct arlan_private *)netdev_priv(dev))->card->cntrlRegImage)
#define writeControlRegister(dev, v) {\
WRITESHMB(((struct arlan_private *)netdev_priv(dev))->card->cntrlRegImage, ((v) & 0xF));\
WRITESHMB(((struct arlan_private *)netdev_priv(dev))->card->controlRegister, (v)); }
#define arlan_interrupt_lancpu(dev) {\
int cr; \
\
cr = readControlRegister(dev);\
if (cr & ARLAN_CHANNEL_ATTENTION) { \
writeControlRegister(dev, (cr & ~ARLAN_CHANNEL_ATTENTION));\
} else \
writeControlRegister(dev, (cr | ARLAN_CHANNEL_ATTENTION));\
}
#define clearChannelAttention(dev) { \
writeControlRegister(dev, readControlRegister(dev) & ~ARLAN_CHANNEL_ATTENTION); }
#define setHardwareReset(dev) {\
writeControlRegister(dev, readControlRegister(dev) | ARLAN_RESET); }
#define clearHardwareReset(dev) {\
writeControlRegister(dev, readControlRegister(dev) & ~ARLAN_RESET); }
#define setInterruptEnable(dev) {\
writeControlRegister(dev, readControlRegister(dev) | ARLAN_INTERRUPT_ENABLE) ; }
#define clearInterruptEnable(dev) {\
writeControlRegister(dev, readControlRegister(dev) & ~ARLAN_INTERRUPT_ENABLE) ; }
#define setClearInterrupt(dev) {\
writeControlRegister(dev, readControlRegister(dev) | ARLAN_CLEAR_INTERRUPT) ; }
#define clearClearInterrupt(dev) {\
writeControlRegister(dev, readControlRegister(dev) & ~ARLAN_CLEAR_INTERRUPT); }
#define setPowerOff(dev) {\
writeControlRegister(dev, readControlRegister(dev) | (ARLAN_POWER && ARLAN_ACCESS));\
writeControlRegister(dev, readControlRegister(dev) & ~ARLAN_ACCESS); }
#define setPowerOn(dev) {\
writeControlRegister(dev, readControlRegister(dev) & ~(ARLAN_POWER)); }
#define arlan_lock_card_access(dev) {\
writeControlRegister(dev, readControlRegister(dev) & ~ARLAN_ACCESS); }
#define arlan_unlock_card_access(dev) {\
writeControlRegister(dev, readControlRegister(dev) | ARLAN_ACCESS); }
#define ARLAN_COMMAND_RX 0x000001
#define ARLAN_COMMAND_NOOP 0x000002
#define ARLAN_COMMAND_NOOPINT 0x000004
#define ARLAN_COMMAND_TX 0x000008
#define ARLAN_COMMAND_CONF 0x000010
#define ARLAN_COMMAND_RESET 0x000020
#define ARLAN_COMMAND_TX_ABORT 0x000040
#define ARLAN_COMMAND_RX_ABORT 0x000080
#define ARLAN_COMMAND_POWERDOWN 0x000100
#define ARLAN_COMMAND_POWERUP 0x000200
#define ARLAN_COMMAND_SLOW_POLL 0x000400
#define ARLAN_COMMAND_ACTIVATE 0x000800
#define ARLAN_COMMAND_INT_ACK 0x001000
#define ARLAN_COMMAND_INT_ENABLE 0x002000
#define ARLAN_COMMAND_WAIT_NOW 0x004000
#define ARLAN_COMMAND_LONG_WAIT_NOW 0x008000
#define ARLAN_COMMAND_STANDBY 0x010000
#define ARLAN_COMMAND_INT_RACK 0x020000
#define ARLAN_COMMAND_INT_RENABLE 0x040000
#define ARLAN_COMMAND_CONF_WAIT 0x080000
#define ARLAN_COMMAND_TBUSY_CLEAR 0x100000
#define ARLAN_COMMAND_CLEAN_AND_CONF (ARLAN_COMMAND_TX_ABORT\
| ARLAN_COMMAND_RX_ABORT\
| ARLAN_COMMAND_CONF)
#define ARLAN_COMMAND_CLEAN_AND_RESET (ARLAN_COMMAND_TX_ABORT\
| ARLAN_COMMAND_RX_ABORT\
| ARLAN_COMMAND_RESET)
#define ARLAN_DEBUG_CHAIN_LOCKS 0x00001
#define ARLAN_DEBUG_RESET 0x00002
#define ARLAN_DEBUG_TIMING 0x00004
#define ARLAN_DEBUG_CARD_STATE 0x00008
#define ARLAN_DEBUG_TX_CHAIN 0x00010
#define ARLAN_DEBUG_MULTICAST 0x00020
#define ARLAN_DEBUG_HEADER_DUMP 0x00040
#define ARLAN_DEBUG_INTERRUPT 0x00080
#define ARLAN_DEBUG_STARTUP 0x00100
#define ARLAN_DEBUG_SHUTDOWN 0x00200

View file

@ -771,7 +771,7 @@ static struct usb_driver oled_driver = {
};
static CLASS_ATTR_STRING(version, S_IRUGO,
ASUS_OLED_UNDERSCORE_NAME " " ASUS_OLED_VERSION);
ASUS_OLED_UNDERSCORE_NAME " " ASUS_OLED_VERSION);
static int __init asus_oled_init(void)
{

View file

@ -1,3 +1,17 @@
batman-adv 0.2.1:
* support latest kernels (2.6.20 - 2.6.33)
* receive packets directly using skbs, remove old sockets and threads
* fix various regressions in the vis server
* don't disable interrupts while sending
* replace internal logging mechanism with standard kernel logging
* move vis formats into userland, one general format remains in the kernel
* allow MAC address to be set, correctly initialize them
* code refactoring and cleaning for coding style
* many bugs (null pointers, locking, hash iterators) squashed
-- Sun, 21 Mar 2010 20:46:47 +0100
batman-adv 0.2:
* support latest kernels (2.6.20 - 2.6.31)

View file

@ -1,5 +1,5 @@
#
# Copyright (C) 2007-2009 B.A.T.M.A.N. contributors:
# Copyright (C) 2007-2010 B.A.T.M.A.N. contributors:
#
# Marek Lindner, Simon Wunderlich
#
@ -19,4 +19,4 @@
#
obj-m += batman-adv.o
batman-adv-objs := main.o proc.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
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

View file

@ -1,149 +1,240 @@
[state: 06-01-2010]
[state: 03-05-2010]
BATMAN-ADV
----------
Batman-advanced is a new approach to wireless networking which does no longer
operate on the IP basis. Unlike B.A.T.M.A.N, which exchanges information
using UDP packets and sets routing tables, batman-advanced operates on ISO/OSI
Layer 2 only and uses and routes (or better: bridges) Ethernet Frames. It
emulates a virtual network switch of all nodes participating. Therefore all
nodes appear to be link local, thus all higher operating protocols won't be
affected by any changes within the network. You can run almost any protocol
above B.A.T.M.A.N. Advanced, prominent examples are: IPv4, IPv6, DHCP, IPX.
Batman advanced is a new approach to wireless networking which
does no longer operate on the IP basis. Unlike the batman daemon,
which exchanges information using UDP packets and sets routing
tables, batman-advanced operates on ISO/OSI Layer 2 only and uses
and routes (or better: bridges) Ethernet Frames. It emulates a
virtual network switch of all nodes participating. Therefore all
nodes appear to be link local, thus all higher operating proto-
cols won't be affected by any changes within the network. You can
run almost any protocol above batman advanced, prominent examples
are: IPv4, IPv6, DHCP, IPX.
Batman advanced was implemented as a Linux kernel driver to re-
duce the overhead to a minimum. It does not depend on any (other)
network driver, and can be used on wifi as well as ethernet lan,
vpn, etc ... (anything with ethernet-style layer 2).
CONFIGURATION
-------------
Load the batman-adv module into your kernel:
# insmod batman-adv.ko
The module is now waiting for activation. You must add some in-
terfaces on which batman can operate. After loading the module
batman advanced will scan your systems interfaces to search for
compatible interfaces. Once found, it will create subfolders in
the /sys directories of each supported interface, e.g.
# ls /sys/class/net/eth0/batman_adv/
# iface_status mesh_iface
If an interface does not have the "batman_adv" subfolder it prob-
ably is not supported. Not supported interfaces are: loopback,
non-ethernet and batman's own interfaces.
Note: After the module was loaded it will continuously watch for
new interfaces to verify the compatibility. There is no need to
reload the module if you plug your USB wifi adapter into your ma-
chine after batman advanced was initially loaded.
To activate a given interface simply write "bat0" into its
"mesh_iface" file inside the batman_adv subfolder:
# echo bat0 > /sys/class/net/eth0/batman_adv/mesh_iface
Repeat this step for all interfaces you wish to add. Now batman
starts using/broadcasting on this/these interface(s).
By reading the "iface_status" file you can check its status:
# cat /sys/class/net/eth0/batman_adv/iface_status
# active
To deactivate an interface you have to write "none" into its
"mesh_iface" file:
# echo none > /sys/class/net/eth0/batman_adv/mesh_iface
All mesh wide settings can be found in batman's own interface
folder:
# ls /sys/class/net/bat0/mesh/
# aggregate_ogm originators transtable_global vis_mode
# orig_interval transtable_local vis_data
Some of the files contain all sort of status information regard-
ing the mesh network. For example, you can view the table of
originators (mesh participants) with:
# cat /sys/class/net/bat0/mesh/originators
Other files allow to change batman's behaviour to better fit your
requirements. For instance, you can check the current originator
interval (value in milliseconds which determines how often batman
sends its broadcast packets):
# cat /sys/class/net/bat0/mesh/orig_interval
# status: 1000
and also change its value:
# echo 3000 > /sys/class/net/bat0/mesh/orig_interval
In very mobile scenarios, you might want to adjust the originator
interval to a lower value. This will make the mesh more respon-
sive to topology changes, but will also increase the overhead.
This is batman-advanced implemented as Linux kernel driver. It does not depend
on any network (other) driver, and can be used on wifi as well as ethernet,
vpn, etc ... (anything with ethernet-style layer 2).
USAGE
-----
insmod the batman-adv.ko in your kernel:
To make use of your newly created mesh, batman advanced provides
a new interface "bat0" which you should use from this point on.
All interfaces added to batman advanced are not relevant any
longer because batman handles them for you. Basically, one "hands
over" the data by using the batman interface and batman will make
sure it reaches its destination.
# insmod batman-adv.ko
The "bat0" interface can be used like any other regular inter-
face. It needs an IP address which can be either statically con-
figured or dynamically (by using DHCP or similar services):
the module is now waiting for activation. You must add some interfaces
on which batman can operate. Each interface must be added separately:
# NodeA: ifconfig bat0 192.168.0.1
# NodeB: ifconfig bat0 192.168.0.2
# NodeB: ping 192.168.0.1
# echo wlan0 > /proc/net/batman-adv/interfaces
Note: In order to avoid problems remove all IP addresses previ-
ously assigned to interfaces now used by batman advanced, e.g.
( # echo wlan1 > /proc/net/batman-adv/interfaces )
( # echo eth0 > /proc/net/batman-adv/interfaces )
( ... )
# ifconfig eth0 0.0.0.0
Now batman starts broadcasting on this interface.
You can now view the table of originators (mesh participants) with:
# cat /proc/net/batman-adv/originators
VISUALIZATION
-------------
The module will create a new interface "bat0", which can be used as a
regular interface:
If you want topology visualization, at least one mesh node must
be configured as VIS-server:
# ifconfig bat0 inet 192.168.0.1 up
# ping 192.168.0.2
...
# echo "server" > /sys/class/net/bat0/mesh/vis_mode
If you want topology visualization, your meshnode must be configured
as VIS-server:
Each node is either configured as "server" or as "client" (de-
fault: "client"). Clients send their topology data to the server
next to them, and server synchronize with other servers. If there
is no server configured (default) within the mesh, no topology
information will be transmitted. With these "synchronizing
servers", there can be 1 or more vis servers sharing the same (or
at least very similar) data.
# echo "server" > /proc/net/batman-adv/vis
When configured as server, you can get a topology snapshot of
your mesh:
Each node is either configured as "server" or as "client" (default:
"client"). Clients send their topology data to the server next to them,
and server synchronize with other servers. If there is no server
configured (default) within the mesh, no topology information will be
transmitted. With these "synchronizing servers", there can be 1 or
more vis servers sharing the same (or at least very similar) data.
# cat /sys/class/net/bat0/mesh/vis_data
When configured as server, you can get a topology snapshot of your mesh:
This raw output is intended to be easily parsable and convertable
with other tools. Have a look at the batctl README if you want a
vis output in dot or json format for instance and how those out-
puts could then be visualised in an image.
# cat /proc/net/batman-adv/vis
The raw format consists of comma separated values per entry where
each entry is giving information about a certain source inter-
face. Each entry can/has to have the following values:
-> "mac" - mac address of an originator's source interface
(each line begins with it)
-> "TQ mac value" - src mac's link quality towards mac address
of a neighbor originator's interface which
is being used for routing
-> "HNA mac" - HNA announced by source mac
-> "PRIMARY" - this is a primary interface
-> "SEC mac" - secondary mac address of source
(requires preceding PRIMARY)
The output is in a generic raw format. Use the batctl tool (See below)
to convert this to other formats more suitable for graphing, eg
graphviz dot, or JSON data-interchange format.
The TQ value has a range from 4 to 255 with 255 being the best.
The HNA entries are showing which hosts are connected to the mesh
via bat0 or being bridged into the mesh network. The PRIMARY/SEC
values are only applied on primary interfaces
In very mobile scenarios, you might want to adjust the originator
interval to a lower value. This will make the mesh more responsive to
topology changes, but will also increase the overhead. Please make sure
that all nodes in your mesh use the same interval. The default value
is 1000 ms (1 second).
# echo 1000 > /proc/net/batman-adv/orig_interval
To deactivate batman, do:
# echo "" > /proc/net/batman-adv/interfaces
LOGGING/DEBUGGING
-----------------
All error messages, warnings and information messages are sent to the
kernel log. Depending on your operating system distribution this can be
read in one of a number of ways. Try using the commands: dmesg,
logread, or looking in the files /var/log/kern.log or
/var/log/syslog. All batman-adv messages are prefixed with
All error messages, warnings and information messages are sent to
the kernel log. Depending on your operating system distribution
this can be read in one of a number of ways. Try using the com-
mands: dmesg, logread, or looking in the files /var/log/kern.log
or /var/log/syslog. All batman-adv messages are prefixed with
"batman-adv:" So to see just these messages try
dmesg | grep batman-adv
# dmesg | grep batman-adv
When investigating problems with your mesh network it is sometimes
necessary to see more detail debug messages. This must be enabled when
compiling the batman-adv module. Use "make menuconfig" and enable the
When investigating problems with your mesh network it is some-
times necessary to see more detail debug messages. This must be
enabled when compiling the batman-adv module. When building bat-
man-adv as part of kernel, use "make menuconfig" and enable the
option "B.A.T.M.A.N. debugging".
The additional debug output is by default disabled. It can be enabled
either at kernel module load time or during run time. To enable debug
output at module load time, add the module parameter debug=<value>.
<value> can take one of four values.
The additional debug output is by default disabled. It can be en-
abled either at kernel modules load time or during run time. To
enable debug output at module load time, add the module parameter
debug=<value>. <value> can take one of four values.
0 - All debug output disabled
0 - All debug output disabled
1 - Enable messages related to routing / flooding / broadcasting
2 - Enable route or hna added / changed / deleted
3 - Enable all messages
e.g.
modprobe batman-adv debug=2
# modprobe batman-adv debug=2
will load the module and enable debug messages for when routes or HNAs
change.
will load the module and enable debug messages for when routes or
HNAs change.
The debug output can also be changed at runtime using the file
The debug output can also be changed at runtime using the file
/sys/module/batman-adv/parameters/debug. e.g.
echo 2 > /sys/module/batman-adv/parameters/debug
# echo 2 > /sys/module/batman-adv/parameters/debug
enables debug messages for when routes or HNAs
The debug output is sent to the kernel logs. So try dmesg, logread etc
to see the debug messages.
The debug output is sent to the kernel logs. So try dmesg, lo-
gread, etc to see the debug messages.
BATCTL
------
B.A.T.M.A.N. advanced operates on layer 2 and thus all hosts
participating in the virtual switch are completely transparent for all
protocols above layer 2. Therefore the common diagnosis tools do not
work as expected. To overcome these problems batctl was created. At
the moment the batctl contains ping, traceroute, tcpdump and
As batman advanced operates on layer 2 all hosts participating in
the virtual switch are completely transparent for all protocols
above layer 2. Therefore the common diagnosis tools do not work
as expected. To overcome these problems batctl was created. At
the moment the batctl contains ping, traceroute, tcpdump and
interfaces to the kernel module settings.
For more information, please see the manpage (man batctl).
batctl is available on http://www.open-mesh.net/
batctl is available on http://www.open-mesh.org/
CONTACT
-------
Please send us comments, experiences, questions, anything :)
IRC: #batman on irc.freenode.org
Mailing-list: b.a.t.m.a.n@open-mesh.net
(subscription at https://list.open-mesh.net/mm/listinfo/b.a.t.m.a.n )
IRC: #batman on irc.freenode.org
Mailing-list: b.a.t.m.a.n@open-mesh.net (optional subscription
at https://lists.open-mesh.org/mm/listinfo/b.a.t.m.a.n)
You can also contact the Authors:
Marek Lindner <lindner_marek@yahoo.de>
Simon Wunderlich <siwu@hrz.tu-chemnitz.de>
Marek Lindner <lindner_marek@yahoo.de>
Simon Wunderlich <siwu@hrz.tu-chemnitz.de>

View file

@ -1,23 +1,6 @@
=> proc interface
* implement new interface to add/delete interfaces and setting options
* /proc/sys/net/batman-adv/ as main folder
* in interfaces/ list every available interface of the host
* each interfaces/$iface/ contains the following files:
-> enable (def: 0) [add/remove this interface to batman-adv]
-> ogm_interval (def: 1000) [ogm interval of that interface]
-> context (def: bat0) [later we want to support multiple mesh instances via
-> bat0/bat1/bat2/..]
-> status (read-only) [outputs the interface status from batman's
-> perspective]
* in mesh/batX/ list every available mesh subnet
-> vis_server (def: 0) [enable/disable vis server for that mesh]
-> vis_data (read-only) [outputs the vis data in a raw format]
-> aggregate_ogm (def: 1) [enable/disable ogm aggregation for that mesh]
-> originators (read-only) [outputs the originator table]
-> transtable_global (read-only) [outputs the global translation table]
-> transtable_local (read-only) [outputs the local translation table]
=> fix checkpatch.pl errors
Request a review.
Process the comments from the review.
Move into mainline proper.
Please send all patches to:
Marek Lindner <lindner_marek@yahoo.de>

View file

@ -1,5 +1,5 @@
/*
* Copyright (C) 2007-2009 B.A.T.M.A.N. contributors:
* Copyright (C) 2007-2010 B.A.T.M.A.N. contributors:
*
* Marek Lindner, Simon Wunderlich
*
@ -52,6 +52,8 @@ static bool can_aggregate_with(struct batman_packet *new_batman_packet,
*/
if (time_before(send_time, forw_packet->send_time) &&
time_after_eq(send_time + msecs_to_jiffies(MAX_AGGREGATION_MS),
forw_packet->send_time) &&
(aggregated_bytes <= MAX_AGGREGATION_BYTES)) {
/**
@ -79,14 +81,21 @@ static bool can_aggregate_with(struct batman_packet *new_batman_packet,
* interface only - we still can aggregate */
if ((directlink) &&
(new_batman_packet->ttl == 1) &&
(forw_packet->if_incoming == if_incoming))
return true;
(forw_packet->if_incoming == if_incoming) &&
/* packets from direct neighbors or
* own secondary interface packets
* (= secondary interface packets in general) */
(batman_packet->flags & DIRECTLINK ||
(forw_packet->own &&
forw_packet->if_incoming->if_num != 0)))
return true;
}
return false;
}
#define atomic_dec_not_zero(v) atomic_add_unless((v), -1, 0)
/* create a new aggregated packet and add this packet to it */
static void new_aggregated_packet(unsigned char *packet_buff,
int packet_len,
@ -98,13 +107,26 @@ static void new_aggregated_packet(unsigned char *packet_buff,
struct forw_packet *forw_packet_aggr;
unsigned long flags;
/* own packet should always be scheduled */
if (!own_packet) {
if (!atomic_dec_not_zero(&batman_queue_left)) {
bat_dbg(DBG_BATMAN, "batman packet queue full\n");
return;
}
}
forw_packet_aggr = kmalloc(sizeof(struct forw_packet), GFP_ATOMIC);
if (!forw_packet_aggr)
if (!forw_packet_aggr) {
if (!own_packet)
atomic_inc(&batman_queue_left);
return;
}
forw_packet_aggr->packet_buff = kmalloc(MAX_AGGREGATION_BYTES,
GFP_ATOMIC);
if (!forw_packet_aggr->packet_buff) {
if (!own_packet)
atomic_inc(&batman_queue_left);
kfree(forw_packet_aggr);
return;
}
@ -157,7 +179,8 @@ static void aggregate(struct forw_packet *forw_packet_aggr,
(1 << forw_packet_aggr->num_packets);
}
void add_bat_packet_to_list(unsigned char *packet_buff, int packet_len,
void add_bat_packet_to_list(struct bat_priv *bat_priv,
unsigned char *packet_buff, int packet_len,
struct batman_if *if_incoming, char own_packet,
unsigned long send_time)
{
@ -175,7 +198,7 @@ void add_bat_packet_to_list(unsigned char *packet_buff, int packet_len,
/* find position for the packet in the forward queue */
spin_lock_irqsave(&forw_bat_list_lock, flags);
/* own packets are not to be aggregated */
if ((atomic_read(&aggregation_enabled)) && (!own_packet)) {
if ((atomic_read(&bat_priv->aggregation_enabled)) && (!own_packet)) {
hlist_for_each_entry(forw_packet_pos, tmp_node, &forw_bat_list,
list) {
if (can_aggregate_with(batman_packet,
@ -195,6 +218,16 @@ void add_bat_packet_to_list(unsigned char *packet_buff, int packet_len,
if (forw_packet_aggr == NULL) {
/* the following section can run without the lock */
spin_unlock_irqrestore(&forw_bat_list_lock, flags);
/**
* if we could not aggregate this packet with one of the others
* we hold it back for a while, so that it might be aggregated
* later on
*/
if ((!own_packet) &&
(atomic_read(&bat_priv->aggregation_enabled)))
send_time += msecs_to_jiffies(MAX_AGGREGATION_MS);
new_aggregated_packet(packet_buff, packet_len,
send_time, direct_link,
if_incoming, own_packet);

View file

@ -1,5 +1,5 @@
/*
* Copyright (C) 2007-2009 B.A.T.M.A.N. contributors:
* Copyright (C) 2007-2010 B.A.T.M.A.N. contributors:
*
* Marek Lindner, Simon Wunderlich
*
@ -30,8 +30,9 @@ static inline int aggregated_packet(int buff_pos, int packet_len, int num_hna)
(next_buff_pos <= MAX_AGGREGATION_BYTES);
}
void add_bat_packet_to_list(unsigned char *packet_buff, int packet_len,
struct batman_if *if_outgoing, char own_packet,
void add_bat_packet_to_list(struct bat_priv *bat_priv,
unsigned char *packet_buff, int packet_len,
struct batman_if *if_incoming, char own_packet,
unsigned long send_time);
void receive_aggr_bat_packet(struct ethhdr *ethhdr, unsigned char *packet_buff,
int packet_len, struct batman_if *if_incoming);

View file

@ -0,0 +1,484 @@
/*
* 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 "bat_sysfs.h"
#include "translation-table.h"
#include "originator.h"
#include "hard-interface.h"
#include "vis.h"
#define to_dev(obj) container_of(obj, struct device, kobj)
struct bat_attribute {
struct attribute attr;
ssize_t (*show)(struct kobject *kobj, struct attribute *attr,
char *buf);
ssize_t (*store)(struct kobject *kobj, struct attribute *attr,
char *buf, size_t count);
};
struct hardif_attribute {
struct attribute attr;
ssize_t (*show)(struct kobject *kobj, struct attribute *attr,
char *buf);
ssize_t (*store)(struct kobject *kobj, struct attribute *attr,
char *buf, size_t count);
};
#define BAT_ATTR(_name, _mode, _show, _store) \
struct bat_attribute bat_attr_##_name = { \
.attr = {.name = __stringify(_name), \
.mode = _mode }, \
.show = _show, \
.store = _store, \
};
#define BAT_BIN_ATTR(_name, _mode, _read, _write) \
struct bin_attribute bat_attr_##_name = { \
.attr = { .name = __stringify(_name), \
.mode = _mode, }, \
.read = _read, \
.write = _write, \
};
#define HARDIF_ATTR(_name, _mode, _show, _store) \
struct hardif_attribute hardif_attr_##_name = { \
.attr = {.name = __stringify(_name), \
.mode = _mode }, \
.show = _show, \
.store = _store, \
};
static ssize_t show_aggr_ogm(struct kobject *kobj, struct attribute *attr,
char *buff)
{
struct device *dev = to_dev(kobj->parent);
struct bat_priv *bat_priv = netdev_priv(to_net_dev(dev));
int aggr_status = atomic_read(&bat_priv->aggregation_enabled);
return sprintf(buff, "status: %s\ncommands: enable, disable, 0, 1\n",
aggr_status == 0 ? "disabled" : "enabled");
}
static ssize_t store_aggr_ogm(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 aggr_tmp = -1;
if (((count == 2) && (buff[0] == '1')) ||
(strncmp(buff, "enable", 6) == 0))
aggr_tmp = 1;
if (((count == 2) && (buff[0] == '0')) ||
(strncmp(buff, "disable", 7) == 0))
aggr_tmp = 0;
if (aggr_tmp < 0) {
if (buff[count - 1] == '\n')
buff[count - 1] = '\0';
printk(KERN_INFO "batman-adv:Invalid parameter for 'aggregate OGM' setting on mesh %s received: %s\n",
net_dev->name, buff);
return -EINVAL;
}
if (atomic_read(&bat_priv->aggregation_enabled) == aggr_tmp)
return count;
printk(KERN_INFO "batman-adv:Changing aggregation from: %s to: %s on mesh: %s\n",
atomic_read(&bat_priv->aggregation_enabled) == 1 ?
"enabled" : "disabled", aggr_tmp == 1 ? "enabled" : "disabled",
net_dev->name);
atomic_set(&bat_priv->aggregation_enabled, (unsigned)aggr_tmp);
return count;
}
static ssize_t show_vis_mode(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 vis_mode = atomic_read(&bat_priv->vis_mode);
return sprintf(buff, "status: %s\ncommands: client, server, %d, %d\n",
vis_mode == VIS_TYPE_CLIENT_UPDATE ?
"client" : "server",
VIS_TYPE_SERVER_SYNC, VIS_TYPE_CLIENT_UPDATE);
}
static ssize_t store_vis_mode(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 val;
int ret, vis_mode_tmp = -1;
ret = strict_strtoul(buff, 10, &val);
if (((count == 2) && (!ret) && (val == VIS_TYPE_CLIENT_UPDATE)) ||
(strncmp(buff, "client", 6) == 0))
vis_mode_tmp = VIS_TYPE_CLIENT_UPDATE;
if (((count == 2) && (!ret) && (val == VIS_TYPE_SERVER_SYNC)) ||
(strncmp(buff, "server", 6) == 0))
vis_mode_tmp = VIS_TYPE_SERVER_SYNC;
if (vis_mode_tmp < 0) {
if (buff[count - 1] == '\n')
buff[count - 1] = '\0';
printk(KERN_INFO "batman-adv:Invalid parameter for 'vis mode' setting on mesh %s received: %s\n",
net_dev->name, buff);
return -EINVAL;
}
if (atomic_read(&bat_priv->vis_mode) == vis_mode_tmp)
return count;
printk(KERN_INFO "batman-adv:Changing vis mode from: %s to: %s on mesh: %s\n",
atomic_read(&bat_priv->vis_mode) == VIS_TYPE_CLIENT_UPDATE ?
"client" : "server", vis_mode_tmp == VIS_TYPE_CLIENT_UPDATE ?
"client" : "server", net_dev->name);
atomic_set(&bat_priv->vis_mode, (unsigned)vis_mode_tmp);
return count;
}
static ssize_t show_orig_interval(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));
return sprintf(buff, "status: %i\n",
atomic_read(&bat_priv->orig_interval));
}
static ssize_t store_orig_interval(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 orig_interval_tmp;
int ret;
ret = strict_strtoul(buff, 10, &orig_interval_tmp);
if (ret) {
printk(KERN_INFO "batman-adv:Invalid parameter for 'orig_interval' setting on mesh %s received: %s\n",
net_dev->name, buff);
return -EINVAL;
}
if (orig_interval_tmp <= JITTER * 2) {
printk(KERN_INFO "batman-adv:New originator interval too small: %li (min: %i)\n",
orig_interval_tmp, JITTER * 2);
return -EINVAL;
}
if (atomic_read(&bat_priv->orig_interval) == orig_interval_tmp)
return count;
printk(KERN_INFO "batman-adv:Changing originator interval from: %i to: %li on mesh: %s\n",
atomic_read(&bat_priv->orig_interval),
orig_interval_tmp, net_dev->name);
atomic_set(&bat_priv->orig_interval, orig_interval_tmp);
return count;
}
static BAT_ATTR(aggregate_ogm, S_IRUGO | S_IWUSR,
show_aggr_ogm, store_aggr_ogm);
static BAT_ATTR(vis_mode, S_IRUGO | S_IWUSR, show_vis_mode, store_vis_mode);
static BAT_ATTR(orig_interval, S_IRUGO | S_IWUSR,
show_orig_interval, store_orig_interval);
static struct bat_attribute *mesh_attrs[] = {
&bat_attr_aggregate_ogm,
&bat_attr_vis_mode,
&bat_attr_orig_interval,
NULL,
};
static ssize_t transtable_local_read(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 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 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 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,
};
int sysfs_add_meshif(struct net_device *dev)
{
struct kobject *batif_kobject = &dev->dev.kobj;
struct bat_priv *bat_priv = netdev_priv(dev);
struct bat_attribute **bat_attr;
struct bin_attribute **bin_attr;
int err;
/* FIXME: should be done in the general mesh setup
routine as soon as we have it */
atomic_set(&bat_priv->aggregation_enabled, 1);
atomic_set(&bat_priv->vis_mode, VIS_TYPE_CLIENT_UPDATE);
atomic_set(&bat_priv->orig_interval, 1000);
bat_priv->primary_if = NULL;
bat_priv->num_ifaces = 0;
bat_priv->mesh_obj = kobject_create_and_add(SYSFS_IF_MESH_SUBDIR,
batif_kobject);
if (!bat_priv->mesh_obj) {
printk(KERN_ERR "batman-adv:Can't add sysfs directory: %s/%s\n",
dev->name, SYSFS_IF_MESH_SUBDIR);
goto out;
}
for (bat_attr = mesh_attrs; *bat_attr; ++bat_attr) {
err = sysfs_create_file(bat_priv->mesh_obj,
&((*bat_attr)->attr));
if (err) {
printk(KERN_ERR "batman-adv:Can't add sysfs file: %s/%s/%s\n",
dev->name, SYSFS_IF_MESH_SUBDIR,
((*bat_attr)->attr).name);
goto rem_attr;
}
}
for (bin_attr = mesh_bin_attrs; *bin_attr; ++bin_attr) {
err = sysfs_create_bin_file(bat_priv->mesh_obj, (*bin_attr));
if (err) {
printk(KERN_ERR "batman-adv:Can't add sysfs file: %s/%s/%s\n",
dev->name, SYSFS_IF_MESH_SUBDIR,
((*bin_attr)->attr).name);
goto rem_bin_attr;
}
}
return 0;
rem_bin_attr:
for (bin_attr = mesh_bin_attrs; *bin_attr; ++bin_attr)
sysfs_remove_bin_file(bat_priv->mesh_obj, (*bin_attr));
rem_attr:
for (bat_attr = mesh_attrs; *bat_attr; ++bat_attr)
sysfs_remove_file(bat_priv->mesh_obj, &((*bat_attr)->attr));
kobject_put(bat_priv->mesh_obj);
bat_priv->mesh_obj = NULL;
out:
return -ENOMEM;
}
void sysfs_del_meshif(struct net_device *dev)
{
struct bat_priv *bat_priv = netdev_priv(dev);
struct bat_attribute **bat_attr;
struct bin_attribute **bin_attr;
for (bin_attr = mesh_bin_attrs; *bin_attr; ++bin_attr)
sysfs_remove_bin_file(bat_priv->mesh_obj, (*bin_attr));
for (bat_attr = mesh_attrs; *bat_attr; ++bat_attr)
sysfs_remove_file(bat_priv->mesh_obj, &((*bat_attr)->attr));
kobject_put(bat_priv->mesh_obj);
bat_priv->mesh_obj = NULL;
}
static ssize_t show_mesh_iface(struct kobject *kobj, struct attribute *attr,
char *buff)
{
struct device *dev = to_dev(kobj->parent);
struct net_device *net_dev = to_net_dev(dev);
struct batman_if *batman_if = get_batman_if_by_netdev(net_dev);
if (!batman_if)
return 0;
return sprintf(buff, "status: %s\ncommands: none, bat0\n",
batman_if->if_status == IF_NOT_IN_USE ?
"none" : "bat0");
}
static ssize_t store_mesh_iface(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 batman_if *batman_if = get_batman_if_by_netdev(net_dev);
int status_tmp = -1;
if (!batman_if)
return count;
if (strncmp(buff, "none", 4) == 0)
status_tmp = IF_NOT_IN_USE;
if (strncmp(buff, "bat0", 4) == 0)
status_tmp = IF_I_WANT_YOU;
if (status_tmp < 0) {
if (buff[count - 1] == '\n')
buff[count - 1] = '\0';
printk(KERN_ERR "batman-adv:Invalid parameter for 'mesh_iface' setting received: %s\n",
buff);
return -EINVAL;
}
if ((batman_if->if_status == status_tmp) ||
((status_tmp == IF_I_WANT_YOU) &&
(batman_if->if_status != IF_NOT_IN_USE)))
return count;
if (status_tmp == IF_I_WANT_YOU)
status_tmp = hardif_enable_interface(batman_if);
else
hardif_disable_interface(batman_if);
return (status_tmp < 0 ? status_tmp : count);
}
static ssize_t show_iface_status(struct kobject *kobj, struct attribute *attr,
char *buff)
{
struct device *dev = to_dev(kobj->parent);
struct net_device *net_dev = to_net_dev(dev);
struct batman_if *batman_if = get_batman_if_by_netdev(net_dev);
if (!batman_if)
return 0;
switch (batman_if->if_status) {
case IF_TO_BE_REMOVED:
return sprintf(buff, "disabling\n");
case IF_INACTIVE:
return sprintf(buff, "inactive\n");
case IF_ACTIVE:
return sprintf(buff, "active\n");
case IF_TO_BE_ACTIVATED:
return sprintf(buff, "enabling\n");
case IF_NOT_IN_USE:
default:
return sprintf(buff, "not in use\n");
}
}
static HARDIF_ATTR(mesh_iface, S_IRUGO | S_IWUSR,
show_mesh_iface, store_mesh_iface);
static HARDIF_ATTR(iface_status, S_IRUGO, show_iface_status, NULL);
static struct hardif_attribute *batman_attrs[] = {
&hardif_attr_mesh_iface,
&hardif_attr_iface_status,
NULL,
};
int sysfs_add_hardif(struct kobject **hardif_obj, struct net_device *dev)
{
struct kobject *hardif_kobject = &dev->dev.kobj;
struct hardif_attribute **hardif_attr;
int err;
*hardif_obj = kobject_create_and_add(SYSFS_IF_BAT_SUBDIR,
hardif_kobject);
if (!*hardif_obj) {
printk(KERN_ERR "batman-adv:Can't add sysfs directory: %s/%s\n",
dev->name, SYSFS_IF_BAT_SUBDIR);
goto out;
}
for (hardif_attr = batman_attrs; *hardif_attr; ++hardif_attr) {
err = sysfs_create_file(*hardif_obj, &((*hardif_attr)->attr));
if (err) {
printk(KERN_ERR "batman-adv:Can't add sysfs file: %s/%s/%s\n",
dev->name, SYSFS_IF_BAT_SUBDIR,
((*hardif_attr)->attr).name);
goto rem_attr;
}
}
return 0;
rem_attr:
for (hardif_attr = batman_attrs; *hardif_attr; ++hardif_attr)
sysfs_remove_file(*hardif_obj, &((*hardif_attr)->attr));
out:
return -ENOMEM;
}
void sysfs_del_hardif(struct kobject **hardif_obj)
{
kobject_put(*hardif_obj);
*hardif_obj = NULL;
}

View file

@ -0,0 +1,29 @@
/*
* 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
*
*/
#define SYSFS_IF_MESH_SUBDIR "mesh"
#define SYSFS_IF_BAT_SUBDIR "batman_adv"
int sysfs_add_meshif(struct net_device *dev);
void sysfs_del_meshif(struct net_device *dev);
int sysfs_add_hardif(struct kobject **hardif_obj, struct net_device *dev);
void sysfs_del_hardif(struct kobject **hardif_obj);

View file

@ -1,5 +1,5 @@
/*
* Copyright (C) 2006-2009 B.A.T.M.A.N. contributors:
* Copyright (C) 2006-2010 B.A.T.M.A.N. contributors:
*
* Simon Wunderlich, Marek Lindner
*
@ -68,7 +68,7 @@ void bit_shift(TYPE_OF_WORD *seq_bits, int32_t n)
int32_t word_offset, word_num;
int32_t i;
if (n <= 0)
if (n <= 0 || n >= TQ_LOCAL_WINDOW_SIZE)
return;
word_offset = n % WORD_BIT_SIZE;/* shift how much inside each word */
@ -111,48 +111,76 @@ void bit_shift(TYPE_OF_WORD *seq_bits, int32_t n)
seq_bits[i] = 0;
}
static void bit_reset_window(TYPE_OF_WORD *seq_bits)
{
int i;
for (i = 0; i < NUM_WORDS; i++)
seq_bits[i] = 0;
}
/* receive and process one packet, returns 1 if received seq_num is considered
* new, 0 if old */
/* receive and process one packet within the sequence number window.
*
* returns:
* 1 if the window was moved (either new or very old)
* 0 if the window was not moved/shifted.
*/
char bit_get_packet(TYPE_OF_WORD *seq_bits, int16_t seq_num_diff,
int8_t set_mark)
{
int i;
/* sequence number is slightly older. We already got a sequence number
* higher than this one, so we just mark it. */
/* we already got a sequence number higher than this one, so we just
* mark it. this should wrap around the integer just fine */
if ((seq_num_diff < 0) && (seq_num_diff >= -TQ_LOCAL_WINDOW_SIZE)) {
if ((seq_num_diff <= 0) && (seq_num_diff > -TQ_LOCAL_WINDOW_SIZE)) {
if (set_mark)
bit_mark(seq_bits, -seq_num_diff);
return 0;
}
/* it seems we missed a lot of packets or the other host restarted */
if ((seq_num_diff > TQ_LOCAL_WINDOW_SIZE) ||
(seq_num_diff < -TQ_LOCAL_WINDOW_SIZE)) {
/* sequence number is slightly newer, so we shift the window and
* set the mark if required */
if (seq_num_diff > TQ_LOCAL_WINDOW_SIZE)
bat_dbg(DBG_BATMAN,
"We missed a lot of packets (%i) !\n",
seq_num_diff-1);
if (-seq_num_diff > TQ_LOCAL_WINDOW_SIZE)
bat_dbg(DBG_BATMAN,
"Other host probably restarted !\n");
for (i = 0; i < NUM_WORDS; i++)
seq_bits[i] = 0;
if (set_mark)
seq_bits[0] = 1; /* we only have the latest packet */
} else {
if ((seq_num_diff > 0) && (seq_num_diff < TQ_LOCAL_WINDOW_SIZE)) {
bit_shift(seq_bits, seq_num_diff);
if (set_mark)
bit_mark(seq_bits, 0);
return 1;
}
return 1;
/* sequence number is much newer, probably missed a lot of packets */
if ((seq_num_diff >= TQ_LOCAL_WINDOW_SIZE)
|| (seq_num_diff < EXPECTED_SEQNO_RANGE)) {
bat_dbg(DBG_BATMAN,
"We missed a lot of packets (%i) !\n",
seq_num_diff - 1);
bit_reset_window(seq_bits);
if (set_mark)
bit_mark(seq_bits, 0);
return 1;
}
/* received a much older packet. The other host either restarted
* or the old packet got delayed somewhere in the network. The
* packet should be dropped without calling this function if the
* seqno window is protected. */
if ((seq_num_diff <= -TQ_LOCAL_WINDOW_SIZE)
|| (seq_num_diff >= EXPECTED_SEQNO_RANGE)) {
bat_dbg(DBG_BATMAN,
"Other host probably restarted!\n");
bit_reset_window(seq_bits);
if (set_mark)
bit_mark(seq_bits, 0);
return 1;
}
/* never reached */
return 0;
}
/* count the hamming weight, how many good packets did we receive? just count

View file

@ -1,5 +1,5 @@
/*
* Copyright (C) 2006-2009 B.A.T.M.A.N. contributors:
* Copyright (C) 2006-2010 B.A.T.M.A.N. contributors:
*
* Simon Wunderlich, Marek Lindner
*

View file

@ -1,5 +1,5 @@
/*
* Copyright (C) 2007-2009 B.A.T.M.A.N. contributors:
* Copyright (C) 2007-2010 B.A.T.M.A.N. contributors:
*
* Marek Lindner
*
@ -44,10 +44,7 @@ static struct device_client *device_client_hash[256];
void bat_device_init(void)
{
int i;
for (i = 0; i < 256; i++)
device_client_hash[i] = NULL;
memset(device_client_hash, 0, sizeof(device_client_hash));
}
int bat_device_setup(void)
@ -60,7 +57,8 @@ int bat_device_setup(void)
/* 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",
printk(KERN_ERR "batman-adv:"
"Registering the character device failed with %d\n",
tmp_major);
return 0;
}
@ -68,7 +66,8 @@ int bat_device_setup(void)
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");
printk(KERN_ERR "batman-adv:"
"Could not register class 'batman-adv'\n");
return 0;
}
@ -103,15 +102,17 @@ int bat_device_open(struct inode *inode, struct file *file)
if (!device_client)
return -ENOMEM;
for (i = 0; i < 256; i++) {
for (i = 0; i < ARRAY_SIZE(device_client_hash); i++) {
if (!device_client_hash[i]) {
device_client_hash[i] = device_client;
break;
}
}
if (device_client_hash[i] != device_client) {
printk(KERN_ERR "batman-adv:Error - can't add another packet client: maximum number of clients reached \n");
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;
}
@ -212,7 +213,9 @@ ssize_t bat_device_write(struct file *file, const char __user *buff,
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");
bat_dbg(DBG_BATMAN, "batman-adv:"
"Error - can't send packet from char device: "
"invalid packet size\n");
return -EINVAL;
}
@ -223,12 +226,16 @@ ssize_t bat_device_write(struct file *file, const char __user *buff,
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");
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");
bat_dbg(DBG_BATMAN, "batman-adv:"
"Error - can't send packet from char device: "
"got bogus message type (expected: ECHO_REQUEST)\n");
return -EINVAL;
}
@ -253,7 +260,7 @@ ssize_t bat_device_write(struct file *file, const char __user *buff,
if (!orig_node->router)
goto unlock;
batman_if = orig_node->batman_if;
batman_if = orig_node->router->if_incoming;
memcpy(dstaddr, orig_node->router->addr, ETH_ALEN);
spin_unlock_irqrestore(&orig_hash_lock, flags);
@ -261,7 +268,7 @@ ssize_t bat_device_write(struct file *file, const char __user *buff,
if (!batman_if)
goto dst_unreach;
if (batman_if->if_active != IF_ACTIVE)
if (batman_if->if_status != IF_ACTIVE)
goto dst_unreach;
memcpy(icmp_packet.orig,

View file

@ -1,5 +1,5 @@
/*
* Copyright (C) 2007-2009 B.A.T.M.A.N. contributors:
* Copyright (C) 2007-2010 B.A.T.M.A.N. contributors:
*
* Marek Lindner
*

View file

@ -1,5 +1,5 @@
/*
* Copyright (C) 2007-2009 B.A.T.M.A.N. contributors:
* Copyright (C) 2007-2010 B.A.T.M.A.N. contributors:
*
* Marek Lindner, Simon Wunderlich
*
@ -25,22 +25,21 @@
#include "send.h"
#include "translation-table.h"
#include "routing.h"
#include "bat_sysfs.h"
#include "originator.h"
#include "hash.h"
#include <linux/if_arp.h>
#define MIN(x, y) ((x) < (y) ? (x) : (y))
static char avail_ifs;
static char active_ifs;
static void hardif_free_interface(struct rcu_head *rcu);
static struct batman_if *get_batman_if_by_name(char *name)
struct batman_if *get_batman_if_by_netdev(struct net_device *net_dev)
{
struct batman_if *batman_if;
rcu_read_lock();
list_for_each_entry_rcu(batman_if, &if_list, list) {
if (strncmp(batman_if->dev, name, IFNAMSIZ) == 0)
if (batman_if->net_dev == net_dev)
goto out;
}
@ -51,6 +50,115 @@ out:
return batman_if;
}
static int is_valid_iface(struct net_device *net_dev)
{
if (net_dev->flags & IFF_LOOPBACK)
return 0;
if (net_dev->type != ARPHRD_ETHER)
return 0;
if (net_dev->addr_len != ETH_ALEN)
return 0;
/* no batman over batman */
#ifdef HAVE_NET_DEVICE_OPS
if (net_dev->netdev_ops->ndo_start_xmit == interface_tx)
return 0;
#else
if (net_dev->hard_start_xmit == interface_tx)
return 0;
#endif
/* Device is being bridged */
/* if (net_dev->br_port != NULL)
return 0; */
return 1;
}
static struct batman_if *get_active_batman_if(void)
{
struct batman_if *batman_if;
/* TODO: should check interfaces belonging to bat_priv */
rcu_read_lock();
list_for_each_entry_rcu(batman_if, &if_list, list) {
if (batman_if->if_status == IF_ACTIVE)
goto out;
}
batman_if = NULL;
out:
rcu_read_unlock();
return batman_if;
}
static void set_primary_if(struct bat_priv *bat_priv,
struct batman_if *batman_if)
{
struct batman_packet *batman_packet;
bat_priv->primary_if = batman_if;
if (!bat_priv->primary_if)
return;
set_main_if_addr(batman_if->net_dev->dev_addr);
batman_packet = (struct batman_packet *)(batman_if->packet_buff);
batman_packet->flags = 0;
batman_packet->ttl = TTL;
/***
* hacky trick to make sure that we send the HNA information via
* our new primary interface
*/
atomic_set(&hna_local_changed, 1);
}
static bool hardif_is_iface_up(struct batman_if *batman_if)
{
if (batman_if->net_dev->flags & IFF_UP)
return true;
return false;
}
static void update_mac_addresses(struct batman_if *batman_if)
{
addr_to_string(batman_if->addr_str, batman_if->net_dev->dev_addr);
memcpy(((struct batman_packet *)(batman_if->packet_buff))->orig,
batman_if->net_dev->dev_addr, ETH_ALEN);
memcpy(((struct batman_packet *)(batman_if->packet_buff))->prev_sender,
batman_if->net_dev->dev_addr, ETH_ALEN);
}
static void check_known_mac_addr(uint8_t *addr)
{
struct batman_if *batman_if;
rcu_read_lock();
list_for_each_entry_rcu(batman_if, &if_list, list) {
if ((batman_if->if_status != IF_ACTIVE) &&
(batman_if->if_status != IF_TO_BE_ACTIVATED))
continue;
if (!compare_orig(batman_if->net_dev->dev_addr, addr))
continue;
printk(KERN_WARNING "batman-adv:"
"The newly added mac address (%pM) already exists on: %s\n",
addr, batman_if->dev);
printk(KERN_WARNING "batman-adv:"
"It is strongly recommended to keep mac addresses unique"
"to avoid problems!\n");
}
rcu_read_unlock();
}
int hardif_min_mtu(void)
{
struct batman_if *batman_if;
@ -60,8 +168,8 @@ int hardif_min_mtu(void)
rcu_read_lock();
list_for_each_entry_rcu(batman_if, &if_list, list) {
if ((batman_if->if_active == IF_ACTIVE) ||
(batman_if->if_active == IF_TO_BE_ACTIVATED))
if ((batman_if->if_status == IF_ACTIVE) ||
(batman_if->if_status == IF_TO_BE_ACTIVATED))
min_mtu = MIN(batman_if->net_dev->mtu - BAT_HEADER_LEN,
min_mtu);
}
@ -70,26 +178,6 @@ int hardif_min_mtu(void)
return min_mtu;
}
static void check_known_mac_addr(uint8_t *addr)
{
struct batman_if *batman_if;
rcu_read_lock();
list_for_each_entry_rcu(batman_if, &if_list, list) {
if ((batman_if->if_active != IF_ACTIVE) &&
(batman_if->if_active != IF_TO_BE_ACTIVATED))
continue;
if (!compare_orig(batman_if->net_dev->dev_addr, addr))
continue;
printk(KERN_WARNING "batman-adv:The newly added mac address (%pM) already exists on: %s\n",
addr, batman_if->dev);
printk(KERN_WARNING "batman-adv:It is strongly recommended to keep mac addresses unique to avoid problems!\n");
}
rcu_read_unlock();
}
/* adjusts the MTU if a new interface with a smaller MTU appeared. */
void update_min_mtu(void)
{
@ -100,322 +188,250 @@ void update_min_mtu(void)
soft_device->mtu = min_mtu;
}
/* checks if the interface is up. (returns 1 if it is) */
static int hardif_is_interface_up(char *dev)
static void hardif_activate_interface(struct bat_priv *bat_priv,
struct batman_if *batman_if)
{
struct net_device *net_dev;
/**
* if we already have an interface in our interface list and
* the current interface is not the primary interface and
* the primary interface is not up and
* the primary interface has never been up - don't activate any
* secondary interface !
*/
rcu_read_lock();
if ((!list_empty(&if_list)) &&
strncmp(((struct batman_if *)if_list.next)->dev, dev, IFNAMSIZ) &&
!(((struct batman_if *)if_list.next)->if_active == IF_ACTIVE) &&
!(((struct batman_if *)if_list.next)->if_active == IF_TO_BE_ACTIVATED) &&
(!main_if_was_up())) {
rcu_read_unlock();
goto end;
}
rcu_read_unlock();
#ifdef __NET_NET_NAMESPACE_H
net_dev = dev_get_by_name(&init_net, dev);
#else
net_dev = dev_get_by_name(dev);
#endif
if (!net_dev)
goto end;
if (!(net_dev->flags & IFF_UP))
goto failure;
dev_put(net_dev);
return 1;
failure:
dev_put(net_dev);
end:
return 0;
}
/* deactivates the interface. */
void hardif_deactivate_interface(struct batman_if *batman_if)
{
if (batman_if->if_active != IF_ACTIVE)
if (batman_if->if_status != IF_INACTIVE)
return;
dev_hold(batman_if->net_dev);
update_mac_addresses(batman_if);
batman_if->if_status = IF_TO_BE_ACTIVATED;
/**
* batman_if->net_dev has been acquired by dev_get_by_name() in
* proc_interfaces_write() and has to be unreferenced.
* the first active interface becomes our primary interface or
* the next active interface after the old primay interface was removed
*/
if (batman_if->net_dev)
dev_put(batman_if->net_dev);
batman_if->if_active = IF_INACTIVE;
active_ifs--;
printk(KERN_INFO "batman-adv:Interface deactivated: %s\n",
batman_if->dev);
}
/* (re)activate given interface. */
static void hardif_activate_interface(struct batman_if *batman_if)
{
if (batman_if->if_active != IF_INACTIVE)
return;
#ifdef __NET_NET_NAMESPACE_H
batman_if->net_dev = dev_get_by_name(&init_net, batman_if->dev);
#else
batman_if->net_dev = dev_get_by_name(batman_if->dev);
#endif
if (!batman_if->net_dev)
goto dev_err;
check_known_mac_addr(batman_if->net_dev->dev_addr);
addr_to_string(batman_if->addr_str, batman_if->net_dev->dev_addr);
memcpy(((struct batman_packet *)(batman_if->packet_buff))->orig,
batman_if->net_dev->dev_addr, ETH_ALEN);
memcpy(((struct batman_packet *)(batman_if->packet_buff))->prev_sender,
batman_if->net_dev->dev_addr, ETH_ALEN);
batman_if->if_active = IF_TO_BE_ACTIVATED;
active_ifs++;
/* save the mac address if it is our primary interface */
if (batman_if->if_num == 0)
set_main_if_addr(batman_if->net_dev->dev_addr);
if (!bat_priv->primary_if)
set_primary_if(bat_priv, batman_if);
printk(KERN_INFO "batman-adv:Interface activated: %s\n",
batman_if->dev);
batman_if->dev);
if (atomic_read(&module_state) == MODULE_INACTIVE)
activate_module();
update_min_mtu();
return;
}
dev_err:
batman_if->net_dev = NULL;
static void hardif_deactivate_interface(struct batman_if *batman_if)
{
if ((batman_if->if_status != IF_ACTIVE) &&
(batman_if->if_status != IF_TO_BE_ACTIVATED))
return;
dev_put(batman_if->net_dev);
batman_if->if_status = IF_INACTIVE;
printk(KERN_INFO "batman-adv:Interface deactivated: %s\n",
batman_if->dev);
update_min_mtu();
}
int hardif_enable_interface(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 batman_packet *batman_packet;
if (batman_if->if_status != IF_NOT_IN_USE)
goto out;
batman_if->packet_len = BAT_PACKET_LEN;
batman_if->packet_buff = kmalloc(batman_if->packet_len, GFP_ATOMIC);
if (!batman_if->packet_buff) {
printk(KERN_ERR "batman-adv:"
"Can't add interface packet (%s): out of memory\n",
batman_if->dev);
goto err;
}
batman_packet = (struct batman_packet *)(batman_if->packet_buff);
batman_packet->packet_type = BAT_PACKET;
batman_packet->version = COMPAT_VERSION;
batman_packet->flags = 0;
batman_packet->ttl = 2;
batman_packet->tq = TQ_MAX_VALUE;
batman_packet->num_hna = 0;
batman_if->if_num = bat_priv->num_ifaces;
bat_priv->num_ifaces++;
batman_if->if_status = IF_INACTIVE;
orig_hash_add_if(batman_if, bat_priv->num_ifaces);
atomic_set(&batman_if->seqno, 1);
printk(KERN_INFO "batman-adv:Adding interface: %s\n", batman_if->dev);
if (hardif_is_iface_up(batman_if))
hardif_activate_interface(bat_priv, batman_if);
else
printk(KERN_ERR "batman-adv:"
"Not using interface %s "
"(retrying later): interface not active\n",
batman_if->dev);
/* begin scheduling originator messages on that interface */
schedule_own_packet(batman_if);
out:
return 0;
err:
return -ENOMEM;
}
void hardif_disable_interface(struct batman_if *batman_if)
{
/* FIXME: each batman_if will be attached to a softif */
struct bat_priv *bat_priv = netdev_priv(soft_device);
if (batman_if->if_status == IF_ACTIVE)
hardif_deactivate_interface(batman_if);
if (batman_if->if_status != IF_INACTIVE)
return;
printk(KERN_INFO "batman-adv:Removing interface: %s\n", batman_if->dev);
bat_priv->num_ifaces--;
orig_hash_del_if(batman_if, bat_priv->num_ifaces);
if (batman_if == bat_priv->primary_if)
set_primary_if(bat_priv, get_active_batman_if());
kfree(batman_if->packet_buff);
batman_if->packet_buff = NULL;
batman_if->if_status = IF_NOT_IN_USE;
if ((atomic_read(&module_state) == MODULE_ACTIVE) &&
(bat_priv->num_ifaces == 0))
deactivate_module();
}
static struct batman_if *hardif_add_interface(struct net_device *net_dev)
{
struct batman_if *batman_if;
int ret;
ret = is_valid_iface(net_dev);
if (ret != 1)
goto out;
batman_if = kmalloc(sizeof(struct batman_if), GFP_ATOMIC);
if (!batman_if) {
printk(KERN_ERR "batman-adv:"
"Can't add interface (%s): out of memory\n",
net_dev->name);
goto out;
}
batman_if->dev = kstrdup(net_dev->name, GFP_ATOMIC);
if (!batman_if->dev)
goto free_if;
ret = sysfs_add_hardif(&batman_if->hardif_obj, net_dev);
if (ret)
goto free_dev;
batman_if->if_num = -1;
batman_if->net_dev = net_dev;
batman_if->if_status = IF_NOT_IN_USE;
INIT_LIST_HEAD(&batman_if->list);
check_known_mac_addr(batman_if->net_dev->dev_addr);
list_add_tail_rcu(&batman_if->list, &if_list);
return batman_if;
free_dev:
kfree(batman_if->dev);
free_if:
kfree(batman_if);
out:
return NULL;
}
static void hardif_free_interface(struct rcu_head *rcu)
{
struct batman_if *batman_if = container_of(rcu, struct batman_if, rcu);
kfree(batman_if->packet_buff);
/* delete all references to this batman_if */
purge_orig(NULL);
purge_outstanding_packets(batman_if);
kfree(batman_if->dev);
kfree(batman_if);
}
/**
* called by
* - echo '' > /proc/.../interfaces
* - modprobe -r batman-adv-core
*/
/* removes and frees all interfaces */
static void hardif_remove_interface(struct batman_if *batman_if)
{
/* first deactivate interface */
if (batman_if->if_status != IF_NOT_IN_USE)
hardif_disable_interface(batman_if);
if (batman_if->if_status != IF_NOT_IN_USE)
return;
batman_if->if_status = IF_TO_BE_REMOVED;
list_del_rcu(&batman_if->list);
sysfs_del_hardif(&batman_if->hardif_obj);
call_rcu(&batman_if->rcu, hardif_free_interface);
}
void hardif_remove_interfaces(void)
{
struct batman_if *batman_if = NULL;
struct batman_if *batman_if, *batman_if_tmp;
avail_ifs = 0;
/* no lock needed - we don't delete somewhere else */
list_for_each_entry(batman_if, &if_list, list) {
list_del_rcu(&batman_if->list);
/* first deactivate interface */
if (batman_if->if_active != IF_INACTIVE)
hardif_deactivate_interface(batman_if);
call_rcu(&batman_if->rcu, hardif_free_interface);
}
}
static int resize_orig(struct orig_node *orig_node, int if_num)
{
void *data_ptr;
data_ptr = kmalloc((if_num + 1) * sizeof(TYPE_OF_WORD) * NUM_WORDS,
GFP_ATOMIC);
if (!data_ptr) {
printk(KERN_ERR "batman-adv:Can't resize orig: out of memory\n");
return -1;
}
memcpy(data_ptr, orig_node->bcast_own,
if_num * sizeof(TYPE_OF_WORD) * NUM_WORDS);
kfree(orig_node->bcast_own);
orig_node->bcast_own = data_ptr;
data_ptr = kmalloc((if_num + 1) * sizeof(uint8_t), GFP_ATOMIC);
if (!data_ptr) {
printk(KERN_ERR "batman-adv:Can't resize orig: out of memory\n");
return -1;
}
memcpy(data_ptr, orig_node->bcast_own_sum, if_num * sizeof(uint8_t));
kfree(orig_node->bcast_own_sum);
orig_node->bcast_own_sum = data_ptr;
return 0;
}
/* adds an interface the interface list and activate it, if possible */
int hardif_add_interface(char *dev, int if_num)
{
struct batman_if *batman_if;
struct batman_packet *batman_packet;
struct orig_node *orig_node;
unsigned long flags;
HASHIT(hashit);
batman_if = kmalloc(sizeof(struct batman_if), GFP_KERNEL);
if (!batman_if) {
printk(KERN_ERR "batman-adv:Can't add interface (%s): out of memory\n", dev);
return -1;
}
batman_if->net_dev = NULL;
if ((if_num == 0) && (num_hna > 0))
batman_if->packet_len = BAT_PACKET_LEN + num_hna * ETH_ALEN;
else
batman_if->packet_len = BAT_PACKET_LEN;
batman_if->packet_buff = kmalloc(batman_if->packet_len, GFP_KERNEL);
if (!batman_if->packet_buff) {
printk(KERN_ERR "batman-adv:Can't add interface packet (%s): out of memory\n", dev);
goto out;
}
batman_if->if_num = if_num;
batman_if->dev = dev;
batman_if->if_active = IF_INACTIVE;
INIT_RCU_HEAD(&batman_if->rcu);
printk(KERN_INFO "batman-adv:Adding interface: %s\n", dev);
avail_ifs++;
INIT_LIST_HEAD(&batman_if->list);
batman_packet = (struct batman_packet *)(batman_if->packet_buff);
batman_packet->packet_type = BAT_PACKET;
batman_packet->version = COMPAT_VERSION;
batman_packet->flags = 0x00;
batman_packet->ttl = (batman_if->if_num > 0 ? 2 : TTL);
batman_packet->flags = 0;
batman_packet->tq = TQ_MAX_VALUE;
batman_packet->num_hna = 0;
if (batman_if->packet_len != BAT_PACKET_LEN) {
unsigned char *hna_buff;
int hna_len;
hna_buff = batman_if->packet_buff + BAT_PACKET_LEN;
hna_len = batman_if->packet_len - BAT_PACKET_LEN;
batman_packet->num_hna = hna_local_fill_buffer(hna_buff,
hna_len);
}
atomic_set(&batman_if->seqno, 1);
/* resize all orig nodes because orig_node->bcast_own(_sum) depend on
* if_num */
spin_lock_irqsave(&orig_hash_lock, flags);
while (hash_iterate(orig_hash, &hashit)) {
orig_node = hashit.bucket->data;
if (resize_orig(orig_node, if_num) == -1) {
spin_unlock_irqrestore(&orig_hash_lock, flags);
goto out;
}
}
spin_unlock_irqrestore(&orig_hash_lock, flags);
if (!hardif_is_interface_up(batman_if->dev))
printk(KERN_ERR "batman-adv:Not using interface %s (retrying later): interface not active\n", batman_if->dev);
else
hardif_activate_interface(batman_if);
list_add_tail_rcu(&batman_if->list, &if_list);
/* begin sending originator messages on that interface */
schedule_own_packet(batman_if);
return 1;
out:
kfree(batman_if->packet_buff);
kfree(batman_if);
kfree(dev);
return -1;
}
char hardif_get_active_if_num(void)
{
return active_ifs;
list_for_each_entry_safe(batman_if, batman_if_tmp, &if_list, list)
hardif_remove_interface(batman_if);
}
static int hard_if_event(struct notifier_block *this,
unsigned long event, void *ptr)
unsigned long event, void *ptr)
{
struct net_device *dev = (struct net_device *)ptr;
struct batman_if *batman_if = get_batman_if_by_name(dev->name);
struct net_device *net_dev = (struct net_device *)ptr;
struct batman_if *batman_if = get_batman_if_by_netdev(net_dev);
/* FIXME: each batman_if will be attached to a softif */
struct bat_priv *bat_priv = netdev_priv(soft_device);
if (!batman_if)
batman_if = hardif_add_interface(net_dev);
if (!batman_if)
goto out;
switch (event) {
case NETDEV_GOING_DOWN:
case NETDEV_DOWN:
case NETDEV_UNREGISTER:
hardif_deactivate_interface(batman_if);
case NETDEV_REGISTER:
break;
case NETDEV_UP:
hardif_activate_interface(batman_if);
if ((atomic_read(&module_state) == MODULE_INACTIVE) &&
(hardif_get_active_if_num() > 0)) {
activate_module();
}
hardif_activate_interface(bat_priv, batman_if);
break;
case NETDEV_GOING_DOWN:
case NETDEV_DOWN:
hardif_deactivate_interface(batman_if);
break;
case NETDEV_UNREGISTER:
hardif_remove_interface(batman_if);
break;
case NETDEV_CHANGENAME:
break;
case NETDEV_CHANGEADDR:
check_known_mac_addr(batman_if->net_dev->dev_addr);
update_mac_addresses(batman_if);
if (batman_if == bat_priv->primary_if)
set_primary_if(bat_priv, batman_if);
break;
/* NETDEV_CHANGEADDR - mac address change - what are we doing here ? */
default:
break;
};
update_min_mtu();
out:
return NOTIFY_DONE;
}
/* find batman interface by netdev. assumes rcu_read_lock on */
static struct batman_if *find_batman_if(struct net_device *dev)
{
struct batman_if *batman_if;
rcu_read_lock();
list_for_each_entry_rcu(batman_if, &if_list, list) {
if (batman_if->net_dev == dev) {
rcu_read_unlock();
return batman_if;
}
}
rcu_read_unlock();
return NULL;
}
/* receive a packet with the batman ethertype coming on a hard
* interface */
int batman_skb_recv(struct sk_buff *skb, struct net_device *dev,
@ -444,12 +460,12 @@ int batman_skb_recv(struct sk_buff *skb, struct net_device *dev,
|| !skb_mac_header(skb)))
goto err_free;
batman_if = find_batman_if(skb->dev);
batman_if = get_batman_if_by_netdev(skb->dev);
if (!batman_if)
goto err_free;
/* discard frames on not active interfaces */
if (batman_if->if_active != IF_ACTIVE)
if (batman_if->if_status != IF_ACTIVE)
goto err_free;
stats = (struct net_device_stats *)dev_get_stats(skb->dev);

View file

@ -1,5 +1,5 @@
/*
* Copyright (C) 2007-2009 B.A.T.M.A.N. contributors:
* Copyright (C) 2007-2010 B.A.T.M.A.N. contributors:
*
* Marek Lindner, Simon Wunderlich
*
@ -19,19 +19,19 @@
*
*/
#define IF_INACTIVE 0
#define IF_ACTIVE 1
/* #define IF_TO_BE_DEACTIVATED 2 - not needed anymore */
#define IF_TO_BE_ACTIVATED 3
#define IF_NOT_IN_USE 0
#define IF_TO_BE_REMOVED 1
#define IF_INACTIVE 2
#define IF_ACTIVE 3
#define IF_TO_BE_ACTIVATED 4
#define IF_I_WANT_YOU 5
extern struct notifier_block hard_if_notifier;
struct batman_if *get_batman_if_by_netdev(struct net_device *net_dev);
int hardif_enable_interface(struct batman_if *batman_if);
void hardif_disable_interface(struct batman_if *batman_if);
void hardif_remove_interfaces(void);
int hardif_add_interface(char *dev, int if_num);
void hardif_deactivate_interface(struct batman_if *batman_if);
char hardif_get_active_if_num(void);
void hardif_check_interfaces_status(void);
void hardif_check_interfaces_status_wq(struct work_struct *work);
int batman_skb_recv(struct sk_buff *skb,
struct net_device *dev,
struct packet_type *ptype,

View file

@ -1,5 +1,5 @@
/*
* Copyright (C) 2006-2009 B.A.T.M.A.N. contributors:
* Copyright (C) 2006-2010 B.A.T.M.A.N. contributors:
*
* Simon Wunderlich, Marek Lindner
*

View file

@ -1,5 +1,5 @@
/*
* Copyright (C) 2006-2009 B.A.T.M.A.N. contributors:
* Copyright (C) 2006-2010 B.A.T.M.A.N. contributors:
*
* Simon Wunderlich, Marek Lindner
*

View file

@ -1,5 +1,5 @@
/*
* Copyright (C) 2007-2009 B.A.T.M.A.N. contributors:
* Copyright (C) 2007-2010 B.A.T.M.A.N. contributors:
*
* Marek Lindner, Simon Wunderlich
*
@ -20,7 +20,7 @@
*/
#include "main.h"
#include "proc.h"
#include "bat_sysfs.h"
#include "routing.h"
#include "send.h"
#include "originator.h"
@ -41,12 +41,11 @@ DEFINE_SPINLOCK(orig_hash_lock);
DEFINE_SPINLOCK(forw_bat_list_lock);
DEFINE_SPINLOCK(forw_bcast_list_lock);
atomic_t originator_interval;
atomic_t vis_interval;
atomic_t vis_mode;
atomic_t aggregation_enabled;
atomic_t bcast_queue_left;
atomic_t batman_queue_left;
int16_t num_hna;
int16_t num_ifs;
struct net_device *soft_device;
@ -81,11 +80,10 @@ int init_module(void)
atomic_set(&module_state, MODULE_INACTIVE);
atomic_set(&originator_interval, 1000);
atomic_set(&vis_interval, 1000);/* TODO: raise this later, this is only
* for debugging now. */
atomic_set(&vis_mode, VIS_TYPE_CLIENT_UPDATE);
atomic_set(&aggregation_enabled, 1);
atomic_set(&bcast_queue_left, BCAST_QUEUE_LEN);
atomic_set(&batman_queue_left, BATMAN_QUEUE_LEN);
/* the name should not be longer than 10 chars - see
* http://lwn.net/Articles/23634/ */
@ -94,10 +92,6 @@ int init_module(void)
if (!bat_event_workqueue)
return -ENOMEM;
retval = setup_procfs();
if (retval < 0)
return retval;
bat_device_init();
/* initialize layer 2 interface */
@ -105,25 +99,35 @@ int init_module(void)
interface_setup);
if (!soft_device) {
printk(KERN_ERR "batman-adv:Unable to allocate the batman interface\n");
printk(KERN_ERR "batman-adv:"
"Unable to allocate the batman interface\n");
goto end;
}
retval = register_netdev(soft_device);
if (retval < 0) {
printk(KERN_ERR "batman-adv:Unable to register the batman interface: %i\n", retval);
printk(KERN_ERR "batman-adv:"
"Unable to register the batman interface: %i\n", retval);
goto free_soft_device;
}
retval = sysfs_add_meshif(soft_device);
if (retval < 0)
goto unreg_soft_device;
register_netdevice_notifier(&hard_if_notifier);
dev_add_pack(&batman_adv_packet_type);
printk(KERN_INFO "batman-adv:B.A.T.M.A.N. advanced %s%s (compatibility version %i) loaded \n",
SOURCE_VERSION, REVISION_VERSION_STR, COMPAT_VERSION);
printk(KERN_INFO "batman-adv:"
"B.A.T.M.A.N. advanced %s%s (compatibility version %i) loaded\n",
SOURCE_VERSION, REVISION_VERSION_STR, COMPAT_VERSION);
return 0;
unreg_soft_device:
unregister_netdevice(soft_device);
free_soft_device:
free_netdev(soft_device);
soft_device = NULL;
@ -133,18 +137,19 @@ end:
void cleanup_module(void)
{
shutdown_module();
deactivate_module();
unregister_netdevice_notifier(&hard_if_notifier);
hardif_remove_interfaces();
if (soft_device) {
sysfs_del_meshif(soft_device);
unregister_netdev(soft_device);
soft_device = NULL;
}
dev_remove_pack(&batman_adv_packet_type);
unregister_netdevice_notifier(&hard_if_notifier);
cleanup_procfs();
destroy_workqueue(bat_event_workqueue);
bat_event_workqueue = NULL;
}
@ -174,18 +179,20 @@ void activate_module(void)
goto end;
err:
printk(KERN_ERR "batman-adv:Unable to allocate memory for mesh information structures: out of mem ?\n");
shutdown_module();
printk(KERN_ERR "batman-adv:"
"Unable to allocate memory for mesh information structures: "
"out of mem ?\n");
deactivate_module();
end:
return;
}
/* shuts down the whole module.*/
void shutdown_module(void)
void deactivate_module(void)
{
atomic_set(&module_state, MODULE_DEACTIVATING);
purge_outstanding_packets();
purge_outstanding_packets(NULL);
flush_workqueue(bat_event_workqueue);
vis_quit();
@ -200,7 +207,6 @@ void shutdown_module(void)
synchronize_net();
bat_device_destroy();
hardif_remove_interfaces();
synchronize_rcu();
atomic_set(&module_state, MODULE_INACTIVE);
}
@ -217,7 +223,7 @@ void dec_module_count(void)
int addr_to_string(char *buff, uint8_t *addr)
{
return sprintf(buff, "%02x:%02x:%02x:%02x:%02x:%02x",
return sprintf(buff, MAC_FMT,
addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]);
}

View file

@ -1,5 +1,5 @@
/*
* Copyright (C) 2007-2009 B.A.T.M.A.N. contributors:
* Copyright (C) 2007-2010 B.A.T.M.A.N. contributors:
*
* Marek Lindner, Simon Wunderlich
*
@ -22,11 +22,12 @@
/* Kernel Programming */
#define LINUX
#define DRIVER_AUTHOR "Marek Lindner <lindner_marek@yahoo.de>, Simon Wunderlich <siwu@hrz.tu-chemnitz.de>"
#define DRIVER_AUTHOR "Marek Lindner <lindner_marek@yahoo.de>, " \
"Simon Wunderlich <siwu@hrz.tu-chemnitz.de>"
#define DRIVER_DESC "B.A.T.M.A.N. advanced"
#define DRIVER_DEVICE "batman-adv"
#define SOURCE_VERSION "0.2.1-beta"
#define SOURCE_VERSION "0.2.2-beta"
/* B.A.T.M.A.N. parameters */
@ -34,8 +35,6 @@
#define TQ_MAX_VALUE 255
#define JITTER 20
#define TTL 50 /* Time To Live of broadcast messages */
#define MAX_ADDR 16 /* number of interfaces which can be added to
* batman. */
#define PURGE_TIMEOUT 200000 /* purge originators after time in ms if no
* valid packet comes in -> TODO: check
@ -63,10 +62,16 @@
* forw_packet->direct_link_flags */
#define MAX_AGGREGATION_MS 100
#define RESET_PROTECTION_MS 30000
#define EXPECTED_SEQNO_RANGE 4096
/* don't reset again within 30 seconds */
#define MODULE_INACTIVE 0
#define MODULE_ACTIVE 1
#define MODULE_DEACTIVATING 2
#define BCAST_QUEUE_LEN 256
#define BATMAN_QUEUE_LEN 256
/*
* Debug Messages
@ -129,12 +134,10 @@ extern spinlock_t orig_hash_lock;
extern spinlock_t forw_bat_list_lock;
extern spinlock_t forw_bcast_list_lock;
extern atomic_t originator_interval;
extern atomic_t vis_interval;
extern atomic_t vis_mode;
extern atomic_t aggregation_enabled;
extern atomic_t bcast_queue_left;
extern atomic_t batman_queue_left;
extern int16_t num_hna;
extern int16_t num_ifs;
extern struct net_device *soft_device;
@ -143,7 +146,7 @@ extern atomic_t module_state;
extern struct workqueue_struct *bat_event_workqueue;
void activate_module(void);
void shutdown_module(void);
void deactivate_module(void);
void inc_module_count(void);
void dec_module_count(void);
int addr_to_string(char *buff, uint8_t *addr);

View file

@ -1,5 +1,5 @@
/*
* Copyright (C) 2009 B.A.T.M.A.N. contributors:
* Copyright (C) 2009-2010 B.A.T.M.A.N. contributors:
*
* Marek Lindner, Simon Wunderlich
*
@ -26,6 +26,7 @@
#include "hash.h"
#include "translation-table.h"
#include "routing.h"
#include "hard-interface.h"
static DECLARE_DELAYED_WORK(purge_orig_wq, purge_orig);
@ -117,6 +118,8 @@ void free_orig_node(void *data)
* address if it does not exits */
struct orig_node *get_orig_node(uint8_t *addr)
{
/* FIXME: each batman_if will be attached to a softif */
struct bat_priv *bat_priv = netdev_priv(soft_device);
struct orig_node *orig_node;
struct hashtable_t *swaphash;
int size;
@ -126,7 +129,7 @@ struct orig_node *get_orig_node(uint8_t *addr)
if (orig_node != NULL)
return orig_node;
bat_dbg(DBG_BATMAN, "Creating new originator: %pM \n", addr);
bat_dbg(DBG_BATMAN, "Creating new originator: %pM\n", addr);
orig_node = kzalloc(sizeof(struct orig_node), GFP_ATOMIC);
if (!orig_node)
@ -136,16 +139,19 @@ struct orig_node *get_orig_node(uint8_t *addr)
memcpy(orig_node->orig, addr, ETH_ALEN);
orig_node->router = NULL;
orig_node->batman_if = NULL;
orig_node->hna_buff = NULL;
orig_node->bcast_seqno_reset = jiffies - 1
- msecs_to_jiffies(RESET_PROTECTION_MS);
orig_node->batman_seqno_reset = jiffies - 1
- msecs_to_jiffies(RESET_PROTECTION_MS);
size = num_ifs * sizeof(TYPE_OF_WORD) * NUM_WORDS;
size = bat_priv->num_ifaces * sizeof(TYPE_OF_WORD) * NUM_WORDS;
orig_node->bcast_own = kzalloc(size, GFP_ATOMIC);
if (!orig_node->bcast_own)
goto free_orig_node;
size = num_ifs * sizeof(uint8_t);
size = bat_priv->num_ifaces * sizeof(uint8_t);
orig_node->bcast_own_sum = kzalloc(size, GFP_ATOMIC);
if (!orig_node->bcast_own_sum)
goto free_bcast_own;
@ -158,7 +164,7 @@ struct orig_node *get_orig_node(uint8_t *addr)
if (swaphash == NULL)
printk(KERN_ERR
"batman-adv:Couldn't resize orig hash table \n");
"batman-adv:Couldn't resize orig hash table\n");
else
orig_hash = swaphash;
}
@ -182,16 +188,29 @@ static bool purge_orig_neighbors(struct orig_node *orig_node,
*best_neigh_node = NULL;
/* for all neighbors towards this originator ... */
list_for_each_safe(list_pos, list_pos_tmp, &orig_node->neigh_list) {
neigh_node = list_entry(list_pos, struct neigh_node, list);
if (time_after(jiffies,
if ((time_after(jiffies,
(neigh_node->last_valid +
((PURGE_TIMEOUT * HZ) / 1000)))) {
((PURGE_TIMEOUT * HZ) / 1000)))) ||
(neigh_node->if_incoming->if_status ==
IF_TO_BE_REMOVED)) {
bat_dbg(DBG_BATMAN, "neighbor timeout: originator %pM, neighbor: %pM, last_valid %lu\n", orig_node->orig, neigh_node->addr, (neigh_node->last_valid / HZ));
if (neigh_node->if_incoming->if_status ==
IF_TO_BE_REMOVED)
bat_dbg(DBG_BATMAN,
"neighbor purge: originator %pM, "
"neighbor: %pM, iface: %s\n",
orig_node->orig, neigh_node->addr,
neigh_node->if_incoming->dev);
else
bat_dbg(DBG_BATMAN,
"neighbor timeout: originator %pM, "
"neighbor: %pM, last_valid: %lu\n",
orig_node->orig, neigh_node->addr,
(neigh_node->last_valid / HZ));
neigh_purged = true;
list_del(list_pos);
@ -205,7 +224,6 @@ static bool purge_orig_neighbors(struct orig_node *orig_node,
return neigh_purged;
}
static bool purge_orig_node(struct orig_node *orig_node)
{
struct neigh_node *best_neigh_node;
@ -224,6 +242,7 @@ static bool purge_orig_node(struct orig_node *orig_node)
orig_node->hna_buff,
orig_node->hna_buff_len);
}
return false;
}
@ -246,7 +265,257 @@ void purge_orig(struct work_struct *work)
spin_unlock_irqrestore(&orig_hash_lock, flags);
start_purge_timer();
/* if work == NULL we were not called by the timer
* and thus do not need to re-arm the timer */
if (work)
start_purge_timer();
}
ssize_t orig_fill_buffer_text(struct net_device *net_dev, char *buff,
size_t count, loff_t off)
{
HASHIT(hashit);
struct bat_priv *bat_priv = netdev_priv(net_dev);
struct orig_node *orig_node;
struct neigh_node *neigh_node;
size_t hdr_len, tmp_len;
int batman_count = 0, bytes_written = 0;
unsigned long flags;
char orig_str[ETH_STR_LEN], router_str[ETH_STR_LEN];
if (!bat_priv->primary_if) {
if (off == 0)
return sprintf(buff,
"BATMAN mesh %s disabled - "
"please specify interfaces to enable it\n",
net_dev->name);
return 0;
}
if (bat_priv->primary_if->if_status != IF_ACTIVE && off == 0)
return sprintf(buff,
"BATMAN mesh %s "
"disabled - primary interface not active\n",
net_dev->name);
else if (bat_priv->primary_if->if_status != IF_ACTIVE)
return 0;
rcu_read_lock();
hdr_len = sprintf(buff,
" %-14s (%s/%i) %17s [%10s]: %20s "
"... [B.A.T.M.A.N. adv %s%s, MainIF/MAC: %s/%s (%s)]\n",
"Originator", "#", TQ_MAX_VALUE, "Nexthop", "outgoingIF",
"Potential nexthops", SOURCE_VERSION, REVISION_VERSION_STR,
bat_priv->primary_if->dev, bat_priv->primary_if->addr_str,
net_dev->name);
rcu_read_unlock();
if (off < hdr_len)
bytes_written = hdr_len;
spin_lock_irqsave(&orig_hash_lock, flags);
while (hash_iterate(orig_hash, &hashit)) {
orig_node = hashit.bucket->data;
if (!orig_node->router)
continue;
if (orig_node->router->tq_avg == 0)
continue;
/* estimated line length */
if (count < bytes_written + 200)
break;
addr_to_string(orig_str, orig_node->orig);
addr_to_string(router_str, orig_node->router->addr);
tmp_len = sprintf(buff + bytes_written,
"%-17s (%3i) %17s [%10s]:",
orig_str, orig_node->router->tq_avg,
router_str,
orig_node->router->if_incoming->dev);
list_for_each_entry(neigh_node, &orig_node->neigh_list, list) {
addr_to_string(orig_str, neigh_node->addr);
tmp_len += sprintf(buff + bytes_written + tmp_len,
" %17s (%3i)", orig_str,
neigh_node->tq_avg);
}
tmp_len += sprintf(buff + bytes_written + tmp_len, "\n");
batman_count++;
hdr_len += tmp_len;
if (off >= hdr_len)
continue;
bytes_written += tmp_len;
}
spin_unlock_irqrestore(&orig_hash_lock, flags);
if ((batman_count == 0) && (off == 0))
bytes_written += sprintf(buff + bytes_written,
"No batman nodes in range ...\n");
return bytes_written;
}
static int orig_node_add_if(struct orig_node *orig_node, int max_if_num)
{
void *data_ptr;
data_ptr = kmalloc(max_if_num * sizeof(TYPE_OF_WORD) * NUM_WORDS,
GFP_ATOMIC);
if (!data_ptr) {
printk(KERN_ERR
"batman-adv:Can't resize orig: out of memory\n");
return -1;
}
memcpy(data_ptr, orig_node->bcast_own,
(max_if_num - 1) * sizeof(TYPE_OF_WORD) * NUM_WORDS);
kfree(orig_node->bcast_own);
orig_node->bcast_own = data_ptr;
data_ptr = kmalloc(max_if_num * sizeof(uint8_t), GFP_ATOMIC);
if (!data_ptr) {
printk(KERN_ERR
"batman-adv:Can't resize orig: out of memory\n");
return -1;
}
memcpy(data_ptr, orig_node->bcast_own_sum,
(max_if_num - 1) * sizeof(uint8_t));
kfree(orig_node->bcast_own_sum);
orig_node->bcast_own_sum = data_ptr;
return 0;
}
int orig_hash_add_if(struct batman_if *batman_if, int max_if_num)
{
struct orig_node *orig_node;
HASHIT(hashit);
/* resize all orig nodes because orig_node->bcast_own(_sum) depend on
* if_num */
spin_lock(&orig_hash_lock);
while (hash_iterate(orig_hash, &hashit)) {
orig_node = hashit.bucket->data;
if (orig_node_add_if(orig_node, max_if_num) == -1)
goto err;
}
spin_unlock(&orig_hash_lock);
return 0;
err:
spin_unlock(&orig_hash_lock);
return -ENOMEM;
}
static int orig_node_del_if(struct orig_node *orig_node,
int max_if_num, int del_if_num)
{
void *data_ptr = NULL;
int chunk_size;
/* last interface was removed */
if (max_if_num == 0)
goto free_bcast_own;
chunk_size = sizeof(TYPE_OF_WORD) * NUM_WORDS;
data_ptr = kmalloc(max_if_num * chunk_size, GFP_ATOMIC);
if (!data_ptr) {
printk(KERN_ERR
"batman-adv:Can't resize orig: out of memory\n");
return -1;
}
/* copy first part */
memcpy(data_ptr, orig_node->bcast_own, del_if_num * chunk_size);
/* copy second part */
memcpy(data_ptr,
orig_node->bcast_own + ((del_if_num + 1) * chunk_size),
(max_if_num - del_if_num) * chunk_size);
free_bcast_own:
kfree(orig_node->bcast_own);
orig_node->bcast_own = data_ptr;
if (max_if_num == 0)
goto free_own_sum;
data_ptr = kmalloc(max_if_num * sizeof(uint8_t), GFP_ATOMIC);
if (!data_ptr) {
printk(KERN_ERR
"batman-adv:Can't resize orig: out of memory\n");
return -1;
}
memcpy(data_ptr, orig_node->bcast_own_sum,
del_if_num * sizeof(uint8_t));
memcpy(data_ptr,
orig_node->bcast_own_sum + ((del_if_num + 1) * sizeof(uint8_t)),
(max_if_num - del_if_num) * sizeof(uint8_t));
free_own_sum:
kfree(orig_node->bcast_own_sum);
orig_node->bcast_own_sum = data_ptr;
return 0;
}
int orig_hash_del_if(struct batman_if *batman_if, int max_if_num)
{
struct batman_if *batman_if_tmp;
struct orig_node *orig_node;
HASHIT(hashit);
int ret;
/* resize all orig nodes because orig_node->bcast_own(_sum) depend on
* if_num */
spin_lock(&orig_hash_lock);
while (hash_iterate(orig_hash, &hashit)) {
orig_node = hashit.bucket->data;
ret = orig_node_del_if(orig_node, max_if_num,
batman_if->if_num);
if (ret == -1)
goto err;
}
/* renumber remaining batman interfaces _inside_ of orig_hash_lock */
rcu_read_lock();
list_for_each_entry_rcu(batman_if_tmp, &if_list, list) {
if (batman_if_tmp->if_status == IF_NOT_IN_USE)
continue;
if (batman_if == batman_if_tmp)
continue;
if (batman_if_tmp->if_num > batman_if->if_num)
batman_if_tmp->if_num--;
}
rcu_read_unlock();
batman_if->if_num = -1;
spin_unlock(&orig_hash_lock);
return 0;
err:
spin_unlock(&orig_hash_lock);
return -ENOMEM;
}

View file

@ -1,5 +1,5 @@
/*
* Copyright (C) 2007-2009 B.A.T.M.A.N. contributors:
* Copyright (C) 2007-2010 B.A.T.M.A.N. contributors:
*
* Marek Lindner, Simon Wunderlich
*
@ -28,4 +28,7 @@ struct orig_node *get_orig_node(uint8_t *addr);
struct neigh_node *
create_neighbor(struct orig_node *orig_node, struct orig_node *orig_neigh_node,
uint8_t *neigh, struct batman_if *if_incoming);
ssize_t orig_fill_buffer_text(struct net_device *net_dev, char *buff,
size_t count, loff_t off);
int orig_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);

View file

@ -1,5 +1,5 @@
/*
* Copyright (C) 2007-2009 B.A.T.M.A.N. contributors:
* Copyright (C) 2007-2010 B.A.T.M.A.N. contributors:
*
* Marek Lindner, Simon Wunderlich
*

View file

@ -1,670 +0,0 @@
/*
* Copyright (C) 2007-2009 B.A.T.M.A.N. contributors:
*
* Marek Lindner, Simon Wunderlich
*
* 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 "proc.h"
#include "routing.h"
#include "translation-table.h"
#include "hard-interface.h"
#include "types.h"
#include "hash.h"
#include "vis.h"
static struct proc_dir_entry *proc_batman_dir, *proc_interface_file;
static struct proc_dir_entry *proc_orig_interval_file, *proc_originators_file;
static struct proc_dir_entry *proc_transt_local_file;
static struct proc_dir_entry *proc_transt_global_file;
static struct proc_dir_entry *proc_vis_srv_file, *proc_vis_data_file;
static struct proc_dir_entry *proc_aggr_file;
static int proc_interfaces_read(struct seq_file *seq, void *offset)
{
struct batman_if *batman_if;
rcu_read_lock();
list_for_each_entry_rcu(batman_if, &if_list, list) {
seq_printf(seq, "[%8s] %s %s \n",
(batman_if->if_active == IF_ACTIVE ?
"active" : "inactive"),
batman_if->dev,
(batman_if->if_active == IF_ACTIVE ?
batman_if->addr_str : " "));
}
rcu_read_unlock();
return 0;
}
static int proc_interfaces_open(struct inode *inode, struct file *file)
{
return single_open(file, proc_interfaces_read, NULL);
}
static ssize_t proc_interfaces_write(struct file *instance,
const char __user *userbuffer,
size_t count, loff_t *data)
{
char *if_string, *colon_ptr = NULL, *cr_ptr = NULL;
int not_copied = 0, if_num = 0, add_success;
struct batman_if *batman_if = NULL;
if_string = kmalloc(count, GFP_KERNEL);
if (!if_string)
return -ENOMEM;
if (count > IFNAMSIZ - 1) {
printk(KERN_WARNING "batman-adv:Can't add interface: device name is too long\n");
goto end;
}
not_copied = copy_from_user(if_string, userbuffer, count);
if_string[count - not_copied - 1] = 0;
colon_ptr = strchr(if_string, ':');
if (colon_ptr)
*colon_ptr = 0;
if (!colon_ptr) {
cr_ptr = strchr(if_string, '\n');
if (cr_ptr)
*cr_ptr = 0;
}
if (strlen(if_string) == 0) {
shutdown_module();
num_ifs = 0;
goto end;
}
/* add interface */
rcu_read_lock();
list_for_each_entry_rcu(batman_if, &if_list, list) {
if (strncmp(batman_if->dev, if_string, count) == 0) {
printk(KERN_ERR "batman-adv:Given interface is already active: %s\n", if_string);
rcu_read_unlock();
goto end;
}
if_num++;
}
rcu_read_unlock();
add_success = hardif_add_interface(if_string, if_num);
if (add_success < 0)
goto end;
num_ifs = if_num + 1;
if ((atomic_read(&module_state) == MODULE_INACTIVE) &&
(hardif_get_active_if_num() > 0))
activate_module();
return count;
end:
kfree(if_string);
return count;
}
static int proc_orig_interval_read(struct seq_file *seq, void *offset)
{
seq_printf(seq, "%i\n", atomic_read(&originator_interval));
return 0;
}
static ssize_t proc_orig_interval_write(struct file *file,
const char __user *buffer,
size_t count, loff_t *ppos)
{
char *interval_string;
int not_copied = 0;
unsigned long originator_interval_tmp;
int retval;
interval_string = kmalloc(count, GFP_KERNEL);
if (!interval_string)
return -ENOMEM;
not_copied = copy_from_user(interval_string, buffer, count);
interval_string[count - not_copied - 1] = 0;
retval = strict_strtoul(interval_string, 10, &originator_interval_tmp);
if (retval) {
printk(KERN_ERR "batman-adv:New originator interval invalid\n");
goto end;
}
if (originator_interval_tmp <= JITTER * 2) {
printk(KERN_WARNING "batman-adv:New originator interval too small: %li (min: %i)\n",
originator_interval_tmp, JITTER * 2);
goto end;
}
printk(KERN_INFO "batman-adv:Changing originator interval from: %i to: %li\n",
atomic_read(&originator_interval), originator_interval_tmp);
atomic_set(&originator_interval, originator_interval_tmp);
end:
kfree(interval_string);
return count;
}
static int proc_orig_interval_open(struct inode *inode, struct file *file)
{
return single_open(file, proc_orig_interval_read, NULL);
}
static int proc_originators_read(struct seq_file *seq, void *offset)
{
HASHIT(hashit);
struct orig_node *orig_node;
struct neigh_node *neigh_node;
int batman_count = 0;
char orig_str[ETH_STR_LEN], router_str[ETH_STR_LEN];
unsigned long flags;
rcu_read_lock();
if (list_empty(&if_list)) {
rcu_read_unlock();
seq_printf(seq, "BATMAN disabled - please specify interfaces to enable it \n");
goto end;
}
if (((struct batman_if *)if_list.next)->if_active != IF_ACTIVE) {
rcu_read_unlock();
seq_printf(seq, "BATMAN disabled - primary interface not active \n");
goto end;
}
seq_printf(seq,
" %-14s (%s/%i) %17s [%10s]: %20s ... [B.A.T.M.A.N. adv %s%s, MainIF/MAC: %s/%s] \n",
"Originator", "#", TQ_MAX_VALUE, "Nexthop", "outgoingIF",
"Potential nexthops", SOURCE_VERSION, REVISION_VERSION_STR,
((struct batman_if *)if_list.next)->dev,
((struct batman_if *)if_list.next)->addr_str);
rcu_read_unlock();
spin_lock_irqsave(&orig_hash_lock, flags);
while (hash_iterate(orig_hash, &hashit)) {
orig_node = hashit.bucket->data;
if (!orig_node->router)
continue;
if (orig_node->router->tq_avg == 0)
continue;
batman_count++;
addr_to_string(orig_str, orig_node->orig);
addr_to_string(router_str, orig_node->router->addr);
seq_printf(seq, "%-17s (%3i) %17s [%10s]:",
orig_str, orig_node->router->tq_avg,
router_str, orig_node->router->if_incoming->dev);
list_for_each_entry(neigh_node, &orig_node->neigh_list, list) {
addr_to_string(orig_str, neigh_node->addr);
seq_printf(seq, " %17s (%3i)",
orig_str, neigh_node->tq_avg);
}
seq_printf(seq, "\n");
}
spin_unlock_irqrestore(&orig_hash_lock, flags);
if (batman_count == 0)
seq_printf(seq, "No batman nodes in range ... \n");
end:
return 0;
}
static int proc_originators_open(struct inode *inode, struct file *file)
{
return single_open(file, proc_originators_read, NULL);
}
static int proc_transt_local_read(struct seq_file *seq, void *offset)
{
char *buf;
buf = kmalloc(4096, GFP_KERNEL);
if (!buf)
return 0;
rcu_read_lock();
if (list_empty(&if_list)) {
rcu_read_unlock();
seq_printf(seq, "BATMAN disabled - please specify interfaces to enable it \n");
goto end;
}
rcu_read_unlock();
seq_printf(seq, "Locally retrieved addresses (from %s) announced via HNA:\n", soft_device->name);
hna_local_fill_buffer_text(buf, 4096);
seq_printf(seq, "%s", buf);
end:
kfree(buf);
return 0;
}
static int proc_transt_local_open(struct inode *inode, struct file *file)
{
return single_open(file, proc_transt_local_read, NULL);
}
static int proc_transt_global_read(struct seq_file *seq, void *offset)
{
char *buf;
buf = kmalloc(4096, GFP_KERNEL);
if (!buf)
return 0;
rcu_read_lock();
if (list_empty(&if_list)) {
rcu_read_unlock();
seq_printf(seq, "BATMAN disabled - please specify interfaces to enable it \n");
goto end;
}
rcu_read_unlock();
seq_printf(seq, "Globally announced HNAs received via the mesh (translation table):\n");
hna_global_fill_buffer_text(buf, 4096);
seq_printf(seq, "%s", buf);
end:
kfree(buf);
return 0;
}
static int proc_transt_global_open(struct inode *inode, struct file *file)
{
return single_open(file, proc_transt_global_read, NULL);
}
/* setting the mode of the vis server by the user */
static ssize_t proc_vis_srv_write(struct file *file, const char __user * buffer,
size_t count, loff_t *ppos)
{
char *vis_mode_string;
int not_copied = 0;
vis_mode_string = kmalloc(count, GFP_KERNEL);
if (!vis_mode_string)
return -ENOMEM;
not_copied = copy_from_user(vis_mode_string, buffer, count);
vis_mode_string[count - not_copied - 1] = 0;
if ((strcmp(vis_mode_string, "client") == 0) ||
(strcmp(vis_mode_string, "disabled") == 0)) {
printk(KERN_INFO "batman-adv:Setting VIS mode to client (disabling vis server)\n");
atomic_set(&vis_mode, VIS_TYPE_CLIENT_UPDATE);
} else if ((strcmp(vis_mode_string, "server") == 0) ||
(strcmp(vis_mode_string, "enabled") == 0)) {
printk(KERN_INFO "batman-adv:Setting VIS mode to server (enabling vis server)\n");
atomic_set(&vis_mode, VIS_TYPE_SERVER_SYNC);
} else
printk(KERN_ERR "batman-adv:Unknown VIS mode: %s\n",
vis_mode_string);
kfree(vis_mode_string);
return count;
}
static int proc_vis_srv_read(struct seq_file *seq, void *offset)
{
int vis_server = atomic_read(&vis_mode);
seq_printf(seq, "[%c] client mode (server disabled) \n",
(vis_server == VIS_TYPE_CLIENT_UPDATE) ? 'x' : ' ');
seq_printf(seq, "[%c] server mode (server enabled) \n",
(vis_server == VIS_TYPE_SERVER_SYNC) ? 'x' : ' ');
return 0;
}
static int proc_vis_srv_open(struct inode *inode, struct file *file)
{
return single_open(file, proc_vis_srv_read, NULL);
}
static int proc_vis_data_read(struct seq_file *seq, void *offset)
{
HASHIT(hashit);
struct vis_info *info;
struct vis_info_entry *entries;
HLIST_HEAD(vis_if_list);
int i;
char tmp_addr_str[ETH_STR_LEN];
unsigned long flags;
int vis_server = atomic_read(&vis_mode);
rcu_read_lock();
if (list_empty(&if_list) || (vis_server == VIS_TYPE_CLIENT_UPDATE)) {
rcu_read_unlock();
goto end;
}
rcu_read_unlock();
spin_lock_irqsave(&vis_hash_lock, flags);
while (hash_iterate(vis_hash, &hashit)) {
info = hashit.bucket->data;
entries = (struct vis_info_entry *)
((char *)info + sizeof(struct vis_info));
addr_to_string(tmp_addr_str, info->packet.vis_orig);
seq_printf(seq, "%s,", tmp_addr_str);
for (i = 0; i < info->packet.entries; i++) {
proc_vis_read_entry(seq, &entries[i], &vis_if_list,
info->packet.vis_orig);
}
/* add primary/secondary records */
proc_vis_read_prim_sec(seq, &vis_if_list);
seq_printf(seq, "\n");
}
spin_unlock_irqrestore(&vis_hash_lock, flags);
end:
return 0;
}
static int proc_vis_data_open(struct inode *inode, struct file *file)
{
return single_open(file, proc_vis_data_read, NULL);
}
static int proc_aggr_read(struct seq_file *seq, void *offset)
{
seq_printf(seq, "%i\n", atomic_read(&aggregation_enabled));
return 0;
}
static ssize_t proc_aggr_write(struct file *file, const char __user *buffer,
size_t count, loff_t *ppos)
{
char *aggr_string;
int not_copied = 0;
unsigned long aggregation_enabled_tmp;
int retval;
aggr_string = kmalloc(count, GFP_KERNEL);
if (!aggr_string)
return -ENOMEM;
not_copied = copy_from_user(aggr_string, buffer, count);
aggr_string[count - not_copied - 1] = 0;
retval = strict_strtoul(aggr_string, 10, &aggregation_enabled_tmp);
if (retval || aggregation_enabled_tmp > 1) {
printk(KERN_ERR "batman-adv:Aggregation can only be enabled (1) or disabled (0), given value: %li\n", aggregation_enabled_tmp);
} else {
printk(KERN_INFO "batman-adv:Changing aggregation from: %s (%i) to: %s (%li)\n",
(atomic_read(&aggregation_enabled) == 1 ?
"enabled" : "disabled"),
atomic_read(&aggregation_enabled),
(aggregation_enabled_tmp == 1 ? "enabled" : "disabled"),
aggregation_enabled_tmp);
atomic_set(&aggregation_enabled,
(unsigned)aggregation_enabled_tmp);
}
kfree(aggr_string);
return count;
}
static int proc_aggr_open(struct inode *inode, struct file *file)
{
return single_open(file, proc_aggr_read, NULL);
}
/* satisfying different prototypes ... */
static ssize_t proc_dummy_write(struct file *file, const char __user *buffer,
size_t count, loff_t *ppos)
{
return count;
}
static const struct file_operations proc_aggr_fops = {
.owner = THIS_MODULE,
.open = proc_aggr_open,
.read = seq_read,
.write = proc_aggr_write,
.llseek = seq_lseek,
.release = single_release,
};
static const struct file_operations proc_vis_srv_fops = {
.owner = THIS_MODULE,
.open = proc_vis_srv_open,
.read = seq_read,
.write = proc_vis_srv_write,
.llseek = seq_lseek,
.release = single_release,
};
static const struct file_operations proc_vis_data_fops = {
.owner = THIS_MODULE,
.open = proc_vis_data_open,
.read = seq_read,
.write = proc_dummy_write,
.llseek = seq_lseek,
.release = single_release,
};
static const struct file_operations proc_originators_fops = {
.owner = THIS_MODULE,
.open = proc_originators_open,
.read = seq_read,
.write = proc_dummy_write,
.llseek = seq_lseek,
.release = single_release,
};
static const struct file_operations proc_transt_local_fops = {
.owner = THIS_MODULE,
.open = proc_transt_local_open,
.read = seq_read,
.write = proc_dummy_write,
.llseek = seq_lseek,
.release = single_release,
};
static const struct file_operations proc_transt_global_fops = {
.owner = THIS_MODULE,
.open = proc_transt_global_open,
.read = seq_read,
.write = proc_dummy_write,
.llseek = seq_lseek,
.release = single_release,
};
static const struct file_operations proc_interfaces_fops = {
.owner = THIS_MODULE,
.open = proc_interfaces_open,
.read = seq_read,
.write = proc_interfaces_write,
.llseek = seq_lseek,
.release = single_release,
};
static const struct file_operations proc_orig_interval_fops = {
.owner = THIS_MODULE,
.open = proc_orig_interval_open,
.read = seq_read,
.write = proc_orig_interval_write,
.llseek = seq_lseek,
.release = single_release,
};
void cleanup_procfs(void)
{
if (proc_transt_global_file)
remove_proc_entry(PROC_FILE_TRANST_GLOBAL, proc_batman_dir);
if (proc_transt_local_file)
remove_proc_entry(PROC_FILE_TRANST_LOCAL, proc_batman_dir);
if (proc_originators_file)
remove_proc_entry(PROC_FILE_ORIGINATORS, proc_batman_dir);
if (proc_orig_interval_file)
remove_proc_entry(PROC_FILE_ORIG_INTERVAL, proc_batman_dir);
if (proc_interface_file)
remove_proc_entry(PROC_FILE_INTERFACES, proc_batman_dir);
if (proc_vis_data_file)
remove_proc_entry(PROC_FILE_VIS_DATA, proc_batman_dir);
if (proc_vis_srv_file)
remove_proc_entry(PROC_FILE_VIS_SRV, proc_batman_dir);
if (proc_aggr_file)
remove_proc_entry(PROC_FILE_AGGR, proc_batman_dir);
if (proc_batman_dir)
#ifdef __NET_NET_NAMESPACE_H
remove_proc_entry(PROC_ROOT_DIR, init_net.proc_net);
#else
remove_proc_entry(PROC_ROOT_DIR, proc_net);
#endif
}
int setup_procfs(void)
{
#ifdef __NET_NET_NAMESPACE_H
proc_batman_dir = proc_mkdir(PROC_ROOT_DIR, init_net.proc_net);
#else
proc_batman_dir = proc_mkdir(PROC_ROOT_DIR, proc_net);
#endif
if (!proc_batman_dir) {
printk(KERN_ERR "batman-adv: Registering the '/proc/net/%s' folder failed\n", PROC_ROOT_DIR);
return -EFAULT;
}
proc_interface_file = create_proc_entry(PROC_FILE_INTERFACES,
S_IWUSR | S_IRUGO,
proc_batman_dir);
if (proc_interface_file) {
proc_interface_file->proc_fops = &proc_interfaces_fops;
} else {
printk(KERN_ERR "batman-adv: Registering the '/proc/net/%s/%s' file failed\n", PROC_ROOT_DIR, PROC_FILE_INTERFACES);
cleanup_procfs();
return -EFAULT;
}
proc_orig_interval_file = create_proc_entry(PROC_FILE_ORIG_INTERVAL,
S_IWUSR | S_IRUGO,
proc_batman_dir);
if (proc_orig_interval_file) {
proc_orig_interval_file->proc_fops = &proc_orig_interval_fops;
} else {
printk(KERN_ERR "batman-adv: Registering the '/proc/net/%s/%s' file failed\n", PROC_ROOT_DIR, PROC_FILE_ORIG_INTERVAL);
cleanup_procfs();
return -EFAULT;
}
proc_originators_file = create_proc_entry(PROC_FILE_ORIGINATORS,
S_IRUGO, proc_batman_dir);
if (proc_originators_file) {
proc_originators_file->proc_fops = &proc_originators_fops;
} else {
printk(KERN_ERR "batman-adv: Registering the '/proc/net/%s/%s' file failed\n", PROC_ROOT_DIR, PROC_FILE_ORIGINATORS);
cleanup_procfs();
return -EFAULT;
}
proc_transt_local_file = create_proc_entry(PROC_FILE_TRANST_LOCAL,
S_IRUGO, proc_batman_dir);
if (proc_transt_local_file) {
proc_transt_local_file->proc_fops = &proc_transt_local_fops;
} else {
printk(KERN_ERR "batman-adv: Registering the '/proc/net/%s/%s' file failed\n", PROC_ROOT_DIR, PROC_FILE_TRANST_LOCAL);
cleanup_procfs();
return -EFAULT;
}
proc_transt_global_file = create_proc_entry(PROC_FILE_TRANST_GLOBAL,
S_IRUGO, proc_batman_dir);
if (proc_transt_global_file) {
proc_transt_global_file->proc_fops = &proc_transt_global_fops;
} else {
printk(KERN_ERR "batman-adv: Registering the '/proc/net/%s/%s' file failed\n", PROC_ROOT_DIR, PROC_FILE_TRANST_GLOBAL);
cleanup_procfs();
return -EFAULT;
}
proc_vis_srv_file = create_proc_entry(PROC_FILE_VIS_SRV,
S_IWUSR | S_IRUGO,
proc_batman_dir);
if (proc_vis_srv_file) {
proc_vis_srv_file->proc_fops = &proc_vis_srv_fops;
} else {
printk(KERN_ERR "batman-adv: Registering the '/proc/net/%s/%s' file failed\n", PROC_ROOT_DIR, PROC_FILE_VIS_SRV);
cleanup_procfs();
return -EFAULT;
}
proc_vis_data_file = create_proc_entry(PROC_FILE_VIS_DATA, S_IRUGO,
proc_batman_dir);
if (proc_vis_data_file) {
proc_vis_data_file->proc_fops = &proc_vis_data_fops;
} else {
printk(KERN_ERR "batman-adv: Registering the '/proc/net/%s/%s' file failed\n", PROC_ROOT_DIR, PROC_FILE_VIS_DATA);
cleanup_procfs();
return -EFAULT;
}
proc_aggr_file = create_proc_entry(PROC_FILE_AGGR, S_IWUSR | S_IRUGO,
proc_batman_dir);
if (proc_aggr_file) {
proc_aggr_file->proc_fops = &proc_aggr_fops;
} else {
printk(KERN_ERR "batman-adv: Registering the '/proc/net/%s/%s' file failed\n", PROC_ROOT_DIR, PROC_FILE_AGGR);
cleanup_procfs();
return -EFAULT;
}
return 0;
}

View file

@ -1,40 +0,0 @@
/*
* Copyright (C) 2007-2009 B.A.T.M.A.N. contributors:
*
* Marek Lindner, Simon Wunderlich
*
* 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/proc_fs.h>
#include <linux/seq_file.h>
#define PROC_ROOT_DIR "batman-adv"
#define PROC_FILE_INTERFACES "interfaces"
#define PROC_FILE_ORIG_INTERVAL "orig_interval"
#define PROC_FILE_ORIGINATORS "originators"
#define PROC_FILE_GATEWAYS "gateways"
#define PROC_FILE_LOG "log"
#define PROC_FILE_LOG_LEVEL "log_level"
#define PROC_FILE_TRANST_LOCAL "transtable_local"
#define PROC_FILE_TRANST_GLOBAL "transtable_global"
#define PROC_FILE_VIS_SRV "vis_server"
#define PROC_FILE_VIS_DATA "vis_data"
#define PROC_FILE_AGGR "aggregate_ogm"
void cleanup_procfs(void);
int setup_procfs(void);

View file

@ -1,5 +1,5 @@
/*
* Copyright (C) 2007-2009 B.A.T.M.A.N. contributors:
* Copyright (C) 2007-2010 B.A.T.M.A.N. contributors:
*
* Marek Lindner
*

View file

@ -1,5 +1,5 @@
/*
* Copyright (C) 2007-2009 B.A.T.M.A.N. contributors:
* Copyright (C) 2007-2010 B.A.T.M.A.N. contributors:
*
* Marek Lindner
*

View file

@ -1,5 +1,5 @@
/*
* Copyright (C) 2007-2009 B.A.T.M.A.N. contributors:
* Copyright (C) 2007-2010 B.A.T.M.A.N. contributors:
*
* Marek Lindner, Simon Wunderlich
*
@ -94,14 +94,13 @@ static void update_route(struct orig_node *orig_node,
/* route changed */
} else {
bat_dbg(DBG_ROUTES, "Changing route towards: %pM (now via %pM - was via %pM)\n", orig_node->orig, neigh_node->addr, orig_node->router->addr);
bat_dbg(DBG_ROUTES,
"Changing route towards: %pM "
"(now via %pM - was via %pM)\n",
orig_node->orig, neigh_node->addr,
orig_node->router->addr);
}
if (neigh_node != NULL)
orig_node->batman_if = neigh_node->if_incoming;
else
orig_node->batman_if = NULL;
orig_node->router = neigh_node;
}
@ -210,9 +209,13 @@ static int isBidirectionalNeigh(struct orig_node *orig_node,
batman_packet->tq = ((batman_packet->tq *
orig_neigh_node->tq_own *
orig_neigh_node->tq_asym_penalty) /
(TQ_MAX_VALUE * TQ_MAX_VALUE));
(TQ_MAX_VALUE * TQ_MAX_VALUE));
bat_dbg(DBG_BATMAN, "bidirectional: orig = %-15pM neigh = %-15pM => own_bcast = %2i, real recv = %2i, local tq: %3i, asym_penalty: %3i, total tq: %3i \n",
bat_dbg(DBG_BATMAN,
"bidirectional: "
"orig = %-15pM neigh = %-15pM => own_bcast = %2i, "
"real recv = %2i, local tq: %3i, asym_penalty: %3i, "
"total tq: %3i\n",
orig_node->orig, orig_neigh_node->orig, total_count,
neigh_node->real_packet_count, orig_neigh_node->tq_own,
orig_neigh_node->tq_asym_penalty, batman_packet->tq);
@ -234,7 +237,8 @@ static void update_orig(struct orig_node *orig_node, struct ethhdr *ethhdr,
struct neigh_node *neigh_node = NULL, *tmp_neigh_node = NULL;
int tmp_hna_buff_len;
bat_dbg(DBG_BATMAN, "update_originator(): Searching and updating originator entry of received packet \n");
bat_dbg(DBG_BATMAN, "update_originator(): "
"Searching and updating originator entry of received packet\n");
list_for_each_entry(tmp_neigh_node, &orig_node->neigh_list, list) {
if (compare_orig(tmp_neigh_node->addr, ethhdr->h_source) &&
@ -309,6 +313,38 @@ update_hna:
update_routes(orig_node, orig_node->router, hna_buff, tmp_hna_buff_len);
}
/* checks whether the host restarted and is in the protection time.
* returns:
* 0 if the packet is to be accepted
* 1 if the packet is to be ignored.
*/
static int window_protected(int16_t seq_num_diff,
unsigned long *last_reset)
{
if ((seq_num_diff <= -TQ_LOCAL_WINDOW_SIZE)
|| (seq_num_diff >= EXPECTED_SEQNO_RANGE)) {
if (time_after(jiffies, *last_reset +
msecs_to_jiffies(RESET_PROTECTION_MS))) {
*last_reset = jiffies;
bat_dbg(DBG_BATMAN,
"old packet received, start protection\n");
return 0;
} else
return 1;
}
return 0;
}
/* processes a batman packet for all interfaces, adjusts the sequence number and
* finds out whether it is a duplicate.
* returns:
* 1 the packet is a duplicate
* 0 the packet has not yet been received
* -1 the packet is old and has been received while the seqno window
* was protected. Caller should drop it.
*/
static char count_real_packets(struct ethhdr *ethhdr,
struct batman_packet *batman_packet,
struct batman_if *if_incoming)
@ -316,32 +352,42 @@ static char count_real_packets(struct ethhdr *ethhdr,
struct orig_node *orig_node;
struct neigh_node *tmp_neigh_node;
char is_duplicate = 0;
uint16_t seq_diff;
int16_t seq_diff;
int need_update = 0;
int set_mark;
orig_node = get_orig_node(batman_packet->orig);
if (orig_node == NULL)
return 0;
seq_diff = batman_packet->seqno - orig_node->last_real_seqno;
/* signalize caller that the packet is to be dropped. */
if (window_protected(seq_diff, &orig_node->batman_seqno_reset))
return -1;
list_for_each_entry(tmp_neigh_node, &orig_node->neigh_list, list) {
if (!is_duplicate)
is_duplicate =
get_bit_status(tmp_neigh_node->real_bits,
is_duplicate |= get_bit_status(tmp_neigh_node->real_bits,
orig_node->last_real_seqno,
batman_packet->seqno);
seq_diff = batman_packet->seqno - orig_node->last_real_seqno;
if (compare_orig(tmp_neigh_node->addr, ethhdr->h_source) &&
(tmp_neigh_node->if_incoming == if_incoming))
bit_get_packet(tmp_neigh_node->real_bits, seq_diff, 1);
set_mark = 1;
else
bit_get_packet(tmp_neigh_node->real_bits, seq_diff, 0);
set_mark = 0;
/* if the window moved, set the update flag. */
need_update |= bit_get_packet(tmp_neigh_node->real_bits,
seq_diff, set_mark);
tmp_neigh_node->real_packet_count =
bit_packet_count(tmp_neigh_node->real_bits);
}
if (!is_duplicate) {
bat_dbg(DBG_BATMAN, "updating last_seqno: old %d, new %d \n",
if (need_update) {
bat_dbg(DBG_BATMAN, "updating last_seqno: old %d, new %d\n",
orig_node->last_real_seqno, batman_packet->seqno);
orig_node->last_real_seqno = batman_packet->seqno;
}
@ -385,14 +431,16 @@ void receive_bat_packet(struct ethhdr *ethhdr,
is_single_hop_neigh = (compare_orig(ethhdr->h_source,
batman_packet->orig) ? 1 : 0);
bat_dbg(DBG_BATMAN, "Received BATMAN packet via NB: %pM, IF: %s [%s] (from OG: %pM, via prev OG: %pM, seqno %d, tq %d, TTL %d, V %d, IDF %d) \n",
bat_dbg(DBG_BATMAN, "Received BATMAN packet via NB: %pM, IF: %s [%s] "
"(from OG: %pM, via prev OG: %pM, seqno %d, tq %d, "
"TTL %d, V %d, IDF %d)\n",
ethhdr->h_source, if_incoming->dev, if_incoming->addr_str,
batman_packet->orig, batman_packet->prev_sender,
batman_packet->seqno, batman_packet->tq, batman_packet->ttl,
batman_packet->version, has_directlink_flag);
list_for_each_entry_rcu(batman_if, &if_list, list) {
if (batman_if->if_active != IF_ACTIVE)
if (batman_if->if_status != IF_ACTIVE)
continue;
if (compare_orig(ethhdr->h_source,
@ -420,13 +468,16 @@ void receive_bat_packet(struct ethhdr *ethhdr,
if (is_my_addr) {
bat_dbg(DBG_BATMAN,
"Drop packet: received my own broadcast (sender: %pM)\n",
"Drop packet: received my own broadcast (sender: %pM"
")\n",
ethhdr->h_source);
return;
}
if (is_broadcast) {
bat_dbg(DBG_BATMAN, "Drop packet: ignoring all packets with broadcast source addr (sender: %pM) \n", ethhdr->h_source);
bat_dbg(DBG_BATMAN, "Drop packet: "
"ignoring all packets with broadcast source addr (sender: %pM"
")\n", ethhdr->h_source);
return;
}
@ -454,28 +505,37 @@ void receive_bat_packet(struct ethhdr *ethhdr,
bit_packet_count(word);
}
bat_dbg(DBG_BATMAN, "Drop packet: originator packet from myself (via neighbor) \n");
return;
}
if (batman_packet->tq == 0) {
count_real_packets(ethhdr, batman_packet, if_incoming);
bat_dbg(DBG_BATMAN, "Drop packet: originator packet with tq equal 0 \n");
bat_dbg(DBG_BATMAN, "Drop packet: "
"originator packet from myself (via neighbor)\n");
return;
}
if (is_my_oldorig) {
bat_dbg(DBG_BATMAN, "Drop packet: ignoring all rebroadcast echos (sender: %pM) \n", ethhdr->h_source);
bat_dbg(DBG_BATMAN,
"Drop packet: ignoring all rebroadcast echos (sender: "
"%pM)\n", ethhdr->h_source);
return;
}
is_duplicate = count_real_packets(ethhdr, batman_packet, if_incoming);
orig_node = get_orig_node(batman_packet->orig);
if (orig_node == NULL)
return;
is_duplicate = count_real_packets(ethhdr, batman_packet, if_incoming);
if (is_duplicate == -1) {
bat_dbg(DBG_BATMAN,
"Drop packet: packet within seqno protection time "
"(sender: %pM)\n", ethhdr->h_source);
return;
}
if (batman_packet->tq == 0) {
bat_dbg(DBG_BATMAN,
"Drop packet: originator packet with tq equal 0\n");
return;
}
/* avoid temporary routing loops */
if ((orig_node->router) &&
(orig_node->router->orig_node->router) &&
@ -484,7 +544,9 @@ void receive_bat_packet(struct ethhdr *ethhdr,
!(compare_orig(batman_packet->orig, batman_packet->prev_sender)) &&
(compare_orig(orig_node->router->addr,
orig_node->router->orig_node->router->addr))) {
bat_dbg(DBG_BATMAN, "Drop packet: ignoring all rebroadcast packets that may make me loop (sender: %pM) \n", ethhdr->h_source);
bat_dbg(DBG_BATMAN,
"Drop packet: ignoring all rebroadcast packets that "
"may make me loop (sender: %pM)\n", ethhdr->h_source);
return;
}
@ -522,7 +584,8 @@ void receive_bat_packet(struct ethhdr *ethhdr,
schedule_forward_packet(orig_node, ethhdr, batman_packet,
1, hna_buff_len, if_incoming);
bat_dbg(DBG_BATMAN, "Forwarding packet: rebroadcast neighbor packet with direct link flag\n");
bat_dbg(DBG_BATMAN, "Forwarding packet: "
"rebroadcast neighbor packet with direct link flag\n");
return;
}
@ -549,6 +612,7 @@ int recv_bat_packet(struct sk_buff *skb,
{
struct ethhdr *ethhdr;
unsigned long flags;
struct sk_buff *skb_old;
/* drop packet if it has not necessary minimum size */
if (skb_headlen(skb) < sizeof(struct batman_packet))
@ -564,12 +628,20 @@ int recv_bat_packet(struct sk_buff *skb,
if (is_bcast(ethhdr->h_source))
return NET_RX_DROP;
spin_lock_irqsave(&orig_hash_lock, flags);
/* TODO: we use headlen instead of "length", because
* only this data is paged in. */
/* TODO: is another skb_copy needed here? there will be
* written on the data, but nobody (?) should further use
* this data */
/* create a copy of the skb, if needed, to modify it. */
if (!skb_clone_writable(skb, skb_headlen(skb))) {
skb_old = skb;
skb = skb_copy(skb, GFP_ATOMIC);
if (!skb)
return NET_RX_DROP;
ethhdr = (struct ethhdr *)skb_mac_header(skb);
kfree_skb(skb_old);
}
spin_lock_irqsave(&orig_hash_lock, flags);
receive_aggr_bat_packet(ethhdr,
skb->data,
skb_headlen(skb),
@ -591,8 +663,8 @@ static int recv_my_icmp_packet(struct sk_buff *skb)
unsigned long flags;
uint8_t dstaddr[ETH_ALEN];
icmp_packet = (struct icmp_packet *) skb->data;
ethhdr = (struct ethhdr *) skb_mac_header(skb);
icmp_packet = (struct icmp_packet *)skb->data;
ethhdr = (struct ethhdr *)skb_mac_header(skb);
/* add data to device queue */
if (icmp_packet->msg_type != ECHO_REQUEST) {
@ -608,12 +680,11 @@ static int recv_my_icmp_packet(struct sk_buff *skb)
ret = NET_RX_DROP;
if ((orig_node != NULL) &&
(orig_node->batman_if != NULL) &&
(orig_node->router != NULL)) {
/* don't lock while sending the packets ... we therefore
* copy the required data before sending */
batman_if = orig_node->batman_if;
batman_if = orig_node->router->if_incoming;
memcpy(dstaddr, orig_node->router->addr, ETH_ALEN);
spin_unlock_irqrestore(&orig_hash_lock, flags);
@ -624,7 +695,9 @@ static int recv_my_icmp_packet(struct sk_buff *skb)
skb = skb_copy(skb, GFP_ATOMIC);
if (!skb)
return NET_RX_DROP;
icmp_packet = (struct icmp_packet *) skb->data;
icmp_packet = (struct icmp_packet *)skb->data;
ethhdr = (struct ethhdr *)skb_mac_header(skb);
kfree_skb(skb_old);
}
@ -658,8 +731,10 @@ static int recv_icmp_ttl_exceeded(struct sk_buff *skb)
/* send TTL exceeded if packet is an echo request (traceroute) */
if (icmp_packet->msg_type != ECHO_REQUEST) {
printk(KERN_WARNING "batman-adv:Warning - can't forward icmp packet from %pM to %pM: ttl exceeded\n",
icmp_packet->orig, icmp_packet->dst);
printk(KERN_WARNING "batman-adv:"
"Warning - can't forward icmp packet from %pM to %pM: "
"ttl exceeded\n",
icmp_packet->orig, icmp_packet->dst);
return NET_RX_DROP;
}
@ -670,12 +745,11 @@ static int recv_icmp_ttl_exceeded(struct sk_buff *skb)
ret = NET_RX_DROP;
if ((orig_node != NULL) &&
(orig_node->batman_if != NULL) &&
(orig_node->router != NULL)) {
/* don't lock while sending the packets ... we therefore
* copy the required data before sending */
batman_if = orig_node->batman_if;
batman_if = orig_node->router->if_incoming;
memcpy(dstaddr, orig_node->router->addr, ETH_ALEN);
spin_unlock_irqrestore(&orig_hash_lock, flags);
@ -686,6 +760,7 @@ static int recv_icmp_ttl_exceeded(struct sk_buff *skb)
if (!skb)
return NET_RX_DROP;
icmp_packet = (struct icmp_packet *) skb->data;
ethhdr = (struct ethhdr *)skb_mac_header(skb);
kfree_skb(skb_old);
}
@ -734,7 +809,7 @@ int recv_icmp_packet(struct sk_buff *skb)
if (!is_my_mac(ethhdr->h_dest))
return NET_RX_DROP;
icmp_packet = (struct icmp_packet *) skb->data;
icmp_packet = (struct icmp_packet *)skb->data;
/* packet for me */
if (is_my_mac(icmp_packet->dst))
@ -752,12 +827,11 @@ int recv_icmp_packet(struct sk_buff *skb)
hash_find(orig_hash, icmp_packet->dst));
if ((orig_node != NULL) &&
(orig_node->batman_if != NULL) &&
(orig_node->router != NULL)) {
/* don't lock while sending the packets ... we therefore
* copy the required data before sending */
batman_if = orig_node->batman_if;
batman_if = orig_node->router->if_incoming;
memcpy(dstaddr, orig_node->router->addr, ETH_ALEN);
spin_unlock_irqrestore(&orig_hash_lock, flags);
@ -767,7 +841,8 @@ int recv_icmp_packet(struct sk_buff *skb)
skb = skb_copy(skb, GFP_ATOMIC);
if (!skb)
return NET_RX_DROP;
icmp_packet = (struct icmp_packet *) skb->data;
icmp_packet = (struct icmp_packet *)skb->data;
ethhdr = (struct ethhdr *)skb_mac_header(skb);
kfree_skb(skb_old);
}
@ -824,7 +899,9 @@ int recv_unicast_packet(struct sk_buff *skb)
/* TTL exceeded */
if (unicast_packet->ttl < 2) {
printk(KERN_WARNING "batman-adv:Warning - can't forward unicast packet from %pM to %pM: ttl exceeded\n",
printk(KERN_WARNING "batman-adv:Warning - "
"can't forward unicast packet from %pM to %pM: "
"ttl exceeded\n",
ethhdr->h_source, unicast_packet->dest);
return NET_RX_DROP;
}
@ -836,12 +913,11 @@ int recv_unicast_packet(struct sk_buff *skb)
hash_find(orig_hash, unicast_packet->dest));
if ((orig_node != NULL) &&
(orig_node->batman_if != NULL) &&
(orig_node->router != NULL)) {
/* don't lock while sending the packets ... we therefore
* copy the required data before sending */
batman_if = orig_node->batman_if;
batman_if = orig_node->router->if_incoming;
memcpy(dstaddr, orig_node->router->addr, ETH_ALEN);
spin_unlock_irqrestore(&orig_hash_lock, flags);
@ -851,7 +927,8 @@ int recv_unicast_packet(struct sk_buff *skb)
skb = skb_copy(skb, GFP_ATOMIC);
if (!skb)
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);
kfree_skb(skb_old);
}
/* decrement ttl */
@ -867,13 +944,13 @@ int recv_unicast_packet(struct sk_buff *skb)
return ret;
}
int recv_bcast_packet(struct sk_buff *skb)
{
struct orig_node *orig_node;
struct bcast_packet *bcast_packet;
struct ethhdr *ethhdr;
int hdr_size = sizeof(struct bcast_packet);
int16_t seq_diff;
unsigned long flags;
/* drop packet if it has not necessary minimum size */
@ -894,7 +971,7 @@ int recv_bcast_packet(struct sk_buff *skb)
if (is_my_mac(ethhdr->h_source))
return NET_RX_DROP;
bcast_packet = (struct bcast_packet *) skb->data;
bcast_packet = (struct bcast_packet *)skb->data;
/* ignore broadcasts originated by myself */
if (is_my_mac(bcast_packet->orig))
@ -909,7 +986,7 @@ int recv_bcast_packet(struct sk_buff *skb)
return NET_RX_DROP;
}
/* check flood history */
/* check whether the packet is a duplicate */
if (get_bit_status(orig_node->bcast_bits,
orig_node->last_bcast_seqno,
ntohs(bcast_packet->seqno))) {
@ -917,14 +994,20 @@ int recv_bcast_packet(struct sk_buff *skb)
return NET_RX_DROP;
}
/* mark broadcast in flood history */
if (bit_get_packet(orig_node->bcast_bits,
ntohs(bcast_packet->seqno) -
orig_node->last_bcast_seqno, 1))
seq_diff = ntohs(bcast_packet->seqno) - orig_node->last_bcast_seqno;
/* check whether the packet is old and the host just restarted. */
if (window_protected(seq_diff, &orig_node->bcast_seqno_reset)) {
spin_unlock_irqrestore(&orig_hash_lock, flags);
return NET_RX_DROP;
}
/* mark broadcast in flood history, update window position
* if required. */
if (bit_get_packet(orig_node->bcast_bits, seq_diff, 1))
orig_node->last_bcast_seqno = ntohs(bcast_packet->seqno);
spin_unlock_irqrestore(&orig_hash_lock, flags);
/* rebroadcast packet */
add_bcast_packet_to_list(skb);
@ -938,6 +1021,7 @@ int recv_vis_packet(struct sk_buff *skb)
{
struct vis_packet *vis_packet;
struct ethhdr *ethhdr;
struct bat_priv *bat_priv;
int hdr_size = sizeof(struct vis_packet);
if (skb_headlen(skb) < hdr_size)
@ -957,15 +1041,20 @@ int recv_vis_packet(struct sk_buff *skb)
if (is_my_mac(vis_packet->sender_orig))
return NET_RX_DROP;
/* FIXME: each batman_if will be attached to a softif */
bat_priv = netdev_priv(soft_device);
switch (vis_packet->vis_type) {
case VIS_TYPE_SERVER_SYNC:
/* TODO: handle fragmented skbs properly */
receive_server_sync_packet(vis_packet, skb_headlen(skb));
receive_server_sync_packet(bat_priv, vis_packet,
skb_headlen(skb));
break;
case VIS_TYPE_CLIENT_UPDATE:
/* TODO: handle fragmented skbs properly */
receive_client_update_packet(vis_packet, skb_headlen(skb));
receive_client_update_packet(bat_priv, vis_packet,
skb_headlen(skb));
break;
default: /* ignore unknown packet */

View file

@ -1,5 +1,5 @@
/*
* Copyright (C) 2007-2009 B.A.T.M.A.N. contributors:
* Copyright (C) 2007-2010 B.A.T.M.A.N. contributors:
*
* Marek Lindner, Simon Wunderlich
*

View file

@ -1,5 +1,5 @@
/*
* Copyright (C) 2007-2009 B.A.T.M.A.N. contributors:
* Copyright (C) 2007-2010 B.A.T.M.A.N. contributors:
*
* Marek Lindner, Simon Wunderlich
*
@ -36,25 +36,17 @@ static uint8_t hop_penalty(const uint8_t tq)
}
/* when do we schedule our own packet to be sent */
static unsigned long own_send_time(void)
static unsigned long own_send_time(struct bat_priv *bat_priv)
{
return jiffies +
(((atomic_read(&originator_interval) - JITTER +
(((atomic_read(&bat_priv->orig_interval) - JITTER +
(random32() % 2*JITTER)) * HZ) / 1000);
}
/* when do we schedule a forwarded packet to be sent */
static unsigned long forward_send_time(void)
static unsigned long forward_send_time(struct bat_priv *bat_priv)
{
unsigned long send_time = jiffies; /* Starting now plus... */
if (atomic_read(&aggregation_enabled))
send_time += (((MAX_AGGREGATION_MS - (JITTER/2) +
(random32() % JITTER)) * HZ) / 1000);
else
send_time += (((random32() % (JITTER/2)) * HZ) / 1000);
return send_time;
return jiffies + (((random32() % (JITTER/2)) * HZ) / 1000);
}
/* send out an already prepared packet to the given address via the
@ -65,7 +57,7 @@ int send_skb_packet(struct sk_buff *skb,
{
struct ethhdr *ethhdr;
if (batman_if->if_active != IF_ACTIVE)
if (batman_if->if_status != IF_ACTIVE)
goto send_skb_err;
if (unlikely(!batman_if->net_dev))
@ -73,7 +65,8 @@ int send_skb_packet(struct sk_buff *skb,
if (!(batman_if->net_dev->flags & IFF_UP)) {
printk(KERN_WARNING
"batman-adv:Interface %s is not up - can't send packet via that interface!\n",
"batman-adv:Interface %s "
"is not up - can't send packet via that interface!\n",
batman_if->dev);
goto send_skb_err;
}
@ -131,10 +124,11 @@ static void send_packet_to_if(struct forw_packet *forw_packet,
int16_t buff_pos;
struct batman_packet *batman_packet;
if (batman_if->if_active != IF_ACTIVE)
if (batman_if->if_status != IF_ACTIVE)
return;
packet_num = buff_pos = 0;
packet_num = 0;
buff_pos = 0;
batman_packet = (struct batman_packet *)
(forw_packet->packet_buff);
@ -155,9 +149,9 @@ static void send_packet_to_if(struct forw_packet *forw_packet,
"Sending own" :
"Forwarding"));
bat_dbg(DBG_BATMAN,
"%s %spacket (originator %pM, seqno %d, TQ %d, TTL %d, IDF %s) on interface %s [%s]\n",
fwd_str,
(packet_num > 0 ? "aggregated " : ""),
"%s %spacket (originator %pM, seqno %d, TQ %d, TTL %d,"
" IDF %s) on interface %s [%s]\n",
fwd_str, (packet_num > 0 ? "aggregated " : ""),
batman_packet->orig, ntohs(batman_packet->seqno),
batman_packet->tq, batman_packet->ttl,
(batman_packet->flags & DIRECTLINK ?
@ -185,11 +179,12 @@ static void send_packet(struct forw_packet *forw_packet)
unsigned char directlink = (batman_packet->flags & DIRECTLINK ? 1 : 0);
if (!forw_packet->if_incoming) {
printk(KERN_ERR "batman-adv: Error - can't forward packet: incoming iface not specified\n");
printk(KERN_ERR "batman-adv: Error - can't forward packet: "
"incoming iface not specified\n");
return;
}
if (forw_packet->if_incoming->if_active != IF_ACTIVE)
if (forw_packet->if_incoming->if_status != IF_ACTIVE)
return;
/* multihomed peer assumed */
@ -199,7 +194,8 @@ static void send_packet(struct forw_packet *forw_packet)
/* FIXME: what about aggregated packets ? */
bat_dbg(DBG_BATMAN,
"%s packet (originator %pM, seqno %d, TTL %d) on interface %s [%s]\n",
"%s packet (originator %pM, seqno %d, TTL %d) "
"on interface %s [%s]\n",
(forw_packet->own ? "Sending own" : "Forwarding"),
batman_packet->orig, ntohs(batman_packet->seqno),
batman_packet->ttl, forw_packet->if_incoming->dev,
@ -246,9 +242,17 @@ static void rebuild_batman_packet(struct batman_if *batman_if)
void schedule_own_packet(struct batman_if *batman_if)
{
/* FIXME: each batman_if will be attached to a softif */
struct bat_priv *bat_priv = netdev_priv(soft_device);
unsigned long send_time;
struct batman_packet *batman_packet;
int vis_server = atomic_read(&vis_mode);
int vis_server;
if ((batman_if->if_status == IF_NOT_IN_USE) ||
(batman_if->if_status == IF_TO_BE_REMOVED))
return;
vis_server = atomic_read(&bat_priv->vis_mode);
/**
* the interface gets activated here to avoid race conditions between
@ -257,11 +261,12 @@ void schedule_own_packet(struct batman_if *batman_if)
* outdated packets (especially uninitialized mac addresses) in the
* packet queue
*/
if (batman_if->if_active == IF_TO_BE_ACTIVATED)
batman_if->if_active = IF_ACTIVE;
if (batman_if->if_status == IF_TO_BE_ACTIVATED)
batman_if->if_status = IF_ACTIVE;
/* if local hna has changed and interface is a primary interface */
if ((atomic_read(&hna_local_changed)) && (batman_if->if_num == 0))
if ((atomic_read(&hna_local_changed)) &&
(batman_if == bat_priv->primary_if))
rebuild_batman_packet(batman_if);
/**
@ -276,15 +281,17 @@ void schedule_own_packet(struct batman_if *batman_if)
if (vis_server == VIS_TYPE_SERVER_SYNC)
batman_packet->flags = VIS_SERVER;
else
batman_packet->flags = 0;
batman_packet->flags &= ~VIS_SERVER;
/* could be read by receive_bat_packet() */
atomic_inc(&batman_if->seqno);
slide_own_bcast_window(batman_if);
send_time = own_send_time();
add_bat_packet_to_list(batman_if->packet_buff,
batman_if->packet_len, batman_if, 1, send_time);
send_time = own_send_time(bat_priv);
add_bat_packet_to_list(bat_priv,
batman_if->packet_buff,
batman_if->packet_len,
batman_if, 1, send_time);
}
void schedule_forward_packet(struct orig_node *orig_node,
@ -293,11 +300,13 @@ void schedule_forward_packet(struct orig_node *orig_node,
uint8_t directlink, int hna_buff_len,
struct batman_if *if_incoming)
{
/* FIXME: each batman_if will be attached to a softif */
struct bat_priv *bat_priv = netdev_priv(soft_device);
unsigned char in_tq, in_ttl, tq_avg = 0;
unsigned long send_time;
if (batman_packet->ttl <= 1) {
bat_dbg(DBG_BATMAN, "ttl exceeded \n");
bat_dbg(DBG_BATMAN, "ttl exceeded\n");
return;
}
@ -316,7 +325,8 @@ void schedule_forward_packet(struct orig_node *orig_node,
batman_packet->tq = orig_node->router->tq_avg;
if (orig_node->router->last_ttl)
batman_packet->ttl = orig_node->router->last_ttl - 1;
batman_packet->ttl = orig_node->router->last_ttl
- 1;
}
tq_avg = orig_node->router->tq_avg;
@ -325,7 +335,8 @@ void schedule_forward_packet(struct orig_node *orig_node,
/* apply hop penalty */
batman_packet->tq = hop_penalty(batman_packet->tq);
bat_dbg(DBG_BATMAN, "Forwarding packet: tq_orig: %i, tq_avg: %i, tq_forw: %i, ttl_orig: %i, ttl_forw: %i \n",
bat_dbg(DBG_BATMAN, "Forwarding packet: tq_orig: %i, tq_avg: %i, "
"tq_forw: %i, ttl_orig: %i, ttl_forw: %i\n",
in_tq, tq_avg, batman_packet->tq, in_ttl - 1,
batman_packet->ttl);
@ -336,8 +347,9 @@ void schedule_forward_packet(struct orig_node *orig_node,
else
batman_packet->flags &= ~DIRECTLINK;
send_time = forward_send_time();
add_bat_packet_to_list((unsigned char *)batman_packet,
send_time = forward_send_time(bat_priv);
add_bat_packet_to_list(bat_priv,
(unsigned char *)batman_packet,
sizeof(struct batman_packet) + hna_buff_len,
if_incoming, 0, send_time);
}
@ -368,19 +380,32 @@ static void _add_bcast_packet_to_list(struct forw_packet *forw_packet,
send_time);
}
void add_bcast_packet_to_list(struct sk_buff *skb)
#define atomic_dec_not_zero(v) atomic_add_unless((v), -1, 0)
/* add a broadcast packet to the queue and setup timers. broadcast packets
* are sent multiple times to increase probability for beeing received.
*
* This function returns NETDEV_TX_OK on success and NETDEV_TX_BUSY on
* errors.
*
* The skb is not consumed, so the caller should make sure that the
* skb is freed. */
int add_bcast_packet_to_list(struct sk_buff *skb)
{
struct forw_packet *forw_packet;
if (!atomic_dec_not_zero(&bcast_queue_left)) {
bat_dbg(DBG_BATMAN, "bcast packet queue full\n");
goto out;
}
forw_packet = kmalloc(sizeof(struct forw_packet), GFP_ATOMIC);
if (!forw_packet)
return;
goto out_and_inc;
skb = skb_copy(skb, GFP_ATOMIC);
if (!skb) {
kfree(forw_packet);
return;
}
if (!skb)
goto packet_free;
skb_reset_mac_header(skb);
@ -391,6 +416,14 @@ void add_bcast_packet_to_list(struct sk_buff *skb)
forw_packet->num_packets = 0;
_add_bcast_packet_to_list(forw_packet, 1);
return NETDEV_TX_OK;
packet_free:
kfree(forw_packet);
out_and_inc:
atomic_inc(&bcast_queue_left);
out:
return NETDEV_TX_BUSY;
}
void send_outstanding_bcast_packet(struct work_struct *work)
@ -425,8 +458,10 @@ void send_outstanding_bcast_packet(struct work_struct *work)
if ((forw_packet->num_packets < 3) &&
(atomic_read(&module_state) != MODULE_DEACTIVATING))
_add_bcast_packet_to_list(forw_packet, ((5 * HZ) / 1000));
else
else {
forw_packet_free(forw_packet);
atomic_inc(&bcast_queue_left);
}
}
void send_outstanding_bat_packet(struct work_struct *work)
@ -452,22 +487,38 @@ void send_outstanding_bat_packet(struct work_struct *work)
(atomic_read(&module_state) != MODULE_DEACTIVATING))
schedule_own_packet(forw_packet->if_incoming);
/* don't count own packet */
if (!forw_packet->own)
atomic_inc(&batman_queue_left);
forw_packet_free(forw_packet);
}
void purge_outstanding_packets(void)
void purge_outstanding_packets(struct batman_if *batman_if)
{
struct forw_packet *forw_packet;
struct hlist_node *tmp_node, *safe_tmp_node;
unsigned long flags;
bat_dbg(DBG_BATMAN, "purge_outstanding_packets()\n");
if (batman_if)
bat_dbg(DBG_BATMAN, "purge_outstanding_packets(): %s\n",
batman_if->dev);
else
bat_dbg(DBG_BATMAN, "purge_outstanding_packets()\n");
/* free bcast list */
spin_lock_irqsave(&forw_bcast_list_lock, flags);
hlist_for_each_entry_safe(forw_packet, tmp_node, safe_tmp_node,
&forw_bcast_list, list) {
/**
* if purge_outstanding_packets() was called with an argmument
* we delete only packets belonging to the given interface
*/
if ((batman_if) &&
(forw_packet->if_incoming != batman_if))
continue;
spin_unlock_irqrestore(&forw_bcast_list_lock, flags);
/**
@ -484,6 +535,14 @@ void purge_outstanding_packets(void)
hlist_for_each_entry_safe(forw_packet, tmp_node, safe_tmp_node,
&forw_bat_list, list) {
/**
* if purge_outstanding_packets() was called with an argmument
* we delete only packets belonging to the given interface
*/
if ((batman_if) &&
(forw_packet->if_incoming != batman_if))
continue;
spin_unlock_irqrestore(&forw_bat_list_lock, flags);
/**

View file

@ -1,5 +1,5 @@
/*
* Copyright (C) 2007-2009 B.A.T.M.A.N. contributors:
* Copyright (C) 2007-2010 B.A.T.M.A.N. contributors:
*
* Marek Lindner, Simon Wunderlich
*
@ -33,7 +33,7 @@ void schedule_forward_packet(struct orig_node *orig_node,
struct batman_packet *batman_packet,
uint8_t directlink, int hna_buff_len,
struct batman_if *if_outgoing);
void 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 purge_outstanding_packets(void);
void purge_outstanding_packets(struct batman_if *batman_if);

View file

@ -1,5 +1,5 @@
/*
* Copyright (C) 2007-2009 B.A.T.M.A.N. contributors:
* Copyright (C) 2007-2010 B.A.T.M.A.N. contributors:
*
* Marek Lindner, Simon Wunderlich
*
@ -152,9 +152,13 @@ int interface_set_mac_addr(struct net_device *dev, void *p)
if (!is_valid_ether_addr(addr->sa_data))
return -EADDRNOTAVAIL;
hna_local_remove(dev->dev_addr, "mac address changed");
/* only modify hna-table if it has been initialised before */
if (atomic_read(&module_state) == MODULE_ACTIVE) {
hna_local_remove(dev->dev_addr, "mac address changed");
hna_local_add(addr->sa_data);
}
memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN);
hna_local_add(dev->dev_addr);
return 0;
}
@ -178,6 +182,7 @@ int interface_tx(struct sk_buff *skb, struct net_device *dev)
struct ethhdr *ethhdr = (struct ethhdr *)skb->data;
struct bat_priv *priv = netdev_priv(dev);
struct batman_if *batman_if;
struct bat_priv *bat_priv;
uint8_t dstaddr[6];
int data_len = skb->len;
unsigned long flags;
@ -185,6 +190,9 @@ int interface_tx(struct sk_buff *skb, struct net_device *dev)
if (atomic_read(&module_state) != MODULE_ACTIVE)
goto dropped;
/* FIXME: each batman_if will be attached to a softif */
bat_priv = netdev_priv(soft_device);
dev->trans_start = jiffies;
/* TODO: check this for locks */
hna_local_add(ethhdr->h_source);
@ -208,10 +216,10 @@ int interface_tx(struct sk_buff *skb, struct net_device *dev)
/* set broadcast sequence number */
bcast_packet->seqno = htons(bcast_seqno);
bcast_seqno++;
/* broadcast packet. on success, increase seqno. */
if (add_bcast_packet_to_list(skb) == NETDEV_TX_OK)
bcast_seqno++;
/* broadcast packet */
add_bcast_packet_to_list(skb);
/* a copy is stored in the bcast list, therefore removing
* the original skb. */
kfree_skb(skb);
@ -228,8 +236,9 @@ int interface_tx(struct sk_buff *skb, struct net_device *dev)
orig_node = transtable_search(ethhdr->h_dest);
if ((orig_node) &&
(orig_node->batman_if) &&
(orig_node->router)) {
struct neigh_node *router = orig_node->router;
if (my_skb_push(skb, sizeof(struct unicast_packet)) < 0)
goto unlock;
@ -244,14 +253,14 @@ int interface_tx(struct sk_buff *skb, struct net_device *dev)
memcpy(unicast_packet->dest, orig_node->orig, ETH_ALEN);
/* net_dev won't be available when not active */
if (orig_node->batman_if->if_active != IF_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 = orig_node->batman_if;
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);
send_skb_packet(skb, batman_if, dstaddr);
@ -268,6 +277,7 @@ unlock:
spin_unlock_irqrestore(&orig_hash_lock, flags);
dropped:
priv->stats.tx_dropped++;
kfree_skb(skb);
end:
return NETDEV_TX_OK;
}

View file

@ -1,5 +1,5 @@
/*
* Copyright (C) 2007-2009 B.A.T.M.A.N. contributors:
* Copyright (C) 2007-2010 B.A.T.M.A.N. contributors:
*
* Marek Lindner
*

View file

@ -1,5 +1,5 @@
/*
* Copyright (C) 2007-2009 B.A.T.M.A.N. contributors:
* Copyright (C) 2007-2010 B.A.T.M.A.N. contributors:
*
* Marek Lindner, Simon Wunderlich
*
@ -77,11 +77,14 @@ void hna_local_add(uint8_t *addr)
MAC-flooding. */
if ((num_hna + 1 > (ETH_DATA_LEN - BAT_PACKET_LEN) / ETH_ALEN) ||
(num_hna + 1 > 255)) {
bat_dbg(DBG_ROUTES, "Can't add new local hna entry (%pM): number of local hna entries exceeds packet size \n", addr);
bat_dbg(DBG_ROUTES,
"Can't add new local hna entry (%pM): "
"number of local hna entries exceeds packet size\n",
addr);
return;
}
bat_dbg(DBG_ROUTES, "Creating new local hna entry: %pM \n",
bat_dbg(DBG_ROUTES, "Creating new local hna entry: %pM\n",
addr);
hna_local_entry = kmalloc(sizeof(struct hna_local_entry), GFP_ATOMIC);
@ -108,7 +111,8 @@ void hna_local_add(uint8_t *addr)
hna_local_hash->size * 2);
if (swaphash == NULL)
printk(KERN_ERR "batman-adv:Couldn't resize local hna hash table \n");
printk(KERN_ERR "batman-adv:"
"Couldn't resize local hna hash table\n");
else
hna_local_hash = swaphash;
}
@ -156,24 +160,49 @@ int hna_local_fill_buffer(unsigned char *buff, int buff_len)
return i;
}
int hna_local_fill_buffer_text(unsigned char *buff, int buff_len)
int hna_local_fill_buffer_text(struct net_device *net_dev, char *buff,
size_t count, loff_t off)
{
struct bat_priv *bat_priv = netdev_priv(net_dev);
struct hna_local_entry *hna_local_entry;
HASHIT(hashit);
int bytes_written = 0;
unsigned long flags;
size_t hdr_len;
if (!bat_priv->primary_if) {
if (off == 0)
return sprintf(buff,
"BATMAN mesh %s disabled - "
"please specify interfaces to enable it\n",
net_dev->name);
return 0;
}
hdr_len = sprintf(buff,
"Locally retrieved addresses (from %s) "
"announced via HNA:\n",
net_dev->name);
if (off < hdr_len)
bytes_written = hdr_len;
spin_lock_irqsave(&hna_local_hash_lock, flags);
while (hash_iterate(hna_local_hash, &hashit)) {
hdr_len += 21;
if (buff_len < bytes_written + ETH_STR_LEN + 4)
if (count < bytes_written + 22)
break;
if (off >= hdr_len)
continue;
hna_local_entry = hashit.bucket->data;
bytes_written += snprintf(buff + bytes_written, ETH_STR_LEN + 4,
" * %02x:%02x:%02x:%02x:%02x:%02x\n",
bytes_written += snprintf(buff + bytes_written, 22,
" * " MAC_FMT "\n",
hna_local_entry->addr[0],
hna_local_entry->addr[1],
hna_local_entry->addr[2],
@ -183,7 +212,6 @@ int hna_local_fill_buffer_text(unsigned char *buff, int buff_len)
}
spin_unlock_irqrestore(&hna_local_hash_lock, flags);
return bytes_written;
}
@ -197,7 +225,7 @@ static void _hna_local_del(void *data)
static void hna_local_del(struct hna_local_entry *hna_local_entry,
char *message)
{
bat_dbg(DBG_ROUTES, "Deleting local hna entry (%pM): %s \n",
bat_dbg(DBG_ROUTES, "Deleting local hna entry (%pM): %s\n",
hna_local_entry->addr, message);
hash_remove(hna_local_hash, hna_local_entry->addr);
@ -295,7 +323,8 @@ void hna_global_add_orig(struct orig_node *orig_node,
memcpy(hna_global_entry->addr, hna_ptr, ETH_ALEN);
bat_dbg(DBG_ROUTES,
"Creating new global hna entry: %pM (via %pM)\n",
"Creating new global hna entry: "
"%pM (via %pM)\n",
hna_global_entry->addr, orig_node->orig);
spin_lock_irqsave(&hna_global_hash_lock, flags);
@ -340,7 +369,8 @@ void hna_global_add_orig(struct orig_node *orig_node,
hna_global_hash->size * 2);
if (swaphash == NULL)
printk(KERN_ERR "batman-adv:Couldn't resize global hna hash table \n");
printk(KERN_ERR "batman-adv:"
"Couldn't resize global hna hash table\n");
else
hna_global_hash = swaphash;
}
@ -348,24 +378,49 @@ void hna_global_add_orig(struct orig_node *orig_node,
spin_unlock_irqrestore(&hna_global_hash_lock, flags);
}
int hna_global_fill_buffer_text(unsigned char *buff, int buff_len)
int hna_global_fill_buffer_text(struct net_device *net_dev, char *buff,
size_t count, loff_t off)
{
struct bat_priv *bat_priv = netdev_priv(net_dev);
struct hna_global_entry *hna_global_entry;
HASHIT(hashit);
int bytes_written = 0;
unsigned long flags;
size_t hdr_len;
if (!bat_priv->primary_if) {
if (off == 0)
return sprintf(buff,
"BATMAN mesh %s disabled - "
"please specify interfaces to enable it\n",
net_dev->name);
return 0;
}
hdr_len = sprintf(buff,
"Globally announced HNAs received via the mesh %s "
"(translation table):\n",
net_dev->name);
if (off < hdr_len)
bytes_written = hdr_len;
spin_lock_irqsave(&hna_global_hash_lock, flags);
while (hash_iterate(hna_global_hash, &hashit)) {
if (buff_len < bytes_written + (2 * ETH_STR_LEN) + 10)
hdr_len += 43;
if (count < bytes_written + 44)
break;
if (off >= hdr_len)
continue;
hna_global_entry = hashit.bucket->data;
bytes_written += snprintf(buff + bytes_written,
(2 * ETH_STR_LEN) + 10,
" * %02x:%02x:%02x:%02x:%02x:%02x via %02x:%02x:%02x:%02x:%02x:%02x \n",
bytes_written += snprintf(buff + bytes_written, 44,
" * " MAC_FMT " via " MAC_FMT "\n",
hna_global_entry->addr[0],
hna_global_entry->addr[1],
hna_global_entry->addr[2],
@ -381,14 +436,13 @@ int hna_global_fill_buffer_text(unsigned char *buff, int buff_len)
}
spin_unlock_irqrestore(&hna_global_hash_lock, flags);
return bytes_written;
}
void _hna_global_del_orig(struct hna_global_entry *hna_global_entry,
char *message)
{
bat_dbg(DBG_ROUTES, "Deleting global hna entry %pM (via %pM): %s \n",
bat_dbg(DBG_ROUTES, "Deleting global hna entry %pM (via %pM): %s\n",
hna_global_entry->addr, hna_global_entry->orig_node->orig,
message);

View file

@ -1,5 +1,5 @@
/*
* Copyright (C) 2007-2009 B.A.T.M.A.N. contributors:
* Copyright (C) 2007-2010 B.A.T.M.A.N. contributors:
*
* Marek Lindner, Simon Wunderlich
*
@ -25,13 +25,15 @@ int hna_local_init(void);
void hna_local_add(uint8_t *addr);
void hna_local_remove(uint8_t *addr, char *message);
int hna_local_fill_buffer(unsigned char *buff, int buff_len);
int hna_local_fill_buffer_text(unsigned char *buff, int buff_len);
int hna_local_fill_buffer_text(struct net_device *net_dev, char *buff,
size_t count, loff_t off);
void hna_local_purge(struct work_struct *work);
void hna_local_free(void);
int hna_global_init(void);
void hna_global_add_orig(struct orig_node *orig_node, unsigned char *hna_buff,
int hna_buff_len);
int hna_global_fill_buffer_text(unsigned char *buff, int buff_len);
int hna_global_fill_buffer_text(struct net_device *net_dev, char *buff,
size_t count, loff_t off);
void _hna_global_del_orig(struct hna_global_entry *hna_global_entry,
char *orig_str);
void hna_global_del_orig(struct orig_node *orig_node, char *message);

View file

@ -1,5 +1,5 @@
/*
* Copyright (C) 2007-2009 B.A.T.M.A.N. contributors:
* Copyright (C) 2007-2010 B.A.T.M.A.N. contributors:
*
* Marek Lindner, Simon Wunderlich
*
@ -29,43 +29,61 @@
#include "packet.h"
#include "bitarray.h"
#define BAT_HEADER_LEN (sizeof(struct ethhdr) + ((sizeof(struct unicast_packet) > sizeof(struct bcast_packet) ? sizeof(struct unicast_packet) : sizeof(struct bcast_packet))))
#define BAT_HEADER_LEN (sizeof(struct ethhdr) + \
((sizeof(struct unicast_packet) > sizeof(struct bcast_packet) ? \
sizeof(struct unicast_packet) : \
sizeof(struct bcast_packet))))
struct batman_if {
struct list_head list;
int16_t if_num;
char *dev;
char if_active;
char if_status;
char addr_str[ETH_STR_LEN];
struct net_device *net_dev;
atomic_t seqno;
unsigned char *packet_buff;
int packet_len;
struct kobject *hardif_obj;
struct rcu_head rcu;
};
struct orig_node { /* structure for orig_list maintaining nodes of mesh */
/**
* orig_node - structure for orig_list maintaining nodes of mesh
* @last_valid: when last packet from this node was received
* @bcast_seqno_reset: time when the broadcast seqno window was reset
* @batman_seqno_reset: time when the batman seqno window was reset
* @flags: for now only VIS_SERVER flag
* @last_real_seqno: last and best known squence number
* @last_ttl: ttl of last received packet
* @last_bcast_seqno: last broadcast sequence number received by this host
*/
struct orig_node {
uint8_t orig[ETH_ALEN];
struct neigh_node *router;
struct batman_if *batman_if;
TYPE_OF_WORD *bcast_own;
uint8_t *bcast_own_sum;
uint8_t tq_own;
int tq_asym_penalty;
unsigned long last_valid; /* when last packet from this node was received */
/* uint8_t gwflags; * flags related to gateway functions: gateway class */
uint8_t flags; /* for now only VIS_SERVER flag. */
unsigned long last_valid;
unsigned long bcast_seqno_reset;
unsigned long batman_seqno_reset;
uint8_t flags;
unsigned char *hna_buff;
int16_t hna_buff_len;
uint16_t last_real_seqno; /* last and best known squence number */
uint8_t last_ttl; /* ttl of last received packet */
uint16_t last_real_seqno;
uint8_t last_ttl;
TYPE_OF_WORD bcast_bits[NUM_WORDS];
uint16_t last_bcast_seqno; /* last broadcast sequence number received by this host */
uint16_t last_bcast_seqno;
struct list_head neigh_list;
};
/**
* neigh_node
* @last_valid: when last packet via this neighbor was received
*/
struct neigh_node {
struct list_head list;
uint8_t addr[ETH_ALEN];
@ -74,7 +92,7 @@ struct neigh_node {
uint8_t tq_index;
uint8_t tq_avg;
uint8_t last_ttl;
unsigned long last_valid; /* when last packet via this neighbor was received */
unsigned long last_valid;
TYPE_OF_WORD real_bits[NUM_WORDS];
struct orig_node *orig_node;
struct batman_if *if_incoming;
@ -82,6 +100,12 @@ struct neigh_node {
struct bat_priv {
struct net_device_stats stats;
atomic_t aggregation_enabled;
atomic_t vis_mode;
atomic_t orig_interval;
char num_ifaces;
struct batman_if *primary_if;
struct kobject *mesh_obj;
};
struct device_client {
@ -108,7 +132,11 @@ struct hna_global_entry {
struct orig_node *orig_node;
};
struct forw_packet { /* structure for forw_list maintaining packets to be send/forwarded */
/**
* forw_packet - structure for forw_list maintaining packets to be
* send/forwarded
*/
struct forw_packet {
struct hlist_node list;
unsigned long send_time;
uint8_t own;

View file

@ -1,5 +1,5 @@
/*
* Copyright (C) 2008-2009 B.A.T.M.A.N. contributors:
* Copyright (C) 2008-2010 B.A.T.M.A.N. contributors:
*
* Simon Wunderlich
*
@ -27,24 +27,44 @@
#include "hard-interface.h"
#include "hash.h"
/* Returns the smallest signed integer in two's complement with the sizeof x */
#define smallest_signed_int(x) (1u << (7u + 8u * (sizeof(x) - 1u)))
/* Checks if a sequence number x is a predecessor/successor of y.
they handle overflows/underflows and can correctly check for a
predecessor/successor unless the variable sequence number has grown by
more then 2**(bitwidth(x)-1)-1.
This means that for a uint8_t with the maximum value 255, it would think:
* when adding nothing - it is neither a predecessor nor a successor
* before adding more than 127 to the starting value - it is a predecessor,
* when adding 128 - it is neither a predecessor nor a successor,
* after adding more than 127 to the starting value - it is a successor */
#define seq_before(x, y) ({typeof(x) _dummy = (x - y); \
_dummy > smallest_signed_int(_dummy); })
#define seq_after(x, y) seq_before(y, x)
struct hashtable_t *vis_hash;
DEFINE_SPINLOCK(vis_hash_lock);
static DEFINE_SPINLOCK(recv_list_lock);
static struct vis_info *my_vis_info;
static struct list_head send_list; /* always locked with vis_hash_lock */
static void start_vis_timer(void);
/* free the info */
static void free_info(void *data)
static void free_info(struct kref *ref)
{
struct vis_info *info = data;
struct vis_info *info = container_of(ref, struct vis_info, refcount);
struct recvlist_node *entry, *tmp;
unsigned long flags;
list_del_init(&info->send_list);
spin_lock_irqsave(&recv_list_lock, flags);
list_for_each_entry_safe(entry, tmp, &info->recv_list, list) {
list_del(&entry->list);
kfree(entry);
}
spin_unlock_irqrestore(&recv_list_lock, flags);
kfree(info);
}
@ -82,7 +102,7 @@ static int vis_info_choose(void *data, int size)
/* insert interface to the list of interfaces of one originator, if it
* does not already exist in the list */
static void proc_vis_insert_interface(const uint8_t *interface,
static void vis_data_insert_interface(const uint8_t *interface,
struct hlist_head *if_list,
bool primary)
{
@ -103,42 +123,135 @@ static void proc_vis_insert_interface(const uint8_t *interface,
hlist_add_head(&entry->list, if_list);
}
void proc_vis_read_prim_sec(struct seq_file *seq,
struct hlist_head *if_list)
static ssize_t vis_data_read_prim_sec(char *buff, struct hlist_head *if_list)
{
struct if_list_entry *entry;
struct hlist_node *pos, *n;
struct hlist_node *pos;
char tmp_addr_str[ETH_STR_LEN];
size_t len = 0;
hlist_for_each_entry_safe(entry, pos, n, if_list, list) {
if (entry->primary) {
seq_printf(seq, "PRIMARY, ");
} else {
hlist_for_each_entry(entry, pos, if_list, list) {
if (entry->primary)
len += sprintf(buff + len, "PRIMARY, ");
else {
addr_to_string(tmp_addr_str, entry->addr);
seq_printf(seq, "SEC %s, ", tmp_addr_str);
len += sprintf(buff + len, "SEC %s, ", tmp_addr_str);
}
hlist_del(&entry->list);
kfree(entry);
}
return len;
}
/* read an entry */
void proc_vis_read_entry(struct seq_file *seq,
struct vis_info_entry *entry,
struct hlist_head *if_list,
uint8_t *vis_orig)
static ssize_t vis_data_read_entry(char *buff, struct vis_info_entry *entry,
uint8_t *src, bool primary)
{
char to[40];
addr_to_string(to, entry->dest);
if (entry->quality == 0) {
proc_vis_insert_interface(vis_orig, if_list, true);
seq_printf(seq, "HNA %s, ", to);
} else {
proc_vis_insert_interface(entry->src, if_list,
compare_orig(entry->src, vis_orig));
seq_printf(seq, "TQ %s %d, ", to, entry->quality);
if (primary && entry->quality == 0)
return sprintf(buff, "HNA %s, ", to);
else if (compare_orig(entry->src, src))
return sprintf(buff, "TQ %s %d, ", to, entry->quality);
return 0;
}
ssize_t vis_fill_buffer_text(struct net_device *net_dev, char *buff,
size_t count, loff_t off)
{
HASHIT(hashit);
struct vis_info *info;
struct vis_info_entry *entries;
struct bat_priv *bat_priv = netdev_priv(net_dev);
HLIST_HEAD(vis_if_list);
struct if_list_entry *entry;
struct hlist_node *pos, *n;
size_t hdr_len, tmp_len;
int i, bytes_written = 0;
char tmp_addr_str[ETH_STR_LEN];
unsigned long flags;
int vis_server = atomic_read(&bat_priv->vis_mode);
if ((!bat_priv->primary_if) ||
(vis_server == VIS_TYPE_CLIENT_UPDATE))
return 0;
hdr_len = 0;
spin_lock_irqsave(&vis_hash_lock, flags);
while (hash_iterate(vis_hash, &hashit)) {
info = hashit.bucket->data;
entries = (struct vis_info_entry *)
((char *)info + sizeof(struct vis_info));
/* estimated line length */
if (count < bytes_written + 200)
break;
for (i = 0; i < info->packet.entries; i++) {
if (entries[i].quality == 0)
continue;
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) {
addr_to_string(tmp_addr_str, entry->addr);
tmp_len = sprintf(buff + bytes_written,
"%s,", tmp_addr_str);
for (i = 0; i < info->packet.entries; i++)
tmp_len += vis_data_read_entry(
buff + bytes_written + tmp_len,
&entries[i], entry->addr,
entry->primary);
/* add primary/secondary records */
if (compare_orig(entry->addr, info->packet.vis_orig))
tmp_len += vis_data_read_prim_sec(
buff + bytes_written + tmp_len,
&vis_if_list);
tmp_len += sprintf(buff + bytes_written + tmp_len,
"\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_del(&entry->list);
kfree(entry);
}
}
spin_unlock_irqrestore(&vis_hash_lock, flags);
return bytes_written;
}
/* add the info packet to the send list, if it was not
* already linked in. */
static void send_list_add(struct vis_info *info)
{
if (list_empty(&info->send_list)) {
kref_get(&info->refcount);
list_add_tail(&info->send_list, &send_list);
}
}
/* delete the info packet from the send list, if it was
* linked in. */
static void send_list_del(struct vis_info *info)
{
if (!list_empty(&info->send_list)) {
list_del_init(&info->send_list);
kref_put(&info->refcount, free_info);
}
}
@ -146,32 +259,41 @@ void proc_vis_read_entry(struct seq_file *seq,
static void recv_list_add(struct list_head *recv_list, char *mac)
{
struct recvlist_node *entry;
unsigned long flags;
entry = kmalloc(sizeof(struct recvlist_node), GFP_ATOMIC);
if (!entry)
return;
memcpy(entry->mac, mac, ETH_ALEN);
spin_lock_irqsave(&recv_list_lock, flags);
list_add_tail(&entry->list, recv_list);
spin_unlock_irqrestore(&recv_list_lock, flags);
}
/* returns 1 if this mac is in the recv_list */
static int recv_list_is_in(struct list_head *recv_list, char *mac)
{
struct recvlist_node *entry;
unsigned long flags;
spin_lock_irqsave(&recv_list_lock, flags);
list_for_each_entry(entry, recv_list, list) {
if (memcmp(entry->mac, mac, ETH_ALEN) == 0)
if (memcmp(entry->mac, mac, ETH_ALEN) == 0) {
spin_unlock_irqrestore(&recv_list_lock, flags);
return 1;
}
}
spin_unlock_irqrestore(&recv_list_lock, flags);
return 0;
}
/* try to add the packet to the vis_hash. return NULL if invalid (e.g. too old,
* broken.. ). vis hash must be locked outside. is_new is set when the packet
* broken.. ). vis hash must be locked outside. is_new is set when the packet
* is newer than old entries in the hash. */
static struct vis_info *add_packet(struct vis_packet *vis_packet,
int vis_info_len, int *is_new)
int vis_info_len, int *is_new,
int make_broadcast)
{
struct vis_info *info, *old_info;
struct vis_info search_elem;
@ -186,7 +308,7 @@ static struct vis_info *add_packet(struct vis_packet *vis_packet,
old_info = hash_find(vis_hash, &search_elem);
if (old_info != NULL) {
if (vis_packet->seqno - old_info->packet.seqno <= 0) {
if (!seq_after(vis_packet->seqno, old_info->packet.seqno)) {
if (old_info->packet.seqno == vis_packet->seqno) {
recv_list_add(&old_info->recv_list,
vis_packet->sender_orig);
@ -198,13 +320,15 @@ static struct vis_info *add_packet(struct vis_packet *vis_packet,
}
/* remove old entry */
hash_remove(vis_hash, old_info);
free_info(old_info);
send_list_del(old_info);
kref_put(&old_info->refcount, free_info);
}
info = kmalloc(sizeof(struct vis_info) + vis_info_len, GFP_ATOMIC);
if (info == NULL)
return NULL;
kref_init(&info->refcount);
INIT_LIST_HEAD(&info->send_list);
INIT_LIST_HEAD(&info->recv_list);
info->first_seen = jiffies;
@ -214,16 +338,21 @@ static struct vis_info *add_packet(struct vis_packet *vis_packet,
/* initialize and add new packet. */
*is_new = 1;
/* Make it a broadcast packet, if required */
if (make_broadcast)
memcpy(info->packet.target_orig, broadcastAddr, ETH_ALEN);
/* repair if entries is longer than packet. */
if (info->packet.entries * sizeof(struct vis_info_entry) > vis_info_len)
info->packet.entries = vis_info_len / sizeof(struct vis_info_entry);
info->packet.entries = vis_info_len /
sizeof(struct vis_info_entry);
recv_list_add(&info->recv_list, info->packet.sender_orig);
/* try to add it */
if (hash_add(vis_hash, info) < 0) {
/* did not work (for some reason) */
free_info(info);
kref_put(&old_info->refcount, free_info);
info = NULL;
}
@ -231,62 +360,65 @@ static struct vis_info *add_packet(struct vis_packet *vis_packet,
}
/* handle the server sync packet, forward if needed. */
void receive_server_sync_packet(struct vis_packet *vis_packet, int vis_info_len)
void receive_server_sync_packet(struct bat_priv *bat_priv,
struct vis_packet *vis_packet,
int vis_info_len)
{
struct vis_info *info;
int is_new;
int is_new, make_broadcast;
unsigned long flags;
int vis_server = atomic_read(&vis_mode);
int vis_server = atomic_read(&bat_priv->vis_mode);
make_broadcast = (vis_server == VIS_TYPE_SERVER_SYNC);
spin_lock_irqsave(&vis_hash_lock, flags);
info = add_packet(vis_packet, vis_info_len, &is_new);
info = add_packet(vis_packet, vis_info_len, &is_new, make_broadcast);
if (info == NULL)
goto end;
/* only if we are server ourselves and packet is newer than the one in
* hash.*/
if (vis_server == VIS_TYPE_SERVER_SYNC && is_new) {
memcpy(info->packet.target_orig, broadcastAddr, ETH_ALEN);
if (list_empty(&info->send_list))
list_add_tail(&info->send_list, &send_list);
}
if (vis_server == VIS_TYPE_SERVER_SYNC && is_new)
send_list_add(info);
end:
spin_unlock_irqrestore(&vis_hash_lock, flags);
}
/* handle an incoming client update packet and schedule forward if needed. */
void receive_client_update_packet(struct vis_packet *vis_packet,
void receive_client_update_packet(struct bat_priv *bat_priv,
struct vis_packet *vis_packet,
int vis_info_len)
{
struct vis_info *info;
int is_new;
unsigned long flags;
int vis_server = atomic_read(&vis_mode);
int vis_server = atomic_read(&bat_priv->vis_mode);
int are_target = 0;
/* clients shall not broadcast. */
if (is_bcast(vis_packet->target_orig))
return;
/* Are we the target for this VIS packet? */
if (vis_server == VIS_TYPE_SERVER_SYNC &&
is_my_mac(vis_packet->target_orig))
are_target = 1;
spin_lock_irqsave(&vis_hash_lock, flags);
info = add_packet(vis_packet, vis_info_len, &is_new);
info = add_packet(vis_packet, vis_info_len, &is_new, are_target);
if (info == NULL)
goto end;
/* note that outdated packets will be dropped at this point. */
/* send only if we're the target server or ... */
if (vis_server == VIS_TYPE_SERVER_SYNC &&
is_my_mac(info->packet.target_orig) &&
is_new) {
if (are_target && is_new) {
info->packet.vis_type = VIS_TYPE_SERVER_SYNC; /* upgrade! */
memcpy(info->packet.target_orig, broadcastAddr, ETH_ALEN);
if (list_empty(&info->send_list))
list_add_tail(&info->send_list, &send_list);
send_list_add(info);
/* ... we're not the recipient (and thus need to forward). */
} else if (!is_my_mac(info->packet.target_orig)) {
if (list_empty(&info->send_list))
list_add_tail(&info->send_list, &send_list);
send_list_add(info);
}
end:
spin_unlock_irqrestore(&vis_hash_lock, flags);
@ -327,7 +459,7 @@ static bool vis_packet_full(struct vis_info *info)
/* generates a packet of own vis data,
* returns 0 on success, -1 if no packet could be generated */
static int generate_vis_packet(void)
static int generate_vis_packet(struct bat_priv *bat_priv)
{
HASHIT(hashit_local);
HASHIT(hashit_global);
@ -339,7 +471,7 @@ static int generate_vis_packet(void)
unsigned long flags;
info->first_seen = jiffies;
info->packet.vis_type = atomic_read(&vis_mode);
info->packet.vis_type = atomic_read(&bat_priv->vis_mode);
spin_lock_irqsave(&orig_hash_lock, flags);
memcpy(info->packet.target_orig, broadcastAddr, ETH_ALEN);
@ -361,14 +493,17 @@ static int generate_vis_packet(void)
while (hash_iterate(orig_hash, &hashit_global)) {
orig_node = hashit_global.bucket->data;
if (orig_node->router != NULL
&& compare_orig(orig_node->router->addr, orig_node->orig)
&& orig_node->batman_if
&& (orig_node->batman_if->if_active == IF_ACTIVE)
&& compare_orig(orig_node->router->addr,
orig_node->orig)
&& (orig_node->router->if_incoming->if_status ==
IF_ACTIVE)
&& orig_node->router->tq_avg > 0) {
/* fill one entry into buffer. */
entry = &entry_array[info->packet.entries];
memcpy(entry->src, orig_node->batman_if->net_dev->dev_addr, ETH_ALEN);
memcpy(entry->src,
orig_node->router->if_incoming->net_dev->dev_addr,
ETH_ALEN);
memcpy(entry->dest, orig_node->orig, ETH_ALEN);
entry->quality = orig_node->router->tq_avg;
info->packet.entries++;
@ -400,6 +535,8 @@ static int generate_vis_packet(void)
return 0;
}
/* free old vis packets. Must be called with this vis_hash_lock
* held */
static void purge_vis_packets(void)
{
HASHIT(hashit);
@ -412,7 +549,8 @@ static void purge_vis_packets(void)
if (time_after(jiffies,
info->first_seen + (VIS_TIMEOUT*HZ)/1000)) {
hash_remove_bucket(vis_hash, &hashit);
free_info(info);
send_list_del(info);
kref_put(&info->refcount, free_info);
}
}
}
@ -422,6 +560,8 @@ static void broadcast_vis_packet(struct vis_info *info, int packet_length)
HASHIT(hashit);
struct orig_node *orig_node;
unsigned long flags;
struct batman_if *batman_if;
uint8_t dstaddr[ETH_ALEN];
spin_lock_irqsave(&orig_hash_lock, flags);
@ -430,45 +570,55 @@ static void broadcast_vis_packet(struct vis_info *info, int packet_length)
orig_node = hashit.bucket->data;
/* if it's a vis server and reachable, send it. */
if (orig_node &&
(orig_node->flags & VIS_SERVER) &&
orig_node->batman_if &&
orig_node->router) {
if ((!orig_node) || (!orig_node->router))
continue;
if (!(orig_node->flags & VIS_SERVER))
continue;
/* don't send it if we already received the packet from
* this node. */
if (recv_list_is_in(&info->recv_list, orig_node->orig))
continue;
/* don't send it if we already received the packet from
* this node. */
if (recv_list_is_in(&info->recv_list, orig_node->orig))
continue;
memcpy(info->packet.target_orig, orig_node->orig, ETH_ALEN);
batman_if = orig_node->router->if_incoming;
memcpy(dstaddr, orig_node->router->addr, ETH_ALEN);
spin_unlock_irqrestore(&orig_hash_lock, flags);
memcpy(info->packet.target_orig,
orig_node->orig, ETH_ALEN);
send_raw_packet((unsigned char *)&info->packet,
packet_length, batman_if, dstaddr);
spin_lock_irqsave(&orig_hash_lock, flags);
send_raw_packet((unsigned char *) &info->packet,
packet_length,
orig_node->batman_if,
orig_node->router->addr);
}
}
memcpy(info->packet.target_orig, broadcastAddr, ETH_ALEN);
spin_unlock_irqrestore(&orig_hash_lock, flags);
memcpy(info->packet.target_orig, broadcastAddr, ETH_ALEN);
}
static void unicast_vis_packet(struct vis_info *info, int packet_length)
{
struct orig_node *orig_node;
unsigned long flags;
struct batman_if *batman_if;
uint8_t dstaddr[ETH_ALEN];
spin_lock_irqsave(&orig_hash_lock, flags);
orig_node = ((struct orig_node *)
hash_find(orig_hash, info->packet.target_orig));
if ((orig_node != NULL) &&
(orig_node->batman_if != NULL) &&
(orig_node->router != NULL)) {
send_raw_packet((unsigned char *) &info->packet, packet_length,
orig_node->batman_if,
orig_node->router->addr);
}
if ((!orig_node) || (!orig_node->router))
goto out;
/* don't lock while sending the packets ... we therefore
* copy the required data before sending */
batman_if = orig_node->router->if_incoming;
memcpy(dstaddr, orig_node->router->addr, ETH_ALEN);
spin_unlock_irqrestore(&orig_hash_lock, flags);
send_raw_packet((unsigned char *)&info->packet,
packet_length, batman_if, dstaddr);
return;
out:
spin_unlock_irqrestore(&orig_hash_lock, flags);
}
@ -500,17 +650,28 @@ static void send_vis_packets(struct work_struct *work)
{
struct vis_info *info, *temp;
unsigned long flags;
/* FIXME: each batman_if will be attached to a softif */
struct bat_priv *bat_priv = netdev_priv(soft_device);
spin_lock_irqsave(&vis_hash_lock, flags);
purge_vis_packets();
if (generate_vis_packet() == 0)
if (generate_vis_packet(bat_priv) == 0) {
/* schedule if generation was successful */
list_add_tail(&my_vis_info->send_list, &send_list);
send_list_add(my_vis_info);
}
list_for_each_entry_safe(info, temp, &send_list, send_list) {
list_del_init(&info->send_list);
kref_get(&info->refcount);
spin_unlock_irqrestore(&vis_hash_lock, flags);
send_vis_packet(info);
spin_lock_irqsave(&vis_hash_lock, flags);
send_list_del(info);
kref_put(&info->refcount, free_info);
}
spin_unlock_irqrestore(&vis_hash_lock, flags);
start_vis_timer();
@ -543,6 +704,7 @@ int vis_init(void)
my_vis_info->first_seen = jiffies - atomic_read(&vis_interval);
INIT_LIST_HEAD(&my_vis_info->recv_list);
INIT_LIST_HEAD(&my_vis_info->send_list);
kref_init(&my_vis_info->refcount);
my_vis_info->packet.version = COMPAT_VERSION;
my_vis_info->packet.packet_type = BAT_VIS;
my_vis_info->packet.ttl = TTL;
@ -556,9 +718,9 @@ int vis_init(void)
if (hash_add(vis_hash, my_vis_info) < 0) {
printk(KERN_ERR
"batman-adv:Can't add own vis packet into hash\n");
free_info(my_vis_info); /* not in hash, need to remove it
* manually. */
"batman-adv:Can't add own vis packet into hash\n");
/* not in hash, need to remove it manually. */
kref_put(&my_vis_info->refcount, free_info);
goto err;
}
@ -572,6 +734,15 @@ err:
return 0;
}
/* Decrease the reference count on a hash item info */
static void free_info_ref(void *data)
{
struct vis_info *info = data;
send_list_del(info);
kref_put(&info->refcount, free_info);
}
/* shutdown vis-server */
void vis_quit(void)
{
@ -583,7 +754,7 @@ void vis_quit(void)
spin_lock_irqsave(&vis_hash_lock, flags);
/* properly remove, kill timers ... */
hash_delete(vis_hash, free_info);
hash_delete(vis_hash, free_info_ref);
vis_hash = NULL;
my_vis_info = NULL;
spin_unlock_irqrestore(&vis_hash_lock, flags);

View file

@ -1,5 +1,5 @@
/*
* Copyright (C) 2008-2009 B.A.T.M.A.N. contributors:
* Copyright (C) 2008-2010 B.A.T.M.A.N. contributors:
*
* Simon Wunderlich, Marek Lindner
*
@ -20,8 +20,6 @@
*/
#define VIS_TIMEOUT 200000
#define VIS_FORMAT_DD_NAME "dot_draw"
#define VIS_FORMAT_JSON_NAME "json"
struct vis_info {
unsigned long first_seen;
@ -29,6 +27,7 @@ struct vis_info {
/* list of server-neighbors we received a vis-packet
* from. we should not reply to them. */
struct list_head send_list;
struct kref refcount;
/* this packet might be part of the vis send queue. */
struct vis_packet packet;
/* vis_info may follow here*/
@ -48,15 +47,13 @@ struct recvlist_node {
extern struct hashtable_t *vis_hash;
extern spinlock_t vis_hash_lock;
void proc_vis_read_entry(struct seq_file *seq,
struct vis_info_entry *entry,
struct hlist_head *if_list,
uint8_t *vis_orig);
void proc_vis_read_prim_sec(struct seq_file *seq,
struct hlist_head *if_list);
void receive_server_sync_packet(struct vis_packet *vis_packet,
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,
struct vis_packet *vis_packet,
int vis_info_len);
void receive_client_update_packet(struct vis_packet *vis_packet,
void receive_client_update_packet(struct bat_priv *bat_priv,
struct vis_packet *vis_packet,
int vis_info_len);
int vis_init(void);
void vis_quit(void);

File diff suppressed because it is too large Load diff

View file

@ -9,4 +9,3 @@ comedi-objs := \
range.o \
drivers.o \
comedi_compat32.o \
comedi_ksyms.o \

View file

@ -46,8 +46,10 @@
#define COMEDI_DEVCONF_AUX_DATA2_LENGTH 26
#define COMEDI_DEVCONF_AUX_DATA1_LENGTH 27
#define COMEDI_DEVCONF_AUX_DATA0_LENGTH 28
#define COMEDI_DEVCONF_AUX_DATA_HI 29 /* most significant 32 bits of pointer address (if needed) */
#define COMEDI_DEVCONF_AUX_DATA_LO 30 /* least significant 32 bits of pointer address */
/* most significant 32 bits of pointer address (if needed) */
#define COMEDI_DEVCONF_AUX_DATA_HI 29
/* least significant 32 bits of pointer address */
#define COMEDI_DEVCONF_AUX_DATA_LO 30
#define COMEDI_DEVCONF_AUX_DATA_LENGTH 31 /* total data length */
/* max length of device and driver names */
@ -55,8 +57,10 @@
/* packs and unpacks a channel/range number */
#define CR_PACK(chan, rng, aref) ((((aref)&0x3)<<24) | (((rng)&0xff)<<16) | (chan))
#define CR_PACK_FLAGS(chan, range, aref, flags) (CR_PACK(chan, range, aref) | ((flags) & CR_FLAGS_MASK))
#define CR_PACK(chan, rng, aref) \
((((aref)&0x3)<<24) | (((rng)&0xff)<<16) | (chan))
#define CR_PACK_FLAGS(chan, range, aref, flags) \
(CR_PACK(chan, range, aref) | ((flags) & CR_FLAGS_MASK))
#define CR_CHAN(a) ((a)&0xffff)
#define CR_RANGE(a) (((a)>>16)&0xff)
@ -125,7 +129,8 @@
/* command flags */
/* These flags are used in comedi_cmd structures */
#define CMDF_PRIORITY 0x00000008 /* try to use a real-time interrupt while performing command */
/* try to use a real-time interrupt while performing command */
#define CMDF_PRIORITY 0x00000008
#define TRIG_RT CMDF_PRIORITY /* compatibility definition */
@ -151,15 +156,15 @@
#define TRIG_ANY 0xffffffff
#define TRIG_INVALID 0x00000000
#define TRIG_NONE 0x00000001 /* never trigger */
#define TRIG_NOW 0x00000002 /* trigger now + N ns */
#define TRIG_FOLLOW 0x00000004 /* trigger on next lower level trig */
#define TRIG_TIME 0x00000008 /* trigger at time N ns */
#define TRIG_TIMER 0x00000010 /* trigger at rate N ns */
#define TRIG_COUNT 0x00000020 /* trigger when count reaches N */
#define TRIG_EXT 0x00000040 /* trigger on external signal N */
#define TRIG_INT 0x00000080 /* trigger on comedi-internal signal N */
#define TRIG_OTHER 0x00000100 /* driver defined */
#define TRIG_NONE 0x00000001 /* never trigger */
#define TRIG_NOW 0x00000002 /* trigger now + N ns */
#define TRIG_FOLLOW 0x00000004 /* trigger on next lower level trig */
#define TRIG_TIME 0x00000008 /* trigger at time N ns */
#define TRIG_TIMER 0x00000010 /* trigger at rate N ns */
#define TRIG_COUNT 0x00000020 /* trigger when count reaches N */
#define TRIG_EXT 0x00000040 /* trigger on external signal N */
#define TRIG_INT 0x00000080 /* trigger on comedi-internal signal N */
#define TRIG_OTHER 0x00000100 /* driver defined */
/* subdevice flags */
@ -176,14 +181,17 @@
#define SDF_MODE3 0x0400 /* can do mode 3 */
#define SDF_MODE4 0x0800 /* can do mode 4 */
#define SDF_CMD 0x1000 /* can do commands (deprecated) */
#define SDF_SOFT_CALIBRATED 0x2000 /* subdevice uses software calibration */
#define SDF_CMD_WRITE 0x4000 /* can do output commands */
#define SDF_CMD_READ 0x8000 /* can do input commands */
#define SDF_SOFT_CALIBRATED 0x2000 /* subdevice uses software calibration */
#define SDF_CMD_WRITE 0x4000 /* can do output commands */
#define SDF_CMD_READ 0x8000 /* can do input commands */
#define SDF_READABLE 0x00010000 /* subdevice can be read (e.g. analog input) */
#define SDF_WRITABLE 0x00020000 /* subdevice can be written (e.g. analog output) */
/* subdevice can be read (e.g. analog input) */
#define SDF_READABLE 0x00010000
/* subdevice can be written (e.g. analog output) */
#define SDF_WRITABLE 0x00020000
#define SDF_WRITEABLE SDF_WRITABLE /* spelling error in API */
#define SDF_INTERNAL 0x00040000 /* subdevice does not have externally visible lines */
/* subdevice does not have externally visible lines */
#define SDF_INTERNAL 0x00040000
#define SDF_GROUND 0x00100000 /* can do aref=ground */
#define SDF_COMMON 0x00200000 /* can do aref=common */
#define SDF_DIFF 0x00400000 /* can do aref=diff */
@ -242,22 +250,25 @@
INSN_CONFIG_DISARM = 32,
INSN_CONFIG_GET_COUNTER_STATUS = 33,
INSN_CONFIG_RESET = 34,
INSN_CONFIG_GPCT_SINGLE_PULSE_GENERATOR = 1001, /* Use CTR as single pulsegenerator */
INSN_CONFIG_GPCT_PULSE_TRAIN_GENERATOR = 1002, /* Use CTR as pulsetraingenerator */
INSN_CONFIG_GPCT_QUADRATURE_ENCODER = 1003, /* Use the counter as encoder */
/* Use CTR as single pulsegenerator */
INSN_CONFIG_GPCT_SINGLE_PULSE_GENERATOR = 1001,
/* Use CTR as pulsetraingenerator */
INSN_CONFIG_GPCT_PULSE_TRAIN_GENERATOR = 1002,
/* Use the counter as encoder */
INSN_CONFIG_GPCT_QUADRATURE_ENCODER = 1003,
INSN_CONFIG_SET_GATE_SRC = 2001, /* Set gate source */
INSN_CONFIG_GET_GATE_SRC = 2002, /* Get gate source */
INSN_CONFIG_SET_CLOCK_SRC = 2003, /* Set master clock source */
INSN_CONFIG_GET_CLOCK_SRC = 2004, /* Get master clock source */
INSN_CONFIG_SET_OTHER_SRC = 2005, /* Set other source */
/* INSN_CONFIG_GET_OTHER_SRC = 2006,*//* Get other source */
INSN_CONFIG_GET_HARDWARE_BUFFER_SIZE = 2006, /* Get size in bytes of
subdevice's on-board
fifos used during
streaming
input/output */
/* Set master clock source */
INSN_CONFIG_SET_CLOCK_SRC = 2003,
INSN_CONFIG_GET_CLOCK_SRC = 2004, /* Get master clock source */
INSN_CONFIG_SET_OTHER_SRC = 2005, /* Set other source */
/* INSN_CONFIG_GET_OTHER_SRC = 2006,*//* Get other source */
/* Get size in bytes of subdevice's on-board fifos used during
* streaming input/output */
INSN_CONFIG_GET_HARDWARE_BUFFER_SIZE = 2006,
INSN_CONFIG_SET_COUNTER_MODE = 4097,
INSN_CONFIG_8254_SET_MODE = INSN_CONFIG_SET_COUNTER_MODE, /* deprecated */
/* INSN_CONFIG_8254_SET_MODE is deprecated */
INSN_CONFIG_8254_SET_MODE = INSN_CONFIG_SET_COUNTER_MODE,
INSN_CONFIG_8254_READ_STATUS = 4098,
INSN_CONFIG_SET_ROUTING = 4099,
INSN_CONFIG_GET_ROUTING = 4109,
@ -265,8 +276,11 @@
INSN_CONFIG_PWM_SET_PERIOD = 5000, /* sets frequency */
INSN_CONFIG_PWM_GET_PERIOD = 5001, /* gets frequency */
INSN_CONFIG_GET_PWM_STATUS = 5002, /* is it running? */
INSN_CONFIG_PWM_SET_H_BRIDGE = 5003, /* sets H bridge: duty cycle and sign bit for a relay at the same time */
INSN_CONFIG_PWM_GET_H_BRIDGE = 5004 /* gets H bridge data: duty cycle and the sign bit */
/* sets H bridge: duty cycle and sign bit for a relay at the
* same time */
INSN_CONFIG_PWM_SET_H_BRIDGE = 5003,
/* gets H bridge data: duty cycle and the sign bit */
INSN_CONFIG_PWM_GET_H_BRIDGE = 5004
};
enum comedi_io_direction {
@ -321,7 +335,7 @@
struct comedi_insn {
unsigned int insn;
unsigned int n;
unsigned int *data;
unsigned int __user *data;
unsigned int subdev;
unsigned int chanspec;
unsigned int unused[3];
@ -329,7 +343,7 @@
struct comedi_insnlist {
unsigned int n_insns;
struct comedi_insn *insns;
struct comedi_insn __user *insns;
};
struct comedi_cmd {
@ -351,24 +365,24 @@
unsigned int stop_src;
unsigned int stop_arg;
unsigned int *chanlist; /* channel/range list */
unsigned int __user *chanlist; /* channel/range list */
unsigned int chanlist_len;
short *data; /* data list, size depends on subd flags */
short __user *data; /* data list, size depends on subd flags */
unsigned int data_len;
};
struct comedi_chaninfo {
unsigned int subdev;
unsigned int *maxdata_list;
unsigned int *flaglist;
unsigned int *rangelist;
unsigned int __user *maxdata_list;
unsigned int __user *flaglist;
unsigned int __user *rangelist;
unsigned int unused[4];
};
struct comedi_rangeinfo {
unsigned int range_type;
void *range_ptr;
void __user *range_ptr;
};
struct comedi_krange {
@ -387,7 +401,8 @@
unsigned int flags; /* channel flags */
unsigned int range_type; /* lookup in kernel */
unsigned int settling_time_0;
unsigned insn_bits_support; /* see support_level enum for values */
/* see support_level enum for values */
unsigned insn_bits_support;
unsigned int unused[8];
};
@ -451,7 +466,8 @@
#define COMEDI_CB_EOS 1 /* end of scan */
#define COMEDI_CB_EOA 2 /* end of acquisition */
#define COMEDI_CB_BLOCK 4 /* data has arrived: wakes up read() / write() */
#define COMEDI_CB_BLOCK 4 /* data has arrived:
* wakes up read() / write() */
#define COMEDI_CB_EOBUF 8 /* DEPRECATED: end of buffer */
#define COMEDI_CB_ERROR 16 /* card error during acquisition */
#define COMEDI_CB_OVERFLOW 32 /* buffer overflow/underflow */
@ -485,12 +501,15 @@
I8254_MODE2 = (2 << 1), /* Rate generator */
I8254_MODE3 = (3 << 1), /* Square wave mode */
I8254_MODE4 = (4 << 1), /* Software triggered strobe */
I8254_MODE5 = (5 << 1), /* Hardware triggered strobe (retriggerable) */
I8254_BCD = 1, /* use binary-coded decimal instead of binary (pretty useless) */
I8254_MODE5 = (5 << 1), /* Hardware triggered strobe
* (retriggerable) */
I8254_BCD = 1, /* use binary-coded decimal instead of binary
* (pretty useless) */
I8254_BINARY = 0
};
static inline unsigned NI_USUAL_PFI_SELECT(unsigned pfi_channel) {
static inline unsigned NI_USUAL_PFI_SELECT(unsigned pfi_channel)
{
if (pfi_channel < 10)
return 0x1 + pfi_channel;
else
@ -580,24 +599,30 @@
NI_GPCT_LOGIC_LOW_CLOCK_SRC_BITS = 0x3,
NI_GPCT_NEXT_GATE_CLOCK_SRC_BITS = 0x4,
NI_GPCT_NEXT_TC_CLOCK_SRC_BITS = 0x5,
NI_GPCT_SOURCE_PIN_i_CLOCK_SRC_BITS = 0x6, /* NI 660x-specific */
/* NI 660x-specific */
NI_GPCT_SOURCE_PIN_i_CLOCK_SRC_BITS = 0x6,
NI_GPCT_PXI10_CLOCK_SRC_BITS = 0x7,
NI_GPCT_PXI_STAR_TRIGGER_CLOCK_SRC_BITS = 0x8,
NI_GPCT_ANALOG_TRIGGER_OUT_CLOCK_SRC_BITS = 0x9,
NI_GPCT_PRESCALE_MODE_CLOCK_SRC_MASK = 0x30000000,
NI_GPCT_NO_PRESCALE_CLOCK_SRC_BITS = 0x0,
NI_GPCT_PRESCALE_X2_CLOCK_SRC_BITS = 0x10000000, /* divide source by 2 */
NI_GPCT_PRESCALE_X8_CLOCK_SRC_BITS = 0x20000000, /* divide source by 8 */
/* divide source by 2 */
NI_GPCT_PRESCALE_X2_CLOCK_SRC_BITS = 0x10000000,
/* divide source by 8 */
NI_GPCT_PRESCALE_X8_CLOCK_SRC_BITS = 0x20000000,
NI_GPCT_INVERT_CLOCK_SRC_BIT = 0x80000000
};
static inline unsigned NI_GPCT_SOURCE_PIN_CLOCK_SRC_BITS(unsigned n) {
static inline unsigned NI_GPCT_SOURCE_PIN_CLOCK_SRC_BITS(unsigned n)
{
/* NI 660x-specific */
return 0x10 + n;
}
static inline unsigned NI_GPCT_RTSI_CLOCK_SRC_BITS(unsigned n) {
static inline unsigned NI_GPCT_RTSI_CLOCK_SRC_BITS(unsigned n)
{
return 0x18 + n;
}
static inline unsigned NI_GPCT_PFI_CLOCK_SRC_BITS(unsigned n) {
static inline unsigned NI_GPCT_PFI_CLOCK_SRC_BITS(unsigned n)
{
/* no pfi on NI 660x */
return 0x20 + n;
}
@ -622,19 +647,24 @@ May be bitwise-or'd with CR_EDGE or CR_INVERT. */
NI_GPCT_UP_DOWN_PIN_i_GATE_SELECT = 0x201,
NI_GPCT_SELECTED_GATE_GATE_SELECT = 0x21e,
/* m-series "second gate" sources are unknown,
we should add them here with an offset of 0x300 when known. */
* we should add them here with an offset of 0x300 when
* known. */
NI_GPCT_DISABLED_GATE_SELECT = 0x8000,
};
static inline unsigned NI_GPCT_GATE_PIN_GATE_SELECT(unsigned n) {
static inline unsigned NI_GPCT_GATE_PIN_GATE_SELECT(unsigned n)
{
return 0x102 + n;
}
static inline unsigned NI_GPCT_RTSI_GATE_SELECT(unsigned n) {
static inline unsigned NI_GPCT_RTSI_GATE_SELECT(unsigned n)
{
return NI_USUAL_RTSI_SELECT(n);
}
static inline unsigned NI_GPCT_PFI_GATE_SELECT(unsigned n) {
static inline unsigned NI_GPCT_PFI_GATE_SELECT(unsigned n)
{
return NI_USUAL_PFI_SELECT(n);
}
static inline unsigned NI_GPCT_UP_DOWN_PIN_GATE_SELECT(unsigned n) {
static inline unsigned NI_GPCT_UP_DOWN_PIN_GATE_SELECT(unsigned n)
{
return 0x202 + n;
}
@ -650,7 +680,8 @@ INSN_CONFIG_SET_OTHER_SRC when using NI general-purpose counters. */
/* Still unknown, probably only need NI_GPCT_PFI_OTHER_SELECT */
NI_GPCT_DISABLED_OTHER_SELECT = 0x8000,
};
static inline unsigned NI_GPCT_PFI_OTHER_SELECT(unsigned n) {
static inline unsigned NI_GPCT_PFI_OTHER_SELECT(unsigned n)
{
return NI_USUAL_PFI_SELECT(n);
}
@ -658,14 +689,14 @@ INSN_CONFIG_SET_OTHER_SRC when using NI general-purpose counters. */
INSN_CONFIG_ARM */
enum ni_gpct_arm_source {
NI_GPCT_ARM_IMMEDIATE = 0x0,
NI_GPCT_ARM_PAIRED_IMMEDIATE = 0x1, /* Start both the counter and
the adjacent paired counter
simultaneously */
/* NI doesn't document bits for selecting hardware arm triggers. If
* the NI_GPCT_ARM_UNKNOWN bit is set, we will pass the least
* significant bits (3 bits for 660x or 5 bits for m-series) through to
* the hardware. This will at least allow someone to figure out what
* the bits do later. */
NI_GPCT_ARM_PAIRED_IMMEDIATE = 0x1, /* Start both the counter
* and the adjacent paired
* counter simultaneously */
/* NI doesn't document bits for selecting hardware arm triggers.
* If the NI_GPCT_ARM_UNKNOWN bit is set, we will pass the least
* significant bits (3 bits for 660x or 5 bits for m-series)
* through to the hardware. This will at least allow someone to
* figure out what the bits do later. */
NI_GPCT_ARM_UNKNOWN = 0x1000,
};
@ -699,7 +730,8 @@ INSN_CONFIG_ARM */
NI_MIO_PLL_PXI10_CLOCK = 3,
NI_MIO_PLL_RTSI0_CLOCK = 4
};
static inline unsigned NI_MIO_PLL_RTSI_CLOCK(unsigned rtsi_channel) {
static inline unsigned NI_MIO_PLL_RTSI_CLOCK(unsigned rtsi_channel)
{
return NI_MIO_PLL_RTSI0_CLOCK + rtsi_channel;
}
@ -716,10 +748,11 @@ INSN_CONFIG_ARM */
NI_RTSI_OUTPUT_G_GATE0 = 6,
NI_RTSI_OUTPUT_RGOUT0 = 7,
NI_RTSI_OUTPUT_RTSI_BRD_0 = 8,
NI_RTSI_OUTPUT_RTSI_OSC = 12 /* pre-m-series always have RTSI clock
on line 7 */
NI_RTSI_OUTPUT_RTSI_OSC = 12 /* pre-m-series always have RTSI
* clock on line 7 */
};
static inline unsigned NI_RTSI_OUTPUT_RTSI_BRD(unsigned n) {
static inline unsigned NI_RTSI_OUTPUT_RTSI_BRD(unsigned n)
{
return NI_RTSI_OUTPUT_RTSI_BRD_0 + n;
}
@ -754,7 +787,8 @@ INSN_CONFIG_ARM */
NI_PFI_OUTPUT_CDI_SAMPLE = 29,
NI_PFI_OUTPUT_CDO_UPDATE = 30
};
static inline unsigned NI_PFI_OUTPUT_RTSI(unsigned rtsi_channel) {
static inline unsigned NI_PFI_OUTPUT_RTSI(unsigned rtsi_channel)
{
return NI_PFI_OUTPUT_RTSI0 + rtsi_channel;
}
@ -772,10 +806,12 @@ INSN_CONFIG_ARM */
/* NI External Trigger lines. These values are not arbitrary, but are related
* to the bits required to program the board (offset by 1 for historical
* reasons). */
static inline unsigned NI_EXT_PFI(unsigned pfi_channel) {
static inline unsigned NI_EXT_PFI(unsigned pfi_channel)
{
return NI_USUAL_PFI_SELECT(pfi_channel) - 1;
}
static inline unsigned NI_EXT_RTSI(unsigned rtsi_channel) {
static inline unsigned NI_EXT_RTSI(unsigned rtsi_channel)
{
return NI_USUAL_RTSI_SELECT(rtsi_channel) - 1;
}
@ -801,21 +837,25 @@ INSN_CONFIG_ARM */
NI_CDIO_SCAN_BEGIN_SRC_FREQ_OUT = 32,
NI_CDIO_SCAN_BEGIN_SRC_DIO_CHANGE_DETECT_IRQ = 33
};
static inline unsigned NI_CDIO_SCAN_BEGIN_SRC_PFI(unsigned pfi_channel) {
static inline unsigned NI_CDIO_SCAN_BEGIN_SRC_PFI(unsigned pfi_channel)
{
return NI_USUAL_PFI_SELECT(pfi_channel);
}
static inline unsigned NI_CDIO_SCAN_BEGIN_SRC_RTSI(unsigned
rtsi_channel) {
static inline unsigned
NI_CDIO_SCAN_BEGIN_SRC_RTSI(unsigned rtsi_channel)
{
return NI_USUAL_RTSI_SELECT(rtsi_channel);
}
/* scan_begin_src for scan_begin_arg==TRIG_EXT with analog output command on NI
* boards. These scan begin sources can also be bitwise-or'd with CR_INVERT to
* change polarity. */
static inline unsigned NI_AO_SCAN_BEGIN_SRC_PFI(unsigned pfi_channel) {
static inline unsigned NI_AO_SCAN_BEGIN_SRC_PFI(unsigned pfi_channel)
{
return NI_USUAL_PFI_SELECT(pfi_channel);
}
static inline unsigned NI_AO_SCAN_BEGIN_SRC_RTSI(unsigned rtsi_channel) {
static inline unsigned NI_AO_SCAN_BEGIN_SRC_RTSI(unsigned rtsi_channel)
{
return NI_USUAL_RTSI_SELECT(rtsi_channel);
}

View file

@ -25,9 +25,8 @@
*/
#define __NO_VERSION__
#include "comedi.h"
#include <linux/uaccess.h>
#include "comedi.h"
#include "comedi_compat32.h"
#ifdef CONFIG_COMPAT

View file

@ -49,7 +49,7 @@
#include <linux/io.h>
#include <linux/uaccess.h>
/* #include "kvmem.h" */
#include "internal.h"
MODULE_AUTHOR("http://www.comedi.org");
MODULE_DESCRIPTION("Comedi core module");
@ -57,13 +57,14 @@ MODULE_LICENSE("GPL");
#ifdef CONFIG_COMEDI_DEBUG
int comedi_debug;
EXPORT_SYMBOL(comedi_debug);
module_param(comedi_debug, int, 0644);
#endif
int comedi_autoconfig = 1;
module_param(comedi_autoconfig, bool, 0444);
int comedi_num_legacy_minors;
static int comedi_num_legacy_minors;
module_param(comedi_num_legacy_minors, int, 0444);
static DEFINE_SPINLOCK(comedi_file_info_table_lock);
@ -71,25 +72,32 @@ static struct comedi_device_file_info
*comedi_file_info_table[COMEDI_NUM_MINORS];
static int do_devconfig_ioctl(struct comedi_device *dev,
struct comedi_devconfig *arg);
static int do_bufconfig_ioctl(struct comedi_device *dev, void *arg);
struct comedi_devconfig __user *arg);
static int do_bufconfig_ioctl(struct comedi_device *dev,
struct comedi_bufconfig __user *arg);
static int do_devinfo_ioctl(struct comedi_device *dev,
struct comedi_devinfo *arg, struct file *file);
struct comedi_devinfo __user *arg,
struct file *file);
static int do_subdinfo_ioctl(struct comedi_device *dev,
struct comedi_subdinfo *arg, void *file);
struct comedi_subdinfo __user *arg, void *file);
static int do_chaninfo_ioctl(struct comedi_device *dev,
struct comedi_chaninfo *arg);
static int do_bufinfo_ioctl(struct comedi_device *dev, void *arg);
static int do_cmd_ioctl(struct comedi_device *dev, void *arg, void *file);
struct comedi_chaninfo __user *arg);
static int do_bufinfo_ioctl(struct comedi_device *dev,
struct comedi_bufinfo __user *arg);
static int do_cmd_ioctl(struct comedi_device *dev,
struct comedi_cmd __user *arg, void *file);
static int do_lock_ioctl(struct comedi_device *dev, unsigned int arg,
void *file);
static int do_unlock_ioctl(struct comedi_device *dev, unsigned int arg,
void *file);
static int do_cancel_ioctl(struct comedi_device *dev, unsigned int arg,
void *file);
static int do_cmdtest_ioctl(struct comedi_device *dev, void *arg, void *file);
static int do_insnlist_ioctl(struct comedi_device *dev, void *arg, void *file);
static int do_insn_ioctl(struct comedi_device *dev, void *arg, void *file);
static int do_cmdtest_ioctl(struct comedi_device *dev,
struct comedi_cmd __user *arg, void *file);
static int do_insnlist_ioctl(struct comedi_device *dev,
struct comedi_insnlist __user *arg, void *file);
static int do_insn_ioctl(struct comedi_device *dev,
struct comedi_insn __user *arg, void *file);
static int do_poll_ioctl(struct comedi_device *dev, unsigned int subd,
void *file);
@ -128,7 +136,8 @@ static long comedi_unlocked_ioctl(struct file *file, unsigned int cmd,
/* Device config is special, because it must work on
* an unconfigured device. */
if (cmd == COMEDI_DEVCONFIG) {
rc = do_devconfig_ioctl(dev, (void *)arg);
rc = do_devconfig_ioctl(dev,
(struct comedi_devconfig __user *)arg);
goto done;
}
@ -140,22 +149,27 @@ static long comedi_unlocked_ioctl(struct file *file, unsigned int cmd,
switch (cmd) {
case COMEDI_BUFCONFIG:
rc = do_bufconfig_ioctl(dev, (void *)arg);
rc = do_bufconfig_ioctl(dev,
(struct comedi_bufconfig __user *)arg);
break;
case COMEDI_DEVINFO:
rc = do_devinfo_ioctl(dev, (void *)arg, file);
rc = do_devinfo_ioctl(dev, (struct comedi_devinfo __user *)arg,
file);
break;
case COMEDI_SUBDINFO:
rc = do_subdinfo_ioctl(dev, (void *)arg, file);
rc = do_subdinfo_ioctl(dev,
(struct comedi_subdinfo __user *)arg,
file);
break;
case COMEDI_CHANINFO:
rc = do_chaninfo_ioctl(dev, (void *)arg);
rc = do_chaninfo_ioctl(dev, (void __user *)arg);
break;
case COMEDI_RANGEINFO:
rc = do_rangeinfo_ioctl(dev, (void *)arg);
rc = do_rangeinfo_ioctl(dev, (void __user *)arg);
break;
case COMEDI_BUFINFO:
rc = do_bufinfo_ioctl(dev, (void *)arg);
rc = do_bufinfo_ioctl(dev,
(struct comedi_bufinfo __user *)arg);
break;
case COMEDI_LOCK:
rc = do_lock_ioctl(dev, arg, file);
@ -167,16 +181,20 @@ static long comedi_unlocked_ioctl(struct file *file, unsigned int cmd,
rc = do_cancel_ioctl(dev, arg, file);
break;
case COMEDI_CMD:
rc = do_cmd_ioctl(dev, (void *)arg, file);
rc = do_cmd_ioctl(dev, (struct comedi_cmd __user *)arg, file);
break;
case COMEDI_CMDTEST:
rc = do_cmdtest_ioctl(dev, (void *)arg, file);
rc = do_cmdtest_ioctl(dev, (struct comedi_cmd __user *)arg,
file);
break;
case COMEDI_INSNLIST:
rc = do_insnlist_ioctl(dev, (void *)arg, file);
rc = do_insnlist_ioctl(dev,
(struct comedi_insnlist __user *)arg,
file);
break;
case COMEDI_INSN:
rc = do_insn_ioctl(dev, (void *)arg, file);
rc = do_insn_ioctl(dev, (struct comedi_insn __user *)arg,
file);
break;
case COMEDI_POLL:
rc = do_poll_ioctl(dev, arg, file);
@ -205,7 +223,7 @@ done:
none
*/
static int do_devconfig_ioctl(struct comedi_device *dev,
struct comedi_devconfig *arg)
struct comedi_devconfig __user *arg)
{
struct comedi_devconfig it;
int ret;
@ -285,7 +303,8 @@ static int do_devconfig_ioctl(struct comedi_device *dev,
modified bufconfig at arg
*/
static int do_bufconfig_ioctl(struct comedi_device *dev, void *arg)
static int do_bufconfig_ioctl(struct comedi_device *dev,
struct comedi_bufconfig __user *arg)
{
struct comedi_bufconfig bc;
struct comedi_async *async;
@ -346,7 +365,8 @@ copyback:
*/
static int do_devinfo_ioctl(struct comedi_device *dev,
struct comedi_devinfo *arg, struct file *file)
struct comedi_devinfo __user *arg,
struct file *file)
{
struct comedi_devinfo devinfo;
const unsigned minor = iminor(file->f_dentry->d_inode);
@ -396,7 +416,7 @@ static int do_devinfo_ioctl(struct comedi_device *dev,
*/
static int do_subdinfo_ioctl(struct comedi_device *dev,
struct comedi_subdinfo *arg, void *file)
struct comedi_subdinfo __user *arg, void *file)
{
int ret, i;
struct comedi_subdinfo *tmp, *us;
@ -478,7 +498,7 @@ static int do_subdinfo_ioctl(struct comedi_device *dev,
*/
static int do_chaninfo_ioctl(struct comedi_device *dev,
struct comedi_chaninfo *arg)
struct comedi_chaninfo __user *arg)
{
struct comedi_subdevice *s;
struct comedi_chaninfo it;
@ -542,7 +562,8 @@ static int do_chaninfo_ioctl(struct comedi_device *dev,
modified bufinfo at arg
*/
static int do_bufinfo_ioctl(struct comedi_device *dev, void *arg)
static int do_bufinfo_ioctl(struct comedi_device *dev,
struct comedi_bufinfo __user *arg)
{
struct comedi_bufinfo bi;
struct comedi_subdevice *s;
@ -598,23 +619,24 @@ copyback:
static int parse_insn(struct comedi_device *dev, struct comedi_insn *insn,
unsigned int *data, void *file);
/*
* COMEDI_INSNLIST
* synchronous instructions
* COMEDI_INSNLIST
* synchronous instructions
*
* arg:
* pointer to sync cmd structure
* arg:
* pointer to sync cmd structure
*
* reads:
* sync cmd struct at arg
* instruction list
* data (for writes)
* reads:
* sync cmd struct at arg
* instruction list
* data (for writes)
*
* writes:
* data (for reads)
* writes:
* data (for reads)
*/
/* arbitrary limits */
#define MAX_SAMPLES 256
static int do_insnlist_ioctl(struct comedi_device *dev, void *arg, void *file)
static int do_insnlist_ioctl(struct comedi_device *dev,
struct comedi_insnlist __user *arg, void *file)
{
struct comedi_insnlist insnlist;
struct comedi_insn *insns = NULL;
@ -736,7 +758,8 @@ static int check_insn_config_length(struct comedi_insn *insn,
/* by default we allow the insn since we don't have checks for
* all possible cases yet */
default:
printk("comedi: no check for data length of config insn id "
printk(KERN_WARNING
"comedi: no check for data length of config insn id "
"%i is implemented.\n"
" Add a check to %s in %s.\n"
" Assuming n=%i is correct.\n", data[0], __func__,
@ -837,7 +860,7 @@ static int parse_insn(struct comedi_device *dev, struct comedi_insn *insn,
goto out;
}
ret = check_chanlist(s, 1, &insn->chanspec);
ret = comedi_check_chanlist(s, 1, &insn->chanspec);
if (ret < 0) {
ret = -EINVAL;
DPRINTK("bad chanspec\n");
@ -894,20 +917,21 @@ out:
}
/*
* COMEDI_INSN
* synchronous instructions
* COMEDI_INSN
* synchronous instructions
*
* arg:
* pointer to insn
* arg:
* pointer to insn
*
* reads:
* struct comedi_insn struct at arg
* data (for writes)
* reads:
* struct comedi_insn struct at arg
* data (for writes)
*
* writes:
* data (for reads)
* writes:
* data (for reads)
*/
static int do_insn_ioctl(struct comedi_device *dev, void *arg, void *file)
static int do_insn_ioctl(struct comedi_device *dev,
struct comedi_insn __user *arg, void *file)
{
struct comedi_insn insn;
unsigned int *data = NULL;
@ -928,8 +952,9 @@ static int do_insn_ioctl(struct comedi_device *dev, void *arg, void *file)
if (insn.n > MAX_SAMPLES)
insn.n = MAX_SAMPLES;
if (insn.insn & INSN_MASK_WRITE) {
if (copy_from_user
(data, insn.data, insn.n * sizeof(unsigned int))) {
if (copy_from_user(data,
insn.data,
insn.n * sizeof(unsigned int))) {
ret = -EFAULT;
goto error;
}
@ -938,8 +963,9 @@ static int do_insn_ioctl(struct comedi_device *dev, void *arg, void *file)
if (ret < 0)
goto error;
if (insn.insn & INSN_MASK_READ) {
if (copy_to_user
(insn.data, data, insn.n * sizeof(unsigned int))) {
if (copy_to_user(insn.data,
data,
insn.n * sizeof(unsigned int))) {
ret = -EFAULT;
goto error;
}
@ -952,30 +978,27 @@ error:
return ret;
}
/*
COMEDI_CMD
command ioctl
static void comedi_set_subdevice_runflags(struct comedi_subdevice *s,
unsigned mask, unsigned bits)
{
unsigned long flags;
arg:
pointer to cmd structure
spin_lock_irqsave(&s->spin_lock, flags);
s->runflags &= ~mask;
s->runflags |= (bits & mask);
spin_unlock_irqrestore(&s->spin_lock, flags);
}
reads:
cmd structure at arg
channel/range list
writes:
modified cmd structure at arg
*/
static int do_cmd_ioctl(struct comedi_device *dev, void *arg, void *file)
static int do_cmd_ioctl(struct comedi_device *dev,
struct comedi_cmd __user *cmd, void *file)
{
struct comedi_cmd user_cmd;
struct comedi_subdevice *s;
struct comedi_async *async;
int ret = 0;
unsigned int *chanlist_saver = NULL;
unsigned int __user *chanlist_saver = NULL;
if (copy_from_user(&user_cmd, arg, sizeof(struct comedi_cmd))) {
if (copy_from_user(&user_cmd, cmd, sizeof(struct comedi_cmd))) {
DPRINTK("bad cmd address\n");
return -EFAULT;
}
@ -1050,7 +1073,9 @@ static int do_cmd_ioctl(struct comedi_device *dev, void *arg, void *file)
}
/* make sure each element in channel/gain list is valid */
ret = check_chanlist(s, async->cmd.chanlist_len, async->cmd.chanlist);
ret = comedi_check_chanlist(s,
async->cmd.chanlist_len,
async->cmd.chanlist);
if (ret < 0) {
DPRINTK("bad chanlist\n");
goto cleanup;
@ -1064,7 +1089,7 @@ static int do_cmd_ioctl(struct comedi_device *dev, void *arg, void *file)
/* restore chanlist pointer before copying back */
user_cmd.chanlist = chanlist_saver;
user_cmd.data = NULL;
if (copy_to_user(arg, &user_cmd, sizeof(struct comedi_cmd))) {
if (copy_to_user(cmd, &user_cmd, sizeof(struct comedi_cmd))) {
DPRINTK("fault writing cmd\n");
ret = -EFAULT;
goto cleanup;
@ -1114,13 +1139,14 @@ cleanup:
modified cmd structure at arg
*/
static int do_cmdtest_ioctl(struct comedi_device *dev, void *arg, void *file)
static int do_cmdtest_ioctl(struct comedi_device *dev,
struct comedi_cmd __user *arg, void *file)
{
struct comedi_cmd user_cmd;
struct comedi_subdevice *s;
int ret = 0;
unsigned int *chanlist = NULL;
unsigned int *chanlist_saver = NULL;
unsigned int __user *chanlist_saver = NULL;
if (copy_from_user(&user_cmd, arg, sizeof(struct comedi_cmd))) {
DPRINTK("bad cmd address\n");
@ -1172,7 +1198,7 @@ static int do_cmdtest_ioctl(struct comedi_device *dev, void *arg, void *file)
}
/* make sure each element in channel/gain list is valid */
ret = check_chanlist(s, user_cmd.chanlist_len, chanlist);
ret = comedi_check_chanlist(s, user_cmd.chanlist_len, chanlist);
if (ret < 0) {
DPRINTK("bad chanlist\n");
goto cleanup;
@ -1371,7 +1397,7 @@ static int do_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
return ret;
}
void comedi_unmap(struct vm_area_struct *area)
static void comedi_unmap(struct vm_area_struct *area)
{
struct comedi_async *async;
struct comedi_device *dev;
@ -1509,8 +1535,8 @@ static unsigned int comedi_poll(struct file *file, poll_table * wait)
return mask;
}
static ssize_t comedi_write(struct file *file, const char *buf, size_t nbytes,
loff_t *offset)
static ssize_t comedi_write(struct file *file, const char __user *buf,
size_t nbytes, loff_t *offset)
{
struct comedi_subdevice *s;
struct comedi_async *async;
@ -1611,7 +1637,7 @@ done:
return count ? count : retval;
}
static ssize_t comedi_read(struct file *file, char *buf, size_t nbytes,
static ssize_t comedi_read(struct file *file, char __user *buf, size_t nbytes,
loff_t *offset)
{
struct comedi_subdevice *s;
@ -1925,7 +1951,7 @@ static int __init comedi_init(void)
}
comedi_class = class_create(THIS_MODULE, "comedi");
if (IS_ERR(comedi_class)) {
printk("comedi: failed to create class");
printk(KERN_ERR "comedi: failed to create class");
cdev_del(&comedi_cdev);
unregister_chrdev_region(MKDEV(COMEDI_MAJOR, 0),
COMEDI_NUM_MINORS);
@ -1971,8 +1997,10 @@ module_exit(comedi_cleanup);
void comedi_error(const struct comedi_device *dev, const char *s)
{
printk("comedi%d: %s: %s\n", dev->minor, dev->driver->driver_name, s);
printk(KERN_ERR "comedi%d: %s: %s\n", dev->minor,
dev->driver->driver_name, s);
}
EXPORT_SYMBOL(comedi_error);
void comedi_event(struct comedi_device *dev, struct comedi_subdevice *s)
{
@ -2015,17 +2043,7 @@ void comedi_event(struct comedi_device *dev, struct comedi_subdevice *s)
}
s->async->events = 0;
}
void comedi_set_subdevice_runflags(struct comedi_subdevice *s, unsigned mask,
unsigned bits)
{
unsigned long flags;
spin_lock_irqsave(&s->spin_lock, flags);
s->runflags &= ~mask;
s->runflags |= (bits & mask);
spin_unlock_irqrestore(&s->spin_lock, flags);
}
EXPORT_SYMBOL(comedi_event);
unsigned comedi_get_subdevice_runflags(struct comedi_subdevice *s)
{
@ -2037,6 +2055,7 @@ unsigned comedi_get_subdevice_runflags(struct comedi_subdevice *s)
spin_unlock_irqrestore(&s->spin_lock, flags);
return runflags;
}
EXPORT_SYMBOL(comedi_get_subdevice_runflags);
static int is_device_busy(struct comedi_device *dev)
{
@ -2057,7 +2076,7 @@ static int is_device_busy(struct comedi_device *dev)
return 0;
}
void comedi_device_init(struct comedi_device *dev)
static void comedi_device_init(struct comedi_device *dev)
{
memset(dev, 0, sizeof(struct comedi_device));
spin_lock_init(&dev->spinlock);
@ -2065,7 +2084,7 @@ void comedi_device_init(struct comedi_device *dev)
dev->minor = -1;
}
void comedi_device_cleanup(struct comedi_device *dev)
static void comedi_device_cleanup(struct comedi_device *dev)
{
if (dev == NULL)
return;
@ -2105,7 +2124,8 @@ int comedi_alloc_board_minor(struct device *hardware_device)
kfree(info->device);
kfree(info);
printk(KERN_ERR
"comedi: error: ran out of minor numbers for board device files.\n");
"comedi: error: "
"ran out of minor numbers for board device files.\n");
return -EBUSY;
}
info->device->minor = i;
@ -2118,7 +2138,8 @@ int comedi_alloc_board_minor(struct device *hardware_device)
retval = device_create_file(csdev, &dev_attr_max_read_buffer_kb);
if (retval) {
printk(KERN_ERR
"comedi: failed to create sysfs attribute file \"%s\".\n",
"comedi: "
"failed to create sysfs attribute file \"%s\".\n",
dev_attr_max_read_buffer_kb.attr.name);
comedi_free_board_minor(i);
return retval;
@ -2126,7 +2147,8 @@ int comedi_alloc_board_minor(struct device *hardware_device)
retval = device_create_file(csdev, &dev_attr_read_buffer_kb);
if (retval) {
printk(KERN_ERR
"comedi: failed to create sysfs attribute file \"%s\".\n",
"comedi: "
"failed to create sysfs attribute file \"%s\".\n",
dev_attr_read_buffer_kb.attr.name);
comedi_free_board_minor(i);
return retval;
@ -2134,7 +2156,8 @@ int comedi_alloc_board_minor(struct device *hardware_device)
retval = device_create_file(csdev, &dev_attr_max_write_buffer_kb);
if (retval) {
printk(KERN_ERR
"comedi: failed to create sysfs attribute file \"%s\".\n",
"comedi: "
"failed to create sysfs attribute file \"%s\".\n",
dev_attr_max_write_buffer_kb.attr.name);
comedi_free_board_minor(i);
return retval;
@ -2142,7 +2165,8 @@ int comedi_alloc_board_minor(struct device *hardware_device)
retval = device_create_file(csdev, &dev_attr_write_buffer_kb);
if (retval) {
printk(KERN_ERR
"comedi: failed to create sysfs attribute file \"%s\".\n",
"comedi: "
"failed to create sysfs attribute file \"%s\".\n",
dev_attr_write_buffer_kb.attr.name);
comedi_free_board_minor(i);
return retval;
@ -2201,7 +2225,8 @@ int comedi_alloc_subdevice_minor(struct comedi_device *dev,
if (i == COMEDI_NUM_MINORS) {
kfree(info);
printk(KERN_ERR
"comedi: error: ran out of minor numbers for board device files.\n");
"comedi: error: "
"ran out of minor numbers for board device files.\n");
return -EBUSY;
}
s->minor = i;
@ -2215,7 +2240,8 @@ int comedi_alloc_subdevice_minor(struct comedi_device *dev,
retval = device_create_file(csdev, &dev_attr_max_read_buffer_kb);
if (retval) {
printk(KERN_ERR
"comedi: failed to create sysfs attribute file \"%s\".\n",
"comedi: "
"failed to create sysfs attribute file \"%s\".\n",
dev_attr_max_read_buffer_kb.attr.name);
comedi_free_subdevice_minor(s);
return retval;
@ -2223,7 +2249,8 @@ int comedi_alloc_subdevice_minor(struct comedi_device *dev,
retval = device_create_file(csdev, &dev_attr_read_buffer_kb);
if (retval) {
printk(KERN_ERR
"comedi: failed to create sysfs attribute file \"%s\".\n",
"comedi: "
"failed to create sysfs attribute file \"%s\".\n",
dev_attr_read_buffer_kb.attr.name);
comedi_free_subdevice_minor(s);
return retval;
@ -2231,7 +2258,8 @@ int comedi_alloc_subdevice_minor(struct comedi_device *dev,
retval = device_create_file(csdev, &dev_attr_max_write_buffer_kb);
if (retval) {
printk(KERN_ERR
"comedi: failed to create sysfs attribute file \"%s\".\n",
"comedi: "
"failed to create sysfs attribute file \"%s\".\n",
dev_attr_max_write_buffer_kb.attr.name);
comedi_free_subdevice_minor(s);
return retval;
@ -2239,7 +2267,8 @@ int comedi_alloc_subdevice_minor(struct comedi_device *dev,
retval = device_create_file(csdev, &dev_attr_write_buffer_kb);
if (retval) {
printk(KERN_ERR
"comedi: failed to create sysfs attribute file \"%s\".\n",
"comedi: "
"failed to create sysfs attribute file \"%s\".\n",
dev_attr_write_buffer_kb.attr.name);
comedi_free_subdevice_minor(s);
return retval;
@ -2283,6 +2312,7 @@ struct comedi_device_file_info *comedi_get_device_file_info(unsigned minor)
spin_unlock_irqrestore(&comedi_file_info_table_lock, flags);
return info;
}
EXPORT_SYMBOL_GPL(comedi_get_device_file_info);
static int resize_async_buffer(struct comedi_device *dev,
struct comedi_subdevice *s,

View file

@ -5,5 +5,6 @@
extern struct class *comedi_class;
extern const struct file_operations comedi_fops;
extern int comedi_autoconfig;
extern struct comedi_driver *comedi_drivers;
#endif /* _COMEDI_FOPS_H */

View file

@ -1,69 +0,0 @@
/*
module/exp_ioctl.c
exported comedi functions
COMEDI - Linux Control and Measurement Device Interface
Copyright (C) 1997-8 David A. Schleef <ds@schleef.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#define __NO_VERSION__
#include "comedidev.h"
/* for drivers */
EXPORT_SYMBOL(comedi_driver_register);
EXPORT_SYMBOL(comedi_driver_unregister);
/* EXPORT_SYMBOL(comedi_bufcheck); */
/* EXPORT_SYMBOL(comedi_done); */
/* EXPORT_SYMBOL(comedi_error_done); */
EXPORT_SYMBOL(comedi_error);
/* EXPORT_SYMBOL(comedi_eobuf); */
/* EXPORT_SYMBOL(comedi_eos); */
EXPORT_SYMBOL(comedi_event);
EXPORT_SYMBOL(comedi_get_subdevice_runflags);
EXPORT_SYMBOL(comedi_set_subdevice_runflags);
EXPORT_SYMBOL(range_bipolar10);
EXPORT_SYMBOL(range_bipolar5);
EXPORT_SYMBOL(range_bipolar2_5);
EXPORT_SYMBOL(range_unipolar10);
EXPORT_SYMBOL(range_unipolar5);
EXPORT_SYMBOL(range_unknown);
#ifdef CONFIG_COMEDI_DEBUG
EXPORT_SYMBOL(comedi_debug);
#endif
EXPORT_SYMBOL_GPL(comedi_alloc_board_minor);
EXPORT_SYMBOL_GPL(comedi_free_board_minor);
EXPORT_SYMBOL_GPL(comedi_pci_auto_config);
EXPORT_SYMBOL_GPL(comedi_pci_auto_unconfig);
EXPORT_SYMBOL_GPL(comedi_usb_auto_config);
EXPORT_SYMBOL_GPL(comedi_usb_auto_unconfig);
/* for kcomedilib */
EXPORT_SYMBOL(check_chanlist);
EXPORT_SYMBOL_GPL(comedi_get_device_file_info);
EXPORT_SYMBOL(comedi_buf_put);
EXPORT_SYMBOL(comedi_buf_get);
EXPORT_SYMBOL(comedi_buf_read_n_available);
EXPORT_SYMBOL(comedi_buf_write_free);
EXPORT_SYMBOL(comedi_buf_write_alloc);
EXPORT_SYMBOL(comedi_buf_read_free);
EXPORT_SYMBOL(comedi_buf_read_alloc);
EXPORT_SYMBOL(comedi_buf_memcpy_to);
EXPORT_SYMBOL(comedi_buf_memcpy_from);
EXPORT_SYMBOL(comedi_reset_async_buf);

View file

@ -57,7 +57,7 @@
static int __init x ## _init_module(void) \
{return comedi_driver_register(&(x)); } \
static void __exit x ## _cleanup_module(void) \
{comedi_driver_unregister(&(x)); } \
{comedi_driver_unregister(&(x)); } \
module_init(x ## _init_module); \
module_exit(x ## _cleanup_module);
@ -109,17 +109,9 @@
COMEDI_MODULE_MACROS \
COMEDI_PCI_INITCLEANUP_NOMODULE(comedi_driver, pci_id_table)
#define PCI_VENDOR_ID_INOVA 0x104c
#define PCI_VENDOR_ID_NATINST 0x1093
#define PCI_VENDOR_ID_DATX 0x1116
#define PCI_VENDOR_ID_COMPUTERBOARDS 0x1307
#define PCI_VENDOR_ID_ADVANTECH 0x13fe
#define PCI_VENDOR_ID_RTD 0x1435
#define PCI_VENDOR_ID_AMPLICON 0x14dc
#define PCI_VENDOR_ID_ADLINK 0x144a
#define PCI_VENDOR_ID_ICP 0x104c
#define PCI_VENDOR_ID_CONTEC 0x1221
#define PCI_VENDOR_ID_MEILHAUS 0x1402
#define COMEDI_NUM_MINORS 0x100
#define COMEDI_NUM_BOARD_MINORS 0x30
@ -132,7 +124,7 @@ struct comedi_subdevice {
struct comedi_device *device;
int type;
int n_chan;
volatile int subdev_flags;
int subdev_flags;
int len_chanlist; /* maximum length of channel/gain list */
void *private;
@ -359,9 +351,6 @@ void cleanup_polling(void);
void start_polling(struct comedi_device *);
void stop_polling(struct comedi_device *);
int comedi_buf_alloc(struct comedi_device *dev, struct comedi_subdevice *s,
unsigned long new_size);
#ifdef CONFIG_PROC_FS
void comedi_proc_init(void);
void comedi_proc_cleanup(void);
@ -385,24 +374,17 @@ enum subdevice_runflags {
SRF_RUNNING = 0x08000000
};
/*
various internal comedi functions
*/
int do_rangeinfo_ioctl(struct comedi_device *dev, struct comedi_rangeinfo *arg);
int check_chanlist(struct comedi_subdevice *s, int n, unsigned int *chanlist);
void comedi_set_subdevice_runflags(struct comedi_subdevice *s, unsigned mask,
unsigned bits);
int comedi_check_chanlist(struct comedi_subdevice *s,
int n,
unsigned int *chanlist);
unsigned comedi_get_subdevice_runflags(struct comedi_subdevice *s);
int insn_inval(struct comedi_device *dev, struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data);
/* range stuff */
#define RANGE(a, b) {(a)*1e6, (b)*1e6, 0}
#define RANGE_ext(a, b) {(a)*1e6, (b)*1e6, RF_EXTERNAL}
#define RANGE_mA(a, b) {(a)*1e6, (b)*1e6, UNIT_mA}
#define RANGE_unitless(a, b) {(a)*1e6, (b)*1e6, 0} /* XXX */
#define RANGE_unitless(a, b) {(a)*1e6, (b)*1e6, 0}
#define BIP_RANGE(a) {-(a)*1e6, (a)*1e6, 0}
#define UNI_RANGE(a) {0, (a)*1e6, 0}
@ -505,8 +487,6 @@ static inline unsigned comedi_buf_read_n_allocated(struct comedi_async *async)
return async->buf_read_alloc_count - async->buf_read_count;
}
void comedi_reset_async_buf(struct comedi_async *async);
static inline void *comedi_aux_data(int options[], int n)
{
unsigned long address;
@ -532,8 +512,6 @@ static inline void *comedi_aux_data(int options[], int n)
return (void *)address;
}
int comedi_alloc_board_minor(struct device *hardware_device);
void comedi_free_board_minor(unsigned minor);
int comedi_alloc_subdevice_minor(struct comedi_device *dev,
struct comedi_subdevice *s);
void comedi_free_subdevice_minor(struct comedi_subdevice *s);

View file

@ -24,170 +24,14 @@
#ifndef _LINUX_COMEDILIB_H
#define _LINUX_COMEDILIB_H
#include "comedi.h"
/* Kernel internal stuff. Needed by real-time modules and such. */
#ifndef __KERNEL__
#error linux/comedilib.h should not be included by non-kernel-space code
#endif
/* exported functions */
#ifndef KCOMEDILIB_DEPRECATED
/* these functions may not be called at real-time priority */
void *comedi_open(const char *path);
int comedi_close(void *dev);
/* these functions may be called at any priority, but may fail at
real-time priority */
int comedi_lock(void *dev, unsigned int subdev);
int comedi_unlock(void *dev, unsigned int subdev);
/* these functions may be called at any priority, but you must hold
the lock for the subdevice */
int comedi_loglevel(int loglevel);
void comedi_perror(const char *s);
char *comedi_strerror(int errnum);
int comedi_errno(void);
int comedi_fileno(void *dev);
int comedi_cancel(void *dev, unsigned int subdev);
int comedi_register_callback(void *dev, unsigned int subdev,
unsigned int mask, int (*cb) (unsigned int,
void *), void *arg);
int comedi_command(void *dev, struct comedi_cmd *cmd);
int comedi_command_test(void *dev, struct comedi_cmd *cmd);
int comedi_trigger(void *dev, unsigned int subdev, struct comedi_trig *it);
int __comedi_trigger(void *dev, unsigned int subdev, struct comedi_trig *it);
int comedi_data_write(void *dev, unsigned int subdev, unsigned int chan,
unsigned int range, unsigned int aref, unsigned int data);
int comedi_data_read(void *dev, unsigned int subdev, unsigned int chan,
unsigned int range, unsigned int aref, unsigned int *data);
int comedi_data_read_hint(void *dev, unsigned int subdev,
unsigned int chan, unsigned int range,
unsigned int aref);
int comedi_data_read_delayed(void *dev, unsigned int subdev, unsigned int chan,
unsigned int range, unsigned int aref,
unsigned int *data, unsigned int nano_sec);
int comedi_dio_config(void *dev, unsigned int subdev, unsigned int chan,
unsigned int io);
int comedi_dio_read(void *dev, unsigned int subdev, unsigned int chan,
unsigned int *val);
int comedi_dio_write(void *dev, unsigned int subdev, unsigned int chan,
unsigned int val);
int comedi_dio_bitfield(void *dev, unsigned int subdev, unsigned int mask,
unsigned int *bits);
int comedi_get_n_subdevices(void *dev);
int comedi_get_version_code(void *dev);
const char *comedi_get_driver_name(void *dev);
const char *comedi_get_board_name(void *dev);
int comedi_get_subdevice_type(void *dev, unsigned int subdevice);
int comedi_find_subdevice_by_type(void *dev, int type, unsigned int subd);
int comedi_get_n_channels(void *dev, unsigned int subdevice);
unsigned int comedi_get_maxdata(void *dev, unsigned int subdevice, unsigned
int chan);
int comedi_get_n_ranges(void *dev, unsigned int subdevice, unsigned int chan);
int comedi_do_insn(void *dev, struct comedi_insn *insn);
int comedi_poll(void *dev, unsigned int subdev);
/* DEPRECATED functions */
int comedi_get_rangetype(void *dev, unsigned int subdevice, unsigned int chan);
/* ALPHA functions */
unsigned int comedi_get_subdevice_flags(void *dev, unsigned int subdevice);
int comedi_get_len_chanlist(void *dev, unsigned int subdevice);
int comedi_get_krange(void *dev, unsigned int subdevice, unsigned int
chan, unsigned int range, struct comedi_krange *krange);
unsigned int comedi_get_buf_head_pos(void *dev, unsigned int subdevice);
int comedi_set_user_int_count(void *dev, unsigned int subdevice,
unsigned int buf_user_count);
int comedi_map(void *dev, unsigned int subdev, void *ptr);
int comedi_unmap(void *dev, unsigned int subdev);
int comedi_get_buffer_size(void *dev, unsigned int subdev);
int comedi_mark_buffer_read(void *dev, unsigned int subdevice,
unsigned int num_bytes);
int comedi_mark_buffer_written(void *d, unsigned int subdevice,
unsigned int num_bytes);
int comedi_get_buffer_contents(void *dev, unsigned int subdevice);
int comedi_get_buffer_offset(void *dev, unsigned int subdevice);
#else
/* these functions may not be called at real-time priority */
int comedi_open(unsigned int minor);
void comedi_close(unsigned int minor);
/* these functions may be called at any priority, but may fail at
real-time priority */
int comedi_lock(unsigned int minor, unsigned int subdev);
int comedi_unlock(unsigned int minor, unsigned int subdev);
/* these functions may be called at any priority, but you must hold
the lock for the subdevice */
int comedi_cancel(unsigned int minor, unsigned int subdev);
int comedi_register_callback(unsigned int minor, unsigned int subdev,
unsigned int mask, int (*cb) (unsigned int,
void *), void *arg);
int comedi_command(unsigned int minor, struct comedi_cmd *cmd);
int comedi_command_test(unsigned int minor, struct comedi_cmd *cmd);
int comedi_trigger(unsigned int minor, unsigned int subdev,
struct comedi_trig *it);
int __comedi_trigger(unsigned int minor, unsigned int subdev,
struct comedi_trig *it);
int comedi_data_write(unsigned int dev, unsigned int subdev, unsigned int chan,
unsigned int range, unsigned int aref, unsigned int data);
int comedi_data_read(unsigned int dev, unsigned int subdev, unsigned int chan,
unsigned int range, unsigned int aref, unsigned int *data);
int comedi_dio_config(unsigned int dev, unsigned int subdev, unsigned int chan,
unsigned int io);
int comedi_dio_read(unsigned int dev, unsigned int subdev, unsigned int chan,
unsigned int *val);
int comedi_dio_write(unsigned int dev, unsigned int subdev, unsigned int chan,
unsigned int val);
int comedi_dio_bitfield(unsigned int dev, unsigned int subdev,
struct comedi_device *comedi_open(const char *path);
int comedi_close(struct comedi_device *dev);
int comedi_dio_config(struct comedi_device *dev, unsigned int subdev,
unsigned int chan, unsigned int io);
int comedi_dio_bitfield(struct comedi_device *dev, unsigned int subdev,
unsigned int mask, unsigned int *bits);
int comedi_get_n_subdevices(unsigned int dev);
int comedi_get_version_code(unsigned int dev);
char *comedi_get_driver_name(unsigned int dev);
char *comedi_get_board_name(unsigned int minor);
int comedi_get_subdevice_type(unsigned int minor, unsigned int subdevice);
int comedi_find_subdevice_by_type(unsigned int minor, int type,
int comedi_find_subdevice_by_type(struct comedi_device *dev, int type,
unsigned int subd);
int comedi_get_n_channels(unsigned int minor, unsigned int subdevice);
unsigned int comedi_get_maxdata(unsigned int minor, unsigned int subdevice, unsigned
int chan);
int comedi_get_n_ranges(unsigned int minor, unsigned int subdevice, unsigned int
chan);
int comedi_do_insn(unsigned int minor, struct comedi_insn *insn);
int comedi_poll(unsigned int minor, unsigned int subdev);
/* DEPRECATED functions */
int comedi_get_rangetype(unsigned int minor, unsigned int subdevice,
unsigned int chan);
/* ALPHA functions */
unsigned int comedi_get_subdevice_flags(unsigned int minor, unsigned int
subdevice);
int comedi_get_len_chanlist(unsigned int minor, unsigned int subdevice);
int comedi_get_krange(unsigned int minor, unsigned int subdevice, unsigned int
chan, unsigned int range, struct comedi_krange *krange);
unsigned int comedi_get_buf_head_pos(unsigned int minor, unsigned int
subdevice);
int comedi_set_user_int_count(unsigned int minor, unsigned int subdevice,
unsigned int buf_user_count);
int comedi_map(unsigned int minor, unsigned int subdev, void **ptr);
int comedi_unmap(unsigned int minor, unsigned int subdev);
#endif
int comedi_get_n_channels(struct comedi_device *dev, unsigned int subdevice);
#endif

View file

@ -37,16 +37,16 @@
#include <linux/ioport.h>
#include <linux/mm.h>
#include <linux/slab.h>
#include "comedidev.h"
#include "wrapper.h"
#include <linux/highmem.h> /* for SuSE brokenness */
#include <linux/vmalloc.h>
#include <linux/cdev.h>
#include <linux/dma-mapping.h>
#include <linux/io.h>
#include <asm/system.h>
#include "comedidev.h"
#include "internal.h"
static int postconfig(struct comedi_device *dev);
static int insn_rw_emulate_bits(struct comedi_device *dev,
struct comedi_subdevice *s,
@ -54,16 +54,9 @@ static int insn_rw_emulate_bits(struct comedi_device *dev,
static void *comedi_recognize(struct comedi_driver *driv, const char *name);
static void comedi_report_boards(struct comedi_driver *driv);
static int poll_invalid(struct comedi_device *dev, struct comedi_subdevice *s);
int comedi_buf_alloc(struct comedi_device *dev, struct comedi_subdevice *s,
unsigned long new_size);
struct comedi_driver *comedi_drivers;
int comedi_modprobe(int minor)
{
return -EINVAL;
}
static void cleanup_device(struct comedi_device *dev)
{
int i;
@ -84,7 +77,7 @@ static void cleanup_device(struct comedi_device *dev)
}
kfree(dev->private);
dev->private = NULL;
dev->driver = 0;
dev->driver = NULL;
dev->board_name = NULL;
dev->board_ptr = NULL;
dev->iobase = 0;
@ -102,7 +95,8 @@ static void __comedi_device_detach(struct comedi_device *dev)
if (dev->driver)
dev->driver->detach(dev);
else
printk("BUG: dev->driver=NULL in comedi_device_detach()\n");
printk(KERN_WARNING
"BUG: dev->driver=NULL in comedi_device_detach()\n");
cleanup_device(dev);
}
@ -124,7 +118,7 @@ int comedi_device_attach(struct comedi_device *dev, struct comedi_devconfig *it)
for (driv = comedi_drivers; driv; driv = driv->next) {
if (!try_module_get(driv->module)) {
printk
("comedi: failed to increment module count, skipping\n");
(KERN_INFO "comedi: failed to increment module count, skipping\n");
continue;
}
if (driv->num_names) {
@ -139,7 +133,8 @@ int comedi_device_attach(struct comedi_device *dev, struct comedi_devconfig *it)
continue;
}
}
/* initialize dev->driver here so comedi_error() can be called from attach */
/* initialize dev->driver here so
* comedi_error() can be called from attach */
dev->driver = driv;
ret = driv->attach(dev, it);
if (ret < 0) {
@ -154,7 +149,8 @@ int comedi_device_attach(struct comedi_device *dev, struct comedi_devconfig *it)
/* report valid board names before returning error */
for (driv = comedi_drivers; driv; driv = driv->next) {
if (!try_module_get(driv->module)) {
printk("comedi: failed to increment module count\n");
printk(KERN_INFO
"comedi: failed to increment module count\n");
continue;
}
comedi_report_boards(driv);
@ -172,7 +168,8 @@ attached:
}
if (!dev->board_name) {
printk("BUG: dev->board_name=<%p>\n", dev->board_name);
printk(KERN_WARNING "BUG: dev->board_name=<%p>\n",
dev->board_name);
dev->board_name = "BUG";
}
smp_wmb();
@ -188,6 +185,7 @@ int comedi_driver_register(struct comedi_driver *driver)
return 0;
}
EXPORT_SYMBOL(comedi_driver_register);
int comedi_driver_unregister(struct comedi_driver *driver)
{
@ -208,7 +206,7 @@ int comedi_driver_unregister(struct comedi_driver *driver)
if (dev->attached && dev->driver == driver) {
if (dev->use_count)
printk
("BUG! detaching device with use_count=%d\n",
(KERN_WARNING "BUG! detaching device with use_count=%d\n",
dev->use_count);
comedi_device_detach(dev);
}
@ -228,6 +226,7 @@ int comedi_driver_unregister(struct comedi_driver *driver)
}
return -EINVAL;
}
EXPORT_SYMBOL(comedi_driver_unregister);
static int postconfig(struct comedi_device *dev)
{
@ -253,7 +252,8 @@ static int postconfig(struct comedi_device *dev)
async =
kzalloc(sizeof(struct comedi_async), GFP_KERNEL);
if (async == NULL) {
printk("failed to allocate async struct\n");
printk(KERN_INFO
"failed to allocate async struct\n");
return -ENOMEM;
}
init_waitqueue_head(&async->wait_head);
@ -268,7 +268,7 @@ static int postconfig(struct comedi_device *dev)
async->prealloc_buf = NULL;
async->prealloc_bufsz = 0;
if (comedi_buf_alloc(dev, s, DEFAULT_BUF_SIZE) < 0) {
printk("Buffer allocation failed\n");
printk(KERN_INFO "Buffer allocation failed\n");
return -ENOMEM;
}
if (s->buf_change) {
@ -303,8 +303,9 @@ static int postconfig(struct comedi_device *dev)
return 0;
}
/* generic recognize function for drivers that register their supported board names */
void *comedi_recognize(struct comedi_driver *driv, const char *name)
/* generic recognize function for drivers
* that register their supported board names */
static void *comedi_recognize(struct comedi_driver *driv, const char *name)
{
unsigned i;
const char *const *name_ptr = driv->board_name;
@ -319,22 +320,22 @@ void *comedi_recognize(struct comedi_driver *driv, const char *name)
return NULL;
}
void comedi_report_boards(struct comedi_driver *driv)
static void comedi_report_boards(struct comedi_driver *driv)
{
unsigned int i;
const char *const *name_ptr;
printk("comedi: valid board names for %s driver are:\n",
printk(KERN_INFO "comedi: valid board names for %s driver are:\n",
driv->driver_name);
name_ptr = driv->board_name;
for (i = 0; i < driv->num_names; i++) {
printk(" %s\n", *name_ptr);
printk(KERN_INFO " %s\n", *name_ptr);
name_ptr = (const char **)((char *)name_ptr + driv->offset);
}
if (driv->num_names == 0)
printk(" %s\n", driv->driver_name);
printk(KERN_INFO " %s\n", driv->driver_name);
}
static int poll_invalid(struct comedi_device *dev, struct comedi_subdevice *s)
@ -371,8 +372,9 @@ static int insn_rw_emulate_bits(struct comedi_device *dev,
if (insn->insn == INSN_WRITE) {
if (!(s->subdev_flags & SDF_WRITABLE))
return -EINVAL;
new_data[0] = 1 << (chan - base_bitfield_channel); /* mask */
new_data[1] = data[0] ? (1 << (chan - base_bitfield_channel)) : 0; /* bits */
new_data[0] = 1 << (chan - base_bitfield_channel); /* mask */
new_data[1] = data[0] ? (1 << (chan - base_bitfield_channel))
: 0; /* bits */
}
ret = s->insn_bits(dev, s, &new_insn, new_data);
@ -440,9 +442,7 @@ int comedi_buf_alloc(struct comedi_device *dev, struct comedi_subdevice *s,
unsigned i;
for (i = 0; i < async->n_buf_pages; ++i) {
if (async->buf_page_list[i].virt_addr) {
mem_map_unreserve(virt_to_page
(async->buf_page_list[i].
virt_addr));
clear_bit(PG_reserved, &(virt_to_page(async->buf_page_list[i].virt_addr)->flags));
if (s->async_dma_dir != DMA_NONE) {
dma_free_coherent(dev->hw_dev,
PAGE_SIZE,
@ -495,12 +495,9 @@ int comedi_buf_alloc(struct comedi_device *dev, struct comedi_subdevice *s,
if (async->buf_page_list[i].virt_addr == NULL)
break;
mem_map_reserve(virt_to_page
(async->buf_page_list[i].
virt_addr));
pages[i] =
virt_to_page(async->
buf_page_list[i].virt_addr);
set_bit(PG_reserved,
&(virt_to_page(async->buf_page_list[i].virt_addr)->flags));
pages[i] = virt_to_page(async->buf_page_list[i].virt_addr);
}
}
if (i == n_pages) {
@ -517,9 +514,7 @@ int comedi_buf_alloc(struct comedi_device *dev, struct comedi_subdevice *s,
NULL) {
break;
}
mem_map_unreserve(virt_to_page
(async->buf_page_list
[i].virt_addr));
clear_bit(PG_reserved, &(virt_to_page(async->buf_page_list[i].virt_addr)->flags));
if (s->async_dma_dir != DMA_NONE) {
dma_free_coherent(dev->hw_dev,
PAGE_SIZE,
@ -549,8 +544,8 @@ int comedi_buf_alloc(struct comedi_device *dev, struct comedi_subdevice *s,
/* munging is applied to data by core as it passes between user
* and kernel space */
unsigned int comedi_buf_munge(struct comedi_async *async,
unsigned int num_bytes)
static unsigned int comedi_buf_munge(struct comedi_async *async,
unsigned int num_bytes)
{
struct comedi_subdevice *s = async->subdevice;
unsigned int count = 0;
@ -568,7 +563,8 @@ unsigned int comedi_buf_munge(struct comedi_async *async,
block_size = num_bytes - count;
if (block_size < 0) {
printk("%s: %s: bug! block_size is negative\n",
printk(KERN_WARNING
"%s: %s: bug! block_size is negative\n",
__FILE__, __func__);
break;
}
@ -579,7 +575,8 @@ unsigned int comedi_buf_munge(struct comedi_async *async,
s->munge(s->device, s, async->prealloc_buf + async->munge_ptr,
block_size, async->munge_chan);
smp_wmb(); /* barrier insures data is munged in buffer before munge_count is incremented */
smp_wmb(); /* barrier insures data is munged in buffer
* before munge_count is incremented */
async->munge_chan += block_size / num_sample_bytes;
async->munge_chan %= async->cmd.chanlist_len;
@ -626,6 +623,7 @@ unsigned int comedi_buf_write_alloc(struct comedi_async *async,
smp_mb();
return nbytes;
}
EXPORT_SYMBOL(comedi_buf_write_alloc);
/* allocates nothing unless it can completely fulfill the request */
unsigned int comedi_buf_write_alloc_strict(struct comedi_async *async,
@ -649,7 +647,7 @@ unsigned comedi_buf_write_free(struct comedi_async *async, unsigned int nbytes)
if ((int)(async->buf_write_count + nbytes -
async->buf_write_alloc_count) > 0) {
printk
("comedi: attempted to write-free more bytes than have been write-allocated.\n");
(KERN_INFO "comedi: attempted to write-free more bytes than have been write-allocated.\n");
nbytes = async->buf_write_alloc_count - async->buf_write_count;
}
async->buf_write_count += nbytes;
@ -660,6 +658,7 @@ unsigned comedi_buf_write_free(struct comedi_async *async, unsigned int nbytes)
return nbytes;
}
EXPORT_SYMBOL(comedi_buf_write_free);
/* allocates a chunk for the reader from filled (and munged) buffer space */
unsigned comedi_buf_read_alloc(struct comedi_async *async, unsigned nbytes)
@ -674,16 +673,18 @@ unsigned comedi_buf_read_alloc(struct comedi_async *async, unsigned nbytes)
smp_rmb();
return nbytes;
}
EXPORT_SYMBOL(comedi_buf_read_alloc);
/* transfers control of a chunk from reader to free buffer space */
unsigned comedi_buf_read_free(struct comedi_async *async, unsigned int nbytes)
{
/* barrier insures data has been read out of buffer before read count is incremented */
/* barrier insures data has been read out of
* buffer before read count is incremented */
smp_mb();
if ((int)(async->buf_read_count + nbytes -
async->buf_read_alloc_count) > 0) {
printk
("comedi: attempted to read-free more bytes than have been read-allocated.\n");
printk(KERN_INFO
"comedi: attempted to read-free more bytes than have been read-allocated.\n");
nbytes = async->buf_read_alloc_count - async->buf_read_count;
}
async->buf_read_count += nbytes;
@ -691,6 +692,7 @@ unsigned comedi_buf_read_free(struct comedi_async *async, unsigned int nbytes)
async->buf_read_ptr %= async->prealloc_bufsz;
return nbytes;
}
EXPORT_SYMBOL(comedi_buf_read_free);
void comedi_buf_memcpy_to(struct comedi_async *async, unsigned int offset,
const void *data, unsigned int num_bytes)
@ -716,6 +718,7 @@ void comedi_buf_memcpy_to(struct comedi_async *async, unsigned int offset,
write_ptr = 0;
}
}
EXPORT_SYMBOL(comedi_buf_memcpy_to);
void comedi_buf_memcpy_from(struct comedi_async *async, unsigned int offset,
void *dest, unsigned int nbytes)
@ -742,6 +745,7 @@ void comedi_buf_memcpy_from(struct comedi_async *async, unsigned int offset,
read_ptr = 0;
}
}
EXPORT_SYMBOL(comedi_buf_memcpy_from);
unsigned int comedi_buf_read_n_available(struct comedi_async *async)
{
@ -757,6 +761,7 @@ unsigned int comedi_buf_read_n_available(struct comedi_async *async)
smp_rmb();
return num_bytes;
}
EXPORT_SYMBOL(comedi_buf_read_n_available);
int comedi_buf_get(struct comedi_async *async, short *x)
{
@ -769,6 +774,7 @@ int comedi_buf_get(struct comedi_async *async, short *x)
comedi_buf_read_free(async, sizeof(short));
return 1;
}
EXPORT_SYMBOL(comedi_buf_get);
int comedi_buf_put(struct comedi_async *async, short x)
{
@ -782,6 +788,7 @@ int comedi_buf_put(struct comedi_async *async, short x)
comedi_buf_write_free(async, sizeof(short));
return 1;
}
EXPORT_SYMBOL(comedi_buf_put);
void comedi_reset_async_buf(struct comedi_async *async)
{
@ -802,8 +809,9 @@ void comedi_reset_async_buf(struct comedi_async *async)
async->events = 0;
}
int comedi_auto_config(struct device *hardware_device, const char *board_name,
const int *options, unsigned num_options)
static int comedi_auto_config(struct device *hardware_device,
const char *board_name, const int *options,
unsigned num_options)
{
struct comedi_devconfig it;
int minor;
@ -848,7 +856,7 @@ cleanup:
return retval;
}
void comedi_auto_unconfig(struct device *hardware_device)
static void comedi_auto_unconfig(struct device *hardware_device)
{
unsigned *minor = (unsigned *)dev_get_drvdata(hardware_device);
if (minor == NULL)
@ -873,20 +881,24 @@ int comedi_pci_auto_config(struct pci_dev *pcidev, const char *board_name)
return comedi_auto_config(&pcidev->dev, board_name,
options, ARRAY_SIZE(options));
}
EXPORT_SYMBOL_GPL(comedi_pci_auto_config);
void comedi_pci_auto_unconfig(struct pci_dev *pcidev)
{
comedi_auto_unconfig(&pcidev->dev);
}
EXPORT_SYMBOL_GPL(comedi_pci_auto_unconfig);
int comedi_usb_auto_config(struct usb_device *usbdev, const char *board_name)
{
BUG_ON(usbdev == NULL);
return comedi_auto_config(&usbdev->dev, board_name, NULL, 0);
}
EXPORT_SYMBOL_GPL(comedi_usb_auto_config);
void comedi_usb_auto_unconfig(struct usb_device *usbdev)
{
BUG_ON(usbdev == NULL);
comedi_auto_unconfig(&usbdev->dev);
}
EXPORT_SYMBOL_GPL(comedi_usb_auto_unconfig);

View file

@ -214,7 +214,8 @@ static inline void i8253_cascade_ns_to_timer_2div(int i8253_osc_base,
#ifndef CMDTEST
/* i8254_load programs 8254 counter chip. It should also work for the 8253.
* base_address is the lowest io address for the chip (the address of counter 0).
* base_address is the lowest io address
* for the chip (the address of counter 0).
* counter_number is the counter you want to load (0,1 or 2)
* count is the number to load into the counter.
*

View file

@ -82,6 +82,7 @@ I/O port base address can be found in the output of 'lspci -v'.
#include <linux/ioport.h>
#include <linux/slab.h>
#include "8255.h"
#define _8255_SIZE 4
@ -395,8 +396,6 @@ static int dev_8255_attach(struct comedi_device *dev,
unsigned long iobase;
int i;
printk("comedi%d: 8255:", dev->minor);
dev->board_name = "8255";
for (i = 0; i < COMEDI_NDEVCONFOPTS; i++) {
@ -405,13 +404,20 @@ static int dev_8255_attach(struct comedi_device *dev,
break;
}
if (i == 0) {
printk(" no devices specified\n");
printk(KERN_WARNING
"comedi%d: 8255: no devices specified\n", dev->minor);
return -EINVAL;
}
ret = alloc_subdevices(dev, i);
if (ret < 0)
if (ret < 0) {
/* FIXME this printk call should give a proper message, the
* below line just maintains previous functionality */
printk("comedi%d: 8255:", dev->minor);
return ret;
}
printk(KERN_INFO "comedi%d: 8255:", dev->minor);
for (i = 0; i < dev->n_subdevices; i++) {
iobase = it->options[i];
@ -438,7 +444,7 @@ static int dev_8255_detach(struct comedi_device *dev)
unsigned long iobase;
struct comedi_subdevice *s;
printk("comedi%d: 8255: remove\n", dev->minor);
printk(KERN_INFO "comedi%d: 8255: remove\n", dev->minor);
for (i = 0; i < dev->n_subdevices; i++) {
s = dev->subdevices + i;

View file

@ -26,8 +26,6 @@
#include "../comedidev.h"
#if defined(CONFIG_COMEDI_8255) || defined(CONFIG_COMEDI_8255_MODULE)
int subdev_8255_init(struct comedi_device *dev, struct comedi_subdevice *s,
int (*cb) (int, int, int, unsigned long),
unsigned long arg);
@ -38,24 +36,4 @@ void subdev_8255_cleanup(struct comedi_device *dev, struct comedi_subdevice *s);
void subdev_8255_interrupt(struct comedi_device *dev,
struct comedi_subdevice *s);
#else
static inline int subdev_8255_init(struct comedi_device *dev,
struct comedi_subdevice *s, void *x,
unsigned long y)
{
printk("8255 support not configured -- disabling subdevice\n");
s->type = COMEDI_SUBD_UNUSED;
return 0;
}
static inline void subdev_8255_cleanup(struct comedi_device *dev,
struct comedi_subdevice *s)
{
}
#endif
#endif

View file

@ -2,132 +2,137 @@
#
# Comedi "helper" modules
obj-$(CONFIG_COMEDI) += comedi_fc.o
obj-$(CONFIG_COMEDI) += comedi_bond.o
obj-$(CONFIG_COMEDI) += comedi_test.o
obj-$(CONFIG_COMEDI) += comedi_parport.o
obj-$(CONFIG_COMEDI) += pcm_common.o
# Comedi misc drivers
obj-$(CONFIG_COMEDI_BOND) += comedi_bond.o
obj-$(CONFIG_COMEDI_TEST) += comedi_test.o
obj-$(CONFIG_COMEDI_PARPORT) += comedi_parport.o
obj-$(CONFIG_COMEDI_SERIAL2002) += serial2002.o
obj-$(CONFIG_COMEDI_SKEL) += skel.o
# Comedi ISA drivers
obj-$(CONFIG_COMEDI_8255) += 8255.o
obj-$(CONFIG_COMEDI_ACL7225B) += acl7225b.o
obj-$(CONFIG_COMEDI_PCL711) += pcl711.o
obj-$(CONFIG_COMEDI_PCL724) += pcl724.o
obj-$(CONFIG_COMEDI_PCL725) += pcl725.o
obj-$(CONFIG_COMEDI_PCL726) += pcl726.o
obj-$(CONFIG_COMEDI_PCL730) += pcl730.o
obj-$(CONFIG_COMEDI_PCL812) += pcl812.o
obj-$(CONFIG_COMEDI_PCL816) += pcl816.o
obj-$(CONFIG_COMEDI_PCL818) += pcl818.o
obj-$(CONFIG_COMEDI_PCM3724) += pcm3724.o
obj-$(CONFIG_COMEDI_PCM3730) += pcm3730.o
obj-$(CONFIG_COMEDI_RTI800) += rti800.o
obj-$(CONFIG_COMEDI_RTI802) += rti802.o
obj-$(CONFIG_COMEDI_DAS08) += das08.o
obj-$(CONFIG_COMEDI_DAS16M1) += das16m1.o
obj-$(CONFIG_COMEDI_DAS16) += das16.o
obj-$(CONFIG_COMEDI_DAS800) += das800.o
obj-$(CONFIG_COMEDI_DAS1800) += das1800.o
obj-$(CONFIG_COMEDI_DAS6402) += das6402.o
obj-$(CONFIG_COMEDI_DT2801) += dt2801.o
obj-$(CONFIG_COMEDI_DT2811) += dt2811.o
obj-$(CONFIG_COMEDI_DT2814) += dt2814.o
obj-$(CONFIG_COMEDI_DT2815) += dt2815.o
obj-$(CONFIG_COMEDI_DT2817) += dt2817.o
obj-$(CONFIG_COMEDI_DT282X) += dt282x.o
obj-$(CONFIG_COMEDI_DMM32AT) += dmm32at.o
obj-$(CONFIG_COMEDI_FL512) += fl512.o
obj-$(CONFIG_COMEDI_AIO_AIO12_8) += aio_aio12_8.o
obj-$(CONFIG_COMEDI_AIO_IIRO_16) += aio_iiro_16.o
obj-$(CONFIG_COMEDI_C6XDIGIO) += c6xdigio.o
obj-$(CONFIG_COMEDI_MPC624) += mpc624.o
obj-$(CONFIG_COMEDI_ADQ12B) += adq12b.o
obj-$(CONFIG_COMEDI_NI_AT_A2150) += ni_at_a2150.o
obj-$(CONFIG_COMEDI_NI_AT_AO) += ni_at_ao.o
obj-$(CONFIG_COMEDI_NI_ATMIO) += ni_atmio.o
obj-$(CONFIG_COMEDI_NI_ATMIO16D) += ni_atmio16d.o
obj-$(CONFIG_COMEDI_PCMAD) += pcmad.o
obj-$(CONFIG_COMEDI_PCMDA12) += pcmda12.o
obj-$(CONFIG_COMEDI_PCMMIO) += pcmmio.o
obj-$(CONFIG_COMEDI_PCMUIO) += pcmuio.o
obj-$(CONFIG_COMEDI_MULTIQ3) += multiq3.o
obj-$(CONFIG_COMEDI_POC) += poc.o
# Comedi PCI drivers
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += 8255.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += acl7225b.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += addi_apci_035.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += addi_apci_1032.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += addi_apci_1500.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += addi_apci_1516.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += addi_apci_1564.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += addi_apci_16xx.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += addi_apci_2016.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += addi_apci_2032.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += addi_apci_2200.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += addi_apci_3001.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += addi_apci_3120.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += addi_apci_3501.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += addi_apci_3xxx.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += adl_pci6208.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += adl_pci7296.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += adl_pci7432.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += adl_pci8164.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += adl_pci9111.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += adl_pci9118.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += adq12b.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += adv_pci1710.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += adv_pci1723.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += adv_pci_dio.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += aio_aio12_8.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += aio_iiro_16.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += amplc_dio200.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += amplc_pc236.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += amplc_pc263.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += amplc_pci224.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += amplc_pci230.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += c6xdigio.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += cb_pcidas64.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += cb_pcidas.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += cb_pcidda.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += cb_pcidio.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += cb_pcimdas.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += cb_pcimdda.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += comedi_bond.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += comedi_parport.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += comedi_test.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += contec_pci_dio.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += daqboard2000.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += das08.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += das16m1.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += das16.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += das1800.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += das6402.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += das800.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += dmm32at.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += dt2801.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += dt2811.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += dt2814.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += dt2815.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += dt2817.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += dt282x.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += dt3000.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += fl512.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += gsc_hpdi.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += icp_multi.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += ii_pci20kc.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += jr3_pci.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += ke_counter.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += me4000.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += me_daq.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += mite.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += mpc624.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += multiq3.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += ni_6527.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += ni_65xx.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += ni_660x.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += ni_670x.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += ni_at_a2150.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += ni_at_ao.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += ni_atmio16d.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += ni_atmio.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += ni_labpc.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += ni_pcidio.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += ni_pcimio.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += ni_tiocmd.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += ni_tio.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += pcl711.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += pcl724.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += pcl725.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += pcl726.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += pcl730.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += pcl812.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += pcl816.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += pcl818.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += pcm3724.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += pcm3730.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += pcmad.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += pcmda12.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += pcmmio.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += pcmuio.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += poc.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += rtd520.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += rti800.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += rti802.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += s526.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += s626.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += serial2002.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += skel.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += ssv_dnp.o
obj-$(CONFIG_COMEDI_PCI_DRIVERS) += unioxx5.o
obj-$(CONFIG_COMEDI_ADDI_APCI_035) += addi_apci_035.o
obj-$(CONFIG_COMEDI_ADDI_APCI_1032) += addi_apci_1032.o
obj-$(CONFIG_COMEDI_ADDI_APCI_1500) += addi_apci_1500.o
obj-$(CONFIG_COMEDI_ADDI_APCI_1516) += addi_apci_1516.o
obj-$(CONFIG_COMEDI_ADDI_APCI_1564) += addi_apci_1564.o
obj-$(CONFIG_COMEDI_ADDI_APCI_16XX) += addi_apci_16xx.o
obj-$(CONFIG_COMEDI_ADDI_APCI_2016) += addi_apci_2016.o
obj-$(CONFIG_COMEDI_ADDI_APCI_2032) += addi_apci_2032.o
obj-$(CONFIG_COMEDI_ADDI_APCI_2200) += addi_apci_2200.o
obj-$(CONFIG_COMEDI_ADDI_APCI_3001) += addi_apci_3001.o
obj-$(CONFIG_COMEDI_ADDI_APCI_3120) += addi_apci_3120.o
obj-$(CONFIG_COMEDI_ADDI_APCI_3501) += addi_apci_3501.o
obj-$(CONFIG_COMEDI_ADDI_APCI_3XXX) += addi_apci_3xxx.o
obj-$(CONFIG_COMEDI_ADL_PCI6208) += adl_pci6208.o
obj-$(CONFIG_COMEDI_ADL_PCI7230) += adl_pci7230.o
obj-$(CONFIG_COMEDI_ADL_PCI7296) += adl_pci7296.o
obj-$(CONFIG_COMEDI_ADL_PCI7432) += adl_pci7432.o
obj-$(CONFIG_COMEDI_ADL_PCI8164) += adl_pci8164.o
obj-$(CONFIG_COMEDI_ADL_PCI9111) += adl_pci9111.o
obj-$(CONFIG_COMEDI_ADL_PCI9118) += adl_pci9118.o
obj-$(CONFIG_COMEDI_ADV_PCI1710) += adv_pci1710.o
obj-$(CONFIG_COMEDI_ADV_PCI1723) += adv_pci1723.o
obj-$(CONFIG_COMEDI_ADV_PCI_DIO) += adv_pci_dio.o
obj-$(CONFIG_COMEDI_AMPLC_DIO200) += amplc_dio200.o
obj-$(CONFIG_COMEDI_AMPLC_PC236) += amplc_pc236.o
obj-$(CONFIG_COMEDI_AMPLC_PC263) += amplc_pc263.o
obj-$(CONFIG_COMEDI_AMPLC_PCI224) += amplc_pci224.o
obj-$(CONFIG_COMEDI_AMPLC_PCI230) += amplc_pci230.o
obj-$(CONFIG_COMEDI_CONTEC_PCI_DIO) += contec_pci_dio.o
obj-$(CONFIG_COMEDI_DT3000) += dt3000.o
obj-$(CONFIG_COMEDI_UNIOXX5) += unioxx5.o
obj-$(CONFIG_COMEDI_GSC_HPDI) += gsc_hpdi.o
obj-$(CONFIG_COMEDI_ICP_MULTI) += icp_multi.o
obj-$(CONFIG_COMEDI_II_PCI20KC) += ii_pci20kc.o
obj-$(CONFIG_COMEDI_DAQBOARD2000) += daqboard2000.o
obj-$(CONFIG_COMEDI_JR3_PCI) += jr3_pci.o
obj-$(CONFIG_COMEDI_KE_COUNTER) += ke_counter.o
obj-$(CONFIG_COMEDI_CB_PCIDAS64) += cb_pcidas64.o
obj-$(CONFIG_COMEDI_CB_PCIDAS) += cb_pcidas.o
obj-$(CONFIG_COMEDI_CB_PCIDDA) += cb_pcidda.o
obj-$(CONFIG_COMEDI_CB_PCIDIO) += cb_pcidio.o
obj-$(CONFIG_COMEDI_CB_PCIMDAS) += cb_pcimdas.o
obj-$(CONFIG_COMEDI_CB_PCIMDDA) += cb_pcimdda.o
obj-$(CONFIG_COMEDI_ME4000) += me4000.o
obj-$(CONFIG_COMEDI_ME_DAQ) += me_daq.o
obj-$(CONFIG_COMEDI_NI_6527) += ni_6527.o
obj-$(CONFIG_COMEDI_NI_65XX) += ni_65xx.o
obj-$(CONFIG_COMEDI_NI_660X) += ni_660x.o
obj-$(CONFIG_COMEDI_NI_670X) += ni_670x.o
obj-$(CONFIG_COMEDI_NI_PCIDIO) += ni_pcidio.o
obj-$(CONFIG_COMEDI_NI_PCIMIO) += ni_pcimio.o
obj-$(CONFIG_COMEDI_RTD520) += rtd520.o
obj-$(CONFIG_COMEDI_S526) += s526.o
obj-$(CONFIG_COMEDI_S626) += s626.o
obj-$(CONFIG_COMEDI_SSV_DNP) += ssv_dnp.o
# Comedi PCMCIA drivers
obj-$(CONFIG_COMEDI_PCMCIA_DRIVERS) += cb_das16_cs.o
obj-$(CONFIG_COMEDI_PCMCIA_DRIVERS) += das08_cs.o
obj-$(CONFIG_COMEDI_PCMCIA_DRIVERS) += ni_daq_700.o
obj-$(CONFIG_COMEDI_PCMCIA_DRIVERS) += ni_daq_dio24.o
obj-$(CONFIG_COMEDI_PCMCIA_DRIVERS) += ni_labpc_cs.o
obj-$(CONFIG_COMEDI_PCMCIA_DRIVERS) += ni_mio_cs.o
obj-$(CONFIG_COMEDI_PCMCIA_DRIVERS) += quatech_daqp_cs.o
obj-$(CONFIG_COMEDI_CB_DAS16_CS) += cb_das16_cs.o
obj-$(CONFIG_COMEDI_DAS08_CS) += das08_cs.o
obj-$(CONFIG_COMEDI_NI_DAQ_700_CS) += ni_daq_700.o
obj-$(CONFIG_COMEDI_NI_DAQ_DIO24_CS) += ni_daq_dio24.o
obj-$(CONFIG_COMEDI_NI_LABPC_CS) += ni_labpc_cs.o
obj-$(CONFIG_COMEDI_NI_MIO_CS) += ni_mio_cs.o
obj-$(CONFIG_COMEDI_QUATECH_DAQP_CS) += quatech_daqp_cs.o
# Comedi USB drivers
obj-$(CONFIG_COMEDI_USB_DRIVERS) += dt9812.o
obj-$(CONFIG_COMEDI_USB_DRIVERS) += usbdux.o
obj-$(CONFIG_COMEDI_USB_DRIVERS) += usbduxfast.o
obj-$(CONFIG_COMEDI_USB_DRIVERS) += vmk80xx.o
obj-$(CONFIG_COMEDI_DT9812) += dt9812.o
obj-$(CONFIG_COMEDI_USBDUX) += usbdux.o
obj-$(CONFIG_COMEDI_USBDUXFAST) += usbduxfast.o
obj-$(CONFIG_COMEDI_VMK80XX) += vmk80xx.o
# Comedi NI drivers
obj-$(CONFIG_COMEDI_MITE) += mite.o
obj-$(CONFIG_COMEDI_NI_TIO) += ni_tio.o
obj-$(CONFIG_COMEDI_NI_TIO) += ni_tiocmd.o
obj-$(CONFIG_COMEDI_NI_LABPC) += ni_labpc.o
obj-$(CONFIG_COMEDI_FC) += comedi_fc.o

View file

@ -212,7 +212,7 @@ struct pcilst_struct {
};
/* ptr to root list of all amcc devices */
struct pcilst_struct *amcc_devices;
static struct pcilst_struct *amcc_devices;
static const int i_ADDIDATADeviceID[] = { 0x15B8, 0x10E8 };
@ -260,12 +260,10 @@ void v_pci_card_list_init(unsigned short pci_vendor, char display)
for (i_Count = 0; i_Count < 2; i_Count++) {
pci_vendor = i_ADDIDATADeviceID[i_Count];
if (pcidev->vendor == pci_vendor) {
amcc = kmalloc(sizeof(*amcc), GFP_KERNEL);
amcc = kzalloc(sizeof(*amcc), GFP_KERNEL);
if (amcc == NULL)
continue;
memset(amcc, 0, sizeof(*amcc));
amcc->pcidev = pcidev;
if (last)
last->next = amcc;

View file

@ -293,8 +293,8 @@ static const struct addi_board boardtypes[] = {
0,
0,
0,
0,
0,
NULL,
NULL,
32,
0,
0,
@ -2527,7 +2527,7 @@ static const struct addi_board boardtypes[] = {
#define n_boardtypes (sizeof(boardtypes)/sizeof(struct addi_board))
struct comedi_driver driver_addi = {
static struct comedi_driver driver_addi = {
.driver_name = "addi_common",
.module = THIS_MODULE,
.attach = i_ADDI_Attach,
@ -2639,9 +2639,8 @@ static int i_ADDI_Attach(struct comedi_device *dev, struct comedi_devconfig *it)
devpriv->ps_BoardInfo = this_board;
devpriv->i_IobaseReserved = (int) io_addr[3];
printk("\nioremap begin");
devpriv->dw_AiBase =
(unsigned long) ioremap(io_addr[3],
this_board->i_IorangeBase3);
devpriv->dw_AiBase = ioremap(io_addr[3],
this_board->i_IorangeBase3);
printk("\nioremap end");
}
@ -2952,7 +2951,7 @@ static int i_ADDI_Detach(struct comedi_device *dev)
devpriv->ui_DmaBufferPages[1]);
}
} else {
iounmap((void *)devpriv->dw_AiBase);
iounmap(devpriv->dw_AiBase);
if (devpriv->allocated) {
i_pci_card_free(devpriv->amcc);

View file

@ -351,7 +351,7 @@ struct addi_private {
int i_IobaseAmcc; /* base+size for AMCC chip */
int i_IobaseAddon; /* addon base address */
int i_IobaseReserved;
unsigned long dw_AiBase;
void __iomem *dw_AiBase;
struct pcilst_struct *amcc; /* ptr too AMCC data */
unsigned char allocated; /* we have blocked card */
unsigned char b_ValidDriver; /* driver is ok */

View file

@ -253,12 +253,10 @@ void v_pci_card_list_init(unsigned short pci_vendor, char display)
pci_for_each_dev(pcidev) {
if (pcidev->vendor == pci_vendor) {
amcc = kmalloc(sizeof(*amcc), GFP_KERNEL);
amcc = kzalloc(sizeof(*amcc), GFP_KERNEL);
if (amcc == NULL)
continue;
memset(amcc, 0, sizeof(*amcc));
amcc->pcidev = pcidev;
if (last) {
last->next = amcc;

View file

@ -52,9 +52,9 @@ You should also find the complete GPL in the COPYING file accompanying this sour
+----------------------------------------------------------------------------+
*/
#include "hwdrv_apci035.h"
int i_WatchdogNbr = 0;
int i_Temp = 0;
int i_Flag = 1;
static int i_WatchdogNbr = 0;
static int i_Temp = 0;
static int i_Flag = 1;
/*
+----------------------------------------------------------------------------+
| Function Name : int i_APCI035_ConfigTimerWatchdog |

View file

@ -19,22 +19,8 @@
#define APCI035_BOARD_VENDOR_ID 0x15B8
#define APCI035_ADDRESS_RANGE 255
int i_TW_Number;
struct {
int i_Gain;
int i_Polarity;
int i_OffsetRange;
int i_Coupling;
int i_SingleDiff;
int i_AutoCalibration;
unsigned int ui_ReloadValue;
unsigned int ui_TimeUnitReloadVal;
int i_Interrupt;
int i_ModuleSelection;
} Config_Parameters_Main;
/* ANALOG INPUT RANGE */
struct comedi_lrange range_apci035_ai = { 8, {
static struct comedi_lrange range_apci035_ai = { 8, {
BIP_RANGE(10),
BIP_RANGE(5),
BIP_RANGE(2),

View file

@ -53,8 +53,8 @@ You should also find the complete GPL in the COPYING file accompanying this sour
*/
#include "hwdrv_apci1032.h"
#include <linux/delay.h>
/* Global variables */
unsigned int ui_InterruptStatus;
static unsigned int ui_InterruptStatus;
/*
+----------------------------------------------------------------------------+

View file

@ -47,16 +47,16 @@ You should also find the complete GPL in the COPYING file accompanying this sour
*/
#include "hwdrv_apci1500.h"
int i_TimerCounter1Init = 0;
int i_TimerCounter2Init = 0;
int i_WatchdogCounter3Init = 0;
int i_Event1Status = 0, i_Event2Status = 0;
int i_TimerCounterWatchdogInterrupt = 0;
int i_Logic = 0, i_CounterLogic = 0;
int i_InterruptMask = 0;
int i_InputChannel = 0;
int i_TimerCounter1Enabled = 0, i_TimerCounter2Enabled =
0, i_WatchdogCounter3Enabled = 0;
static int i_TimerCounter1Init = 0;
static int i_TimerCounter2Init = 0;
static int i_WatchdogCounter3Init = 0;
static int i_Event1Status = 0, i_Event2Status = 0;
static int i_TimerCounterWatchdogInterrupt = 0;
static int i_Logic = 0, i_CounterLogic = 0;
static int i_InterruptMask = 0;
static int i_InputChannel = 0;
static int i_TimerCounter1Enabled = 0, i_TimerCounter2Enabled = 0,
i_WatchdogCounter3Enabled = 0;
/*
+----------------------------------------------------------------------------+
@ -136,9 +136,10 @@ int i_TimerCounter1Enabled = 0, i_TimerCounter2Enabled =
| |
+----------------------------------------------------------------------------+
*/
int i_APCI1500_ConfigDigitalInputEvent(struct comedi_device *dev,
struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
static int i_APCI1500_ConfigDigitalInputEvent(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn,
unsigned int *data)
{
int i_PatternPolarity = 0, i_PatternTransition = 0, i_PatternMask = 0;
int i_MaxChannel = 0, i_Count = 0, i_EventMask = 0;
@ -519,8 +520,10 @@ int i_APCI1500_ConfigDigitalInputEvent(struct comedi_device *dev,
| |
+----------------------------------------------------------------------------+
*/
int i_APCI1500_StartStopInputEvent(struct comedi_device *dev, struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data)
static int i_APCI1500_StartStopInputEvent(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn,
unsigned int *data)
{
int i_Event1InterruptStatus = 0, i_Event2InterruptStatus =
0, i_RegValue;
@ -784,8 +787,10 @@ int i_APCI1500_StartStopInputEvent(struct comedi_device *dev, struct comedi_subd
| |
+----------------------------------------------------------------------------+
*/
int i_APCI1500_Initialisation(struct comedi_device *dev, struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data)
static int i_APCI1500_Initialisation(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn,
unsigned int *data)
{
int i_DummyRead = 0;
/******************/
@ -956,9 +961,10 @@ int i_APCI1500_Initialisation(struct comedi_device *dev, struct comedi_subdevice
| |
+----------------------------------------------------------------------------+
*/
int i_APCI1500_ReadMoreDigitalInput(struct comedi_device *dev, struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data)
static int i_APCI1500_ReadMoreDigitalInput(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn,
unsigned int *data)
{
unsigned int ui_PortValue = data[1];
unsigned int ui_Mask = 0;
@ -1040,8 +1046,10 @@ int i_APCI1500_ReadMoreDigitalInput(struct comedi_device *dev, struct comedi_sub
| |
+----------------------------------------------------------------------------+
*/
int i_APCI1500_ConfigDigitalOutputErrorInterrupt(struct comedi_device *dev,
struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
static int i_APCI1500_ConfigDigitalOutputErrorInterrupt(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn,
unsigned int *data)
{
devpriv->b_OutputMemoryStatus = data[0];
return insn->n;
@ -1066,9 +1074,10 @@ int i_APCI1500_ConfigDigitalOutputErrorInterrupt(struct comedi_device *dev,
| |
+----------------------------------------------------------------------------+
*/
int i_APCI1500_WriteDigitalOutput(struct comedi_device *dev, struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data)
static int i_APCI1500_WriteDigitalOutput(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn,
unsigned int *data)
{
static unsigned int ui_Temp = 0;
unsigned int ui_Temp1;
@ -1260,9 +1269,10 @@ int i_APCI1500_WriteDigitalOutput(struct comedi_device *dev, struct comedi_subde
| |
+----------------------------------------------------------------------------+
*/
int i_APCI1500_ConfigCounterTimerWatchdog(struct comedi_device *dev,
struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
static int i_APCI1500_ConfigCounterTimerWatchdog(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn,
unsigned int *data)
{
int i_TimerCounterMode, i_MasterConfiguration;
@ -1860,8 +1870,10 @@ int i_APCI1500_ConfigCounterTimerWatchdog(struct comedi_device *dev,
| |
+----------------------------------------------------------------------------+
*/
int i_APCI1500_StartStopTriggerTimerCounterWatchdog(struct comedi_device *dev,
struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
static int i_APCI1500_StartStopTriggerTimerCounterWatchdog(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn,
unsigned int *data)
{
int i_CommandAndStatusValue;
@ -2181,9 +2193,10 @@ int i_APCI1500_StartStopTriggerTimerCounterWatchdog(struct comedi_device *dev,
| |
+----------------------------------------------------------------------------+
*/
int i_APCI1500_ReadCounterTimerWatchdog(struct comedi_device *dev,
struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
static int i_APCI1500_ReadCounterTimerWatchdog(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn,
unsigned int *data)
{
int i_CommandAndStatusValue;
switch (data[0]) {
@ -2370,8 +2383,10 @@ int i_APCI1500_ReadCounterTimerWatchdog(struct comedi_device *dev,
| |
+----------------------------------------------------------------------------+
*/
int i_APCI1500_ReadInterruptMask(struct comedi_device *dev, struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data)
static int i_APCI1500_ReadInterruptMask(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn,
unsigned int *data)
{
data[0] = i_InterruptMask;
data[1] = i_InputChannel;
@ -2401,8 +2416,10 @@ int i_APCI1500_ReadInterruptMask(struct comedi_device *dev, struct comedi_subdev
| |
+----------------------------------------------------------------------------+
*/
int i_APCI1500_ConfigureInterrupt(struct comedi_device *dev, struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data)
static int i_APCI1500_ConfigureInterrupt(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn,
unsigned int *data)
{
unsigned int ui_Status;
int i_RegValue;
@ -2821,8 +2838,7 @@ static void v_APCI1500_Interrupt(int irq, void *d)
| |
+----------------------------------------------------------------------------+
*/
int i_APCI1500_Reset(struct comedi_device *dev)
static int i_APCI1500_Reset(struct comedi_device *dev)
{
int i_DummyRead = 0;
i_TimerCounter1Init = 0;

View file

@ -56,8 +56,8 @@ You should also find the complete GPL in the COPYING file accompanying this sour
#include "hwdrv_apci1564.h"
/* Global variables */
unsigned int ui_InterruptStatus_1564 = 0;
unsigned int ui_InterruptData, ui_Type;
static unsigned int ui_InterruptStatus_1564 = 0;
static unsigned int ui_InterruptData, ui_Type;
/*
+----------------------------------------------------------------------------+

View file

@ -53,7 +53,7 @@ You should also find the complete GPL in the COPYING file accompanying this sour
*/
#include "hwdrv_apci2032.h"
unsigned int ui_InterruptData, ui_Type;
static unsigned int ui_InterruptData, ui_Type;
/*
+----------------------------------------------------------------------------+
| Function Name : int i_APCI2032_ConfigDigitalOutput |

View file

@ -32,7 +32,7 @@
#define MODE0 0
#define MODE1 1
/* ANALOG OUTPUT RANGE */
struct comedi_lrange range_apci3501_ao = { 2, {
static struct comedi_lrange range_apci3501_ao = { 2, {
BIP_RANGE(10),
UNI_RANGE(10)
}

View file

@ -67,10 +67,9 @@ You should also find the complete GPL in the COPYING file accompanying this sour
| 1 : Conversion started |
+----------------------------------------------------------------------------+
*/
int i_APCI3XXX_TestConversionStarted(struct comedi_device *dev)
static int i_APCI3XXX_TestConversionStarted(struct comedi_device *dev)
{
if ((readl((void *)(devpriv->dw_AiBase + 8)) & 0x80000UL) == 0x80000UL)
if ((readl(devpriv->dw_AiBase + 8) & 0x80000UL) == 0x80000UL)
return 1;
else
return 0;
@ -104,9 +103,10 @@ int i_APCI3XXX_TestConversionStarted(struct comedi_device *dev)
| -101 : Data size error |
+----------------------------------------------------------------------------+
*/
int i_APCI3XXX_AnalogInputConfigOperatingMode(struct comedi_device *dev,
struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
static int i_APCI3XXX_AnalogInputConfigOperatingMode(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn,
unsigned int *data)
{
int i_ReturnValue = insn->n;
unsigned char b_TimeBase = 0;
@ -204,19 +204,14 @@ int i_APCI3XXX_AnalogInputConfigOperatingMode(struct comedi_device *dev,
/* Set the convert timing unit */
/*******************************/
writel((unsigned int)
b_TimeBase,
(void *)
(devpriv->
dw_AiBase
+
36));
writel((unsigned int)b_TimeBase,
devpriv->dw_AiBase + 36);
/**************************/
/* Set the convert timing */
/*************************/
writel(dw_ReloadValue, (void *)(devpriv->dw_AiBase + 32));
writel(dw_ReloadValue, devpriv->dw_AiBase + 32);
} else {
/**************************/
/* Any conversion started */
@ -294,9 +289,10 @@ int i_APCI3XXX_AnalogInputConfigOperatingMode(struct comedi_device *dev,
| -101 : Data size error |
+----------------------------------------------------------------------------+
*/
int i_APCI3XXX_InsnConfigAnalogInput(struct comedi_device *dev,
struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
static int i_APCI3XXX_InsnConfigAnalogInput(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn,
unsigned int *data)
{
int i_ReturnValue = insn->n;
@ -354,9 +350,10 @@ int i_APCI3XXX_InsnConfigAnalogInput(struct comedi_device *dev,
| -101 : Data size error |
+----------------------------------------------------------------------------+
*/
int i_APCI3XXX_InsnReadAnalogInput(struct comedi_device *dev,
struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
static int i_APCI3XXX_InsnReadAnalogInput(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn,
unsigned int *data)
{
int i_ReturnValue = insn->n;
unsigned char b_Configuration = (unsigned char) CR_RANGE(insn->chanspec);
@ -422,26 +419,20 @@ int i_APCI3XXX_InsnReadAnalogInput(struct comedi_device *dev,
/* Clear the FIFO */
/******************/
writel(0x10000UL,
(void *)(devpriv->dw_AiBase +
12));
writel(0x10000UL, devpriv->dw_AiBase + 12);
/*******************************/
/* Get and save the delay mode */
/*******************************/
dw_Temp =
readl((void *)(devpriv->
dw_AiBase + 4));
dw_Temp = readl(devpriv->dw_AiBase + 4);
dw_Temp = dw_Temp & 0xFFFFFEF0UL;
/***********************************/
/* Channel configuration selection */
/***********************************/
writel(dw_Temp,
(void *)(devpriv->dw_AiBase +
4));
writel(dw_Temp, devpriv->dw_AiBase + 4);
/**************************/
/* Make the configuration */
@ -458,35 +449,28 @@ int i_APCI3XXX_InsnReadAnalogInput(struct comedi_device *dev,
/***************************/
writel(dw_Configuration,
(void *)(devpriv->dw_AiBase +
0));
devpriv->dw_AiBase + 0);
/*********************/
/* Channel selection */
/*********************/
writel(dw_Temp | 0x100UL,
(void *)(devpriv->dw_AiBase +
4));
devpriv->dw_AiBase + 4);
writel((unsigned int) b_Channel,
(void *)(devpriv->dw_AiBase +
0));
devpriv->dw_AiBase + 0);
/***********************/
/* Restaure delay mode */
/***********************/
writel(dw_Temp,
(void *)(devpriv->dw_AiBase +
4));
writel(dw_Temp, devpriv->dw_AiBase + 4);
/***********************************/
/* Set the number of sequence to 1 */
/***********************************/
writel(1,
(void *)(devpriv->dw_AiBase +
48));
writel(1, devpriv->dw_AiBase + 48);
/***************************/
/* Save the interrupt flag */
@ -514,50 +498,29 @@ int i_APCI3XXX_InsnReadAnalogInput(struct comedi_device *dev,
/* Start the conversion */
/************************/
writel(0x80000UL,
(void *)
(devpriv->
dw_AiBase
+ 8));
writel(0x80000UL, devpriv->dw_AiBase + 8);
/****************/
/* Wait the EOS */
/****************/
do {
dw_Temp =
readl(
(void *)
(devpriv->
dw_AiBase
+
20));
dw_Temp =
dw_Temp
& 1;
dw_Temp = readl(devpriv->dw_AiBase + 20);
dw_Temp = dw_Temp & 1;
} while (dw_Temp != 1);
/*************************/
/* Read the analog value */
/*************************/
data[dw_AcquisitionCpt]
=
(unsigned int)
readl((void
*)
(devpriv->
dw_AiBase
+ 28));
data[dw_AcquisitionCpt] = (unsigned int)readl(devpriv->dw_AiBase + 28);
}
} else {
/************************/
/* Start the conversion */
/************************/
writel(0x180000UL,
(void *)(devpriv->
dw_AiBase + 8));
writel(0x180000UL, devpriv->dw_AiBase + 8);
}
} else {
/**************************/
@ -603,7 +566,7 @@ int i_APCI3XXX_InsnReadAnalogInput(struct comedi_device *dev,
+----------------------------------------------------------------------------+
*/
void v_APCI3XXX_Interrupt(int irq, void *d)
static void v_APCI3XXX_Interrupt(int irq, void *d)
{
struct comedi_device *dev = d;
unsigned char b_CopyCpt = 0;
@ -613,13 +576,13 @@ void v_APCI3XXX_Interrupt(int irq, void *d)
/* Test if interrupt occur */
/***************************/
dw_Status = readl((void *)(devpriv->dw_AiBase + 16));
dw_Status = readl(devpriv->dw_AiBase + 16);
if ( (dw_Status & 0x2UL) == 0x2UL) {
/***********************/
/* Reset the interrupt */
/***********************/
writel(dw_Status, (void *)(devpriv->dw_AiBase + 16));
writel(dw_Status, devpriv->dw_AiBase + 16);
/*****************************/
/* Test if interrupt enabled */
@ -634,8 +597,7 @@ void v_APCI3XXX_Interrupt(int irq, void *d)
b_CopyCpt < devpriv->ui_AiNbrofChannels;
b_CopyCpt++) {
devpriv->ui_AiReadData[b_CopyCpt] =
(unsigned int) readl((void *)(devpriv->
dw_AiBase + 28));
(unsigned int)readl(devpriv->dw_AiBase + 28);
}
/**************************/
@ -682,9 +644,10 @@ void v_APCI3XXX_Interrupt(int irq, void *d)
| -101 : Data size error |
+----------------------------------------------------------------------------+
*/
int i_APCI3XXX_InsnWriteAnalogOutput(struct comedi_device *dev,
struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
static int i_APCI3XXX_InsnWriteAnalogOutput(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn,
unsigned int *data)
{
unsigned char b_Range = (unsigned char) CR_RANGE(insn->chanspec);
unsigned char b_Channel = (unsigned char) CR_CHAN(insn->chanspec);
@ -710,24 +673,21 @@ int i_APCI3XXX_InsnWriteAnalogOutput(struct comedi_device *dev,
/* Set the range selection */
/***************************/
writel(b_Range,
(void *)(devpriv->dw_AiBase + 96));
writel(b_Range, devpriv->dw_AiBase + 96);
/**************************************************/
/* Write the analog value to the selected channel */
/**************************************************/
writel((data[0] << 8) | b_Channel,
(void *)(devpriv->dw_AiBase + 100));
devpriv->dw_AiBase + 100);
/****************************/
/* Wait the end of transfer */
/****************************/
do {
dw_Status =
readl((void *)(devpriv->
dw_AiBase + 96));
dw_Status = readl(devpriv->dw_AiBase + 96);
} while ((dw_Status & 0x100) != 0x100);
} else {
/***************************/
@ -788,9 +748,10 @@ int i_APCI3XXX_InsnWriteAnalogOutput(struct comedi_device *dev,
| -101 : Data size error |
+----------------------------------------------------------------------------+
*/
int i_APCI3XXX_InsnConfigInitTTLIO(struct comedi_device *dev,
struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
static int i_APCI3XXX_InsnConfigInitTTLIO(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn,
unsigned int *data)
{
int i_ReturnValue = insn->n;
unsigned char b_Command = 0;
@ -916,9 +877,10 @@ int i_APCI3XXX_InsnConfigInitTTLIO(struct comedi_device *dev,
| -101 : Data size error |
+----------------------------------------------------------------------------+
*/
int i_APCI3XXX_InsnBitsTTLIO(struct comedi_device *dev,
struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
static int i_APCI3XXX_InsnBitsTTLIO(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn,
unsigned int *data)
{
int i_ReturnValue = insn->n;
unsigned char b_ChannelCpt = 0;
@ -1071,9 +1033,10 @@ int i_APCI3XXX_InsnBitsTTLIO(struct comedi_device *dev,
| -101 : Data size error |
+----------------------------------------------------------------------------+
*/
int i_APCI3XXX_InsnReadTTLIO(struct comedi_device *dev,
struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
static int i_APCI3XXX_InsnReadTTLIO(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn,
unsigned int *data)
{
unsigned char b_Channel = (unsigned char) CR_CHAN(insn->chanspec);
int i_ReturnValue = insn->n;
@ -1184,9 +1147,10 @@ int i_APCI3XXX_InsnReadTTLIO(struct comedi_device *dev,
| -101 : Data size error |
+----------------------------------------------------------------------------+
*/
int i_APCI3XXX_InsnWriteTTLIO(struct comedi_device *dev,
struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
static int i_APCI3XXX_InsnWriteTTLIO(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn,
unsigned int *data)
{
int i_ReturnValue = insn->n;
unsigned char b_Channel = (unsigned char) CR_CHAN(insn->chanspec);
@ -1296,8 +1260,10 @@ int i_APCI3XXX_InsnWriteTTLIO(struct comedi_device *dev,
+----------------------------------------------------------------------------+
*/
int i_APCI3XXX_InsnReadDigitalInput(struct comedi_device *dev,
struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
static int i_APCI3XXX_InsnReadDigitalInput(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn,
unsigned int *data)
{
int i_ReturnValue = insn->n;
unsigned char b_Channel = (unsigned char) CR_CHAN(insn->chanspec);
@ -1354,8 +1320,10 @@ int i_APCI3XXX_InsnReadDigitalInput(struct comedi_device *dev,
| -101 : Data size error |
+----------------------------------------------------------------------------+
*/
int i_APCI3XXX_InsnBitsDigitalInput(struct comedi_device *dev,
struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
static int i_APCI3XXX_InsnBitsDigitalInput(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn,
unsigned int *data)
{
int i_ReturnValue = insn->n;
unsigned int dw_Temp = 0;
@ -1407,8 +1375,10 @@ int i_APCI3XXX_InsnBitsDigitalInput(struct comedi_device *dev,
| -101 : Data size error |
+----------------------------------------------------------------------------+
*/
int i_APCI3XXX_InsnBitsDigitalOutput(struct comedi_device *dev,
struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
static int i_APCI3XXX_InsnBitsDigitalOutput(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn,
unsigned int *data)
{
int i_ReturnValue = insn->n;
unsigned char b_ChannelCpt = 0;
@ -1503,8 +1473,10 @@ int i_APCI3XXX_InsnBitsDigitalOutput(struct comedi_device *dev,
+----------------------------------------------------------------------------+
*/
int i_APCI3XXX_InsnWriteDigitalOutput(struct comedi_device *dev,
struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
static int i_APCI3XXX_InsnWriteDigitalOutput(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn,
unsigned int *data)
{
int i_ReturnValue = insn->n;
unsigned char b_Channel = CR_CHAN(insn->chanspec);
@ -1578,8 +1550,10 @@ int i_APCI3XXX_InsnWriteDigitalOutput(struct comedi_device *dev,
+----------------------------------------------------------------------------+
*/
int i_APCI3XXX_InsnReadDigitalOutput(struct comedi_device *dev,
struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
static int i_APCI3XXX_InsnReadDigitalOutput(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn,
unsigned int *data)
{
int i_ReturnValue = insn->n;
unsigned char b_Channel = CR_CHAN(insn->chanspec);
@ -1636,7 +1610,7 @@ int i_APCI3XXX_InsnReadDigitalOutput(struct comedi_device *dev,
+----------------------------------------------------------------------------+
*/
int i_APCI3XXX_Reset(struct comedi_device *dev)
static int i_APCI3XXX_Reset(struct comedi_device *dev)
{
unsigned char b_Cpt = 0;
@ -1656,27 +1630,26 @@ int i_APCI3XXX_Reset(struct comedi_device *dev)
/* Clear the start command */
/***************************/
writel(0, (void *)(devpriv->dw_AiBase + 8));
writel(0, devpriv->dw_AiBase + 8);
/*****************************/
/* Reset the interrupt flags */
/*****************************/
writel(readl((void *)(devpriv->dw_AiBase + 16)),
(void *)(devpriv->dw_AiBase + 16));
writel(readl(devpriv->dw_AiBase + 16), devpriv->dw_AiBase + 16);
/*****************/
/* clear the EOS */
/*****************/
readl((void *)(devpriv->dw_AiBase + 20));
readl(devpriv->dw_AiBase + 20);
/******************/
/* Clear the FIFO */
/******************/
for (b_Cpt = 0; b_Cpt < 16; b_Cpt++) {
readl((void *)(devpriv->dw_AiBase + 28));
readl(devpriv->dw_AiBase + 28);
}
/************************/

View file

@ -54,7 +54,7 @@ References:
#include "../comedidev.h"
#include "comedi_pci.h"
#define PCI6208_DRIVER_NAME "adl_pci6208"
#define PCI6208_DRIVER_NAME "adl_pci6208"
/* Board descriptions */
struct pci6208_board {
@ -134,10 +134,10 @@ static int pci6208_ao_rinsn(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data);
/* static int pci6208_dio_insn_bits (struct comedi_device *dev,
* struct comedi_subdevice *s, */
* struct comedi_subdevice *s, */
/* struct comedi_insn *insn,unsigned int *data); */
/* static int pci6208_dio_insn_config(struct comedi_device *dev,
* struct comedi_subdevice *s, */
* struct comedi_subdevice *s, */
/* struct comedi_insn *insn,unsigned int *data); */
/*
@ -268,7 +268,7 @@ static int pci6208_ao_rinsn(struct comedi_device *dev,
* This allows packed reading/writing of the DIO channels. The
* comedi core can convert between insn_bits and insn_read/write */
/* static int pci6208_dio_insn_bits(struct comedi_device *dev,
* struct comedi_subdevice *s, */
* struct comedi_subdevice *s, */
/* struct comedi_insn *insn,unsigned int *data) */
/* { */
/* if(insn->n!=2)return -EINVAL; */
@ -293,7 +293,7 @@ static int pci6208_ao_rinsn(struct comedi_device *dev,
/* } */
/* static int pci6208_dio_insn_config(struct comedi_device *dev,
* struct comedi_subdevice *s, */
* struct comedi_subdevice *s, */
/* struct comedi_insn *insn,unsigned int *data) */
/* { */
/* int chan=CR_CHAN(insn->chanspec); */

View file

@ -0,0 +1,206 @@
/*
comedi/drivers/adl_pci7230.c
Hardware comedi driver fot PCI7230 Adlink card
Copyright (C) 2010 David Fernandez <dfcastelao@gmail.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*
Driver: adl_pci7230
Description: Driver for the Adlink PCI-7230 32 ch. isolated digital io board
Devices: [ADLink] PCI-7230 (adl_pci7230)
Author: David Fernandez <dfcastelao@gmail.com>
Status: experimental
Updated: Mon, 14 Apr 2008 15:08:14 +0100
Configuration Options:
[0] - PCI bus of device (optional)
[1] - PCI slot of device (optional)
If bus/slot is not specified, the first supported
PCI device found will be used.
*/
#include "../comedidev.h"
#include <linux/kernel.h>
#include "comedi_pci.h"
#define PCI7230_DI 0x00
#define PCI7230_DO 0x00
#define PCI_DEVICE_ID_PCI7230 0x7230
static DEFINE_PCI_DEVICE_TABLE(adl_pci7230_pci_table) = {
{
PCI_VENDOR_ID_ADLINK,
PCI_DEVICE_ID_PCI7230,
PCI_ANY_ID,
PCI_ANY_ID,
0,
0,
0
},
{0}
};
MODULE_DEVICE_TABLE(pci, adl_pci7230_pci_table);
struct adl_pci7230_private {
int data;
struct pci_dev *pci_dev;
};
#define devpriv ((struct adl_pci7230_private *)dev->private)
static int adl_pci7230_attach(struct comedi_device *dev,
struct comedi_devconfig *it);
static int adl_pci7230_detach(struct comedi_device *dev);
static struct comedi_driver driver_adl_pci7230 = {
.driver_name = "adl_pci7230",
.module = THIS_MODULE,
.attach = adl_pci7230_attach,
.detach = adl_pci7230_detach,
};
/* Digital IO */
static int adl_pci7230_di_insn_bits(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn,
unsigned int *data);
static int adl_pci7230_do_insn_bits(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn,
unsigned int *data);
static int adl_pci7230_attach(struct comedi_device *dev,
struct comedi_devconfig *it)
{
struct pci_dev *pcidev;
struct comedi_subdevice *s;
int bus, slot;
printk(KERN_INFO "comedi%d: adl_pci7230\n", dev->minor);
dev->board_name = "pci7230";
bus = it->options[0];
slot = it->options[1];
if (alloc_private(dev, sizeof(struct adl_pci7230_private)) < 0)
return -ENOMEM;
if (alloc_subdevices(dev, 2) < 0)
return -ENOMEM;
for (pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, NULL);
pcidev != NULL;
pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pcidev)) {
if (pcidev->vendor == PCI_VENDOR_ID_ADLINK &&
pcidev->device == PCI_DEVICE_ID_PCI7230) {
if (bus || slot) {
/* requested particular bus/slot */
if (pcidev->bus->number != bus ||
PCI_SLOT(pcidev->devfn) != slot) {
continue;
}
}
devpriv->pci_dev = pcidev;
break;
}
}
if (pcidev == NULL) {
printk(KERN_ERR "comedi%d: no supported board found! (req. bus/slot : %d/%d)\n",
dev->minor, bus, slot);
return -EIO;
}
if (comedi_pci_enable(pcidev, "adl_pci7230") < 0) {
printk(KERN_ERR "comedi%d: Failed to enable PCI device and request regions\n",
dev->minor);
return -EIO;
}
dev->iobase = pci_resource_start(pcidev, 2);
printk(KERN_DEBUG "comedi: base addr %4lx\n", dev->iobase);
s = dev->subdevices + 0;
/* Isolated do */
s->type = COMEDI_SUBD_DO;
s->subdev_flags = SDF_WRITABLE | SDF_GROUND | SDF_COMMON;
s->n_chan = 16;
s->maxdata = 1;
s->range_table = &range_digital;
s->insn_bits = adl_pci7230_do_insn_bits;
s = dev->subdevices + 1;
/* Isolated di */
s->type = COMEDI_SUBD_DI;
s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_COMMON;
s->n_chan = 16;
s->maxdata = 1;
s->range_table = &range_digital;
s->insn_bits = adl_pci7230_di_insn_bits;
printk(KERN_DEBUG "comedi: attached\n");
return 1;
}
static int adl_pci7230_detach(struct comedi_device *dev)
{
printk(KERN_DEBUG "comedi%d: pci7230: remove\n", dev->minor);
if (devpriv && devpriv->pci_dev) {
if (dev->iobase)
comedi_pci_disable(devpriv->pci_dev);
pci_dev_put(devpriv->pci_dev);
}
return 0;
}
static int adl_pci7230_do_insn_bits(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn,
unsigned int *data)
{
if (insn->n != 2)
return -EINVAL;
if (data[0]) {
s->state &= ~data[0];
s->state |= (data[0] & data[1]);
outl((s->state << 16) & 0xffffffff, dev->iobase + PCI7230_DO);
}
return 2;
}
static int adl_pci7230_di_insn_bits(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn,
unsigned int *data)
{
if (insn->n != 2)
return -EINVAL;
data[1] = inl(dev->iobase + PCI7230_DI) & 0xffffffff;
return 2;
}
COMEDI_PCI_INITCLEANUP(driver_adl_pci7230, adl_pci7230_pci_table);

View file

@ -358,8 +358,8 @@ struct pci9111_private_data {
int ao_readback; /* Last written analog output data */
int timer_divisor_1; /* Divisor values for the 8254 timer pacer */
int timer_divisor_2;
unsigned int timer_divisor_1; /* Divisor values for the 8254 timer pacer */
unsigned int timer_divisor_2;
int is_valid; /* Is device valid */
@ -585,19 +585,17 @@ pci9111_ai_do_cmd_test(struct comedi_device *dev,
(cmd->scan_begin_src != TRIG_EXT))
error++;
if ((cmd->convert_src != TRIG_TIMER) && (cmd->convert_src != TRIG_EXT)) {
if ((cmd->convert_src != TRIG_TIMER) && (cmd->convert_src != TRIG_EXT))
error++;
}
if ((cmd->convert_src == TRIG_TIMER) &&
!((cmd->scan_begin_src == TRIG_TIMER) ||
(cmd->scan_begin_src == TRIG_FOLLOW))) {
(cmd->scan_begin_src == TRIG_FOLLOW)))
error++;
}
if ((cmd->convert_src == TRIG_EXT) &&
!((cmd->scan_begin_src == TRIG_EXT) ||
(cmd->scan_begin_src == TRIG_FOLLOW))) {
(cmd->scan_begin_src == TRIG_FOLLOW)))
error++;
}
if (cmd->scan_end_src != TRIG_COUNT)
error++;
@ -1067,9 +1065,8 @@ static int pci9111_ai_insn_read(struct comedi_device *dev,
pci9111_ai_channel_set(CR_CHAN((&insn->chanspec)[0]));
if ((pci9111_ai_range_get()) != CR_RANGE((&insn->chanspec)[0])) {
if ((pci9111_ai_range_get()) != CR_RANGE((&insn->chanspec)[0]))
pci9111_ai_range_set(CR_RANGE((&insn->chanspec)[0]));
}
pci9111_fifo_reset();
@ -1090,11 +1087,10 @@ static int pci9111_ai_insn_read(struct comedi_device *dev,
conversion_done:
if (resolution == PCI9111_HR_AI_RESOLUTION) {
if (resolution == PCI9111_HR_AI_RESOLUTION)
data[i] = pci9111_hr_ai_get_data();
} else {
else
data[i] = pci9111_ai_get_data();
}
}
#ifdef AI_INSN_DEBUG
@ -1131,9 +1127,8 @@ static int pci9111_ao_insn_read(struct comedi_device *dev,
{
int i;
for (i = 0; i < insn->n; i++) {
for (i = 0; i < insn->n; i++)
data[i] = dev_private->ao_readback & PCI9111_AO_RESOLUTION_MASK;
}
return i;
}
@ -1222,9 +1217,8 @@ static int pci9111_attach(struct comedi_device *dev,
int error, i;
const struct pci9111_board *board;
if (alloc_private(dev, sizeof(struct pci9111_private_data)) < 0) {
if (alloc_private(dev, sizeof(struct pci9111_private_data)) < 0)
return -ENOMEM;
}
/* Probe the device to determine what device in the series it is. */
printk("comedi%d: " PCI9111_DRIVER_NAME " driver\n", dev->minor);
@ -1275,9 +1269,6 @@ found:
/* TODO: Warn about non-tested boards. */
switch (board->device_id) {
};
/* Read local configuration register base address [PCI_BASE_ADDRESS #1]. */
lcr_io_base = pci_resource_start(pci_device, 1);
@ -1387,21 +1378,19 @@ static int pci9111_detach(struct comedi_device *dev)
{
/* Reset device */
if (dev->private != 0) {
if (dev->private != NULL) {
if (dev_private->is_valid)
pci9111_reset(dev);
}
/* Release previously allocated irq */
if (dev->irq != 0) {
if (dev->irq != 0)
free_irq(dev->irq, dev);
}
if (dev_private != 0 && dev_private->pci_device != 0) {
if (dev->iobase) {
if (dev_private != NULL && dev_private->pci_device != NULL) {
if (dev->iobase)
comedi_pci_disable(dev_private->pci_device);
}
pci_dev_put(dev_private->pci_device);
}

File diff suppressed because it is too large Load diff

View file

@ -63,6 +63,8 @@ Configuration options:
#define DPRINTK(fmt, args...)
#endif
#define PCI_VENDOR_ID_ADVANTECH 0x13fe
/* hardware types of the cards */
#define TYPE_PCI171X 0
#define TYPE_PCI1713 2
@ -657,9 +659,9 @@ static void interrupt_pci1710_every_sample(void *d)
#endif
++s->async->cur_chan;
if (s->async->cur_chan >= devpriv->ai_n_chan) {
if (s->async->cur_chan >= devpriv->ai_n_chan)
s->async->cur_chan = 0;
}
if (s->async->cur_chan == 0) { /* one scan done */
devpriv->ai_act_scan++;
@ -863,12 +865,12 @@ static int pci171x_ai_docmd_and_mode(int mode, struct comedi_device *dev,
devpriv->ai_eos = 0;
}
if ((devpriv->ai_scans == 0) || (devpriv->ai_scans == -1)) {
if ((devpriv->ai_scans == 0) || (devpriv->ai_scans == -1))
devpriv->neverending_ai = 1;
} /* well, user want neverending */
else {
/* well, user want neverending */
else
devpriv->neverending_ai = 0;
}
switch (mode) {
case 1:
case 2:
@ -935,7 +937,8 @@ static int pci171x_ai_cmdtest(struct comedi_device *dev,
struct comedi_cmd *cmd)
{
int err = 0;
int tmp, divisor1 = 0, divisor2 = 0;
int tmp;
unsigned int divisor1 = 0, divisor2 = 0;
DPRINTK("adv_pci1710 EDBG: BGN: pci171x_ai_cmdtest(...)\n");
#ifdef PCI171X_EXTDEBUG
@ -1109,11 +1112,11 @@ static int pci171x_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
devpriv->ai_timer1 = 0;
devpriv->ai_timer2 = 0;
if (cmd->stop_src == TRIG_COUNT) {
if (cmd->stop_src == TRIG_COUNT)
devpriv->ai_scans = cmd->stop_arg;
} else {
else
devpriv->ai_scans = 0;
}
if (cmd->scan_begin_src == TRIG_FOLLOW) { /* mode 1, 2, 3 */
if (cmd->convert_src == TRIG_TIMER) { /* mode 1 and 2 */
@ -1593,9 +1596,9 @@ static int pci1710_detach(struct comedi_device *dev)
if (dev->irq)
free_irq(dev->irq, dev);
if (devpriv->pcidev) {
if (dev->iobase) {
if (dev->iobase)
comedi_pci_disable(devpriv->pcidev);
}
pci_dev_put(devpriv->pcidev);
}
}

View file

@ -52,7 +52,7 @@ TODO:
#include "comedi_pci.h"
#define ADVANTECH_VENDOR 0x13fe /* Advantech PCI vendor ID */
#define PCI_VENDOR_ID_ADVANTECH 0x13fe /* Advantech PCI vendor ID */
/* hardware types of the cards */
#define TYPE_PCI1723 0
@ -60,35 +60,57 @@ TODO:
#define IORANGE_1723 0x2A
/* all the registers for the pci1723 board */
#define PCI1723_DA(N) ((N)<<1) /* W: D/A register N (0 to 7) */
#define PCI1723_DA(N) ((N)<<1) /* W: D/A register N (0 to 7) */
#define PCI1723_SYN_SET 0x12 /*synchronized set register */
#define PCI1723_ALL_CHNNELE_SYN_STROBE 0x12 /*synchronized status register */
#define PCI1723_SYN_SET 0x12 /* synchronized set register */
#define PCI1723_ALL_CHNNELE_SYN_STROBE 0x12
/* synchronized status register */
#define PCI1723_RANGE_CALIBRATION_MODE 0x14 /* range and calibration mode */
#define PCI1723_RANGE_CALIBRATION_STATUS 0x14 /* range and calibration status */
#define PCI1723_RANGE_CALIBRATION_MODE 0x14
/* range and calibration mode */
#define PCI1723_RANGE_CALIBRATION_STATUS 0x14
/* range and calibration status */
#define PCI1723_CONTROL_CMD_CALIBRATION_FUN 0x16 /* SADC control command for calibration function */
#define PCI1723_STATUS_CMD_CALIBRATION_FUN 0x16 /* SADC control status for calibration function */
#define PCI1723_CONTROL_CMD_CALIBRATION_FUN 0x16
/*
* SADC control command for
* calibration function
*/
#define PCI1723_STATUS_CMD_CALIBRATION_FUN 0x16
/*
* SADC control status for
* calibration function
*/
#define PCI1723_CALIBRATION_PARA_STROBE 0x18 /* Calibration parameter strobe */
#define PCI1723_CALIBRATION_PARA_STROBE 0x18
/* Calibration parameter strobe */
#define PCI1723_DIGITAL_IO_PORT_SET 0x1A /* Digital I/O port setting */
#define PCI1723_DIGITAL_IO_PORT_MODE 0x1A /* Digital I/O port mode */
#define PCI1723_WRITE_DIGITAL_OUTPUT_CMD 0x1C /* Write digital output command */
#define PCI1723_WRITE_DIGITAL_OUTPUT_CMD 0x1C
/* Write digital output command */
#define PCI1723_READ_DIGITAL_INPUT_DATA 0x1C /* Read digital input data */
#define PCI1723_WRITE_CAL_CMD 0x1E /* Write calibration command */
#define PCI1723_READ_CAL_STATUS 0x1E /* Read calibration status */
#define PCI1723_WRITE_CAL_CMD 0x1E /* Write calibration command */
#define PCI1723_READ_CAL_STATUS 0x1E /* Read calibration status */
#define PCI1723_SYN_STROBE 0x20 /* Synchronized strobe */
#define PCI1723_SYN_STROBE 0x20 /* Synchronized strobe */
#define PCI1723_RESET_ALL_CHN_STROBE 0x22 /* Reset all D/A channels strobe */
#define PCI1723_RESET_ALL_CHN_STROBE 0x22
/* Reset all D/A channels strobe */
#define PCI1723_RESET_CAL_CONTROL_STROBE 0x24 /* Reset the calibration controller strobe */
#define PCI1723_RESET_CAL_CONTROL_STROBE 0x24
/*
* Reset the calibration
* controller strobe
*/
#define PCI1723_CHANGE_CHA_OUTPUT_TYPE_STROBE 0x26 /* Change D/A channels output type strobe */
#define PCI1723_CHANGE_CHA_OUTPUT_TYPE_STROBE 0x26
/*
* Change D/A channels output
* type strobe
*/
#define PCI1723_SELECT_CALIBRATION 0x28 /* Select the calibration Ref_V */
@ -104,20 +126,20 @@ static const struct comedi_lrange range_pci1723 = { 1, {
*/
struct pci1723_board {
const char *name;
int vendor_id; /* PCI vendor a device ID of card */
int vendor_id; /* PCI vendor a device ID of card */
int device_id;
int iorange;
char cardtype;
int n_aochan; /* num of D/A chans */
int n_diochan; /* num of DIO chans */
int ao_maxdata; /* resolution of D/A */
const struct comedi_lrange *rangelist_ao; /* rangelist for D/A */
int n_aochan; /* num of D/A chans */
int n_diochan; /* num of DIO chans */
int ao_maxdata; /* resolution of D/A */
const struct comedi_lrange *rangelist_ao; /* rangelist for D/A */
};
static const struct pci1723_board boardtypes[] = {
{
.name = "pci1723",
.vendor_id = ADVANTECH_VENDOR,
.vendor_id = PCI_VENDOR_ID_ADVANTECH,
.device_id = 0x1723,
.iorange = IORANGE_1723,
.cardtype = TYPE_PCI1723,
@ -128,8 +150,10 @@ static const struct pci1723_board boardtypes[] = {
},
};
/* This is used by modprobe to translate PCI IDs to drivers. Should
* only be used for PCI and ISA-PnP devices */
/*
* This is used by modprobe to translate PCI IDs to drivers.
* Should only be used for PCI and ISA-PnP devices
*/
static DEFINE_PCI_DEVICE_TABLE(pci1723_pci_table) = {
{
PCI_VENDOR_ID_ADVANTECH, 0x1723, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {
@ -157,47 +181,47 @@ static struct comedi_driver driver_pci1723 = {
.detach = pci1723_detach,
};
/* this structure is for data unique to this hardware driver. */
/* This structure is for data unique to this hardware driver. */
struct pci1723_private {
int valid; /* card is usable; */
struct pci_dev *pcidev;
unsigned char da_range[8]; /* D/A output range for each channel */
unsigned char da_range[8]; /* D/A output range for each channel */
short ao_data[8]; /* data output buffer */
short ao_data[8]; /* data output buffer */
};
/*the following macro to make it easy to
* access the private structure.
*/
/* The following macro to make it easy to access the private structure. */
#define devpriv ((struct pci1723_private *)dev->private)
#define this_board boardtypes
/*
* the pci1723 card reset;
* The pci1723 card reset;
*/
static int pci1723_reset(struct comedi_device *dev)
{
int i;
DPRINTK("adv_pci1723 EDBG: BGN: pci1723_reset(...)\n");
outw(0x01, dev->iobase + PCI1723_SYN_SET); /* set synchronous output mode */
outw(0x01, dev->iobase + PCI1723_SYN_SET);
/* set synchronous output mode */
for (i = 0; i < 8; i++) {
/* set all outputs to 0V */
/* set all outputs to 0V */
devpriv->ao_data[i] = 0x8000;
outw(devpriv->ao_data[i], dev->iobase + PCI1723_DA(i));
/* set all ranges to +/- 10V */
/* set all ranges to +/- 10V */
devpriv->da_range[i] = 0;
outw(((devpriv->da_range[i] << 4) | i),
PCI1723_RANGE_CALIBRATION_MODE);
}
outw(0, dev->iobase + PCI1723_CHANGE_CHA_OUTPUT_TYPE_STROBE); /* update ranges */
outw(0, dev->iobase + PCI1723_SYN_STROBE); /* update outputs */
outw(0, dev->iobase + PCI1723_CHANGE_CHA_OUTPUT_TYPE_STROBE);
/* update ranges */
outw(0, dev->iobase + PCI1723_SYN_STROBE); /* update outputs */
/* set asynchronous output mode */
/* set asynchronous output mode */
outw(0, dev->iobase + PCI1723_SYN_SET);
DPRINTK("adv_pci1723 EDBG: END: pci1723_reset(...)\n");
@ -251,11 +275,11 @@ static int pci1723_dio_insn_config(struct comedi_device *dev,
unsigned short dio_mode;
mask = 1 << CR_CHAN(insn->chanspec);
if (mask & 0x00FF) {
if (mask & 0x00FF)
bits = 0x00FF;
} else {
else
bits = 0xFF00;
}
switch (data[0]) {
case INSN_CONFIG_DIO_INPUT:
s->io_bits &= ~bits;
@ -270,12 +294,12 @@ static int pci1723_dio_insn_config(struct comedi_device *dev,
return -EINVAL;
}
/* update hardware DIO mode */
dio_mode = 0x0000; /* low byte output, high byte output */
/* update hardware DIO mode */
dio_mode = 0x0000; /* low byte output, high byte output */
if ((s->io_bits & 0x00FF) == 0)
dio_mode |= 0x0001; /* low byte input */
dio_mode |= 0x0001; /* low byte input */
if ((s->io_bits & 0xFF00) == 0)
dio_mode |= 0x0002; /* high byte input */
dio_mode |= 0x0002; /* high byte input */
outw(dio_mode, dev->iobase + PCI1723_DIGITAL_IO_PORT_SET);
return 1;
}
@ -311,7 +335,8 @@ static int pci1723_attach(struct comedi_device *dev,
int opt_bus, opt_slot;
const char *errstr;
printk("comedi%d: adv_pci1723: board=%s", dev->minor, this_board->name);
printk(KERN_ERR "comedi%d: adv_pci1723: board=%s",
dev->minor, this_board->name);
opt_bus = it->options[0];
opt_slot = it->options[1];
@ -349,10 +374,10 @@ static int pci1723_attach(struct comedi_device *dev,
if (!pcidev) {
if (opt_bus || opt_slot) {
printk(" - Card at b:s %d:%d %s\n",
opt_bus, opt_slot, errstr);
printk(KERN_ERR " - Card at b:s %d:%d %s\n",
opt_bus, opt_slot, errstr);
} else {
printk(" - Card %s\n", errstr);
printk(KERN_ERR " - Card %s\n", errstr);
}
return -EIO;
}
@ -362,8 +387,8 @@ static int pci1723_attach(struct comedi_device *dev,
pci_func = PCI_FUNC(pcidev->devfn);
iobase = pci_resource_start(pcidev, 2);
printk(", b:s:f=%d:%d:%d, io=0x%4x", pci_bus, pci_slot, pci_func,
iobase);
printk(KERN_ERR ", b:s:f=%d:%d:%d, io=0x%4x",
pci_bus, pci_slot, pci_func, iobase);
dev->iobase = iobase;
@ -398,22 +423,23 @@ static int pci1723_attach(struct comedi_device *dev,
s->insn_write = pci1723_ao_write_winsn;
s->insn_read = pci1723_insn_read_ao;
/* read DIO config */
switch (inw(dev->iobase + PCI1723_DIGITAL_IO_PORT_MODE) & 0x03) {
case 0x00: /* low byte output, high byte output */
/* read DIO config */
switch (inw(dev->iobase + PCI1723_DIGITAL_IO_PORT_MODE)
& 0x03) {
case 0x00: /* low byte output, high byte output */
s->io_bits = 0xFFFF;
break;
case 0x01: /* low byte input, high byte output */
case 0x01: /* low byte input, high byte output */
s->io_bits = 0xFF00;
break;
case 0x02: /* low byte output, high byte input */
case 0x02: /* low byte output, high byte input */
s->io_bits = 0x00FF;
break;
case 0x03: /* low byte input, high byte input */
case 0x03: /* low byte input, high byte input */
s->io_bits = 0x0000;
break;
}
/* read DIO port state */
/* read DIO port state */
s->state = inw(dev->iobase + PCI1723_READ_DIGITAL_INPUT_DATA);
subdev++;
@ -450,16 +476,15 @@ static int pci1723_attach(struct comedi_device *dev,
*/
static int pci1723_detach(struct comedi_device *dev)
{
printk("comedi%d: pci1723: remove\n", dev->minor);
printk(KERN_ERR "comedi%d: pci1723: remove\n", dev->minor);
if (dev->private) {
if (devpriv->valid)
pci1723_reset(dev);
if (devpriv->pcidev) {
if (dev->iobase) {
if (dev->iobase)
comedi_pci_disable(devpriv->pcidev);
}
pci_dev_put(devpriv->pcidev);
}
}

View file

@ -45,6 +45,8 @@ Configuration options:
#define DPRINTK(fmt, args...)
#endif
#define PCI_VENDOR_ID_ADVANTECH 0x13fe
/* hardware types of the cards */
enum hw_cards_id {
TYPE_PCI1730, TYPE_PCI1733, TYPE_PCI1734, TYPE_PCI1736,
@ -367,9 +369,9 @@ static int pci_dio_insn_bits_di_b(struct comedi_device *dev,
int i;
data[1] = 0;
for (i = 0; i < d->regs; i++) {
for (i = 0; i < d->regs; i++)
data[1] |= inb(dev->iobase + d->addr + i) << (8 * i);
}
return 2;
}
@ -882,9 +884,9 @@ static int CheckAndAllocCard(struct comedi_device *dev,
struct pci_dio_private *pr, *prev;
for (pr = pci_priv, prev = NULL; pr != NULL; prev = pr, pr = pr->next) {
if (pr->pcidev == pcidev) {
if (pr->pcidev == pcidev)
return 0; /* this card is used, look for another */
}
}
if (prev) {
@ -1040,22 +1042,22 @@ static int pci_dio_detach(struct comedi_device *dev)
int subdev;
if (dev->private) {
if (devpriv->valid) {
if (devpriv->valid)
pci_dio_reset(dev);
}
/* This shows the silliness of using this kind of
* scheme for numbering subdevices. Don't do it. --ds */
subdev = 0;
for (i = 0; i < MAX_DI_SUBDEVS; i++) {
if (this_board->sdi[i].chans) {
if (this_board->sdi[i].chans)
subdev++;
}
}
for (i = 0; i < MAX_DO_SUBDEVS; i++) {
if (this_board->sdo[i].chans) {
if (this_board->sdo[i].chans)
subdev++;
}
}
for (i = 0; i < MAX_DIO_SUBDEVG; i++) {
for (j = 0; j < this_board->sdio[i].regs; j++) {
@ -1071,20 +1073,20 @@ static int pci_dio_detach(struct comedi_device *dev)
}
if (devpriv->pcidev) {
if (dev->iobase) {
if (dev->iobase)
comedi_pci_disable(devpriv->pcidev);
}
pci_dev_put(devpriv->pcidev);
}
if (devpriv->prev) {
if (devpriv->prev)
devpriv->prev->next = devpriv->next;
} else {
else
pci_priv = devpriv->next;
}
if (devpriv->next) {
if (devpriv->next)
devpriv->next->prev = devpriv->prev;
}
}
return 0;

View file

@ -110,7 +110,7 @@ static int aio_aio12_8_ai_read(struct comedi_device *dev,
while (timeout &&
!(inb(dev->iobase + AIO12_8_STATUS) & STATUS_ADC_EOC)) {
timeout--;
printk("timeout %d\n", timeout);
printk(KERN_ERR "timeout %d\n", timeout);
udelay(1);
}
if (timeout == 0) {
@ -172,7 +172,7 @@ static int aio_aio12_8_attach(struct comedi_device *dev,
iobase = it->options[0];
if (!request_region(iobase, 24, "aio_aio12_8")) {
printk("I/O port conflict");
printk(KERN_ERR "I/O port conflict");
return -EIO;
}

View file

@ -218,7 +218,7 @@ order they appear in the channel list.
#define DIO200_DRIVER_NAME "amplc_dio200"
/* PCI IDs */
/* #define PCI_VENDOR_ID_AMPLICON 0x14dc */
#define PCI_VENDOR_ID_AMPLICON 0x14dc
#define PCI_DEVICE_ID_AMPLICON_PCI272 0x000a
#define PCI_DEVICE_ID_AMPLICON_PCI215 0x000b
#define PCI_DEVICE_ID_INVALID 0xffff
@ -661,7 +661,7 @@ dio200_inttrig_start_intr(struct comedi_device *dev, struct comedi_subdevice *s,
subpriv = s->private;
spin_lock_irqsave(&subpriv->spinlock, flags);
s->async->inttrig = 0;
s->async->inttrig = NULL;
if (subpriv->active)
event = dio200_start_intr(dev, s);
@ -1364,7 +1364,7 @@ static int dio200_attach(struct comedi_device *dev, struct comedi_devconfig *it)
break;
case sd_8255:
/* digital i/o subdevice (8255) */
ret = subdev_8255_init(dev, s, 0,
ret = subdev_8255_init(dev, s, NULL,
iobase + layout->sdinfo[n]);
if (ret < 0)
return ret;

View file

@ -118,7 +118,7 @@ Caveats:
/*
* PCI IDs.
*/
/* #define PCI_VENDOR_ID_AMPLICON 0x14dc */
#define PCI_VENDOR_ID_AMPLICON 0x14dc
#define PCI_DEVICE_ID_AMPLICON_PCI224 0x0007
#define PCI_DEVICE_ID_AMPLICON_PCI234 0x0008
#define PCI_DEVICE_ID_INVALID 0xffff
@ -496,9 +496,9 @@ pci224_ao_insn_write(struct comedi_device *dev, struct comedi_subdevice *s,
/* Writing a list of values to an AO channel is probably not
* very useful, but that's how the interface is defined. */
for (i = 0; i < insn->n; i++) {
for (i = 0; i < insn->n; i++)
pci224_ao_set_data(dev, chan, range, data[i]);
}
return i;
}
@ -519,9 +519,9 @@ pci224_ao_insn_read(struct comedi_device *dev, struct comedi_subdevice *s,
chan = CR_CHAN(insn->chanspec);
for (i = 0; i < insn->n; i++) {
for (i = 0; i < insn->n; i++)
data[i] = devpriv->ao_readback[chan];
}
return i;
}
@ -544,9 +544,9 @@ static void pci224_ao_stop(struct comedi_device *dev,
{
unsigned long flags;
if (!test_and_clear_bit(AO_CMD_STARTED, &devpriv->state)) {
if (!test_and_clear_bit(AO_CMD_STARTED, &devpriv->state))
return;
}
spin_lock_irqsave(&devpriv->ao_spinlock, flags);
/* Kill the interrupts. */
@ -597,11 +597,11 @@ static void pci224_ao_start(struct comedi_device *dev,
} else {
/* Enable interrupts. */
spin_lock_irqsave(&devpriv->ao_spinlock, flags);
if (cmd->stop_src == TRIG_EXT) {
if (cmd->stop_src == TRIG_EXT)
devpriv->intsce = PCI224_INTR_EXT | PCI224_INTR_DAC;
} else {
else
devpriv->intsce = PCI224_INTR_DAC;
}
outb(devpriv->intsce, devpriv->iobase1 + PCI224_INT_SCE);
spin_unlock_irqrestore(&devpriv->ao_spinlock, flags);
}
@ -630,9 +630,9 @@ static void pci224_ao_handle_fifo(struct comedi_device *dev,
num_scans = comedi_buf_read_n_available(s->async) / bytes_per_scan;
if (!devpriv->ao_stop_continuous) {
/* Fixed number of scans. */
if (num_scans > devpriv->ao_stop_count) {
if (num_scans > devpriv->ao_stop_count)
num_scans = devpriv->ao_stop_count;
}
}
/* Determine how much room is in the FIFO (in samples). */
@ -669,13 +669,13 @@ static void pci224_ao_handle_fifo(struct comedi_device *dev,
}
}
/* Determine how many new scans can be put in the FIFO. */
if (cmd->chanlist_len) {
if (cmd->chanlist_len)
room /= cmd->chanlist_len;
}
/* Determine how many scans to process. */
if (num_scans > room) {
if (num_scans > room)
num_scans = room;
}
/* Process scans. */
for (n = 0; n < num_scans; n++) {
cfc_read_array_from_buffer(s, &devpriv->ao_scan_vals[0],
@ -718,19 +718,19 @@ static void pci224_ao_handle_fifo(struct comedi_device *dev,
trig = PCI224_DACCON_TRIG_Z2CT0;
} else {
/* cmd->scan_begin_src == TRIG_EXT */
if (cmd->scan_begin_arg & CR_INVERT) {
if (cmd->scan_begin_arg & CR_INVERT)
trig = PCI224_DACCON_TRIG_EXTN;
} else {
else
trig = PCI224_DACCON_TRIG_EXTP;
}
}
devpriv->daccon = COMBINE(devpriv->daccon, trig,
PCI224_DACCON_TRIG_MASK);
outw(devpriv->daccon, dev->iobase + PCI224_DACCON);
}
if (s->async->events) {
if (s->async->events)
comedi_event(dev, s);
}
}
/*
@ -855,9 +855,9 @@ pci224_ao_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
err++;
}
tmp = cmd->chanlist_len * CONVERT_PERIOD;
if (tmp < MIN_SCAN_PERIOD) {
if (tmp < MIN_SCAN_PERIOD)
tmp = MIN_SCAN_PERIOD;
}
if (cmd->scan_begin_arg < tmp) {
cmd->scan_begin_arg = tmp;
err++;
@ -966,9 +966,9 @@ pci224_ao_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
devpriv->cached_div1 = div1;
devpriv->cached_div2 = div2;
}
if (tmp != cmd->scan_begin_arg) {
if (tmp != cmd->scan_begin_arg)
err++;
}
}
if (err)
@ -994,13 +994,13 @@ pci224_ao_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
tmp = 0;
for (n = 0; n < cmd->chanlist_len; n++) {
ch = CR_CHAN(cmd->chanlist[n]);
if (tmp & (1U << ch)) {
if (tmp & (1U << ch))
errors |= dupchan_err;
}
tmp |= (1U << ch);
if (CR_RANGE(cmd->chanlist[n]) != range) {
if (CR_RANGE(cmd->chanlist[n]) != range)
errors |= range_err;
}
}
if (errors) {
if (errors & dupchan_err) {
@ -1038,9 +1038,9 @@ static int pci224_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
unsigned long flags;
/* Cannot handle null/empty chanlist. */
if (cmd->chanlist == NULL || cmd->chanlist_len == 0) {
if (cmd->chanlist == NULL || cmd->chanlist_len == 0)
return -EINVAL;
}
/* Determine which channels are enabled and their load order. */
devpriv->ao_enab = 0;
@ -1050,9 +1050,9 @@ static int pci224_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
devpriv->ao_enab |= 1U << ch;
rank = 0;
for (j = 0; j < cmd->chanlist_len; j++) {
if (CR_CHAN(cmd->chanlist[j]) < ch) {
if (CR_CHAN(cmd->chanlist[j]) < ch)
rank++;
}
}
devpriv->ao_scan_order[rank] = i;
}
@ -1221,9 +1221,9 @@ pci224_ao_munge(struct comedi_device *dev, struct comedi_subdevice *s,
offset = 32768;
}
/* Munge the data. */
for (i = 0; i < length; i++) {
for (i = 0; i < length; i++)
array[i] = (array[i] << shift) - offset;
}
}
/*
@ -1254,15 +1254,15 @@ static irqreturn_t pci224_interrupt(int irq, void *d)
cmd = &s->async->cmd;
if (valid_intstat & PCI224_INTR_EXT) {
devpriv->intsce &= ~PCI224_INTR_EXT;
if (cmd->start_src == TRIG_EXT) {
if (cmd->start_src == TRIG_EXT)
pci224_ao_start(dev, s);
} else if (cmd->stop_src == TRIG_EXT) {
else if (cmd->stop_src == TRIG_EXT)
pci224_ao_stop(dev, s);
}
}
if (valid_intstat & PCI224_INTR_DAC) {
if (valid_intstat & PCI224_INTR_DAC)
pci224_ao_handle_fifo(dev, s);
}
}
/* Reenable interrupt sources. */
spin_lock_irqsave(&devpriv->ao_spinlock, flags);
@ -1381,23 +1381,23 @@ static int pci224_attach(struct comedi_device *dev, struct comedi_devconfig *it)
/* Allocate readback buffer for AO channels. */
devpriv->ao_readback = kmalloc(sizeof(devpriv->ao_readback[0]) *
thisboard->ao_chans, GFP_KERNEL);
if (!devpriv->ao_readback) {
if (!devpriv->ao_readback)
return -ENOMEM;
}
/* Allocate buffer to hold values for AO channel scan. */
devpriv->ao_scan_vals = kmalloc(sizeof(devpriv->ao_scan_vals[0]) *
thisboard->ao_chans, GFP_KERNEL);
if (!devpriv->ao_scan_vals) {
if (!devpriv->ao_scan_vals)
return -ENOMEM;
}
/* Allocate buffer to hold AO channel scan order. */
devpriv->ao_scan_order = kmalloc(sizeof(devpriv->ao_scan_order[0]) *
thisboard->ao_chans, GFP_KERNEL);
if (!devpriv->ao_scan_order) {
if (!devpriv->ao_scan_order)
return -ENOMEM;
}
/* Disable interrupt sources. */
devpriv->intsce = 0;
@ -1445,9 +1445,9 @@ static int pci224_attach(struct comedi_device *dev, struct comedi_devconfig *it)
s->range_table_list = range_table_list =
kmalloc(sizeof(struct comedi_lrange *) * s->n_chan,
GFP_KERNEL);
if (!s->range_table_list) {
if (!s->range_table_list)
return -ENOMEM;
}
for (n = 2; n < 3 + s->n_chan; n++) {
if (it->options[n] < 0 || it->options[n] > 1) {
printk(KERN_WARNING "comedi%d: %s: warning! "
@ -1459,11 +1459,11 @@ static int pci224_attach(struct comedi_device *dev, struct comedi_devconfig *it)
for (n = 0; n < s->n_chan; n++) {
if (n < COMEDI_NDEVCONFOPTS - 3 &&
it->options[3 + n] == 1) {
if (it->options[2] == 1) {
if (it->options[2] == 1)
range_table_list[n] = &range_pci234_ext;
} else {
else
range_table_list[n] = &range_bipolar5;
}
} else {
if (it->options[2] == 1) {
range_table_list[n] =
@ -1506,11 +1506,11 @@ static int pci224_attach(struct comedi_device *dev, struct comedi_devconfig *it)
printk(KERN_INFO "comedi%d: %s ", dev->minor, dev->board_name);
printk("(pci %s) ", pci_name(pci_dev));
if (irq) {
if (irq)
printk("(irq %u%s) ", irq, (dev->irq ? "" : " UNAVAILABLE"));
} else {
else
printk("(no irq) ");
}
printk("attached\n");
@ -1529,9 +1529,9 @@ static int pci224_detach(struct comedi_device *dev)
{
printk(KERN_DEBUG "comedi%d: %s: detach\n", dev->minor, DRIVER_NAME);
if (dev->irq) {
if (dev->irq)
free_irq(dev->irq, dev);
}
if (dev->subdevices) {
struct comedi_subdevice *s;
@ -1544,9 +1544,9 @@ static int pci224_detach(struct comedi_device *dev)
kfree(devpriv->ao_scan_vals);
kfree(devpriv->ao_scan_order);
if (devpriv->pci_dev) {
if (dev->iobase) {
if (dev->iobase)
comedi_pci_disable(devpriv->pci_dev);
}
pci_dev_put(devpriv->pci_dev);
}
}

View file

@ -669,9 +669,9 @@ static short pci230_ai_read(struct comedi_device *dev)
/* If a bipolar range was specified, mangle it (twos
* complement->straight binary). */
if (devpriv->ai_bipolar) {
if (devpriv->ai_bipolar)
data ^= 1 << (thisboard->ai_bits - 1);
}
return data;
}
@ -680,9 +680,9 @@ static inline unsigned short pci230_ao_mangle_datum(struct comedi_device *dev,
{
/* If a bipolar range was specified, mangle it (straight binary->twos
* complement). */
if (devpriv->ao_bipolar) {
if (devpriv->ao_bipolar)
datum ^= 1 << (thisboard->ao_bits - 1);
}
/* PCI230 is 12 bit - stored in upper bits of 16 bit register (lower
* four bits reserved for expansion). */
@ -734,9 +734,9 @@ static int pci230_attach(struct comedi_device *dev, struct comedi_devconfig *it)
/* Allocate the private structure area using alloc_private().
* Macro defined in comedidev.h - memsets struct fields to 0. */
if ((alloc_private(dev, sizeof(struct pci230_private))) < 0) {
if ((alloc_private(dev, sizeof(struct pci230_private))) < 0)
return -ENOMEM;
}
spin_lock_init(&devpriv->isr_spinlock);
spin_lock_init(&devpriv->res_spinlock);
spin_lock_init(&devpriv->ai_stop_spinlock);
@ -991,9 +991,9 @@ static int pci230_detach(struct comedi_device *dev)
if (devpriv) {
if (devpriv->pci_dev) {
if (dev->iobase) {
if (dev->iobase)
comedi_pci_disable(devpriv->pci_dev);
}
pci_dev_put(devpriv->pci_dev);
}
}
@ -1055,9 +1055,9 @@ static void put_resources(struct comedi_device *dev, unsigned int res_mask,
&& (res_mask != 0); b <<= 1, i++) {
if ((res_mask & b) != 0) {
res_mask &= ~b;
if (devpriv->res_owner[i] == owner) {
if (devpriv->res_owner[i] == owner)
devpriv->res_owner[i] = OWNER_NONE;
}
}
}
spin_unlock_irqrestore(&devpriv->res_spinlock, irqflags);
@ -1132,11 +1132,11 @@ static int pci230_ai_rinsn(struct comedi_device *dev,
}
devpriv->adcg = (devpriv->adcg & ~(3 << gainshift))
| (pci230_ai_gain[range] << gainshift);
if (devpriv->ai_bipolar) {
if (devpriv->ai_bipolar)
adccon |= PCI230_ADC_IR_BIP;
} else {
else
adccon |= PCI230_ADC_IR_UNI;
}
/* Enable only this channel in the scan list - otherwise by default
* we'll get one sample from each channel. */
@ -1408,13 +1408,13 @@ static int pci230_ao_cmdtest(struct comedi_device *dev,
chan = CR_CHAN(cmd->chanlist[n]);
range = CR_RANGE(cmd->chanlist[n]);
/* Channel numbers must strictly increase. */
if (chan < prev_chan) {
if (chan < prev_chan)
errors |= seq_err;
}
/* Ranges must be the same. */
if (range != first_range) {
if (range != first_range)
errors |= range_err;
}
prev_chan = chan;
}
if (errors != 0) {
@ -1583,9 +1583,9 @@ static int pci230_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
if (cmd->scan_begin_src == TRIG_TIMER) {
/* Claim Z2-CT1. */
if (!get_one_resource(dev, RES_Z2CT1, OWNER_AOCMD)) {
if (!get_one_resource(dev, RES_Z2CT1, OWNER_AOCMD))
return -EBUSY;
}
}
/* Get number of scans required. */
@ -1609,9 +1609,9 @@ static int pci230_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
unsigned int i;
dacen = 0;
for (i = 0; i < cmd->chanlist_len; i++) {
for (i = 0; i < cmd->chanlist_len; i++)
dacen |= 1 << CR_CHAN(cmd->chanlist[i]);
}
/* Set channel scan list. */
outw(dacen, dev->iobase + PCI230P2_DACEN);
/*
@ -1656,9 +1656,9 @@ static int pci230_ai_check_scan_period(struct comedi_cmd *cmd)
int err = 0;
chanlist_len = cmd->chanlist_len;
if (cmd->chanlist_len == 0) {
if (cmd->chanlist_len == 0)
chanlist_len = 1;
}
min_scan_period = chanlist_len * cmd->convert_arg;
if ((min_scan_period < chanlist_len)
|| (min_scan_period < cmd->convert_arg)) {
@ -1777,11 +1777,11 @@ static int pci230_ai_cmdtest(struct comedi_device *dev,
* single-ended or pseudo-differential. */
if (cmd->chanlist && (cmd->chanlist_len > 0)) {
/* Peek analogue reference of first channel. */
if (CR_AREF(cmd->chanlist[0]) == AREF_DIFF) {
if (CR_AREF(cmd->chanlist[0]) == AREF_DIFF)
max_speed_ai = MAX_SPEED_AI_DIFF;
} else {
else
max_speed_ai = MAX_SPEED_AI_SE;
}
} else {
/* No channel list. Assume single-ended. */
max_speed_ai = MAX_SPEED_AI_SE;
@ -1871,9 +1871,9 @@ static int pci230_ai_cmdtest(struct comedi_device *dev,
}
} else if (cmd->scan_begin_src == TRIG_TIMER) {
/* N.B. cmd->convert_arg is also TRIG_TIMER */
if (!pci230_ai_check_scan_period(cmd)) {
if (!pci230_ai_check_scan_period(cmd))
err++;
}
} else {
if (cmd->scan_begin_arg != 0) {
cmd->scan_begin_arg = 0;
@ -1961,13 +1961,13 @@ static int pci230_ai_cmdtest(struct comedi_device *dev,
errors |= seq_err;
}
/* Channels must have same AREF. */
if (aref != prev_aref) {
if (aref != prev_aref)
errors |= aref_err;
}
/* Channel ranges must have same polarity. */
if (polarity != prev_polarity) {
if (polarity != prev_polarity)
errors |= polarity_err;
}
/* Single-ended channel pairs must have same
* range. */
if ((aref != AREF_DIFF)
@ -1987,9 +1987,9 @@ static int pci230_ai_cmdtest(struct comedi_device *dev,
}
/* If channel list is a repeating subsequence, need a whole
* number of repeats. */
if ((n % subseq_len) != 0) {
if ((n % subseq_len) != 0)
errors |= seq_err;
}
if ((devpriv->hwver > 0) && (devpriv->hwver < 4)) {
/*
* Buggy PCI230+ or PCI260+ requires channel 0 to be
@ -2228,9 +2228,9 @@ static void pci230_ai_start(struct comedi_device *dev,
devpriv->adccon = (devpriv->adccon & ~PCI230_ADC_TRIG_MASK)
| conv;
outw(devpriv->adccon, dev->iobase + PCI230_ADCCON);
if (cmd->convert_src == TRIG_INT) {
if (cmd->convert_src == TRIG_INT)
async->inttrig = pci230_ai_inttrig_convert;
}
/* Update FIFO interrupt trigger level, which is currently
* set to "full". */
pci230_ai_update_fifo_trigger_level(dev, s);
@ -2345,9 +2345,9 @@ static int pci230_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
}
}
/* Claim resources. */
if (!get_resources(dev, res_mask, OWNER_AICMD)) {
if (!get_resources(dev, res_mask, OWNER_AICMD))
return -EBUSY;
}
/* Get number of scans required. */
if (cmd->stop_src == TRIG_COUNT) {
@ -2392,11 +2392,11 @@ static int pci230_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
range = CR_RANGE(cmd->chanlist[0]);
devpriv->ai_bipolar = pci230_ai_bipolar[range];
if (devpriv->ai_bipolar) {
if (devpriv->ai_bipolar)
adccon |= PCI230_ADC_IR_BIP;
} else {
else
adccon |= PCI230_ADC_IR_UNI;
}
for (i = 0; i < cmd->chanlist_len; i++) {
unsigned int gainshift;
@ -2543,9 +2543,9 @@ static unsigned int pci230_choose_clk_count(uint64_t ns, unsigned int *count,
for (clk_src = CLK_10MHZ;; clk_src++) {
cnt = divide_ns(ns, pci230_timebase[clk_src], round_mode);
if ((cnt <= 65536) || (clk_src == CLK_1KHZ)) {
if ((cnt <= 65536) || (clk_src == CLK_1KHZ))
break;
}
}
*count = cnt;
return clk_src;
@ -2575,9 +2575,9 @@ static void pci230_ct_setup_ns_mode(struct comedi_device *dev, unsigned int ct,
/* Program clock source. */
outb(CLK_CONFIG(ct, clk_src), devpriv->iobase1 + PCI230_ZCLK_SCE);
/* Set initial count. */
if (count >= 65536) {
if (count >= 65536)
count = 0;
}
i8254_write(devpriv->iobase1 + PCI230_Z2_CT_BASE, 0, ct, count);
}
@ -2599,9 +2599,9 @@ static irqreturn_t pci230_interrupt(int irq, void *d)
/* Read interrupt status/enable register. */
status_int = inb(devpriv->iobase1 + PCI230_INT_STAT);
if (status_int == PCI230_INT_DISABLE) {
if (status_int == PCI230_INT_DISABLE)
return IRQ_NONE;
}
spin_lock_irqsave(&devpriv->isr_spinlock, irqflags);
valid_status_int = devpriv->int_en & status_int;
@ -2660,9 +2660,9 @@ static void pci230_handle_ao_nofifo(struct comedi_device *dev,
struct comedi_async *async = s->async;
struct comedi_cmd *cmd = &async->cmd;
if (!devpriv->ao_continuous && (devpriv->ao_scan_count == 0)) {
if (!devpriv->ao_continuous && (devpriv->ao_scan_count == 0))
return;
}
for (i = 0; i < cmd->chanlist_len; i++) {
/* Read sample from Comedi's circular buffer. */
@ -2711,9 +2711,9 @@ static int pci230_handle_ao_fifo(struct comedi_device *dev,
num_scans = comedi_buf_read_n_available(async) / bytes_per_scan;
if (!devpriv->ao_continuous) {
/* Fixed number of scans. */
if (num_scans > devpriv->ao_scan_count) {
if (num_scans > devpriv->ao_scan_count)
num_scans = devpriv->ao_scan_count;
}
if (devpriv->ao_scan_count == 0) {
/* End of acquisition. */
events |= COMEDI_CB_EOA;
@ -2736,21 +2736,21 @@ static int pci230_handle_ao_fifo(struct comedi_device *dev,
}
if (events == 0) {
/* Determine how much room is in the FIFO (in samples). */
if ((dacstat & PCI230P2_DAC_FIFO_FULL) != 0) {
if ((dacstat & PCI230P2_DAC_FIFO_FULL) != 0)
room = PCI230P2_DAC_FIFOROOM_FULL;
} else if ((dacstat & PCI230P2_DAC_FIFO_HALF) != 0) {
else if ((dacstat & PCI230P2_DAC_FIFO_HALF) != 0)
room = PCI230P2_DAC_FIFOROOM_HALFTOFULL;
} else if ((dacstat & PCI230P2_DAC_FIFO_EMPTY) != 0) {
else if ((dacstat & PCI230P2_DAC_FIFO_EMPTY) != 0)
room = PCI230P2_DAC_FIFOROOM_EMPTY;
} else {
else
room = PCI230P2_DAC_FIFOROOM_ONETOHALF;
}
/* Convert room to number of scans that can be added. */
room /= cmd->chanlist_len;
/* Determine number of scans to process. */
if (num_scans > room) {
if (num_scans > room)
num_scans = room;
}
/* Process scans. */
for (n = 0; n < num_scans; n++) {
for (i = 0; i < cmd->chanlist_len; i++) {
@ -2817,14 +2817,14 @@ static void pci230_handle_ai(struct comedi_device *dev,
} else {
todo = (devpriv->ai_scan_count * scanlen)
- devpriv->ai_scan_pos;
if (todo > PCI230_ADC_FIFOLEVEL_HALFFULL) {
if (todo > PCI230_ADC_FIFOLEVEL_HALFFULL)
todo = PCI230_ADC_FIFOLEVEL_HALFFULL;
}
}
if (todo == 0) {
if (todo == 0)
return;
}
fifoamount = 0;
for (i = 0; i < todo; i++) {
@ -2906,9 +2906,9 @@ static void pci230_ao_stop(struct comedi_device *dev,
spin_lock_irqsave(&devpriv->ao_stop_spinlock, irqflags);
started = test_and_clear_bit(AO_CMD_STARTED, &devpriv->state);
spin_unlock_irqrestore(&devpriv->ao_stop_spinlock, irqflags);
if (!started) {
if (!started)
return;
}
cmd = &s->async->cmd;
if (cmd->scan_begin_src == TRIG_TIMER) {
@ -2968,9 +2968,9 @@ static void pci230_ai_stop(struct comedi_device *dev,
spin_lock_irqsave(&devpriv->ai_stop_spinlock, irqflags);
started = test_and_clear_bit(AI_CMD_STARTED, &devpriv->state);
spin_unlock_irqrestore(&devpriv->ai_stop_spinlock, irqflags);
if (!started) {
if (!started)
return;
}
cmd = &s->async->cmd;
if (cmd->convert_src == TRIG_TIMER) {

View file

@ -175,17 +175,18 @@ static int das16cs_attach(struct comedi_device *dev,
printk("I/O base=0x%04lx ", dev->iobase);
printk("fingerprint:\n");
for (i = 0; i < 48; i += 2) {
for (i = 0; i < 48; i += 2)
printk("%04x ", inw(dev->iobase + i));
}
printk("\n");
ret = request_irq(link->irq, das16cs_interrupt,
IRQF_SHARED, "cb_das16_cs", dev);
if (ret < 0) {
if (ret < 0)
return ret;
}
dev->irq = link->irq;
printk("irq=%u ", dev->irq);
dev->board_ptr = das16cs_probe(dev, link);
@ -262,9 +263,9 @@ static int das16cs_detach(struct comedi_device *dev)
{
printk("comedi%d: das16cs: remove\n", dev->minor);
if (dev->irq) {
if (dev->irq)
free_irq(dev->irq, dev);
}
return 0;
}
@ -834,6 +835,9 @@ static struct pcmcia_device_id das16cs_id_table[] = {
};
MODULE_DEVICE_TABLE(pcmcia, das16cs_id_table);
MODULE_AUTHOR("David A. Schleef <ds@schleef.org>");
MODULE_DESCRIPTION("Comedi driver for Computer Boards PC-CARD DAS16/16");
MODULE_LICENSE("GPL");
struct pcmcia_driver das16cs_driver = {
.probe = das16cs_pcmcia_attach,

View file

@ -107,6 +107,8 @@ TODO:
#define PRESCALED_TIMER_BASE 10000 /* 100kHz 'prescaled' clock for slow aquisition, maybe I'll support this someday */
#define DMA_BUFFER_SIZE 0x1000
#define PCI_VENDOR_ID_COMPUTERBOARDS 0x1307
/* maximum value that can be loaded into board's 24-bit counters*/
static const int max_counter_value = 0xffffff;
@ -1099,9 +1101,9 @@ struct pcidas64_private {
resource_size_t main_phys_iobase;
resource_size_t dio_counter_phys_iobase;
/* base addresses (ioremapped) */
void *plx9080_iobase;
void *main_iobase;
void *dio_counter_iobase;
void __iomem *plx9080_iobase;
void __iomem *main_iobase;
void __iomem *dio_counter_iobase;
/* local address (used by dma controller) */
uint32_t local0_iobase;
uint32_t local1_iobase;
@ -1314,7 +1316,7 @@ static inline int ao_cmd_is_supported(const struct pcidas64_board *board)
static void init_plx9080(struct comedi_device *dev)
{
uint32_t bits;
void *plx_iobase = priv(dev)->plx9080_iobase;
void __iomem *plx_iobase = priv(dev)->plx9080_iobase;
priv(dev)->plx_control_bits =
readl(priv(dev)->plx9080_iobase + PLX_CONTROL_REG);
@ -1404,7 +1406,7 @@ static void init_plx9080(struct comedi_device *dev)
static int setup_subdevices(struct comedi_device *dev)
{
struct comedi_subdevice *s;
void *dio_8255_iobase;
void __iomem *dio_8255_iobase;
int i;
if (alloc_subdevices(dev, 10) < 0)
@ -1430,7 +1432,6 @@ static int setup_subdevices(struct comedi_device *dev)
s->do_cmdtest = ai_cmdtest;
s->cancel = ai_cancel;
if (board(dev)->layout == LAYOUT_4020) {
unsigned int i;
uint8_t data;
/* set adc to read from inputs (not internal calibration sources) */
priv(dev)->i2c_cal_range_bits = adc_src_4020_bits(4);
@ -1612,7 +1613,7 @@ static void init_stc_registers(struct comedi_device *dev)
disable_ai_pacing(dev);
};
int alloc_and_init_dma_members(struct comedi_device *dev)
static int alloc_and_init_dma_members(struct comedi_device *dev)
{
int i;
@ -1621,9 +1622,9 @@ int alloc_and_init_dma_members(struct comedi_device *dev)
priv(dev)->ai_buffer[i] =
pci_alloc_consistent(priv(dev)->hw_dev, DMA_BUFFER_SIZE,
&priv(dev)->ai_buffer_bus_addr[i]);
if (priv(dev)->ai_buffer[i] == NULL) {
if (priv(dev)->ai_buffer[i] == NULL)
return -ENOMEM;
}
}
for (i = 0; i < AO_DMA_RING_COUNT; i++) {
if (ao_cmd_is_supported(board(dev))) {
@ -1632,9 +1633,9 @@ int alloc_and_init_dma_members(struct comedi_device *dev)
DMA_BUFFER_SIZE,
&priv(dev)->
ao_buffer_bus_addr[i]);
if (priv(dev)->ao_buffer[i] == NULL) {
if (priv(dev)->ao_buffer[i] == NULL)
return -ENOMEM;
}
}
}
/* allocate dma descriptors */
@ -1643,9 +1644,9 @@ int alloc_and_init_dma_members(struct comedi_device *dev)
sizeof(struct plx_dma_desc) *
ai_dma_ring_count(board(dev)),
&priv(dev)->ai_dma_desc_bus_addr);
if (priv(dev)->ai_dma_desc == NULL) {
if (priv(dev)->ai_dma_desc == NULL)
return -ENOMEM;
}
DEBUG_PRINT("ai dma descriptors start at bus addr 0x%x\n",
priv(dev)->ai_dma_desc_bus_addr);
if (ao_cmd_is_supported(board(dev))) {
@ -1654,9 +1655,9 @@ int alloc_and_init_dma_members(struct comedi_device *dev)
sizeof(struct plx_dma_desc) *
AO_DMA_RING_COUNT,
&priv(dev)->ao_dma_desc_bus_addr);
if (priv(dev)->ao_dma_desc == NULL) {
if (priv(dev)->ao_dma_desc == NULL)
return -ENOMEM;
}
DEBUG_PRINT("ao dma descriptors start at bus addr 0x%x\n",
priv(dev)->ao_dma_desc_bus_addr);
}
@ -1848,9 +1849,9 @@ static int attach(struct comedi_device *dev, struct comedi_devconfig *it)
printk(" irq %u\n", dev->irq);
retval = setup_subdevices(dev);
if (retval < 0) {
if (retval < 0)
return retval;
}
return 0;
}
@ -1875,12 +1876,12 @@ static int detach(struct comedi_device *dev)
if (priv(dev)->hw_dev) {
if (priv(dev)->plx9080_iobase) {
disable_plx_interrupts(dev);
iounmap((void *)priv(dev)->plx9080_iobase);
iounmap(priv(dev)->plx9080_iobase);
}
if (priv(dev)->main_iobase)
iounmap((void *)priv(dev)->main_iobase);
iounmap(priv(dev)->main_iobase);
if (priv(dev)->dio_counter_iobase)
iounmap((void *)priv(dev)->dio_counter_iobase);
iounmap(priv(dev)->dio_counter_iobase);
/* free pci dma buffers */
for (i = 0; i < ai_dma_ring_count(board(dev)); i++) {
if (priv(dev)->ai_buffer[i])
@ -1919,9 +1920,9 @@ static int detach(struct comedi_device *dev)
priv(dev)->ao_dma_desc,
priv(dev)->
ao_dma_desc_bus_addr);
if (priv(dev)->main_phys_iobase) {
if (priv(dev)->main_phys_iobase)
comedi_pci_disable(priv(dev)->hw_dev);
}
pci_dev_put(priv(dev)->hw_dev);
}
}
@ -2902,9 +2903,9 @@ static void pio_drain_ai_fifo_16(struct comedi_device *dev)
if (cmd->stop_src == TRIG_COUNT) {
if (priv(dev)->ai_count == 0)
break;
if (num_samples > priv(dev)->ai_count) {
if (num_samples > priv(dev)->ai_count)
num_samples = priv(dev)->ai_count;
}
priv(dev)->ai_count -= num_samples;
}
@ -2943,9 +2944,9 @@ static void pio_drain_ai_fifo_32(struct comedi_device *dev)
readw(priv(dev)->main_iobase + ADC_READ_PNTR_REG) & 0x7fff;
if (cmd->stop_src == TRIG_COUNT) {
if (max_transfer > priv(dev)->ai_count) {
if (max_transfer > priv(dev)->ai_count)
max_transfer = priv(dev)->ai_count;
}
}
for (i = 0; read_code != write_code && i < max_transfer;) {
fifo_data = readl(priv(dev)->dio_counter_iobase + ADC_FIFO_REG);
@ -2964,9 +2965,9 @@ static void pio_drain_ai_fifo_32(struct comedi_device *dev)
/* empty fifo */
static void pio_drain_ai_fifo(struct comedi_device *dev)
{
if (board(dev)->layout == LAYOUT_4020) {
if (board(dev)->layout == LAYOUT_4020)
pio_drain_ai_fifo_32(dev);
} else
else
pio_drain_ai_fifo_16(dev);
}
@ -2976,7 +2977,7 @@ static void drain_dma_buffers(struct comedi_device *dev, unsigned int channel)
uint32_t next_transfer_addr;
int j;
int num_samples = 0;
void *pci_addr_reg;
void __iomem *pci_addr_reg;
if (channel)
pci_addr_reg =
@ -3016,8 +3017,9 @@ static void drain_dma_buffers(struct comedi_device *dev, unsigned int channel)
* unused buffer) */
}
void handle_ai_interrupt(struct comedi_device *dev, unsigned short status,
unsigned int plx_status)
static void handle_ai_interrupt(struct comedi_device *dev,
unsigned short status,
unsigned int plx_status)
{
struct comedi_subdevice *s = dev->read_subdev;
struct comedi_async *async = s->async;
@ -3038,9 +3040,9 @@ void handle_ai_interrupt(struct comedi_device *dev, unsigned short status,
priv(dev)->plx9080_iobase + PLX_DMA1_CS_REG);
DEBUG_PRINT("dma1 status 0x%x\n", dma1_status);
if (dma1_status & PLX_DMA_EN_BIT) {
if (dma1_status & PLX_DMA_EN_BIT)
drain_dma_buffers(dev, 1);
}
DEBUG_PRINT(" cleared dma ch1 interrupt\n");
}
spin_unlock_irqrestore(&dev->spinlock, flags);
@ -3227,7 +3229,7 @@ static irqreturn_t handle_interrupt(int irq, void *d)
return IRQ_HANDLED;
}
void abort_dma(struct comedi_device *dev, unsigned int channel)
static void abort_dma(struct comedi_device *dev, unsigned int channel)
{
unsigned long flags;
@ -3422,7 +3424,7 @@ static void load_ao_dma(struct comedi_device *dev, const struct comedi_cmd *cmd)
{
unsigned int num_bytes;
unsigned int next_transfer_addr;
void *pci_addr_reg =
void __iomem *pci_addr_reg =
priv(dev)->plx9080_iobase + PLX_DMA0_PCI_ADDRESS_REG;
unsigned int buffer_index;
@ -3656,24 +3658,26 @@ static int ao_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
return 0;
}
static int dio_callback(int dir, int port, int data, unsigned long iobase)
static int dio_callback(int dir, int port, int data, unsigned long arg)
{
void __iomem *iobase = (void __iomem *)arg;
if (dir) {
writeb(data, (void *)(iobase + port));
writeb(data, iobase + port);
DEBUG_PRINT("wrote 0x%x to port %i\n", data, port);
return 0;
} else {
return readb((void *)(iobase + port));
return readb(iobase + port);
}
}
static int dio_callback_4020(int dir, int port, int data, unsigned long iobase)
static int dio_callback_4020(int dir, int port, int data, unsigned long arg)
{
void __iomem *iobase = (void __iomem *)arg;
if (dir) {
writew(data, (void *)(iobase + 2 * port));
writew(data, iobase + 2 * port);
return 0;
} else {
return readw((void *)(iobase + 2 * port));
return readw(iobase + 2 * port);
}
}
@ -3860,7 +3864,7 @@ static uint16_t read_eeprom(struct comedi_device *dev, uint8_t address)
static const int read_command = 0x6;
unsigned int bitstream = (read_command << 8) | address;
unsigned int bit;
void *const plx_control_addr =
void __iomem * const plx_control_addr =
priv(dev)->plx9080_iobase + PLX_CONTROL_REG;
uint16_t value;
static const int value_length = 16;
@ -4183,7 +4187,8 @@ static const int i2c_low_udelay = 10;
static void i2c_set_sda(struct comedi_device *dev, int state)
{
static const int data_bit = CTL_EE_W;
void *plx_control_addr = priv(dev)->plx9080_iobase + PLX_CONTROL_REG;
void __iomem *plx_control_addr = priv(dev)->plx9080_iobase +
PLX_CONTROL_REG;
if (state) {
/* set data line high */
@ -4202,7 +4207,8 @@ static void i2c_set_sda(struct comedi_device *dev, int state)
static void i2c_set_scl(struct comedi_device *dev, int state)
{
static const int clock_bit = CTL_USERO;
void *plx_control_addr = priv(dev)->plx9080_iobase + PLX_CONTROL_REG;
void __iomem *plx_control_addr = priv(dev)->plx9080_iobase +
PLX_CONTROL_REG;
if (state) {
/* set clock line high */

View file

@ -52,6 +52,8 @@ See http://www.measurementcomputing.com/PDFManuals/pcim-das1602_16.pdf for more
/* #define CBPCIMDAS_DEBUG */
#undef CBPCIMDAS_DEBUG
#define PCI_VENDOR_ID_COMPUTERBOARDS 0x1307
/* Registers for the PCIM-DAS1602/16 */
/* sizes of io regions (bytes) */

View file

@ -91,7 +91,8 @@ Configuration Options:
#include "8255.h"
/* device ids of the cards we support -- currently only 1 card supported */
#define PCI_ID_PCIM_DDA06_16 0x0053
#define PCI_VENDOR_ID_COMPUTERBOARDS 0x1307
#define PCI_ID_PCIM_DDA06_16 0x0053
/*
* This is straight from skel.c -- I did this in case this source file

View file

@ -87,18 +87,17 @@ Configuration Options:
* options that are used with comedi_config.
*/
#include "../comedilib.h"
#include "../comedidev.h"
#include <linux/string.h>
#include <linux/slab.h>
#include "../comedi.h"
#include "../comedilib.h"
#include "../comedidev.h"
/* The maxiumum number of channels per subdevice. */
#define MAX_CHANS 256
#define MODULE_NAME "comedi_bond"
#ifdef MODULE_LICENSE
MODULE_LICENSE("GPL");
#endif
#ifndef STR
# define STR1(x) #x
# define STR(x) STR1(x)
@ -143,7 +142,7 @@ static const struct BondingBoard bondingBoards[] = {
#define thisboard ((const struct BondingBoard *)dev->board_ptr)
struct BondedDevice {
void *dev;
struct comedi_device *dev;
unsigned minor;
unsigned subdev;
unsigned subdev_type;
@ -405,7 +404,7 @@ static void *Realloc(const void *oldmem, size_t newlen, size_t oldlen)
static int doDevConfig(struct comedi_device *dev, struct comedi_devconfig *it)
{
int i;
void *devs_opened[COMEDI_NUM_BOARD_MINORS];
struct comedi_device *devs_opened[COMEDI_NUM_BOARD_MINORS];
memset(devs_opened, 0, sizeof(devs_opened));
devpriv->name[0] = 0;;
@ -414,7 +413,7 @@ static int doDevConfig(struct comedi_device *dev, struct comedi_devconfig *it)
for (i = 0; i < COMEDI_NDEVCONFOPTS && (!i || it->options[i]); ++i) {
char file[] = "/dev/comediXXXXXX";
int minor = it->options[i];
void *d;
struct comedi_device *d;
int sdev = -1, nchans, tmp;
struct BondedDevice *bdev = NULL;

View file

@ -309,18 +309,18 @@ static int parport_attach(struct comedi_device *dev,
iobase = it->options[0];
printk(KERN_INFO "comedi%d: parport: 0x%04lx ", dev->minor, iobase);
if (!request_region(iobase, PARPORT_SIZE, "parport (comedi)")) {
printk("I/O port conflict\n");
printk(KERN_ERR "I/O port conflict\n");
return -EIO;
}
dev->iobase = iobase;
irq = it->options[1];
if (irq) {
printk(" irq=%u", irq);
printk(KERN_INFO " irq=%u", irq);
ret = request_irq(irq, parport_interrupt, 0, "comedi_parport",
dev);
if (ret < 0) {
printk(" irq not available\n");
printk(KERN_ERR " irq not available\n");
return -EINVAL;
}
dev->irq = irq;
@ -380,13 +380,13 @@ static int parport_attach(struct comedi_device *dev,
devpriv->c_data = 0;
outb(devpriv->c_data, dev->iobase + PARPORT_C);
printk("\n");
printk(KERN_INFO "\n");
return 1;
}
static int parport_detach(struct comedi_device *dev)
{
printk("comedi%d: parport: remove\n", dev->minor);
printk(KERN_INFO "comedi%d: parport: remove\n", dev->minor);
if (dev->iobase)
release_region(dev->iobase, PARPORT_SIZE);

View file

@ -1,55 +1,55 @@
/*
comedi/drivers/das08.c
DAS08 driver
* comedi/drivers/das08.c
* DAS08 driver
*
* COMEDI - Linux Control and Measurement Device Interface
* Copyright (C) 2000 David A. Schleef <ds@schleef.org>
* Copyright (C) 2001,2002,2003 Frank Mori Hess <fmhess@users.sourceforge.net>
* Copyright (C) 2004 Salvador E. Tropea <set@users.sf.net> <set@ieee.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*****************************************************************
*/
COMEDI - Linux Control and Measurement Device Interface
Copyright (C) 2000 David A. Schleef <ds@schleef.org>
Copyright (C) 2001,2002,2003 Frank Mori Hess <fmhess@users.sourceforge.net>
Copyright (C) 2004 Salvador E. Tropea <set@users.sf.net> <set@ieee.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*****************************************************************
*/
/*
Driver: das08
Description: DAS-08 compatible boards
Author: Warren Jasper, ds, Frank Hess
Devices: [Keithley Metrabyte] DAS08 (isa-das08), [ComputerBoards] DAS08 (isa-das08),
DAS08-PGM (das08-pgm),
DAS08-PGH (das08-pgh), DAS08-PGL (das08-pgl), DAS08-AOH (das08-aoh),
DAS08-AOL (das08-aol), DAS08-AOM (das08-aom), DAS08/JR-AO (das08/jr-ao),
DAS08/JR-16-AO (das08jr-16-ao), PCI-DAS08 (das08),
PC104-DAS08 (pc104-das08), DAS08/JR/16 (das08jr/16)
Status: works
This is a rewrite of the das08 and das08jr drivers.
Options (for ISA cards):
[0] - base io address
Options (for pci-das08):
[0] - bus (optional)
[1] = slot (optional)
The das08 driver doesn't support asynchronous commands, since
the cheap das08 hardware doesn't really support them. The
comedi_rt_timer driver can be used to emulate commands for this
driver.
*/
* Driver: das08
* Description: DAS-08 compatible boards
* Author: Warren Jasper, ds, Frank Hess
* Devices: [Keithley Metrabyte] DAS08 (isa-das08),
* [ComputerBoards] DAS08 (isa-das08), DAS08-PGM (das08-pgm),
* DAS08-PGH (das08-pgh), DAS08-PGL (das08-pgl), DAS08-AOH (das08-aoh),
* DAS08-AOL (das08-aol), DAS08-AOM (das08-aom), DAS08/JR-AO (das08/jr-ao),
* DAS08/JR-16-AO (das08jr-16-ao), PCI-DAS08 (das08),
* PC104-DAS08 (pc104-das08), DAS08/JR/16 (das08jr/16)
* Status: works
*
* This is a rewrite of the das08 and das08jr drivers.
*
* Options (for ISA cards):
* [0] - base io address
*
* Options (for pci-das08):
* [0] - bus (optional)
* [1] = slot (optional)
*
* The das08 driver doesn't support asynchronous commands, since
* the cheap das08 hardware doesn't really support them. The
* comedi_rt_timer driver can be used to emulate commands for this
* driver.
*/
#include "../comedidev.h"
@ -122,8 +122,8 @@ driver.
*/
#define DAS08JR_DIO 3
#define DAS08JR_AO_LSB(x) ((x)?6:4)
#define DAS08JR_AO_MSB(x) ((x)?7:5)
#define DAS08JR_AO_LSB(x) ((x) ? 6 : 4)
#define DAS08JR_AO_MSB(x) ((x) ? 7 : 5)
/*
cio-das08_aox.pdf
@ -148,8 +148,8 @@ driver.
#define DAS08AO_GAIN_CONTROL 3
#define DAS08AO_GAIN_STATUS 3
#define DAS08AO_AO_LSB(x) ((x)?0xa:8)
#define DAS08AO_AO_MSB(x) ((x)?0xb:9)
#define DAS08AO_AO_LSB(x) ((x) ? 0xa : 8)
#define DAS08AO_AO_MSB(x) ((x) ? 0xb : 9)
#define DAS08AO_AO_UPDATE 8
/* gainlist same as _pgx_ below */
@ -239,8 +239,9 @@ static const struct comedi_lrange *const das08_ai_lranges[] = {
&range_das08_pgm,
};
static const int das08_pgh_gainlist[] =
{ 8, 0, 10, 2, 12, 4, 14, 6, 1, 3, 5, 7 };
static const int das08_pgh_gainlist[] = {
8, 0, 10, 2, 12, 4, 14, 6, 1, 3, 5, 7
};
static const int das08_pgl_gainlist[] = { 8, 0, 2, 4, 6, 1, 3, 5, 7 };
static const int das08_pgm_gainlist[] = { 8, 0, 10, 12, 14, 9, 11, 13, 15 };
@ -535,7 +536,8 @@ static int das08_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
inb(dev->iobase + DAS08_MSB);
/* set multiplexer */
spin_lock(&dev->spinlock); /* lock to prevent race with digital output */
/* lock to prevent race with digital output */
spin_lock(&dev->spinlock);
devpriv->do_mux_bits &= ~DAS08_MUX_MASK;
devpriv->do_mux_bits |= DAS08_MUX(chan);
outb(devpriv->do_mux_bits, dev->iobase + DAS08_CONTROL);
@ -552,7 +554,7 @@ static int das08_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
/* clear over-range bits for 16-bit boards */
if (thisboard->ai_nbits == 16)
if (inb(dev->iobase + DAS08_MSB) & 0x80)
printk("das08: over-range\n");
printk(KERN_INFO "das08: over-range\n");
/* trigger conversion */
outb_p(0, dev->iobase + DAS08_TRIG_12BIT);
@ -562,7 +564,7 @@ static int das08_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
break;
}
if (i == TIMEOUT) {
printk("das08: timeout\n");
printk(KERN_ERR "das08: timeout\n");
return -ETIME;
}
msb = inb(dev->iobase + DAS08_MSB);
@ -607,7 +609,8 @@ static int das08_do_wbits(struct comedi_device *dev, struct comedi_subdevice *s,
/* set new bit values */
wbits |= data[0] & data[1];
/* remember digital output bits */
spin_lock(&dev->spinlock); /* prevent race with setting of analog input mux */
/* prevent race with setting of analog input mux */
spin_lock(&dev->spinlock);
devpriv->do_mux_bits &= ~DAS08_DO_MASK;
devpriv->do_mux_bits |= DAS08_OP(wbits);
outb(devpriv->do_mux_bits, dev->iobase + DAS08_CONTROL);
@ -860,9 +863,9 @@ int das08_common_attach(struct comedi_device *dev, unsigned long iobase)
/* allocate ioports for non-pcmcia, non-pci boards */
if ((thisboard->bustype != pcmcia) && (thisboard->bustype != pci)) {
printk(" iobase 0x%lx\n", iobase);
printk(KERN_INFO " iobase 0x%lx\n", iobase);
if (!request_region(iobase, thisboard->iosize, DRV_NAME)) {
printk(" I/O port conflict\n");
printk(KERN_ERR " I/O port conflict\n");
return -EIO;
}
}
@ -878,8 +881,11 @@ int das08_common_attach(struct comedi_device *dev, unsigned long iobase)
/* ai */
if (thisboard->ai) {
s->type = COMEDI_SUBD_AI;
/* XXX some boards actually have differential inputs instead of single ended.
* The driver does nothing with arefs though, so it's no big deal. */
/* XXX some boards actually have differential
* inputs instead of single ended.
* The driver does nothing with arefs though,
* so it's no big deal.
*/
s->subdev_flags = SDF_READABLE | SDF_GROUND;
s->n_chan = 8;
s->maxdata = (1 << thisboard->ai_nbits) - 1;
@ -966,6 +972,7 @@ int das08_common_attach(struct comedi_device *dev, unsigned long iobase)
return 0;
}
EXPORT_SYMBOL_GPL(das08_common_attach);
static int das08_attach(struct comedi_device *dev, struct comedi_devconfig *it)
{
@ -980,7 +987,7 @@ static int das08_attach(struct comedi_device *dev, struct comedi_devconfig *it)
if (ret < 0)
return ret;
printk("comedi%d: das08: ", dev->minor);
printk(KERN_INFO "comedi%d: das08: ", dev->minor);
/* deal with a pci board */
if (thisboard->bustype == pci) {
#ifdef CONFIG_COMEDI_PCI
@ -1007,20 +1014,21 @@ static int das08_attach(struct comedi_device *dev, struct comedi_devconfig *it)
}
}
if (!pdev) {
printk("No pci das08 cards found\n");
printk(KERN_ERR "No pci das08 cards found\n");
return -EIO;
}
devpriv->pdev = pdev;
/* enable PCI device and reserve I/O spaces */
if (comedi_pci_enable(pdev, DRV_NAME)) {
printk
(" Error enabling PCI device and requesting regions\n");
printk(KERN_ERR " Error enabling PCI device and "
"requesting regions\n");
return -EIO;
}
/* read base addresses */
pci_iobase = pci_resource_start(pdev, 1);
iobase = pci_resource_start(pdev, 2);
printk("pcibase 0x%lx iobase 0x%lx\n", pci_iobase, iobase);
printk(KERN_INFO "pcibase 0x%lx iobase 0x%lx\n",
pci_iobase, iobase);
devpriv->pci_iobase = pci_iobase;
#if 0
/* We could enable to pci-das08's interrupt here to make it possible
@ -1034,17 +1042,18 @@ static int das08_attach(struct comedi_device *dev, struct comedi_devconfig *it)
outw(INTR1_ENABLE | PCI_INTR_ENABLE, pci_iobase + INTCSR);
#endif
#else /* CONFIG_COMEDI_PCI */
printk("this driver has not been built with PCI support.\n");
printk(KERN_ERR "this driver has not been built with PCI support.\n");
return -EINVAL;
#endif /* CONFIG_COMEDI_PCI */
} else {
iobase = it->options[0];
}
printk("\n");
printk(KERN_INFO "\n");
return das08_common_attach(dev, iobase);
}
int das08_common_detach(struct comedi_device *dev)
{
printk(KERN_INFO "comedi%d: das08: remove\n", dev->minor);
@ -1060,9 +1069,9 @@ int das08_common_detach(struct comedi_device *dev)
#ifdef CONFIG_COMEDI_PCI
if (devpriv) {
if (devpriv->pdev) {
if (devpriv->pci_iobase) {
if (devpriv->pci_iobase)
comedi_pci_disable(devpriv->pdev);
}
pci_dev_put(devpriv->pdev);
}
}
@ -1070,6 +1079,7 @@ int das08_common_detach(struct comedi_device *dev)
return 0;
}
EXPORT_SYMBOL_GPL(das08_common_detach);
#ifdef CONFIG_COMEDI_PCI
COMEDI_PCI_INITCLEANUP(driver_das08, das08_pci_table);
@ -1077,8 +1087,6 @@ COMEDI_PCI_INITCLEANUP(driver_das08, das08_pci_table);
COMEDI_INITCLEANUP(driver_das08);
#endif
EXPORT_SYMBOL_GPL(das08_common_attach);
EXPORT_SYMBOL_GPL(das08_common_detach);
#ifdef CONFIG_COMEDI_PCMCIA
EXPORT_SYMBOL_GPL(das08_cs_boards);
#endif

View file

@ -62,7 +62,7 @@ struct i8254_struct {
#define I8254_CTRL 3
struct das08_private_struct {
unsigned int do_mux_bits; /* bits for do/mux register on boards without seperate do register */
unsigned int do_mux_bits; /* bits for do/mux register on boards without separate do register */
unsigned int do_bits; /* bits for do register on boards with register dedicated to digital out only */
const unsigned int *pg_gainlist;
struct pci_dev *pdev; /* struct for pci-das08 */

View file

@ -350,6 +350,10 @@ static struct pcmcia_device_id das08_cs_id_table[] = {
};
MODULE_DEVICE_TABLE(pcmcia, das08_cs_id_table);
MODULE_AUTHOR("David A. Schleef <ds@schleef.org>, "
"Frank Mori Hess <fmhess@users.sourceforge.net>");
MODULE_DESCRIPTION("Comedi driver for ComputerBoards DAS-08 PCMCIA boards");
MODULE_LICENSE("GPL");
struct pcmcia_driver das08_cs_driver = {
.probe = das08_pcmcia_attach,
@ -392,6 +396,5 @@ static void __exit das08_cs_exit_module(void)
comedi_driver_unregister(&driver_das08_cs);
}
MODULE_LICENSE("GPL");
module_init(das08_cs_init_module);
module_exit(das08_cs_exit_module);

View file

@ -74,7 +74,8 @@ Keithley Manuals:
4922.PDF (das-1400)
4923.PDF (das1200, 1400, 1600)
Computer boards manuals also available from their website www.measurementcomputing.com
Computer boards manuals also available from their website
www.measurementcomputing.com
*/
@ -92,7 +93,8 @@ Computer boards manuals also available from their website www.measurementcomputi
/* #define DEBUG */
#ifdef DEBUG
#define DEBUG_PRINT(format, args...) printk("das16: " format, ## args)
#define DEBUG_PRINT(format, args...) \
printk(KERN_DEBUG "das16: " format, ## args)
#else
#define DEBUG_PRINT(format, args...)
#endif
@ -186,15 +188,16 @@ Computer boards manuals also available from their website www.measurementcomputi
*/
static const int sample_size = 2; /* size in bytes of a sample from board */
/* size in bytes of a sample from board */
static const int sample_size = 2;
#define DAS16_TRIG 0
#define DAS16_AI_LSB 0
#define DAS16_AI_MSB 1
#define DAS16_MUX 2
#define DAS16_DIO 3
#define DAS16_AO_LSB(x) ((x)?6:4)
#define DAS16_AO_MSB(x) ((x)?7:5)
#define DAS16_AO_LSB(x) ((x) ? 6 : 4)
#define DAS16_AO_MSB(x) ((x) ? 7 : 5)
#define DAS16_STATUS 8
#define BUSY (1<<7)
#define UNIPOLAR (1<<6)
@ -271,7 +274,7 @@ static const struct comedi_lrange range_das1x02_unip = { 4, {
};
static const struct comedi_lrange range_das16jr = { 9, {
/* also used by 16/330 */
/* also used by 16/330 */
BIP_RANGE(10),
BIP_RANGE(5),
BIP_RANGE(2.5),
@ -547,7 +550,8 @@ static const struct das16_board das16_boards[] = {
.id = 0x20,
},
{
.name = "das-1401", /* 4919.pdf and 4922.pdf (keithley user's manual) */
/* 4919.pdf and 4922.pdf (keithley user's manual) */
.name = "das-1401",
.ai = das16_ai_rinsn,
.ai_nbits = 12,
.ai_speed = 10000,
@ -558,10 +562,11 @@ static const struct das16_board das16_boards[] = {
.i8255_offset = 0x0,
.i8254_offset = 0x0c,
.size = 0x408,
.id = 0xc0 /* 4919.pdf says id bits are 0xe0, 4922.pdf says 0xc0 */
.id = 0xc0 /* 4919.pdf says id bits are 0xe0, 4922.pdf says 0xc0 */
},
{
.name = "das-1402", /* 4919.pdf and 4922.pdf (keithley user's manual) */
/* 4919.pdf and 4922.pdf (keithley user's manual) */
.name = "das-1402",
.ai = das16_ai_rinsn,
.ai_nbits = 12,
.ai_speed = 10000,
@ -572,7 +577,7 @@ static const struct das16_board das16_boards[] = {
.i8255_offset = 0x0,
.i8254_offset = 0x0c,
.size = 0x408,
.id = 0xc0 /* 4919.pdf says id bits are 0xe0, 4922.pdf says 0xc0 */
.id = 0xc0 /* 4919.pdf says id bits are 0xe0, 4922.pdf says 0xc0 */
},
{
.name = "das-1601", /* 4919.pdf */
@ -704,7 +709,8 @@ static const struct das16_board das16_boards[] = {
.name = "das16/jr/ctr5", /* ? */
},
{
.name = "cio-das16/m1/16", /* cio-das16_m1_16.pdf, this board is a bit quirky, no dma */
/* cio-das16_m1_16.pdf, this board is a bit quirky, no dma */
.name = "cio-das16/m1/16",
},
#endif
};
@ -736,14 +742,19 @@ struct das16_private_struct {
unsigned int clockbase; /* master clock speed in ns */
volatile unsigned int control_state; /* dma, interrupt and trigger control bits */
volatile unsigned long adc_byte_count; /* number of bytes remaining */
unsigned int divisor1; /* divisor dividing master clock to get conversion frequency */
unsigned int divisor2; /* divisor dividing master clock to get conversion frequency */
/* divisor dividing master clock to get conversion frequency */
unsigned int divisor1;
/* divisor dividing master clock to get conversion frequency */
unsigned int divisor2;
unsigned int dma_chan; /* dma channel */
uint16_t *dma_buffer[2];
dma_addr_t dma_buffer_addr[2];
unsigned int current_buffer;
volatile unsigned int dma_transfer_size; /* target number of bytes to transfer per dma shot */
/* user-defined analog input and output ranges defined from config options */
/**
* user-defined analog input and output ranges
* defined from config options
*/
struct comedi_lrange *user_ai_range_table;
struct comedi_lrange *user_ao_range_table;
@ -798,7 +809,10 @@ static int das16_cmd_test(struct comedi_device *dev, struct comedi_subdevice *s,
if (err)
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->scan_begin_src != TRIG_TIMER &&
cmd->scan_begin_src != TRIG_EXT &&
cmd->scan_begin_src != TRIG_FOLLOW)
@ -893,12 +907,15 @@ static int das16_cmd_test(struct comedi_device *dev, struct comedi_subdevice *s,
if (CR_CHAN(cmd->chanlist[i]) !=
(start_chan + i) % s->n_chan) {
comedi_error(dev,
"entries in chanlist must be consecutive channels, counting upwards\n");
"entries in chanlist must be "
"consecutive channels, "
"counting upwards\n");
err++;
}
if (CR_RANGE(cmd->chanlist[i]) != gain) {
comedi_error(dev,
"entries in chanlist must all have the same gain\n");
"entries in chanlist must all "
"have the same gain\n");
err++;
}
}
@ -920,12 +937,13 @@ static int das16_cmd_exec(struct comedi_device *dev, struct comedi_subdevice *s)
if (devpriv->dma_chan == 0 || (dev->irq == 0
&& devpriv->timer_mode == 0)) {
comedi_error(dev,
"irq (or use of 'timer mode') dma required to execute comedi_cmd");
"irq (or use of 'timer mode') dma required to "
"execute comedi_cmd");
return -1;
}
if (cmd->flags & TRIG_RT) {
comedi_error(dev,
"isa dma transfers cannot be performed with TRIG_RT, aborting");
comedi_error(dev, "isa dma transfers cannot be performed with "
"TRIG_RT, aborting");
return -1;
}
@ -933,16 +951,17 @@ static int das16_cmd_exec(struct comedi_device *dev, struct comedi_subdevice *s)
cmd->stop_arg * cmd->chanlist_len * sizeof(uint16_t);
/* disable conversions for das1600 mode */
if (thisboard->size > 0x400) {
if (thisboard->size > 0x400)
outb(DAS1600_CONV_DISABLE, dev->iobase + DAS1600_CONV);
}
/* set scan limits */
byte = CR_CHAN(cmd->chanlist[0]);
byte |= CR_CHAN(cmd->chanlist[cmd->chanlist_len - 1]) << 4;
outb(byte, dev->iobase + DAS16_MUX);
/* set gain (this is also burst rate register but according to
* computer boards manual, burst rate does nothing, even on keithley cards) */
* computer boards manual, burst rate does nothing, even on
* keithley cards) */
if (thisboard->ai_pg != das16_pg_none) {
range = CR_RANGE(cmd->chanlist[0]);
outb((das16_gainlists[thisboard->ai_pg])[range],
@ -1005,9 +1024,9 @@ static int das16_cmd_exec(struct comedi_device *dev, struct comedi_subdevice *s)
outb(devpriv->control_state, dev->iobase + DAS16_CONTROL);
/* Enable conversions if using das1600 mode */
if (thisboard->size > 0x400) {
if (thisboard->size > 0x400)
outb(0, dev->iobase + DAS1600_CONV);
}
return 0;
}
@ -1030,9 +1049,9 @@ static int das16_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
}
/* disable burst mode */
if (thisboard->size > 0x400) {
if (thisboard->size > 0x400)
outb(0, dev->iobase + DAS1600_BURST);
}
spin_unlock_irqrestore(&dev->spinlock, flags);
@ -1085,11 +1104,11 @@ static int das16_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
}
msb = inb(dev->iobase + DAS16_AI_MSB);
lsb = inb(dev->iobase + DAS16_AI_LSB);
if (thisboard->ai_nbits == 12) {
if (thisboard->ai_nbits == 12)
data[n] = ((lsb >> 4) & 0xf) | (msb << 4);
} else {
else
data[n] = lsb | (msb << 8);
}
}
return n;
@ -1207,8 +1226,8 @@ static int disable_dma_on_even(struct comedi_device *dev)
residue = get_dma_residue(devpriv->dma_chan);
}
if (i == disable_limit) {
comedi_error(dev,
"failed to get an even dma transfer, could be trouble.");
comedi_error(dev, "failed to get an even dma transfer, "
"could be trouble.");
}
return residue;
}
@ -1254,7 +1273,8 @@ static void das16_interrupt(struct comedi_device *dev)
} else
num_bytes = devpriv->dma_transfer_size - residue;
if (cmd->stop_src == TRIG_COUNT && num_bytes >= devpriv->adc_byte_count) {
if (cmd->stop_src == TRIG_COUNT &&
num_bytes >= devpriv->adc_byte_count) {
num_bytes = devpriv->adc_byte_count;
async->events |= COMEDI_CB_EOA;
}
@ -1275,9 +1295,9 @@ static void das16_interrupt(struct comedi_device *dev)
set_dma_count(devpriv->dma_chan, devpriv->dma_transfer_size);
enable_dma(devpriv->dma_chan);
/* reenable conversions for das1600 mode, (stupid hardware) */
if (thisboard->size > 0x400 && devpriv->timer_mode == 0) {
if (thisboard->size > 0x400 && devpriv->timer_mode == 0)
outb(0x00, dev->iobase + DAS1600_CONV);
}
}
release_dma_lock(dma_flags);
@ -1330,25 +1350,25 @@ static int das16_probe(struct comedi_device *dev, struct comedi_devconfig *it)
status = inb(dev->iobase + DAS16_STATUS);
if ((status & UNIPOLAR)) {
if ((status & UNIPOLAR))
devpriv->ai_unipolar = 1;
} else {
else
devpriv->ai_unipolar = 0;
}
if ((status & DAS16_MUXBIT)) {
if ((status & DAS16_MUXBIT))
devpriv->ai_singleended = 1;
} else {
else
devpriv->ai_singleended = 0;
}
/* diobits indicates boards */
diobits = inb(dev->iobase + DAS16_DIO) & 0xf0;
printk(" id bits are 0x%02x\n", diobits);
printk(KERN_INFO " id bits are 0x%02x\n", diobits);
if (thisboard->id != diobits) {
printk(" requested board's id bits are 0x%x (ignore)\n",
printk(KERN_INFO " requested board's id bits are 0x%x (ignore)\n",
thisboard->id);
}
@ -1363,10 +1383,10 @@ static int das1600_mode_detect(struct comedi_device *dev)
if (status & DAS1600_CLK_10MHZ) {
devpriv->clockbase = 100;
printk(" 10MHz pacer clock\n");
printk(KERN_INFO " 10MHz pacer clock\n");
} else {
devpriv->clockbase = 1000;
printk(" 1MHz pacer clock\n");
printk(KERN_INFO " 1MHz pacer clock\n");
}
reg_dump(dev);
@ -1406,14 +1426,15 @@ static int das16_attach(struct comedi_device *dev, struct comedi_devconfig *it)
if (timer_mode)
irq = 0;
printk("comedi%d: das16:", dev->minor);
printk(KERN_INFO "comedi%d: das16:", dev->minor);
/* check that clock setting is valid */
if (it->options[3]) {
if (it->options[3] != 0 &&
it->options[3] != 1 && it->options[3] != 10) {
printk
("\n Invalid option. Master clock must be set to 1 or 10 (MHz)\n");
("\n Invalid option. Master clock must be set "
"to 1 or 10 (MHz)\n");
return -EINVAL;
}
}
@ -1425,23 +1446,23 @@ static int das16_attach(struct comedi_device *dev, struct comedi_devconfig *it)
if (thisboard->size < 0x400) {
printk(" 0x%04lx-0x%04lx\n", iobase, iobase + thisboard->size);
if (!request_region(iobase, thisboard->size, "das16")) {
printk(" I/O port conflict\n");
printk(KERN_ERR " I/O port conflict\n");
return -EIO;
}
} else {
printk(" 0x%04lx-0x%04lx 0x%04lx-0x%04lx\n",
printk(KERN_INFO " 0x%04lx-0x%04lx 0x%04lx-0x%04lx\n",
iobase, iobase + 0x0f,
iobase + 0x400,
iobase + 0x400 + (thisboard->size & 0x3ff));
if (!request_region(iobase, 0x10, "das16")) {
printk(" I/O port conflict: 0x%04lx-0x%04lx\n",
printk(KERN_ERR " I/O port conflict: 0x%04lx-0x%04lx\n",
iobase, iobase + 0x0f);
return -EIO;
}
if (!request_region(iobase + 0x400, thisboard->size & 0x3ff,
"das16")) {
release_region(iobase, 0x10);
printk(" I/O port conflict: 0x%04lx-0x%04lx\n",
printk(KERN_ERR " I/O port conflict: 0x%04lx-0x%04lx\n",
iobase + 0x400,
iobase + 0x400 + (thisboard->size & 0x3ff));
return -EIO;
@ -1452,7 +1473,7 @@ static int das16_attach(struct comedi_device *dev, struct comedi_devconfig *it)
/* probe id bits to make sure they are consistent */
if (das16_probe(dev, it)) {
printk(" id bits do not match selected board, aborting\n");
printk(KERN_ERR " id bits do not match selected board, aborting\n");
return -EINVAL;
}
dev->board_name = thisboard->name;
@ -1474,7 +1495,7 @@ static int das16_attach(struct comedi_device *dev, struct comedi_devconfig *it)
if (ret < 0)
return ret;
dev->irq = irq;
printk(" ( irq = %u )", irq);
printk(KERN_INFO " ( irq = %u )", irq);
} else if (irq == 0) {
printk(" ( no irq )");
} else {
@ -1488,16 +1509,15 @@ static int das16_attach(struct comedi_device *dev, struct comedi_devconfig *it)
/* allocate dma buffers */
int i;
for (i = 0; i < 2; i++) {
devpriv->dma_buffer[i] = pci_alloc_consistent(NULL,
DAS16_DMA_SIZE,
&devpriv->
dma_buffer_addr
[i]);
devpriv->dma_buffer[i] = pci_alloc_consistent(
NULL, DAS16_DMA_SIZE,
&devpriv->dma_buffer_addr[i]);
if (devpriv->dma_buffer[i] == NULL)
return -ENOMEM;
}
if (request_dma(dma_chan, "das16")) {
printk(" failed to allocate dma channel %i\n",
printk(KERN_ERR " failed to allocate dma channel %i\n",
dma_chan);
return -EINVAL;
}
@ -1506,11 +1526,11 @@ static int das16_attach(struct comedi_device *dev, struct comedi_devconfig *it)
disable_dma(devpriv->dma_chan);
set_dma_mode(devpriv->dma_chan, DMA_MODE_READ);
release_dma_lock(flags);
printk(" ( dma = %u)\n", dma_chan);
printk(KERN_INFO " ( dma = %u)\n", dma_chan);
} else if (dma_chan == 0) {
printk(" ( no dma )\n");
printk(KERN_INFO " ( no dma )\n");
} else {
printk(" invalid dma channel\n");
printk(KERN_ERR " invalid dma channel\n");
return -EINVAL;
}
@ -1569,7 +1589,7 @@ static int das16_attach(struct comedi_device *dev, struct comedi_devconfig *it)
s->subdev_flags |= SDF_DIFF;
}
s->maxdata = (1 << thisboard->ai_nbits) - 1;
if (devpriv->user_ai_range_table) { /* user defined ai range */
if (devpriv->user_ai_range_table) { /* user defined ai range */
s->range_table = devpriv->user_ai_range_table;
} else if (devpriv->ai_unipolar) {
s->range_table = das16_ai_uni_lranges[thisboard->ai_pg];
@ -1592,11 +1612,12 @@ static int das16_attach(struct comedi_device *dev, struct comedi_devconfig *it)
s->subdev_flags = SDF_WRITABLE;
s->n_chan = 2;
s->maxdata = (1 << thisboard->ao_nbits) - 1;
if (devpriv->user_ao_range_table) { /* user defined ao range */
/* user defined ao range */
if (devpriv->user_ao_range_table)
s->range_table = devpriv->user_ao_range_table;
} else {
else
s->range_table = &range_unknown;
}
s->insn_write = thisboard->ao;
} else {
s->type = COMEDI_SUBD_UNUSED;
@ -1656,7 +1677,7 @@ static int das16_attach(struct comedi_device *dev, struct comedi_devconfig *it)
static int das16_detach(struct comedi_device *dev)
{
printk("comedi%d: das16: remove\n", dev->minor);
printk(KERN_INFO "comedi%d: das16: remove\n", dev->minor);
das16_reset(dev);
@ -1750,8 +1771,8 @@ static void das16_ai_munge(struct comedi_device *dev,
for (i = 0; i < num_samples; i++) {
data[i] = le16_to_cpu(data[i]);
if (thisboard->ai_nbits == 12) {
if (thisboard->ai_nbits == 12)
data[i] = (data[i] >> 4) & 0xfff;
}
}
}

View file

@ -797,10 +797,8 @@ static int das1800_detach(struct comedi_device *dev)
free_dma(devpriv->dma0);
if (devpriv->dma1)
free_dma(devpriv->dma1);
if (devpriv->ai_buf0)
kfree(devpriv->ai_buf0);
if (devpriv->ai_buf1)
kfree(devpriv->ai_buf1);
kfree(devpriv->ai_buf0);
kfree(devpriv->ai_buf1);
}
printk("comedi%d: %s: remove\n", dev->minor,
@ -1639,7 +1637,8 @@ static int das1800_ai_rinsn(struct comedi_device *dev,
}
if (i == timeout) {
comedi_error(dev, "timeout");
return -ETIME;
n = -ETIME;
goto exit;
}
dpnt = inw(dev->iobase + DAS1800_FIFO);
/* shift data to offset binary for bipolar ranges */
@ -1647,6 +1646,7 @@ static int das1800_ai_rinsn(struct comedi_device *dev,
dpnt += 1 << (thisboard->resolution - 1);
data[n] = dpnt;
}
exit:
spin_unlock_irqrestore(&dev->spinlock, irq_flags);
return n;

View file

@ -472,7 +472,7 @@ static const struct comedi_lrange *dac_range_table[] = {
static const struct comedi_lrange *dac_range_lkup(int opt)
{
if (opt < 0 || opt > 5)
if (opt < 0 || opt >= 5)
return &range_unknown;
return dac_range_table[opt];
}

View file

@ -34,13 +34,13 @@ Configuration options:
[0] - I/O port base address
[1] - IRQ, although this is currently unused
[2] - A/D reference
0 = signle-ended
1 = differential
0 = signle-ended
1 = differential
2 = pseudo-differential (common reference)
[3] - A/D range
0 = [-5,5]
1 = [-2.5,2.5]
2 = [0,5]
0 = [-5, 5]
1 = [-2.5, 2.5]
2 = [0, 5]
[4] - D/A 0 range (same choices)
[4] - D/A 1 range (same choices)
*/
@ -52,96 +52,58 @@ Configuration options:
static const char *driver_name = "dt2811";
static const struct comedi_lrange range_dt2811_pgh_ai_5_unipolar = { 4, {
RANGE
(0, 5),
RANGE
(0,
2.5),
RANGE
(0,
1.25),
RANGE
(0,
0.625)
}
static const struct comedi_lrange range_dt2811_pgh_ai_5_unipolar = {
4, {
RANGE(0, 5),
RANGE(0, 2.5),
RANGE(0, 1.25),
RANGE(0, 0.625)
}
};
static const struct comedi_lrange range_dt2811_pgh_ai_2_5_bipolar = { 4, {
RANGE
(-2.5,
2.5),
RANGE
(-1.25,
1.25),
RANGE
(-0.625,
0.625),
RANGE
(-0.3125,
0.3125)
}
static const struct comedi_lrange range_dt2811_pgh_ai_2_5_bipolar = {
4, {
RANGE(-2.5, 2.5),
RANGE(-1.25, 1.25),
RANGE(-0.625, 0.625),
RANGE(-0.3125, 0.3125)
}
};
static const struct comedi_lrange range_dt2811_pgh_ai_5_bipolar = { 4, {
RANGE
(-5, 5),
RANGE
(-2.5,
2.5),
RANGE
(-1.25,
1.25),
RANGE
(-0.625,
0.625)
}
static const struct comedi_lrange range_dt2811_pgh_ai_5_bipolar = {
4, {
RANGE(-5, 5),
RANGE(-2.5, 2.5),
RANGE(-1.25, 1.25),
RANGE(-0.625, 0.625)
}
};
static const struct comedi_lrange range_dt2811_pgl_ai_5_unipolar = { 4, {
RANGE
(0, 5),
RANGE
(0,
0.5),
RANGE
(0,
0.05),
RANGE
(0,
0.01)
}
static const struct comedi_lrange range_dt2811_pgl_ai_5_unipolar = {
4, {
RANGE(0, 5),
RANGE(0, 0.5),
RANGE(0, 0.05),
RANGE(0, 0.01)
}
};
static const struct comedi_lrange range_dt2811_pgl_ai_2_5_bipolar = { 4, {
RANGE
(-2.5,
2.5),
RANGE
(-0.25,
0.25),
RANGE
(-0.025,
0.025),
RANGE
(-0.005,
0.005)
}
static const struct comedi_lrange range_dt2811_pgl_ai_2_5_bipolar = {
4, {
RANGE(-2.5, 2.5),
RANGE(-0.25, 0.25),
RANGE(-0.025, 0.025),
RANGE(-0.005, 0.005)
}
};
static const struct comedi_lrange range_dt2811_pgl_ai_5_bipolar = { 4, {
RANGE
(-5, 5),
RANGE
(-0.5,
0.5),
RANGE
(-0.05,
0.05),
RANGE
(-0.01,
0.01)
}
static const struct comedi_lrange range_dt2811_pgl_ai_5_bipolar = {
4, {
RANGE(-5, 5),
RANGE(-0.5, 0.5),
RANGE(-0.05, 0.05),
RANGE(-0.01, 0.01)
}
};
/*
@ -348,21 +310,21 @@ static irqreturn_t dt2811_interrupt(int irq, void *d)
options[0] Board base address
options[1] IRQ
options[2] Input configuration
0 == single-ended
1 == differential
2 == pseudo-differential
0 == single-ended
1 == differential
2 == pseudo-differential
options[3] Analog input range configuration
0 == bipolar 5 (-5V -- +5V)
1 == bipolar 2.5V (-2.5V -- +2.5V)
2 == unipolar 5V (0V -- +5V)
0 == bipolar 5 (-5V -- +5V)
1 == bipolar 2.5V (-2.5V -- +2.5V)
2 == unipolar 5V (0V -- +5V)
options[4] Analog output 0 range configuration
0 == bipolar 5 (-5V -- +5V)
1 == bipolar 2.5V (-2.5V -- +2.5V)
2 == unipolar 5V (0V -- +5V)
0 == bipolar 5 (-5V -- +5V)
1 == bipolar 2.5V (-2.5V -- +2.5V)
2 == unipolar 5V (0V -- +5V)
options[5] Analog output 1 range configuration
0 == bipolar 5 (-5V -- +5V)
1 == bipolar 2.5V (-2.5V -- +2.5V)
2 == unipolar 5V (0V -- +5V)
0 == bipolar 5 (-5V -- +5V)
1 == bipolar 2.5V (-2.5V -- +2.5V)
2 == unipolar 5V (0V -- +5V)
*/
static int dt2811_attach(struct comedi_device *dev, struct comedi_devconfig *it)
@ -377,10 +339,10 @@ static int dt2811_attach(struct comedi_device *dev, struct comedi_devconfig *it)
iobase = it->options[0];
printk("comedi%d: dt2811: base=0x%04lx\n", dev->minor, iobase);
printk(KERN_INFO "comedi%d: dt2811:base=0x%04lx\n", dev->minor, iobase);
if (!request_region(iobase, DT2811_SIZE, driver_name)) {
printk("I/O port conflict\n");
printk(KERN_ERR "I/O port conflict\n");
return -EIO;
}
@ -410,25 +372,25 @@ static int dt2811_attach(struct comedi_device *dev, struct comedi_devconfig *it)
irq = probe_irq_off(irqs);
restore_flags(flags);
/*outb(DT2811_CLRERROR|DT2811_INTENB,dev->iobase+DT2811_ADCSR); */
/*outb(DT2811_CLRERROR|DT2811_INTENB,
dev->iobase+DT2811_ADCSR);*/
if (inb(dev->iobase + DT2811_ADCSR) & DT2811_ADERROR) {
printk("error probing irq (bad) \n");
}
if (inb(dev->iobase + DT2811_ADCSR) & DT2811_ADERROR)
printk(KERN_ERR "error probing irq (bad)\n");
dev->irq = 0;
if (irq > 0) {
i = inb(dev->iobase + DT2811_ADDATLO);
i = inb(dev->iobase + DT2811_ADDATHI);
printk("(irq = %d)\n", irq);
printk(KERN_INFO "(irq = %d)\n", irq);
ret = request_irq(irq, dt2811_interrupt, 0,
driver_name, dev);
if (ret < 0)
return -EIO;
dev->irq = irq;
} else if (irq == 0) {
printk("(no irq)\n");
printk(KERN_INFO "(no irq)\n");
} else {
printk("( multiple irq's -- this is bad! )\n");
printk(KERN_ERR "( multiple irq's -- this is bad! )\n");
}
}
#endif
@ -540,14 +502,12 @@ static int dt2811_attach(struct comedi_device *dev, struct comedi_devconfig *it)
static int dt2811_detach(struct comedi_device *dev)
{
printk("comedi%d: dt2811: remove\n", dev->minor);
printk(KERN_INFO "comedi%d: dt2811: remove\n", dev->minor);
if (dev->irq) {
if (dev->irq)
free_irq(dev->irq, dev);
}
if (dev->iobase) {
if (dev->iobase)
release_region(dev->iobase, DT2811_SIZE);
}
return 0;
}
@ -579,7 +539,7 @@ static int dt2811_ai_insn(struct comedi_device *dev, struct comedi_subdevice *s,
#if 0
/* Wow. This is code from the Comedi stone age. But it hasn't been
* replaced, so I'll let it stay. */
int dt2811_adtrig(kdev_t minor, comedi_adtrig * adtrig)
int dt2811_adtrig(kdev_t minor, comedi_adtrig *adtrig)
{
struct comedi_device *dev = comedi_devices + minor;
@ -589,8 +549,10 @@ int dt2811_adtrig(kdev_t minor, comedi_adtrig * adtrig)
switch (dev->i_admode) {
case COMEDI_MDEMAND:
dev->ntrig = adtrig->n - 1;
/* not neccessary */
/*printk("dt2811: AD soft trigger\n"); */
/*outb(DT2811_CLRERROR|DT2811_INTENB,dev->iobase+DT2811_ADCSR); *//* not neccessary */
/*outb(DT2811_CLRERROR|DT2811_INTENB,
dev->iobase+DT2811_ADCSR); */
outb(dev->curadchan, dev->iobase + DT2811_ADGCR);
do_gettimeofday(&trigtime);
break;
@ -630,9 +592,8 @@ static int dt2811_ao_insn_read(struct comedi_device *dev,
chan = CR_CHAN(insn->chanspec);
for (i = 0; i < insn->n; i++) {
for (i = 0; i < insn->n; i++)
data[i] = devpriv->ao_readback[chan];
}
return i;
}

View file

@ -99,13 +99,13 @@ static int dt2814_ai_insn_read(struct comedi_device *dev,
outb(chan, dev->iobase + DT2814_CSR);
for (i = 0; i < DT2814_TIMEOUT; i++) {
status = inb(dev->iobase + DT2814_CSR);
printk("dt2814: status: %02x\n", status);
printk(KERN_INFO "dt2814: status: %02x\n", status);
udelay(10);
if (status & DT2814_FINISH)
break;
}
if (i >= DT2814_TIMEOUT) {
printk("dt2814: status: %02x\n", status);
printk(KERN_INFO "dt2814: status: %02x\n", status);
return -ETIMEDOUT;
}
@ -173,7 +173,8 @@ static int dt2814_ai_cmdtest(struct comedi_device *dev,
if (err)
return 1;
/* step 2: make sure trigger sources are unique and mutually compatible */
/* step 2: make sure trigger sources are
* unique and mutually compatible */
/* note that mutual compatibility is not an issue here */
if (cmd->stop_src != TRIG_TIMER && cmd->stop_src != TRIG_EXT)
@ -256,9 +257,9 @@ static int dt2814_attach(struct comedi_device *dev, struct comedi_devconfig *it)
unsigned long iobase;
iobase = it->options[0];
printk("comedi%d: dt2814: 0x%04lx ", dev->minor, iobase);
printk(KERN_INFO "comedi%d: dt2814: 0x%04lx ", dev->minor, iobase);
if (!request_region(iobase, DT2814_SIZE, "dt2814")) {
printk("I/O port conflict\n");
printk(KERN_ERR "I/O port conflict\n");
return -EIO;
}
dev->iobase = iobase;
@ -267,7 +268,7 @@ static int dt2814_attach(struct comedi_device *dev, struct comedi_devconfig *it)
outb(0, dev->iobase + DT2814_CSR);
udelay(100);
if (inb(dev->iobase + DT2814_CSR) & DT2814_ERR) {
printk("reset error (fatal)\n");
printk(KERN_ERR "reset error (fatal)\n");
return -EIO;
}
i = inb(dev->iobase + DT2814_DATA);
@ -286,9 +287,9 @@ static int dt2814_attach(struct comedi_device *dev, struct comedi_devconfig *it)
irq = probe_irq_off(irqs);
restore_flags(flags);
if (inb(dev->iobase + DT2814_CSR) & DT2814_ERR) {
printk("error probing irq (bad) \n");
}
if (inb(dev->iobase + DT2814_CSR) & DT2814_ERR)
printk(KERN_DEBUG "error probing irq (bad)\n");
i = inb(dev->iobase + DT2814_DATA);
i = inb(dev->iobase + DT2814_DATA);
@ -297,18 +298,18 @@ static int dt2814_attach(struct comedi_device *dev, struct comedi_devconfig *it)
dev->irq = 0;
if (irq > 0) {
if (request_irq(irq, dt2814_interrupt, 0, "dt2814", dev)) {
printk("(irq %d unavailable)\n", irq);
printk(KERN_WARNING "(irq %d unavailable)\n", irq);
} else {
printk("( irq = %d )\n", irq);
printk(KERN_INFO "( irq = %d )\n", irq);
dev->irq = irq;
}
} else if (irq == 0) {
printk("(no irq)\n");
printk(KERN_WARNING "(no irq)\n");
} else {
#if 0
printk("(probe returned multiple irqs--bad)\n");
printk(KERN_DEBUG "(probe returned multiple irqs--bad)\n");
#else
printk("(irq probe not implemented)\n");
printk(KERN_WARNING "(irq probe not implemented)\n");
#endif
}
@ -337,14 +338,13 @@ static int dt2814_attach(struct comedi_device *dev, struct comedi_devconfig *it)
static int dt2814_detach(struct comedi_device *dev)
{
printk("comedi%d: dt2814: remove\n", dev->minor);
printk(KERN_INFO "comedi%d: dt2814: remove\n", dev->minor);
if (dev->irq) {
if (dev->irq)
free_irq(dev->irq, dev);
}
if (dev->iobase) {
if (dev->iobase)
release_region(dev->iobase, DT2814_SIZE);
}
return 0;
}

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