mirror of https://gitee.com/openkylin/linux.git
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:
commit
d79df0b1ed
|
@ -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
|
||||
|
|
|
@ -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/
|
||||
|
|
|
@ -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.
|
|
@ -0,0 +1 @@
|
|||
obj-$(CONFIG_ADIS16255) += adis16255.o
|
|
@ -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");
|
|
@ -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
|
|
@ -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.
|
|
@ -1,3 +0,0 @@
|
|||
obj-$(CONFIG_ARLAN) += arlan.o
|
||||
|
||||
arlan-objs := arlan-main.o arlan-proc.o
|
|
@ -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
|
@ -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
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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>
|
||||
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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);
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
*
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
*
|
||||
|
|
|
@ -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 @@ static struct batman_if *get_batman_if_by_name(char *name)
|
|||
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);
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
*
|
||||
|
|
|
@ -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
|
||||
*
|
||||
|
|
|
@ -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 @@ int init_module(void)
|
|||
|
||||
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]);
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
*
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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);
|
||||
|
|
@ -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
|
||||
*
|
||||
|
|
|
@ -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
|
||||
*
|
||||
|
|
|
@ -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 @@ static void update_orig(struct orig_node *orig_node, struct ethhdr *ethhdr,
|
|||
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 */
|
||||
|
|
|
@ -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
|
||||
*
|
||||
|
|
|
@ -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);
|
||||
|
||||
/**
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 @@ int interface_tx(struct sk_buff *skb, struct net_device *dev)
|
|||
spin_unlock_irqrestore(&orig_hash_lock, flags);
|
||||
dropped:
|
||||
priv->stats.tx_dropped++;
|
||||
kfree_skb(skb);
|
||||
end:
|
||||
return NETDEV_TX_OK;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
*
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 @@ int vis_init(void)
|
|||
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);
|
||||
|
|
|
@ -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
|
@ -9,4 +9,3 @@ comedi-objs := \
|
|||
range.o \
|
||||
drivers.o \
|
||||
comedi_compat32.o \
|
||||
comedi_ksyms.o \
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -25,9 +25,8 @@
|
|||
*/
|
||||
|
||||
#define __NO_VERSION__
|
||||
#include "comedi.h"
|
||||
#include <linux/uaccess.h>
|
||||
|
||||
#include "comedi.h"
|
||||
#include "comedi_compat32.h"
|
||||
|
||||
#ifdef CONFIG_COMPAT
|
||||
|
|
|
@ -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 @@ static long comedi_unlocked_ioctl(struct file *file, unsigned int cmd,
|
|||
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 @@ static int do_bufconfig_ioctl(struct comedi_device *dev, void *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)
|
||||
{
|
||||
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 @@ static int do_bufinfo_ioctl(struct comedi_device *dev, void *arg)
|
|||
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 @@ static int parse_insn(struct comedi_device *dev, struct comedi_insn *insn,
|
|||
}
|
||||
|
||||
/*
|
||||
* 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 @@ static int do_insn_ioctl(struct comedi_device *dev, void *arg, void *file)
|
|||
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 @@ static int do_cmd_ioctl(struct comedi_device *dev, void *arg, void *file)
|
|||
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 @@ static ssize_t comedi_write(struct file *file, const char *buf, size_t nbytes,
|
|||
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,
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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);
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 @@ int comedi_device_attach(struct comedi_device *dev, struct comedi_devconfig *it)
|
|||
}
|
||||
|
||||
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 @@ int comedi_auto_config(struct device *hardware_device, const char *board_name,
|
|||
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);
|
||||
|
|
|
@ -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.
|
||||
*
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 |
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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;
|
||||
|
||||
/*
|
||||
+----------------------------------------------------------------------------+
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
/*
|
||||
+----------------------------------------------------------------------------+
|
||||
|
|
|
@ -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 |
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
/************************/
|
||||
|
|
|
@ -54,7 +54,7 @@ Configuration Options:
|
|||
#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); */
|
||||
|
|
|
@ -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);
|
|
@ -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 @@ static int pci9111_attach(struct comedi_device *dev,
|
|||
|
||||
/* 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
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -52,7 +52,7 @@ configures all channels in the same group.
|
|||
|
||||
#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 @@ configures all channels in the same group.
|
|||
#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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -118,7 +118,7 @@ Passing a zero for an option is the same as leaving it unspecified.
|
|||
/*
|
||||
* 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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -107,6 +107,8 @@ known. If you have such a board, please file a bug report at
|
|||
#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 */
|
||||
|
|
|
@ -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) */
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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];
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
Loading…
Reference in New Issue