Staging tree pull request for 3.5-rc1
Here is the big staging tree pull request for the 3.5-rc1 merge window. Loads of changes here, and we just narrowly added more lines than we added: 622 files changed, 28356 insertions(+), 26059 deletions(-) But, good news is that there is a number of subsystems that moved out of the staging tree, to their respective "real" portions of the kernel. Code that moved out was: - iio core code - mei driver - vme core and bridge drivers There was one broken network driver that moved into staging as a step before it is removed from the tree (pc300), and there was a few new drivers added to the tree: - new iio drivers - gdm72xx wimax USB driver - ipack subsystem and 2 drivers All of the movements around have acks from the various subsystem maintainers, and all of this has been in the linux-next tree for a while. Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> -----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.18 (GNU/Linux) iEYEABECAAYFAk+7q8MACgkQMUfUDdst+ymjogCguo8fANFVlPWeZGeoBTL+aQfQ yTkAoLE0codmh+2SvhulYgyU1Wh6ZDK2 =nJ2F -----END PGP SIGNATURE----- Merge tag 'staging-3.5-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging Pull staging tree changes from Greg Kroah-Hartman: "Here is the big staging tree pull request for the 3.5-rc1 merge window. Loads of changes here, and we just narrowly added more lines than we added: 622 files changed, 28356 insertions(+), 26059 deletions(-) But, good news is that there is a number of subsystems that moved out of the staging tree, to their respective "real" portions of the kernel. Code that moved out was: - iio core code - mei driver - vme core and bridge drivers There was one broken network driver that moved into staging as a step before it is removed from the tree (pc300), and there was a few new drivers added to the tree: - new iio drivers - gdm72xx wimax USB driver - ipack subsystem and 2 drivers All of the movements around have acks from the various subsystem maintainers, and all of this has been in the linux-next tree for a while. Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>" Fixed up various trivial conflicts, along with a non-trivial one found in -next and pointed out by Olof Johanssen: a clean - but incorrect - merge of the arch/arm/boot/dts/at91sam9g20.dtsi file. Fix up manually as per Stephen Rothwell. * tag 'staging-3.5-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging: (536 commits) Staging: bcm: Remove two unused variables from Adapter.h Staging: bcm: Removes the volatile type definition from Adapter.h Staging: bcm: Rename all "INT" to "int" in Adapter.h Staging: bcm: Fix warning: __packed vs. __attribute__((packed)) in Adapter.h Staging: bcm: Correctly format all comments in Adapter.h Staging: bcm: Fix all whitespace issues in Adapter.h Staging: bcm: Properly format braces in Adapter.h Staging: ipack/bridges/tpci200: remove unneeded casts Staging: ipack/bridges/tpci200: remove TPCI200_SHORTNAME constant Staging: ipack: remove board_name and bus_name fields from struct ipack_device Staging: ipack: improve the register of a bus and a device in the bus. staging: comedi: cleanup all the comedi_driver 'detach' functions staging: comedi: remove all 'default N' in Kconfig staging: line6/config.h: Delete unused header staging: gdm72xx depends on NET staging: gdm72xx: Set up parent link in sysfs for gdm72xx devices staging: drm/omap: initial dmabuf/prime import support staging: drm/omap: dmabuf/prime mmap support pstore/ram: Add ECC support pstore/ram: Switch to persistent_ram routines ...
This commit is contained in:
commit
fb09bafda6
|
@ -108,7 +108,7 @@ Description:
|
|||
physically equivalent inputs when non differential readings are
|
||||
separately available. In differential only parts, then all that
|
||||
is required is a consistent labeling. Units after application
|
||||
of scale and offset are nanofarads..
|
||||
of scale and offset are nanofarads.
|
||||
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_temp_raw
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_tempX_raw
|
||||
|
@ -119,7 +119,7 @@ KernelVersion: 2.6.35
|
|||
Contact: linux-iio@vger.kernel.org
|
||||
Description:
|
||||
Raw (unscaled no bias removal etc) temperature measurement.
|
||||
It an axis is specified it generally means that the temperature
|
||||
If an axis is specified it generally means that the temperature
|
||||
sensor is associated with one part of a compound device (e.g.
|
||||
a gyroscope axis). Units after application of scale and offset
|
||||
are milli degrees Celsuis.
|
||||
|
@ -232,7 +232,7 @@ Description:
|
|||
If known for a device, scale to be applied to <type>Y[_name]_raw
|
||||
post addition of <type>[Y][_name]_offset in order to obtain the
|
||||
measured value in <type> units as specified in
|
||||
<type>[Y][_name]_raw documentation.. If shared across all in
|
||||
<type>[Y][_name]_raw documentation. If shared across all in
|
||||
channels then Y and <x|y|z> are not present and the value is
|
||||
called <type>[Y][_name]_scale. The peak modifier means this
|
||||
value is applied to <type>Y[_name]_peak_raw values.
|
||||
|
@ -243,6 +243,8 @@ What: /sys/bus/iio/devices/iio:deviceX/in_accel_z_calibbias
|
|||
What: /sys/bus/iio/devices/iio:deviceX/in_anglvel_x_calibbias
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_anglvel_y_calibbias
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_anglvel_z_calibbias
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_illuminance0_calibbias
|
||||
What: /sys/bus/iio/devices/iio:deviceX/in_proximity0_calibbias
|
||||
KernelVersion: 2.6.35
|
||||
Contact: linux-iio@vger.kernel.org
|
||||
Description:
|
||||
|
@ -258,6 +260,8 @@ What /sys/bus/iio/devices/iio:deviceX/in_accel_z_calibscale
|
|||
What /sys/bus/iio/devices/iio:deviceX/in_anglvel_x_calibscale
|
||||
What /sys/bus/iio/devices/iio:deviceX/in_anglvel_y_calibscale
|
||||
What /sys/bus/iio/devices/iio:deviceX/in_anglvel_z_calibscale
|
||||
what /sys/bus/iio/devices/iio:deviceX/in_illuminance0_calibscale
|
||||
what /sys/bus/iio/devices/iio:deviceX/in_proximity0_calibscale
|
||||
KernelVersion: 2.6.35
|
||||
Contact: linux-iio@vger.kernel.org
|
||||
Description:
|
||||
|
@ -276,6 +280,13 @@ Description:
|
|||
If a discrete set of scale values are available, they
|
||||
are listed in this attribute.
|
||||
|
||||
What /sys/bus/iio/devices/iio:deviceX/out_voltageY_hardwaregain
|
||||
KernelVersion: 2.6.35
|
||||
Contact: linux-iio@vger.kernel.org
|
||||
Description:
|
||||
Hardware applied gain factor. If shared across all channels,
|
||||
<type>_hardwaregain is used.
|
||||
|
||||
What: /sys/.../in_accel_filter_low_pass_3db_frequency
|
||||
What: /sys/.../in_magn_filter_low_pass_3db_frequency
|
||||
What: /sys/.../in_anglvel_filter_low_pass_3db_frequency
|
||||
|
@ -453,10 +464,14 @@ What: /sys/.../events/in_magn_z_raw_thresh_rising_value
|
|||
What: /sys/.../events/in_magn_z_raw_thresh_falling_value
|
||||
What: /sys/.../events/in_voltageY_supply_raw_thresh_rising_value
|
||||
What: /sys/.../events/in_voltageY_supply_raw_thresh_falling_value
|
||||
What: /sys/.../events/in_voltageY_raw_thresh_rising_value
|
||||
What: /sys/.../events/in_voltageY_raw_thresh_falling_value
|
||||
What: /sys/.../events/in_voltageY_raw_thresh_falling_value
|
||||
What: /sys/.../events/in_tempY_raw_thresh_falling_value
|
||||
What: /sys/.../events/in_tempY_raw_thresh_rising_value
|
||||
What: /sys/.../events/in_tempY_raw_thresh_falling_value
|
||||
What: /sys/.../events/in_illuminance0_thresh_falling_value
|
||||
what: /sys/.../events/in_illuminance0_thresh_rising_value
|
||||
what: /sys/.../events/in_proximity0_thresh_falling_value
|
||||
what: /sys/.../events/in_proximity0_thresh_rising_value
|
||||
KernelVersion: 2.6.37
|
||||
Contact: linux-iio@vger.kernel.org
|
||||
Description:
|
||||
|
@ -490,9 +505,9 @@ What: /sys/.../events/in_magn_z_raw_roc_rising_value
|
|||
What: /sys/.../events/in_magn_z_raw_roc_falling_value
|
||||
What: /sys/.../events/in_voltageY_supply_raw_roc_rising_value
|
||||
What: /sys/.../events/in_voltageY_supply_raw_roc_falling_value
|
||||
What: /sys/.../events/in_voltageY_raw_roc_rising_value
|
||||
What: /sys/.../events/in_voltageY_raw_roc_falling_value
|
||||
What: /sys/.../events/in_voltageY_raw_roc_falling_value
|
||||
What: /sys/.../events/in_tempY_raw_roc_falling_value
|
||||
What: /sys/.../events/in_tempY_raw_roc_rising_value
|
||||
What: /sys/.../events/in_tempY_raw_roc_falling_value
|
||||
KernelVersion: 2.6.37
|
||||
Contact: linux-iio@vger.kernel.org
|
||||
|
@ -556,6 +571,8 @@ What: /sys/.../events/in_tempY_thresh_falling_period
|
|||
What: /sys/.../events/in_tempY_roc_rising_period
|
||||
What: /sys/.../events/in_tempY_roc_falling_period
|
||||
What: /sys/.../events/in_accel_x&y&z_mag_falling_period
|
||||
What: /sys/.../events/in_intensity0_thresh_period
|
||||
What: /sys/.../events/in_proximity0_thresh_period
|
||||
KernelVersion: 2.6.37
|
||||
Contact: linux-iio@vger.kernel.org
|
||||
Description:
|
||||
|
@ -718,24 +735,3 @@ Contact: linux-iio@vger.kernel.org
|
|||
Description:
|
||||
This attribute is used to read the amount of quadrature error
|
||||
present in the device at a given time.
|
||||
|
||||
What: /sys/.../iio:deviceX/ac_excitation_en
|
||||
KernelVersion: 3.1.0
|
||||
Contact: linux-iio@vger.kernel.org
|
||||
Description:
|
||||
This attribute, if available, is used to enable the AC
|
||||
excitation mode found on some converters. In ac excitation mode,
|
||||
the polarity of the excitation voltage is reversed on
|
||||
alternate cycles, to eliminate DC errors.
|
||||
|
||||
What: /sys/.../iio:deviceX/bridge_switch_en
|
||||
KernelVersion: 3.1.0
|
||||
Contact: linux-iio@vger.kernel.org
|
||||
Description:
|
||||
This attribute, if available, is used to close or open the
|
||||
bridge power down switch found on some converters.
|
||||
In bridge applications, such as strain gauges and load cells,
|
||||
the bridge itself consumes the majority of the current in the
|
||||
system. To minimize the current consumption of the system,
|
||||
the bridge can be disconnected (when it is not being used
|
||||
using the bridge_switch_en attribute.
|
|
@ -1,3 +1,3 @@
|
|||
obj-m := DocBook/ accounting/ auxdisplay/ connector/ \
|
||||
filesystems/ filesystems/configfs/ ia64/ laptops/ networking/ \
|
||||
pcmcia/ spi/ timers/ watchdog/src/
|
||||
pcmcia/ spi/ timers/ watchdog/src/ misc-devices/mei/
|
||||
|
|
|
@ -0,0 +1,65 @@
|
|||
* AT91's Analog to Digital Converter (ADC)
|
||||
|
||||
Required properties:
|
||||
- compatible: Should be "atmel,at91sam9260-adc"
|
||||
- reg: Should contain ADC registers location and length
|
||||
- interrupts: Should contain the IRQ line for the ADC
|
||||
- atmel,adc-channel-base: Offset of the first channel data register
|
||||
- atmel,adc-channels-used: Bitmask of the channels muxed and enable for this
|
||||
device
|
||||
- atmel,adc-drdy-mask: Mask of the DRDY interruption in the ADC
|
||||
- atmel,adc-num-channels: Number of channels available in the ADC
|
||||
- atmel,adc-startup-time: Startup Time of the ADC in microseconds as
|
||||
defined in the datasheet
|
||||
- atmel,adc-status-register: Offset of the Interrupt Status Register
|
||||
- atmel,adc-trigger-register: Offset of the Trigger Register
|
||||
- atmel,adc-vref: Reference voltage in millivolts for the conversions
|
||||
|
||||
Optional properties:
|
||||
- atmel,adc-use-external: Boolean to enable of external triggers
|
||||
|
||||
Optional trigger Nodes:
|
||||
- Required properties:
|
||||
* trigger-name: Name of the trigger exposed to the user
|
||||
* trigger-value: Value to put in the Trigger register
|
||||
to activate this trigger
|
||||
- Optional properties:
|
||||
* trigger-external: Is the trigger an external trigger?
|
||||
|
||||
Examples:
|
||||
adc0: adc@fffb0000 {
|
||||
compatible = "atmel,at91sam9260-adc";
|
||||
reg = <0xfffb0000 0x100>;
|
||||
interrupts = <20 4>;
|
||||
atmel,adc-channel-base = <0x30>;
|
||||
atmel,adc-channels-used = <0xff>;
|
||||
atmel,adc-drdy-mask = <0x10000>;
|
||||
atmel,adc-num-channels = <8>;
|
||||
atmel,adc-startup-time = <40>;
|
||||
atmel,adc-status-register = <0x1c>;
|
||||
atmel,adc-trigger-register = <0x08>;
|
||||
atmel,adc-use-external;
|
||||
atmel,adc-vref = <3300>;
|
||||
|
||||
trigger@0 {
|
||||
trigger-name = "external-rising";
|
||||
trigger-value = <0x1>;
|
||||
trigger-external;
|
||||
};
|
||||
trigger@1 {
|
||||
trigger-name = "external-falling";
|
||||
trigger-value = <0x2>;
|
||||
trigger-external;
|
||||
};
|
||||
|
||||
trigger@2 {
|
||||
trigger-name = "external-any";
|
||||
trigger-value = <0x3>;
|
||||
trigger-external;
|
||||
};
|
||||
|
||||
trigger@3 {
|
||||
trigger-name = "continuous";
|
||||
trigger-value = <0x6>;
|
||||
};
|
||||
};
|
|
@ -0,0 +1,16 @@
|
|||
* NXP LPC32xx SoC ADC controller
|
||||
|
||||
Required properties:
|
||||
- compatible: must be "nxp,lpc3220-adc"
|
||||
- reg: physical base address of the controller and length of memory mapped
|
||||
region.
|
||||
- interrupts: The ADC interrupt
|
||||
|
||||
Example:
|
||||
|
||||
adc@40048000 {
|
||||
compatible = "nxp,lpc3220-adc";
|
||||
reg = <0x40048000 0x1000>;
|
||||
interrupt-parent = <&mic>;
|
||||
interrupts = <39 0>;
|
||||
};
|
|
@ -0,0 +1,26 @@
|
|||
* ST SPEAr ADC device driver
|
||||
|
||||
Required properties:
|
||||
- compatible: Should be "st,spear600-adc"
|
||||
- reg: Address and length of the register set for the device
|
||||
- interrupt-parent: Should be the phandle for the interrupt controller
|
||||
that services interrupts for this device
|
||||
- interrupts: Should contain the ADC interrupt
|
||||
- sampling-frequency: Default sampling frequency
|
||||
|
||||
Optional properties:
|
||||
- vref-external: External voltage reference in milli-volts. If omitted
|
||||
the internal voltage reference will be used.
|
||||
- average-samples: Number of samples to generate an average value. If
|
||||
omitted, single data conversion will be used.
|
||||
|
||||
Examples:
|
||||
|
||||
adc: adc@d8200000 {
|
||||
compatible = "st,spear600-adc";
|
||||
reg = <0xd8200000 0x1000>;
|
||||
interrupt-parent = <&vic1>;
|
||||
interrupts = <6>;
|
||||
sampling-frequency = <5000000>;
|
||||
vref-external = <2500>; /* 2.5V VRef */
|
||||
};
|
|
@ -120,6 +120,7 @@ Code Seq#(hex) Include File Comments
|
|||
'G' 00-0F linux/gigaset_dev.h conflict!
|
||||
'H' 00-7F linux/hiddev.h conflict!
|
||||
'H' 00-0F linux/hidraw.h conflict!
|
||||
'H' 01 linux/mei.h conflict!
|
||||
'H' 00-0F sound/asound.h conflict!
|
||||
'H' 20-40 sound/asound_fm.h conflict!
|
||||
'H' 80-8F sound/sfnt_info.h conflict!
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
mei-amt-version
|
|
@ -0,0 +1,8 @@
|
|||
# kbuild trick to avoid linker error. Can be omitted if a module is built.
|
||||
obj- := dummy.o
|
||||
|
||||
# List of programs to build
|
||||
hostprogs-y := mei-amt-version
|
||||
HOSTCFLAGS_mei-amt-version.o += -I$(objtree)/usr/include
|
||||
# Tell kbuild to always build the programs
|
||||
always := $(hostprogs-y)
|
|
@ -0,0 +1,2 @@
|
|||
TODO:
|
||||
- Cleanup and split the timer function
|
|
@ -74,7 +74,7 @@
|
|||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <bits/wordsize.h>
|
||||
#include "mei.h"
|
||||
#include <linux/mei.h>
|
||||
|
||||
/*****************************************************************************
|
||||
* Intel Management Engine Interface
|
|
@ -3,7 +3,7 @@ Ramoops oops/panic logger
|
|||
|
||||
Sergiu Iordache <sergiu@chromium.org>
|
||||
|
||||
Updated: 8 August 2011
|
||||
Updated: 17 November 2011
|
||||
|
||||
0. Introduction
|
||||
|
||||
|
@ -30,6 +30,11 @@ variable while setting 0 in that variable dumps only the panics.
|
|||
The module uses a counter to record multiple dumps but the counter gets reset
|
||||
on restart (i.e. new dumps after the restart will overwrite old ones).
|
||||
|
||||
Ramoops also supports software ECC protection of persistent memory regions.
|
||||
This might be useful when a hardware reset was used to bring the machine back
|
||||
to life (i.e. a watchdog triggered). In such cases, RAM may be somewhat
|
||||
corrupt, but usually it is restorable.
|
||||
|
||||
2. Setting the parameters
|
||||
|
||||
Setting the ramoops parameters can be done in 2 different manners:
|
||||
|
@ -38,7 +43,7 @@ Setting the ramoops parameters can be done in 2 different manners:
|
|||
2. Use a platform device and set the platform data. The parameters can then
|
||||
be set through that platform data. An example of doing that is:
|
||||
|
||||
#include <linux/ramoops.h>
|
||||
#include <linux/pstore_ram.h>
|
||||
[...]
|
||||
|
||||
static struct ramoops_platform_data ramoops_data = {
|
||||
|
@ -46,6 +51,7 @@ static struct ramoops_platform_data ramoops_data = {
|
|||
.mem_address = <...>,
|
||||
.record_size = <...>,
|
||||
.dump_oops = <...>,
|
||||
.ecc = <...>,
|
||||
};
|
||||
|
||||
static struct platform_device ramoops_dev = {
|
||||
|
@ -71,6 +77,6 @@ timestamp and a new line. The dump then continues with the actual data.
|
|||
|
||||
4. Reading the data
|
||||
|
||||
The dump data can be read from memory (through /dev/mem or other means).
|
||||
Getting the module parameters, which are needed in order to parse the data, can
|
||||
be done through /sys/module/ramoops/parameters/* .
|
||||
The dump data can be read from the pstore filesystem. The format for these
|
||||
files is "dmesg-ramoops-N", where N is the record number in memory. To delete
|
||||
a stored record from RAM, simply unlink the respective pstore file.
|
||||
|
|
21
MAINTAINERS
21
MAINTAINERS
|
@ -3406,6 +3406,7 @@ IIO SUBSYSTEM AND DRIVERS
|
|||
M: Jonathan Cameron <jic23@cam.ac.uk>
|
||||
L: linux-iio@vger.kernel.org
|
||||
S: Maintained
|
||||
F: drivers/iio/
|
||||
F: drivers/staging/iio/
|
||||
|
||||
IKANOS/ADI EAGLE ADSL USB DRIVER
|
||||
|
@ -3625,6 +3626,14 @@ S: Supported
|
|||
W: http://wireless.kernel.org/en/users/Drivers/iwmc3200wifi
|
||||
F: drivers/net/wireless/iwmc3200wifi/
|
||||
|
||||
INTEL MANAGEMENT ENGINE (mei)
|
||||
M: Tomas Winkler <tomas.winkler@intel.com>
|
||||
L: linux-kernel@vger.kernel.org
|
||||
S: Supported
|
||||
F: include/linux/mei.h
|
||||
F: drivers/misc/mei/*
|
||||
F: Documentation/mei/*
|
||||
|
||||
IOC3 ETHERNET DRIVER
|
||||
M: Ralf Baechle <ralf@linux-mips.org>
|
||||
L: linux-mips@linux-mips.org
|
||||
|
@ -7350,6 +7359,18 @@ S: Maintained
|
|||
F: drivers/vlynq/vlynq.c
|
||||
F: include/linux/vlynq.h
|
||||
|
||||
VME SUBSYSTEM
|
||||
M: Martyn Welch <martyn.welch@ge.com>
|
||||
M: Manohar Vanga <manohar.vanga@cern.ch>
|
||||
M: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
||||
L: devel@driverdev.osuosl.org
|
||||
S: Maintained
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core.git
|
||||
F: Documentation/vme_api.txt
|
||||
F: drivers/staging/vme/
|
||||
F: drivers/vme/
|
||||
F: include/linux/vme*
|
||||
|
||||
VMWARE VMXNET3 ETHERNET DRIVER
|
||||
M: Shreyas Bhatewara <sbhatewara@vmware.com>
|
||||
M: "VMware, Inc." <pv-drivers@vmware.com>
|
||||
|
|
|
@ -199,6 +199,43 @@
|
|||
interrupts = <25 4>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
adc0: adc@fffb0000 {
|
||||
compatible = "atmel,at91sam9260-adc";
|
||||
reg = <0xfffb0000 0x100>;
|
||||
interrupts = <20 4>;
|
||||
atmel,adc-use-external-triggers;
|
||||
atmel,adc-channels-used = <0xff>;
|
||||
atmel,adc-vref = <3300>;
|
||||
atmel,adc-num-channels = <8>;
|
||||
atmel,adc-startup-time = <40>;
|
||||
atmel,adc-channel-base = <0x30>;
|
||||
atmel,adc-drdy-mask = <0x10000>;
|
||||
atmel,adc-status-register = <0x1c>;
|
||||
atmel,adc-trigger-register = <0x08>;
|
||||
|
||||
trigger@0 {
|
||||
trigger-name = "external-rising";
|
||||
trigger-value = <0x1>;
|
||||
trigger-external;
|
||||
};
|
||||
trigger@1 {
|
||||
trigger-name = "external-falling";
|
||||
trigger-value = <0x2>;
|
||||
trigger-external;
|
||||
};
|
||||
|
||||
trigger@2 {
|
||||
trigger-name = "external-any";
|
||||
trigger-value = <0x3>;
|
||||
trigger-external;
|
||||
};
|
||||
|
||||
trigger@3 {
|
||||
trigger-name = "continuous";
|
||||
trigger-value = <0x6>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
nand0: nand@40000000 {
|
||||
|
|
|
@ -190,6 +190,44 @@
|
|||
interrupts = <27 4>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
adc0: adc@f804c000 {
|
||||
compatible = "atmel,at91sam9260-adc";
|
||||
reg = <0xf804c000 0x100>;
|
||||
interrupts = <19 4>;
|
||||
atmel,adc-use-external;
|
||||
atmel,adc-channels-used = <0xffff>;
|
||||
atmel,adc-vref = <3300>;
|
||||
atmel,adc-num-channels = <12>;
|
||||
atmel,adc-startup-time = <40>;
|
||||
atmel,adc-channel-base = <0x50>;
|
||||
atmel,adc-drdy-mask = <0x1000000>;
|
||||
atmel,adc-status-register = <0x30>;
|
||||
atmel,adc-trigger-register = <0xc0>;
|
||||
|
||||
trigger@0 {
|
||||
trigger-name = "external-rising";
|
||||
trigger-value = <0x1>;
|
||||
trigger-external;
|
||||
};
|
||||
|
||||
trigger@1 {
|
||||
trigger-name = "external-falling";
|
||||
trigger-value = <0x2>;
|
||||
trigger-external;
|
||||
};
|
||||
|
||||
trigger@2 {
|
||||
trigger-name = "external-any";
|
||||
trigger-value = <0x3>;
|
||||
trigger-external;
|
||||
};
|
||||
|
||||
trigger@3 {
|
||||
trigger-name = "continuous";
|
||||
trigger-value = <0x6>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
nand0: nand@40000000 {
|
||||
|
|
|
@ -55,6 +55,13 @@ static struct clk adc_clk = {
|
|||
.pmc_mask = 1 << AT91SAM9260_ID_ADC,
|
||||
.type = CLK_TYPE_PERIPHERAL,
|
||||
};
|
||||
|
||||
static struct clk adc_op_clk = {
|
||||
.name = "adc_op_clk",
|
||||
.type = CLK_TYPE_PERIPHERAL,
|
||||
.rate_hz = 5000000,
|
||||
};
|
||||
|
||||
static struct clk usart0_clk = {
|
||||
.name = "usart0_clk",
|
||||
.pmc_mask = 1 << AT91SAM9260_ID_US0,
|
||||
|
@ -166,6 +173,7 @@ static struct clk *periph_clocks[] __initdata = {
|
|||
&pioB_clk,
|
||||
&pioC_clk,
|
||||
&adc_clk,
|
||||
&adc_op_clk,
|
||||
&usart0_clk,
|
||||
&usart1_clk,
|
||||
&usart2_clk,
|
||||
|
|
|
@ -17,12 +17,15 @@
|
|||
#include <linux/platform_device.h>
|
||||
#include <linux/i2c-gpio.h>
|
||||
|
||||
#include <linux/platform_data/at91_adc.h>
|
||||
|
||||
#include <mach/board.h>
|
||||
#include <mach/cpu.h>
|
||||
#include <mach/at91sam9260.h>
|
||||
#include <mach/at91sam9260_matrix.h>
|
||||
#include <mach/at91_matrix.h>
|
||||
#include <mach/at91sam9_smc.h>
|
||||
#include <mach/at91_adc.h>
|
||||
|
||||
#include "generic.h"
|
||||
|
||||
|
@ -1340,6 +1343,93 @@ void __init at91_add_device_cf(struct at91_cf_data *data)
|
|||
void __init at91_add_device_cf(struct at91_cf_data * data) {}
|
||||
#endif
|
||||
|
||||
/* --------------------------------------------------------------------
|
||||
* ADCs
|
||||
* -------------------------------------------------------------------- */
|
||||
|
||||
#if IS_ENABLED(CONFIG_AT91_ADC)
|
||||
static struct at91_adc_data adc_data;
|
||||
|
||||
static struct resource adc_resources[] = {
|
||||
[0] = {
|
||||
.start = AT91SAM9260_BASE_ADC,
|
||||
.end = AT91SAM9260_BASE_ADC + SZ_16K - 1,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
[1] = {
|
||||
.start = AT91SAM9260_ID_ADC,
|
||||
.end = AT91SAM9260_ID_ADC,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
};
|
||||
|
||||
static struct platform_device at91_adc_device = {
|
||||
.name = "at91_adc",
|
||||
.id = -1,
|
||||
.dev = {
|
||||
.platform_data = &adc_data,
|
||||
},
|
||||
.resource = adc_resources,
|
||||
.num_resources = ARRAY_SIZE(adc_resources),
|
||||
};
|
||||
|
||||
static struct at91_adc_trigger at91_adc_triggers[] = {
|
||||
[0] = {
|
||||
.name = "timer-counter-0",
|
||||
.value = AT91_ADC_TRGSEL_TC0 | AT91_ADC_TRGEN,
|
||||
},
|
||||
[1] = {
|
||||
.name = "timer-counter-1",
|
||||
.value = AT91_ADC_TRGSEL_TC1 | AT91_ADC_TRGEN,
|
||||
},
|
||||
[2] = {
|
||||
.name = "timer-counter-2",
|
||||
.value = AT91_ADC_TRGSEL_TC2 | AT91_ADC_TRGEN,
|
||||
},
|
||||
[3] = {
|
||||
.name = "external",
|
||||
.value = AT91_ADC_TRGSEL_EXTERNAL | AT91_ADC_TRGEN,
|
||||
.is_external = true,
|
||||
},
|
||||
};
|
||||
|
||||
static struct at91_adc_reg_desc at91_adc_register_g20 = {
|
||||
.channel_base = AT91_ADC_CHR(0),
|
||||
.drdy_mask = AT91_ADC_DRDY,
|
||||
.status_register = AT91_ADC_SR,
|
||||
.trigger_register = AT91_ADC_MR,
|
||||
};
|
||||
|
||||
void __init at91_add_device_adc(struct at91_adc_data *data)
|
||||
{
|
||||
if (!data)
|
||||
return;
|
||||
|
||||
if (test_bit(0, &data->channels_used))
|
||||
at91_set_A_periph(AT91_PIN_PC0, 0);
|
||||
if (test_bit(1, &data->channels_used))
|
||||
at91_set_A_periph(AT91_PIN_PC1, 0);
|
||||
if (test_bit(2, &data->channels_used))
|
||||
at91_set_A_periph(AT91_PIN_PC2, 0);
|
||||
if (test_bit(3, &data->channels_used))
|
||||
at91_set_A_periph(AT91_PIN_PC3, 0);
|
||||
|
||||
if (data->use_external_triggers)
|
||||
at91_set_A_periph(AT91_PIN_PA22, 0);
|
||||
|
||||
data->num_channels = 4;
|
||||
data->startup_time = 10;
|
||||
data->registers = &at91_adc_register_g20;
|
||||
data->trigger_number = 4;
|
||||
data->trigger_list = at91_adc_triggers;
|
||||
|
||||
adc_data = *data;
|
||||
platform_device_register(&at91_adc_device);
|
||||
}
|
||||
#else
|
||||
void __init at91_add_device_adc(struct at91_adc_data *data) {}
|
||||
#endif
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/*
|
||||
* These devices are always present and don't need any board-specific
|
||||
|
|
|
@ -176,6 +176,12 @@ static struct clk vdec_clk = {
|
|||
.type = CLK_TYPE_PERIPHERAL,
|
||||
};
|
||||
|
||||
static struct clk adc_op_clk = {
|
||||
.name = "adc_op_clk",
|
||||
.type = CLK_TYPE_PERIPHERAL,
|
||||
.rate_hz = 13200000,
|
||||
};
|
||||
|
||||
static struct clk *periph_clocks[] __initdata = {
|
||||
&pioA_clk,
|
||||
&pioB_clk,
|
||||
|
@ -204,6 +210,7 @@ static struct clk *periph_clocks[] __initdata = {
|
|||
&isi_clk,
|
||||
&udphs_clk,
|
||||
&mmc1_clk,
|
||||
&adc_op_clk,
|
||||
// irq0
|
||||
};
|
||||
|
||||
|
@ -242,6 +249,8 @@ static struct clk_lookup periph_clocks_lookups[] = {
|
|||
CLKDEV_CON_ID("pioC", &pioC_clk),
|
||||
CLKDEV_CON_ID("pioD", &pioDE_clk),
|
||||
CLKDEV_CON_ID("pioE", &pioDE_clk),
|
||||
/* Fake adc clock */
|
||||
CLKDEV_CON_ID("adc_clk", &tsc_clk),
|
||||
};
|
||||
|
||||
static struct clk_lookup usart_clocks_lookups[] = {
|
||||
|
|
|
@ -19,9 +19,12 @@
|
|||
#include <linux/i2c-gpio.h>
|
||||
#include <linux/atmel-mci.h>
|
||||
|
||||
#include <linux/platform_data/at91_adc.h>
|
||||
|
||||
#include <linux/fb.h>
|
||||
#include <video/atmel_lcdc.h>
|
||||
|
||||
#include <mach/at91_adc.h>
|
||||
#include <mach/board.h>
|
||||
#include <mach/at91sam9g45.h>
|
||||
#include <mach/at91sam9g45_matrix.h>
|
||||
|
@ -1181,6 +1184,104 @@ void __init at91_add_device_tsadcc(struct at91_tsadcc_data *data) {}
|
|||
#endif
|
||||
|
||||
|
||||
/* --------------------------------------------------------------------
|
||||
* ADC
|
||||
* -------------------------------------------------------------------- */
|
||||
|
||||
#if IS_ENABLED(CONFIG_AT91_ADC)
|
||||
static struct at91_adc_data adc_data;
|
||||
|
||||
static struct resource adc_resources[] = {
|
||||
[0] = {
|
||||
.start = AT91SAM9G45_BASE_TSC,
|
||||
.end = AT91SAM9G45_BASE_TSC + SZ_16K - 1,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
[1] = {
|
||||
.start = AT91SAM9G45_ID_TSC,
|
||||
.end = AT91SAM9G45_ID_TSC,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
}
|
||||
};
|
||||
|
||||
static struct platform_device at91_adc_device = {
|
||||
.name = "at91_adc",
|
||||
.id = -1,
|
||||
.dev = {
|
||||
.platform_data = &adc_data,
|
||||
},
|
||||
.resource = adc_resources,
|
||||
.num_resources = ARRAY_SIZE(adc_resources),
|
||||
};
|
||||
|
||||
static struct at91_adc_trigger at91_adc_triggers[] = {
|
||||
[0] = {
|
||||
.name = "external-rising",
|
||||
.value = 1,
|
||||
.is_external = true,
|
||||
},
|
||||
[1] = {
|
||||
.name = "external-falling",
|
||||
.value = 2,
|
||||
.is_external = true,
|
||||
},
|
||||
[2] = {
|
||||
.name = "external-any",
|
||||
.value = 3,
|
||||
.is_external = true,
|
||||
},
|
||||
[3] = {
|
||||
.name = "continuous",
|
||||
.value = 6,
|
||||
.is_external = false,
|
||||
},
|
||||
};
|
||||
|
||||
static struct at91_adc_reg_desc at91_adc_register_g45 = {
|
||||
.channel_base = AT91_ADC_CHR(0),
|
||||
.drdy_mask = AT91_ADC_DRDY,
|
||||
.status_register = AT91_ADC_SR,
|
||||
.trigger_register = 0x08,
|
||||
};
|
||||
|
||||
void __init at91_add_device_adc(struct at91_adc_data *data)
|
||||
{
|
||||
if (!data)
|
||||
return;
|
||||
|
||||
if (test_bit(0, &data->channels_used))
|
||||
at91_set_gpio_input(AT91_PIN_PD20, 0);
|
||||
if (test_bit(1, &data->channels_used))
|
||||
at91_set_gpio_input(AT91_PIN_PD21, 0);
|
||||
if (test_bit(2, &data->channels_used))
|
||||
at91_set_gpio_input(AT91_PIN_PD22, 0);
|
||||
if (test_bit(3, &data->channels_used))
|
||||
at91_set_gpio_input(AT91_PIN_PD23, 0);
|
||||
if (test_bit(4, &data->channels_used))
|
||||
at91_set_gpio_input(AT91_PIN_PD24, 0);
|
||||
if (test_bit(5, &data->channels_used))
|
||||
at91_set_gpio_input(AT91_PIN_PD25, 0);
|
||||
if (test_bit(6, &data->channels_used))
|
||||
at91_set_gpio_input(AT91_PIN_PD26, 0);
|
||||
if (test_bit(7, &data->channels_used))
|
||||
at91_set_gpio_input(AT91_PIN_PD27, 0);
|
||||
|
||||
if (data->use_external_triggers)
|
||||
at91_set_A_periph(AT91_PIN_PD28, 0);
|
||||
|
||||
data->num_channels = 8;
|
||||
data->startup_time = 40;
|
||||
data->registers = &at91_adc_register_g45;
|
||||
data->trigger_number = 4;
|
||||
data->trigger_list = at91_adc_triggers;
|
||||
|
||||
adc_data = *data;
|
||||
platform_device_register(&at91_adc_device);
|
||||
}
|
||||
#else
|
||||
void __init at91_add_device_adc(struct at91_adc_data *data) {}
|
||||
#endif
|
||||
|
||||
/* --------------------------------------------------------------------
|
||||
* RTT
|
||||
* -------------------------------------------------------------------- */
|
||||
|
|
|
@ -120,6 +120,11 @@ static struct clk adc_clk = {
|
|||
.pmc_mask = 1 << AT91SAM9X5_ID_ADC,
|
||||
.type = CLK_TYPE_PERIPHERAL,
|
||||
};
|
||||
static struct clk adc_op_clk = {
|
||||
.name = "adc_op_clk",
|
||||
.type = CLK_TYPE_PERIPHERAL,
|
||||
.rate_hz = 5000000,
|
||||
};
|
||||
static struct clk dma0_clk = {
|
||||
.name = "dma0_clk",
|
||||
.pmc_mask = 1 << AT91SAM9X5_ID_DMA0,
|
||||
|
@ -205,6 +210,7 @@ static struct clk *periph_clocks[] __initdata = {
|
|||
&tcb0_clk,
|
||||
&pwm_clk,
|
||||
&adc_clk,
|
||||
&adc_op_clk,
|
||||
&dma0_clk,
|
||||
&dma1_clk,
|
||||
&uhphs_clk,
|
||||
|
|
|
@ -32,6 +32,8 @@
|
|||
#include <linux/regulator/fixed.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
|
||||
#include <linux/platform_data/at91_adc.h>
|
||||
|
||||
#include <mach/hardware.h>
|
||||
#include <asm/setup.h>
|
||||
#include <asm/mach-types.h>
|
||||
|
@ -304,6 +306,16 @@ static void __init ek_add_device_buttons(void)
|
|||
static void __init ek_add_device_buttons(void) {}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* ADCs
|
||||
*/
|
||||
|
||||
static struct at91_adc_data ek_adc_data = {
|
||||
.channels_used = BIT(0) | BIT(1) | BIT(2) | BIT(3),
|
||||
.use_external_triggers = true,
|
||||
.vref = 3300,
|
||||
};
|
||||
|
||||
#if defined(CONFIG_REGULATOR_FIXED_VOLTAGE) || defined(CONFIG_REGULATOR_FIXED_VOLTAGE_MODULE)
|
||||
static struct regulator_consumer_supply ek_audio_consumer_supplies[] = {
|
||||
REGULATOR_SUPPLY("AVDD", "0-001b"),
|
||||
|
@ -389,6 +401,8 @@ static void __init ek_board_init(void)
|
|||
ek_add_device_gpio_leds();
|
||||
/* Push Buttons */
|
||||
ek_add_device_buttons();
|
||||
/* ADCs */
|
||||
at91_add_device_adc(&ek_adc_data);
|
||||
/* PCK0 provides MCLK to the WM8731 */
|
||||
at91_set_B_periph(AT91_PIN_PC1, 0);
|
||||
/* SSC (for WM8731) */
|
||||
|
|
|
@ -27,6 +27,8 @@
|
|||
#include <linux/atmel-mci.h>
|
||||
#include <linux/delay.h>
|
||||
|
||||
#include <linux/platform_data/at91_adc.h>
|
||||
|
||||
#include <mach/hardware.h>
|
||||
#include <video/atmel_lcdc.h>
|
||||
#include <media/soc_camera.h>
|
||||
|
@ -305,6 +307,14 @@ static struct at91_tsadcc_data ek_tsadcc_data = {
|
|||
.ts_sample_hold_time = 0x0a,
|
||||
};
|
||||
|
||||
/*
|
||||
* ADCs
|
||||
*/
|
||||
static struct at91_adc_data ek_adc_data = {
|
||||
.channels_used = BIT(0) | BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(5) | BIT(6) | BIT(7),
|
||||
.use_external_triggers = true,
|
||||
.vref = 3300,
|
||||
};
|
||||
|
||||
/*
|
||||
* GPIO Buttons
|
||||
|
@ -476,6 +486,8 @@ static void __init ek_board_init(void)
|
|||
at91_add_device_lcdc(&ek_lcdc_data);
|
||||
/* Touch Screen */
|
||||
at91_add_device_tsadcc(&ek_tsadcc_data);
|
||||
/* ADC */
|
||||
at91_add_device_adc(&ek_adc_data);
|
||||
/* Push Buttons */
|
||||
ek_add_device_buttons();
|
||||
/* AC97 */
|
||||
|
|
|
@ -144,4 +144,8 @@ source "drivers/extcon/Kconfig"
|
|||
|
||||
source "drivers/memory/Kconfig"
|
||||
|
||||
source "drivers/iio/Kconfig"
|
||||
|
||||
source "drivers/vme/Kconfig"
|
||||
|
||||
endmenu
|
||||
|
|
|
@ -136,3 +136,5 @@ obj-$(CONFIG_HYPERV) += hv/
|
|||
obj-$(CONFIG_PM_DEVFREQ) += devfreq/
|
||||
obj-$(CONFIG_EXTCON) += extcon/
|
||||
obj-$(CONFIG_MEMORY) += memory/
|
||||
obj-$(CONFIG_IIO) += iio/
|
||||
obj-$(CONFIG_VME_BUS) += vme/
|
||||
|
|
|
@ -585,14 +585,6 @@ config DEVPORT
|
|||
|
||||
source "drivers/s390/char/Kconfig"
|
||||
|
||||
config RAMOOPS
|
||||
tristate "Log panic/oops to a RAM buffer"
|
||||
depends on HAS_IOMEM
|
||||
default n
|
||||
help
|
||||
This enables panic and oops messages to be logged to a circular
|
||||
buffer in RAM where it can be read back at some later point.
|
||||
|
||||
config MSM_SMD_PKT
|
||||
bool "Enable device interface for some SMD packet ports"
|
||||
default n
|
||||
|
|
|
@ -58,7 +58,6 @@ obj-$(CONFIG_HANGCHECK_TIMER) += hangcheck-timer.o
|
|||
obj-$(CONFIG_TCG_TPM) += tpm/
|
||||
|
||||
obj-$(CONFIG_PS3_FLASH) += ps3flash.o
|
||||
obj-$(CONFIG_RAMOOPS) += ramoops.o
|
||||
|
||||
obj-$(CONFIG_JS_RTC) += js-rtc.o
|
||||
js-rtc-y = rtc.o
|
||||
|
|
|
@ -1,250 +0,0 @@
|
|||
/*
|
||||
* RAM Oops/Panic logger
|
||||
*
|
||||
* Copyright (C) 2010 Marco Stornelli <marco.stornelli@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* version 2 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 St, Fifth Floor, Boston, MA
|
||||
* 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/kmsg_dump.h>
|
||||
#include <linux/time.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/ramoops.h>
|
||||
|
||||
#define RAMOOPS_KERNMSG_HDR "===="
|
||||
#define MIN_MEM_SIZE 4096UL
|
||||
|
||||
static ulong record_size = MIN_MEM_SIZE;
|
||||
module_param(record_size, ulong, 0400);
|
||||
MODULE_PARM_DESC(record_size,
|
||||
"size of each dump done on oops/panic");
|
||||
|
||||
static ulong mem_address;
|
||||
module_param(mem_address, ulong, 0400);
|
||||
MODULE_PARM_DESC(mem_address,
|
||||
"start of reserved RAM used to store oops/panic logs");
|
||||
|
||||
static ulong mem_size;
|
||||
module_param(mem_size, ulong, 0400);
|
||||
MODULE_PARM_DESC(mem_size,
|
||||
"size of reserved RAM used to store oops/panic logs");
|
||||
|
||||
static int dump_oops = 1;
|
||||
module_param(dump_oops, int, 0600);
|
||||
MODULE_PARM_DESC(dump_oops,
|
||||
"set to 1 to dump oopses, 0 to only dump panics (default 1)");
|
||||
|
||||
static struct ramoops_context {
|
||||
struct kmsg_dumper dump;
|
||||
void *virt_addr;
|
||||
phys_addr_t phys_addr;
|
||||
unsigned long size;
|
||||
unsigned long record_size;
|
||||
int dump_oops;
|
||||
int count;
|
||||
int max_count;
|
||||
} oops_cxt;
|
||||
|
||||
static struct platform_device *dummy;
|
||||
static struct ramoops_platform_data *dummy_data;
|
||||
|
||||
static void ramoops_do_dump(struct kmsg_dumper *dumper,
|
||||
enum kmsg_dump_reason reason, const char *s1, unsigned long l1,
|
||||
const char *s2, unsigned long l2)
|
||||
{
|
||||
struct ramoops_context *cxt = container_of(dumper,
|
||||
struct ramoops_context, dump);
|
||||
unsigned long s1_start, s2_start;
|
||||
unsigned long l1_cpy, l2_cpy;
|
||||
int res, hdr_size;
|
||||
char *buf, *buf_orig;
|
||||
struct timeval timestamp;
|
||||
|
||||
if (reason != KMSG_DUMP_OOPS &&
|
||||
reason != KMSG_DUMP_PANIC)
|
||||
return;
|
||||
|
||||
/* Only dump oopses if dump_oops is set */
|
||||
if (reason == KMSG_DUMP_OOPS && !cxt->dump_oops)
|
||||
return;
|
||||
|
||||
buf = cxt->virt_addr + (cxt->count * cxt->record_size);
|
||||
buf_orig = buf;
|
||||
|
||||
memset(buf, '\0', cxt->record_size);
|
||||
res = sprintf(buf, "%s", RAMOOPS_KERNMSG_HDR);
|
||||
buf += res;
|
||||
do_gettimeofday(×tamp);
|
||||
res = sprintf(buf, "%lu.%lu\n", (long)timestamp.tv_sec, (long)timestamp.tv_usec);
|
||||
buf += res;
|
||||
|
||||
hdr_size = buf - buf_orig;
|
||||
l2_cpy = min(l2, cxt->record_size - hdr_size);
|
||||
l1_cpy = min(l1, cxt->record_size - hdr_size - l2_cpy);
|
||||
|
||||
s2_start = l2 - l2_cpy;
|
||||
s1_start = l1 - l1_cpy;
|
||||
|
||||
memcpy(buf, s1 + s1_start, l1_cpy);
|
||||
memcpy(buf + l1_cpy, s2 + s2_start, l2_cpy);
|
||||
|
||||
cxt->count = (cxt->count + 1) % cxt->max_count;
|
||||
}
|
||||
|
||||
static int __init ramoops_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct ramoops_platform_data *pdata = pdev->dev.platform_data;
|
||||
struct ramoops_context *cxt = &oops_cxt;
|
||||
int err = -EINVAL;
|
||||
|
||||
if (!pdata->mem_size || !pdata->record_size) {
|
||||
pr_err("The memory size and the record size must be "
|
||||
"non-zero\n");
|
||||
goto fail3;
|
||||
}
|
||||
|
||||
pdata->mem_size = rounddown_pow_of_two(pdata->mem_size);
|
||||
pdata->record_size = rounddown_pow_of_two(pdata->record_size);
|
||||
|
||||
/* Check for the minimum memory size */
|
||||
if (pdata->mem_size < MIN_MEM_SIZE &&
|
||||
pdata->record_size < MIN_MEM_SIZE) {
|
||||
pr_err("memory size too small, minium is %lu\n", MIN_MEM_SIZE);
|
||||
goto fail3;
|
||||
}
|
||||
|
||||
if (pdata->mem_size < pdata->record_size) {
|
||||
pr_err("The memory size must be larger than the "
|
||||
"records size\n");
|
||||
goto fail3;
|
||||
}
|
||||
|
||||
cxt->max_count = pdata->mem_size / pdata->record_size;
|
||||
cxt->count = 0;
|
||||
cxt->size = pdata->mem_size;
|
||||
cxt->phys_addr = pdata->mem_address;
|
||||
cxt->record_size = pdata->record_size;
|
||||
cxt->dump_oops = pdata->dump_oops;
|
||||
|
||||
if (!request_mem_region(cxt->phys_addr, cxt->size, "ramoops")) {
|
||||
pr_err("request mem region failed\n");
|
||||
err = -EINVAL;
|
||||
goto fail3;
|
||||
}
|
||||
|
||||
cxt->virt_addr = ioremap(cxt->phys_addr, cxt->size);
|
||||
if (!cxt->virt_addr) {
|
||||
pr_err("ioremap failed\n");
|
||||
goto fail2;
|
||||
}
|
||||
|
||||
cxt->dump.dump = ramoops_do_dump;
|
||||
err = kmsg_dump_register(&cxt->dump);
|
||||
if (err) {
|
||||
pr_err("registering kmsg dumper failed\n");
|
||||
goto fail1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Update the module parameter variables as well so they are visible
|
||||
* through /sys/module/ramoops/parameters/
|
||||
*/
|
||||
mem_size = pdata->mem_size;
|
||||
mem_address = pdata->mem_address;
|
||||
record_size = pdata->record_size;
|
||||
dump_oops = pdata->dump_oops;
|
||||
|
||||
return 0;
|
||||
|
||||
fail1:
|
||||
iounmap(cxt->virt_addr);
|
||||
fail2:
|
||||
release_mem_region(cxt->phys_addr, cxt->size);
|
||||
fail3:
|
||||
return err;
|
||||
}
|
||||
|
||||
static int __exit ramoops_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct ramoops_context *cxt = &oops_cxt;
|
||||
|
||||
if (kmsg_dump_unregister(&cxt->dump) < 0)
|
||||
pr_warn("could not unregister kmsg_dumper\n");
|
||||
|
||||
iounmap(cxt->virt_addr);
|
||||
release_mem_region(cxt->phys_addr, cxt->size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver ramoops_driver = {
|
||||
.remove = __exit_p(ramoops_remove),
|
||||
.driver = {
|
||||
.name = "ramoops",
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
};
|
||||
|
||||
static int __init ramoops_init(void)
|
||||
{
|
||||
int ret;
|
||||
ret = platform_driver_probe(&ramoops_driver, ramoops_probe);
|
||||
if (ret == -ENODEV) {
|
||||
/*
|
||||
* If we didn't find a platform device, we use module parameters
|
||||
* building platform data on the fly.
|
||||
*/
|
||||
pr_info("platform device not found, using module parameters\n");
|
||||
dummy_data = kzalloc(sizeof(struct ramoops_platform_data),
|
||||
GFP_KERNEL);
|
||||
if (!dummy_data)
|
||||
return -ENOMEM;
|
||||
dummy_data->mem_size = mem_size;
|
||||
dummy_data->mem_address = mem_address;
|
||||
dummy_data->record_size = record_size;
|
||||
dummy_data->dump_oops = dump_oops;
|
||||
dummy = platform_create_bundle(&ramoops_driver, ramoops_probe,
|
||||
NULL, 0, dummy_data,
|
||||
sizeof(struct ramoops_platform_data));
|
||||
|
||||
if (IS_ERR(dummy))
|
||||
ret = PTR_ERR(dummy);
|
||||
else
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void __exit ramoops_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&ramoops_driver);
|
||||
kfree(dummy_data);
|
||||
}
|
||||
|
||||
module_init(ramoops_init);
|
||||
module_exit(ramoops_exit);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Marco Stornelli <marco.stornelli@gmail.com>");
|
||||
MODULE_DESCRIPTION("RAM Oops/Panic logger/driver");
|
|
@ -0,0 +1,54 @@
|
|||
#
|
||||
# Industrial I/O subsytem configuration
|
||||
#
|
||||
|
||||
menuconfig IIO
|
||||
tristate "Industrial I/O support"
|
||||
depends on GENERIC_HARDIRQS
|
||||
help
|
||||
The industrial I/O subsystem provides a unified framework for
|
||||
drivers for many different types of embedded sensors using a
|
||||
number of different physical interfaces (i2c, spi, etc). See
|
||||
Documentation/iio for more information.
|
||||
|
||||
if IIO
|
||||
|
||||
config IIO_BUFFER
|
||||
bool "Enable buffer support within IIO"
|
||||
help
|
||||
Provide core support for various buffer based data
|
||||
acquisition methods.
|
||||
|
||||
if IIO_BUFFER
|
||||
|
||||
config IIO_KFIFO_BUF
|
||||
select IIO_TRIGGER
|
||||
tristate "Industrial I/O buffering based on kfifo"
|
||||
help
|
||||
A simple fifo based on kfifo. Use this if you want a fifo
|
||||
rather than a ring buffer. Note that this currently provides
|
||||
no buffer events so it is up to userspace to work out how
|
||||
often to read from the buffer.
|
||||
|
||||
endif # IIO_BUFFER
|
||||
|
||||
config IIO_TRIGGER
|
||||
boolean "Enable triggered sampling support"
|
||||
help
|
||||
Provides IIO core support for triggers. Currently these
|
||||
are used to initialize capture of samples to push into
|
||||
ring buffers. The triggers are effectively a 'capture
|
||||
data now' interrupt.
|
||||
|
||||
config IIO_CONSUMERS_PER_TRIGGER
|
||||
int "Maximum number of consumers per trigger"
|
||||
depends on IIO_TRIGGER
|
||||
default "2"
|
||||
help
|
||||
This value controls the maximum number of consumers that a
|
||||
given trigger may handle. Default is 2.
|
||||
|
||||
source "drivers/iio/adc/Kconfig"
|
||||
source "drivers/iio/amplifiers/Kconfig"
|
||||
|
||||
endif # IIO
|
|
@ -0,0 +1,13 @@
|
|||
#
|
||||
# Makefile for the industrial I/O core.
|
||||
#
|
||||
|
||||
obj-$(CONFIG_IIO) += industrialio.o
|
||||
industrialio-y := industrialio-core.o industrialio-event.o inkern.o
|
||||
industrialio-$(CONFIG_IIO_BUFFER) += industrialio-buffer.o
|
||||
industrialio-$(CONFIG_IIO_TRIGGER) += industrialio-trigger.o
|
||||
|
||||
obj-$(CONFIG_IIO_KFIFO_BUF) += kfifo_buf.o
|
||||
|
||||
obj-y += adc/
|
||||
obj-y += amplifiers/
|
|
@ -0,0 +1,16 @@
|
|||
#
|
||||
# ADC drivers
|
||||
#
|
||||
menu "Analog to digital converters"
|
||||
|
||||
config AT91_ADC
|
||||
tristate "Atmel AT91 ADC"
|
||||
depends on ARCH_AT91
|
||||
select IIO_BUFFER
|
||||
select IIO_KFIFO_BUF
|
||||
select IIO_TRIGGER
|
||||
select SYSFS
|
||||
help
|
||||
Say yes here to build support for Atmel AT91 ADC.
|
||||
|
||||
endmenu
|
|
@ -0,0 +1,5 @@
|
|||
#
|
||||
# Makefile for IIO ADC drivers
|
||||
#
|
||||
|
||||
obj-$(CONFIG_AT91_ADC) += at91_adc.o
|
|
@ -0,0 +1,802 @@
|
|||
/*
|
||||
* Driver for the ADC present in the Atmel AT91 evaluation boards.
|
||||
*
|
||||
* Copyright 2011 Free Electrons
|
||||
*
|
||||
* Licensed under the GPLv2 or later.
|
||||
*/
|
||||
|
||||
#include <linux/bitmap.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/wait.h>
|
||||
|
||||
#include <linux/platform_data/at91_adc.h>
|
||||
|
||||
#include <linux/iio/iio.h>
|
||||
#include <linux/iio/buffer.h>
|
||||
#include <linux/iio/kfifo_buf.h>
|
||||
#include <linux/iio/trigger.h>
|
||||
#include <linux/iio/trigger_consumer.h>
|
||||
|
||||
#include <mach/at91_adc.h>
|
||||
|
||||
#define AT91_ADC_CHAN(st, ch) \
|
||||
(st->registers->channel_base + (ch * 4))
|
||||
#define at91_adc_readl(st, reg) \
|
||||
(readl_relaxed(st->reg_base + reg))
|
||||
#define at91_adc_writel(st, reg, val) \
|
||||
(writel_relaxed(val, st->reg_base + reg))
|
||||
|
||||
struct at91_adc_state {
|
||||
struct clk *adc_clk;
|
||||
u16 *buffer;
|
||||
unsigned long channels_mask;
|
||||
struct clk *clk;
|
||||
bool done;
|
||||
int irq;
|
||||
bool irq_enabled;
|
||||
u16 last_value;
|
||||
struct mutex lock;
|
||||
u8 num_channels;
|
||||
void __iomem *reg_base;
|
||||
struct at91_adc_reg_desc *registers;
|
||||
u8 startup_time;
|
||||
struct iio_trigger **trig;
|
||||
struct at91_adc_trigger *trigger_list;
|
||||
u32 trigger_number;
|
||||
bool use_external;
|
||||
u32 vref_mv;
|
||||
wait_queue_head_t wq_data_avail;
|
||||
};
|
||||
|
||||
static irqreturn_t at91_adc_trigger_handler(int irq, void *p)
|
||||
{
|
||||
struct iio_poll_func *pf = p;
|
||||
struct iio_dev *idev = pf->indio_dev;
|
||||
struct at91_adc_state *st = iio_priv(idev);
|
||||
struct iio_buffer *buffer = idev->buffer;
|
||||
int i, j = 0;
|
||||
|
||||
for (i = 0; i < idev->masklength; i++) {
|
||||
if (!test_bit(i, idev->active_scan_mask))
|
||||
continue;
|
||||
st->buffer[j] = at91_adc_readl(st, AT91_ADC_CHAN(st, i));
|
||||
j++;
|
||||
}
|
||||
|
||||
if (idev->scan_timestamp) {
|
||||
s64 *timestamp = (s64 *)((u8 *)st->buffer +
|
||||
ALIGN(j, sizeof(s64)));
|
||||
*timestamp = pf->timestamp;
|
||||
}
|
||||
|
||||
buffer->access->store_to(buffer, (u8 *)st->buffer, pf->timestamp);
|
||||
|
||||
iio_trigger_notify_done(idev->trig);
|
||||
st->irq_enabled = true;
|
||||
|
||||
/* Needed to ACK the DRDY interruption */
|
||||
at91_adc_readl(st, AT91_ADC_LCDR);
|
||||
|
||||
enable_irq(st->irq);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static irqreturn_t at91_adc_eoc_trigger(int irq, void *private)
|
||||
{
|
||||
struct iio_dev *idev = private;
|
||||
struct at91_adc_state *st = iio_priv(idev);
|
||||
u32 status = at91_adc_readl(st, st->registers->status_register);
|
||||
|
||||
if (!(status & st->registers->drdy_mask))
|
||||
return IRQ_HANDLED;
|
||||
|
||||
if (iio_buffer_enabled(idev)) {
|
||||
disable_irq_nosync(irq);
|
||||
st->irq_enabled = false;
|
||||
iio_trigger_poll(idev->trig, iio_get_time_ns());
|
||||
} else {
|
||||
st->last_value = at91_adc_readl(st, AT91_ADC_LCDR);
|
||||
st->done = true;
|
||||
wake_up_interruptible(&st->wq_data_avail);
|
||||
}
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static int at91_adc_channel_init(struct iio_dev *idev)
|
||||
{
|
||||
struct at91_adc_state *st = iio_priv(idev);
|
||||
struct iio_chan_spec *chan_array, *timestamp;
|
||||
int bit, idx = 0;
|
||||
|
||||
idev->num_channels = bitmap_weight(&st->channels_mask,
|
||||
st->num_channels) + 1;
|
||||
|
||||
chan_array = devm_kzalloc(&idev->dev,
|
||||
((idev->num_channels + 1) *
|
||||
sizeof(struct iio_chan_spec)),
|
||||
GFP_KERNEL);
|
||||
|
||||
if (!chan_array)
|
||||
return -ENOMEM;
|
||||
|
||||
for_each_set_bit(bit, &st->channels_mask, st->num_channels) {
|
||||
struct iio_chan_spec *chan = chan_array + idx;
|
||||
|
||||
chan->type = IIO_VOLTAGE;
|
||||
chan->indexed = 1;
|
||||
chan->channel = bit;
|
||||
chan->scan_index = idx;
|
||||
chan->scan_type.sign = 'u';
|
||||
chan->scan_type.realbits = 10;
|
||||
chan->scan_type.storagebits = 16;
|
||||
chan->info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT |
|
||||
IIO_CHAN_INFO_RAW_SEPARATE_BIT;
|
||||
idx++;
|
||||
}
|
||||
timestamp = chan_array + idx;
|
||||
|
||||
timestamp->type = IIO_TIMESTAMP;
|
||||
timestamp->channel = -1;
|
||||
timestamp->scan_index = idx;
|
||||
timestamp->scan_type.sign = 's';
|
||||
timestamp->scan_type.realbits = 64;
|
||||
timestamp->scan_type.storagebits = 64;
|
||||
|
||||
idev->channels = chan_array;
|
||||
return idev->num_channels;
|
||||
}
|
||||
|
||||
static u8 at91_adc_get_trigger_value_by_name(struct iio_dev *idev,
|
||||
struct at91_adc_trigger *triggers,
|
||||
const char *trigger_name)
|
||||
{
|
||||
struct at91_adc_state *st = iio_priv(idev);
|
||||
u8 value = 0;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < st->trigger_number; i++) {
|
||||
char *name = kasprintf(GFP_KERNEL,
|
||||
"%s-dev%d-%s",
|
||||
idev->name,
|
||||
idev->id,
|
||||
triggers[i].name);
|
||||
if (!name)
|
||||
return -ENOMEM;
|
||||
|
||||
if (strcmp(trigger_name, name) == 0) {
|
||||
value = triggers[i].value;
|
||||
kfree(name);
|
||||
break;
|
||||
}
|
||||
|
||||
kfree(name);
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
static int at91_adc_configure_trigger(struct iio_trigger *trig, bool state)
|
||||
{
|
||||
struct iio_dev *idev = trig->private_data;
|
||||
struct at91_adc_state *st = iio_priv(idev);
|
||||
struct iio_buffer *buffer = idev->buffer;
|
||||
struct at91_adc_reg_desc *reg = st->registers;
|
||||
u32 status = at91_adc_readl(st, reg->trigger_register);
|
||||
u8 value;
|
||||
u8 bit;
|
||||
|
||||
value = at91_adc_get_trigger_value_by_name(idev,
|
||||
st->trigger_list,
|
||||
idev->trig->name);
|
||||
if (value == 0)
|
||||
return -EINVAL;
|
||||
|
||||
if (state) {
|
||||
st->buffer = kmalloc(idev->scan_bytes, GFP_KERNEL);
|
||||
if (st->buffer == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
at91_adc_writel(st, reg->trigger_register,
|
||||
status | value);
|
||||
|
||||
for_each_set_bit(bit, buffer->scan_mask,
|
||||
st->num_channels) {
|
||||
struct iio_chan_spec const *chan = idev->channels + bit;
|
||||
at91_adc_writel(st, AT91_ADC_CHER,
|
||||
AT91_ADC_CH(chan->channel));
|
||||
}
|
||||
|
||||
at91_adc_writel(st, AT91_ADC_IER, reg->drdy_mask);
|
||||
|
||||
} else {
|
||||
at91_adc_writel(st, AT91_ADC_IDR, reg->drdy_mask);
|
||||
|
||||
at91_adc_writel(st, reg->trigger_register,
|
||||
status & ~value);
|
||||
|
||||
for_each_set_bit(bit, buffer->scan_mask,
|
||||
st->num_channels) {
|
||||
struct iio_chan_spec const *chan = idev->channels + bit;
|
||||
at91_adc_writel(st, AT91_ADC_CHDR,
|
||||
AT91_ADC_CH(chan->channel));
|
||||
}
|
||||
kfree(st->buffer);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct iio_trigger_ops at91_adc_trigger_ops = {
|
||||
.owner = THIS_MODULE,
|
||||
.set_trigger_state = &at91_adc_configure_trigger,
|
||||
};
|
||||
|
||||
static struct iio_trigger *at91_adc_allocate_trigger(struct iio_dev *idev,
|
||||
struct at91_adc_trigger *trigger)
|
||||
{
|
||||
struct iio_trigger *trig;
|
||||
int ret;
|
||||
|
||||
trig = iio_trigger_alloc("%s-dev%d-%s", idev->name,
|
||||
idev->id, trigger->name);
|
||||
if (trig == NULL)
|
||||
return NULL;
|
||||
|
||||
trig->dev.parent = idev->dev.parent;
|
||||
trig->private_data = idev;
|
||||
trig->ops = &at91_adc_trigger_ops;
|
||||
|
||||
ret = iio_trigger_register(trig);
|
||||
if (ret)
|
||||
return NULL;
|
||||
|
||||
return trig;
|
||||
}
|
||||
|
||||
static int at91_adc_trigger_init(struct iio_dev *idev)
|
||||
{
|
||||
struct at91_adc_state *st = iio_priv(idev);
|
||||
int i, ret;
|
||||
|
||||
st->trig = devm_kzalloc(&idev->dev,
|
||||
st->trigger_number * sizeof(st->trig),
|
||||
GFP_KERNEL);
|
||||
|
||||
if (st->trig == NULL) {
|
||||
ret = -ENOMEM;
|
||||
goto error_ret;
|
||||
}
|
||||
|
||||
for (i = 0; i < st->trigger_number; i++) {
|
||||
if (st->trigger_list[i].is_external && !(st->use_external))
|
||||
continue;
|
||||
|
||||
st->trig[i] = at91_adc_allocate_trigger(idev,
|
||||
st->trigger_list + i);
|
||||
if (st->trig[i] == NULL) {
|
||||
dev_err(&idev->dev,
|
||||
"Could not allocate trigger %d\n", i);
|
||||
ret = -ENOMEM;
|
||||
goto error_trigger;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
error_trigger:
|
||||
for (i--; i >= 0; i--) {
|
||||
iio_trigger_unregister(st->trig[i]);
|
||||
iio_trigger_free(st->trig[i]);
|
||||
}
|
||||
error_ret:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void at91_adc_trigger_remove(struct iio_dev *idev)
|
||||
{
|
||||
struct at91_adc_state *st = iio_priv(idev);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < st->trigger_number; i++) {
|
||||
iio_trigger_unregister(st->trig[i]);
|
||||
iio_trigger_free(st->trig[i]);
|
||||
}
|
||||
}
|
||||
|
||||
static const struct iio_buffer_setup_ops at91_adc_buffer_ops = {
|
||||
.preenable = &iio_sw_buffer_preenable,
|
||||
.postenable = &iio_triggered_buffer_postenable,
|
||||
.predisable = &iio_triggered_buffer_predisable,
|
||||
};
|
||||
|
||||
static int at91_adc_buffer_init(struct iio_dev *idev)
|
||||
{
|
||||
int ret;
|
||||
|
||||
idev->buffer = iio_kfifo_allocate(idev);
|
||||
if (!idev->buffer) {
|
||||
ret = -ENOMEM;
|
||||
goto error_ret;
|
||||
}
|
||||
|
||||
idev->pollfunc = iio_alloc_pollfunc(&iio_pollfunc_store_time,
|
||||
&at91_adc_trigger_handler,
|
||||
IRQF_ONESHOT,
|
||||
idev,
|
||||
"%s-consumer%d",
|
||||
idev->name,
|
||||
idev->id);
|
||||
if (idev->pollfunc == NULL) {
|
||||
ret = -ENOMEM;
|
||||
goto error_pollfunc;
|
||||
}
|
||||
|
||||
idev->setup_ops = &at91_adc_buffer_ops;
|
||||
idev->modes |= INDIO_BUFFER_TRIGGERED;
|
||||
|
||||
ret = iio_buffer_register(idev,
|
||||
idev->channels,
|
||||
idev->num_channels);
|
||||
if (ret)
|
||||
goto error_register;
|
||||
|
||||
return 0;
|
||||
|
||||
error_register:
|
||||
iio_dealloc_pollfunc(idev->pollfunc);
|
||||
error_pollfunc:
|
||||
iio_kfifo_free(idev->buffer);
|
||||
error_ret:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void at91_adc_buffer_remove(struct iio_dev *idev)
|
||||
{
|
||||
iio_buffer_unregister(idev);
|
||||
iio_dealloc_pollfunc(idev->pollfunc);
|
||||
iio_kfifo_free(idev->buffer);
|
||||
}
|
||||
|
||||
static int at91_adc_read_raw(struct iio_dev *idev,
|
||||
struct iio_chan_spec const *chan,
|
||||
int *val, int *val2, long mask)
|
||||
{
|
||||
struct at91_adc_state *st = iio_priv(idev);
|
||||
int ret;
|
||||
|
||||
switch (mask) {
|
||||
case IIO_CHAN_INFO_RAW:
|
||||
mutex_lock(&st->lock);
|
||||
|
||||
at91_adc_writel(st, AT91_ADC_CHER,
|
||||
AT91_ADC_CH(chan->channel));
|
||||
at91_adc_writel(st, AT91_ADC_IER, st->registers->drdy_mask);
|
||||
at91_adc_writel(st, AT91_ADC_CR, AT91_ADC_START);
|
||||
|
||||
ret = wait_event_interruptible_timeout(st->wq_data_avail,
|
||||
st->done,
|
||||
msecs_to_jiffies(1000));
|
||||
if (ret == 0)
|
||||
return -ETIMEDOUT;
|
||||
else if (ret < 0)
|
||||
return ret;
|
||||
|
||||
*val = st->last_value;
|
||||
|
||||
at91_adc_writel(st, AT91_ADC_CHDR,
|
||||
AT91_ADC_CH(chan->channel));
|
||||
at91_adc_writel(st, AT91_ADC_IDR, st->registers->drdy_mask);
|
||||
|
||||
st->last_value = 0;
|
||||
st->done = false;
|
||||
mutex_unlock(&st->lock);
|
||||
return IIO_VAL_INT;
|
||||
|
||||
case IIO_CHAN_INFO_SCALE:
|
||||
*val = (st->vref_mv * 1000) >> chan->scan_type.realbits;
|
||||
*val2 = 0;
|
||||
return IIO_VAL_INT_PLUS_MICRO;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int at91_adc_probe_dt(struct at91_adc_state *st,
|
||||
struct platform_device *pdev)
|
||||
{
|
||||
struct iio_dev *idev = iio_priv_to_dev(st);
|
||||
struct device_node *node = pdev->dev.of_node;
|
||||
struct device_node *trig_node;
|
||||
int i = 0, ret;
|
||||
u32 prop;
|
||||
|
||||
if (!node)
|
||||
return -EINVAL;
|
||||
|
||||
st->use_external = of_property_read_bool(node, "atmel,adc-use-external-triggers");
|
||||
|
||||
if (of_property_read_u32(node, "atmel,adc-channels-used", &prop)) {
|
||||
dev_err(&idev->dev, "Missing adc-channels-used property in the DT.\n");
|
||||
ret = -EINVAL;
|
||||
goto error_ret;
|
||||
}
|
||||
st->channels_mask = prop;
|
||||
|
||||
if (of_property_read_u32(node, "atmel,adc-num-channels", &prop)) {
|
||||
dev_err(&idev->dev, "Missing adc-num-channels property in the DT.\n");
|
||||
ret = -EINVAL;
|
||||
goto error_ret;
|
||||
}
|
||||
st->num_channels = prop;
|
||||
|
||||
if (of_property_read_u32(node, "atmel,adc-startup-time", &prop)) {
|
||||
dev_err(&idev->dev, "Missing adc-startup-time property in the DT.\n");
|
||||
ret = -EINVAL;
|
||||
goto error_ret;
|
||||
}
|
||||
st->startup_time = prop;
|
||||
|
||||
|
||||
if (of_property_read_u32(node, "atmel,adc-vref", &prop)) {
|
||||
dev_err(&idev->dev, "Missing adc-vref property in the DT.\n");
|
||||
ret = -EINVAL;
|
||||
goto error_ret;
|
||||
}
|
||||
st->vref_mv = prop;
|
||||
|
||||
st->registers = devm_kzalloc(&idev->dev,
|
||||
sizeof(struct at91_adc_reg_desc),
|
||||
GFP_KERNEL);
|
||||
if (!st->registers) {
|
||||
dev_err(&idev->dev, "Could not allocate register memory.\n");
|
||||
ret = -ENOMEM;
|
||||
goto error_ret;
|
||||
}
|
||||
|
||||
if (of_property_read_u32(node, "atmel,adc-channel-base", &prop)) {
|
||||
dev_err(&idev->dev, "Missing adc-channel-base property in the DT.\n");
|
||||
ret = -EINVAL;
|
||||
goto error_ret;
|
||||
}
|
||||
st->registers->channel_base = prop;
|
||||
|
||||
if (of_property_read_u32(node, "atmel,adc-drdy-mask", &prop)) {
|
||||
dev_err(&idev->dev, "Missing adc-drdy-mask property in the DT.\n");
|
||||
ret = -EINVAL;
|
||||
goto error_ret;
|
||||
}
|
||||
st->registers->drdy_mask = prop;
|
||||
|
||||
if (of_property_read_u32(node, "atmel,adc-status-register", &prop)) {
|
||||
dev_err(&idev->dev, "Missing adc-status-register property in the DT.\n");
|
||||
ret = -EINVAL;
|
||||
goto error_ret;
|
||||
}
|
||||
st->registers->status_register = prop;
|
||||
|
||||
if (of_property_read_u32(node, "atmel,adc-trigger-register", &prop)) {
|
||||
dev_err(&idev->dev, "Missing adc-trigger-register property in the DT.\n");
|
||||
ret = -EINVAL;
|
||||
goto error_ret;
|
||||
}
|
||||
st->registers->trigger_register = prop;
|
||||
|
||||
st->trigger_number = of_get_child_count(node);
|
||||
st->trigger_list = devm_kzalloc(&idev->dev, st->trigger_number *
|
||||
sizeof(struct at91_adc_trigger),
|
||||
GFP_KERNEL);
|
||||
if (!st->trigger_list) {
|
||||
dev_err(&idev->dev, "Could not allocate trigger list memory.\n");
|
||||
ret = -ENOMEM;
|
||||
goto error_ret;
|
||||
}
|
||||
|
||||
for_each_child_of_node(node, trig_node) {
|
||||
struct at91_adc_trigger *trig = st->trigger_list + i;
|
||||
const char *name;
|
||||
|
||||
if (of_property_read_string(trig_node, "trigger-name", &name)) {
|
||||
dev_err(&idev->dev, "Missing trigger-name property in the DT.\n");
|
||||
ret = -EINVAL;
|
||||
goto error_ret;
|
||||
}
|
||||
trig->name = name;
|
||||
|
||||
if (of_property_read_u32(trig_node, "trigger-value", &prop)) {
|
||||
dev_err(&idev->dev, "Missing trigger-value property in the DT.\n");
|
||||
ret = -EINVAL;
|
||||
goto error_ret;
|
||||
}
|
||||
trig->value = prop;
|
||||
trig->is_external = of_property_read_bool(trig_node, "trigger-external");
|
||||
i++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
error_ret:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int at91_adc_probe_pdata(struct at91_adc_state *st,
|
||||
struct platform_device *pdev)
|
||||
{
|
||||
struct at91_adc_data *pdata = pdev->dev.platform_data;
|
||||
|
||||
if (!pdata)
|
||||
return -EINVAL;
|
||||
|
||||
st->use_external = pdata->use_external_triggers;
|
||||
st->vref_mv = pdata->vref;
|
||||
st->channels_mask = pdata->channels_used;
|
||||
st->num_channels = pdata->num_channels;
|
||||
st->startup_time = pdata->startup_time;
|
||||
st->trigger_number = pdata->trigger_number;
|
||||
st->trigger_list = pdata->trigger_list;
|
||||
st->registers = pdata->registers;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct iio_info at91_adc_info = {
|
||||
.driver_module = THIS_MODULE,
|
||||
.read_raw = &at91_adc_read_raw,
|
||||
};
|
||||
|
||||
static int __devinit at91_adc_probe(struct platform_device *pdev)
|
||||
{
|
||||
unsigned int prsc, mstrclk, ticks, adc_clk;
|
||||
int ret;
|
||||
struct iio_dev *idev;
|
||||
struct at91_adc_state *st;
|
||||
struct resource *res;
|
||||
|
||||
idev = iio_device_alloc(sizeof(struct at91_adc_state));
|
||||
if (idev == NULL) {
|
||||
ret = -ENOMEM;
|
||||
goto error_ret;
|
||||
}
|
||||
|
||||
st = iio_priv(idev);
|
||||
|
||||
if (pdev->dev.of_node)
|
||||
ret = at91_adc_probe_dt(st, pdev);
|
||||
else
|
||||
ret = at91_adc_probe_pdata(st, pdev);
|
||||
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "No platform data available.\n");
|
||||
ret = -EINVAL;
|
||||
goto error_free_device;
|
||||
}
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
if (!res) {
|
||||
dev_err(&pdev->dev, "No resource defined\n");
|
||||
ret = -ENXIO;
|
||||
goto error_ret;
|
||||
}
|
||||
|
||||
platform_set_drvdata(pdev, idev);
|
||||
|
||||
idev->dev.parent = &pdev->dev;
|
||||
idev->name = dev_name(&pdev->dev);
|
||||
idev->modes = INDIO_DIRECT_MODE;
|
||||
idev->info = &at91_adc_info;
|
||||
|
||||
st->irq = platform_get_irq(pdev, 0);
|
||||
if (st->irq < 0) {
|
||||
dev_err(&pdev->dev, "No IRQ ID is designated\n");
|
||||
ret = -ENODEV;
|
||||
goto error_free_device;
|
||||
}
|
||||
|
||||
if (!request_mem_region(res->start, resource_size(res),
|
||||
"AT91 adc registers")) {
|
||||
dev_err(&pdev->dev, "Resources are unavailable.\n");
|
||||
ret = -EBUSY;
|
||||
goto error_free_device;
|
||||
}
|
||||
|
||||
st->reg_base = ioremap(res->start, resource_size(res));
|
||||
if (!st->reg_base) {
|
||||
dev_err(&pdev->dev, "Failed to map registers.\n");
|
||||
ret = -ENOMEM;
|
||||
goto error_release_mem;
|
||||
}
|
||||
|
||||
/*
|
||||
* Disable all IRQs before setting up the handler
|
||||
*/
|
||||
at91_adc_writel(st, AT91_ADC_CR, AT91_ADC_SWRST);
|
||||
at91_adc_writel(st, AT91_ADC_IDR, 0xFFFFFFFF);
|
||||
ret = request_irq(st->irq,
|
||||
at91_adc_eoc_trigger,
|
||||
0,
|
||||
pdev->dev.driver->name,
|
||||
idev);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "Failed to allocate IRQ.\n");
|
||||
goto error_unmap_reg;
|
||||
}
|
||||
|
||||
st->clk = clk_get(&pdev->dev, "adc_clk");
|
||||
if (IS_ERR(st->clk)) {
|
||||
dev_err(&pdev->dev, "Failed to get the clock.\n");
|
||||
ret = PTR_ERR(st->clk);
|
||||
goto error_free_irq;
|
||||
}
|
||||
|
||||
ret = clk_prepare(st->clk);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "Could not prepare the clock.\n");
|
||||
goto error_free_clk;
|
||||
}
|
||||
|
||||
ret = clk_enable(st->clk);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "Could not enable the clock.\n");
|
||||
goto error_unprepare_clk;
|
||||
}
|
||||
|
||||
st->adc_clk = clk_get(&pdev->dev, "adc_op_clk");
|
||||
if (IS_ERR(st->adc_clk)) {
|
||||
dev_err(&pdev->dev, "Failed to get the ADC clock.\n");
|
||||
ret = PTR_ERR(st->clk);
|
||||
goto error_disable_clk;
|
||||
}
|
||||
|
||||
ret = clk_prepare(st->adc_clk);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "Could not prepare the ADC clock.\n");
|
||||
goto error_free_adc_clk;
|
||||
}
|
||||
|
||||
ret = clk_enable(st->adc_clk);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "Could not enable the ADC clock.\n");
|
||||
goto error_unprepare_adc_clk;
|
||||
}
|
||||
|
||||
/*
|
||||
* Prescaler rate computation using the formula from the Atmel's
|
||||
* datasheet : ADC Clock = MCK / ((Prescaler + 1) * 2), ADC Clock being
|
||||
* specified by the electrical characteristics of the board.
|
||||
*/
|
||||
mstrclk = clk_get_rate(st->clk);
|
||||
adc_clk = clk_get_rate(st->adc_clk);
|
||||
prsc = (mstrclk / (2 * adc_clk)) - 1;
|
||||
|
||||
if (!st->startup_time) {
|
||||
dev_err(&pdev->dev, "No startup time available.\n");
|
||||
ret = -EINVAL;
|
||||
goto error_disable_adc_clk;
|
||||
}
|
||||
|
||||
/*
|
||||
* Number of ticks needed to cover the startup time of the ADC as
|
||||
* defined in the electrical characteristics of the board, divided by 8.
|
||||
* The formula thus is : Startup Time = (ticks + 1) * 8 / ADC Clock
|
||||
*/
|
||||
ticks = round_up((st->startup_time * adc_clk /
|
||||
1000000) - 1, 8) / 8;
|
||||
at91_adc_writel(st, AT91_ADC_MR,
|
||||
(AT91_ADC_PRESCAL_(prsc) & AT91_ADC_PRESCAL) |
|
||||
(AT91_ADC_STARTUP_(ticks) & AT91_ADC_STARTUP));
|
||||
|
||||
/* Setup the ADC channels available on the board */
|
||||
ret = at91_adc_channel_init(idev);
|
||||
if (ret < 0) {
|
||||
dev_err(&pdev->dev, "Couldn't initialize the channels.\n");
|
||||
goto error_disable_adc_clk;
|
||||
}
|
||||
|
||||
init_waitqueue_head(&st->wq_data_avail);
|
||||
mutex_init(&st->lock);
|
||||
|
||||
ret = at91_adc_buffer_init(idev);
|
||||
if (ret < 0) {
|
||||
dev_err(&pdev->dev, "Couldn't initialize the buffer.\n");
|
||||
goto error_disable_adc_clk;
|
||||
}
|
||||
|
||||
ret = at91_adc_trigger_init(idev);
|
||||
if (ret < 0) {
|
||||
dev_err(&pdev->dev, "Couldn't setup the triggers.\n");
|
||||
goto error_unregister_buffer;
|
||||
}
|
||||
|
||||
ret = iio_device_register(idev);
|
||||
if (ret < 0) {
|
||||
dev_err(&pdev->dev, "Couldn't register the device.\n");
|
||||
goto error_remove_triggers;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
error_remove_triggers:
|
||||
at91_adc_trigger_remove(idev);
|
||||
error_unregister_buffer:
|
||||
at91_adc_buffer_remove(idev);
|
||||
error_disable_adc_clk:
|
||||
clk_disable(st->adc_clk);
|
||||
error_unprepare_adc_clk:
|
||||
clk_unprepare(st->adc_clk);
|
||||
error_free_adc_clk:
|
||||
clk_put(st->adc_clk);
|
||||
error_disable_clk:
|
||||
clk_disable(st->clk);
|
||||
error_unprepare_clk:
|
||||
clk_unprepare(st->clk);
|
||||
error_free_clk:
|
||||
clk_put(st->clk);
|
||||
error_free_irq:
|
||||
free_irq(st->irq, idev);
|
||||
error_unmap_reg:
|
||||
iounmap(st->reg_base);
|
||||
error_release_mem:
|
||||
release_mem_region(res->start, resource_size(res));
|
||||
error_free_device:
|
||||
iio_device_free(idev);
|
||||
error_ret:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int __devexit at91_adc_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct iio_dev *idev = platform_get_drvdata(pdev);
|
||||
struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
struct at91_adc_state *st = iio_priv(idev);
|
||||
|
||||
iio_device_unregister(idev);
|
||||
at91_adc_trigger_remove(idev);
|
||||
at91_adc_buffer_remove(idev);
|
||||
clk_disable_unprepare(st->adc_clk);
|
||||
clk_put(st->adc_clk);
|
||||
clk_disable(st->clk);
|
||||
clk_unprepare(st->clk);
|
||||
clk_put(st->clk);
|
||||
free_irq(st->irq, idev);
|
||||
iounmap(st->reg_base);
|
||||
release_mem_region(res->start, resource_size(res));
|
||||
iio_device_free(idev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id at91_adc_dt_ids[] = {
|
||||
{ .compatible = "atmel,at91sam9260-adc" },
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, at91_adc_dt_ids);
|
||||
|
||||
static struct platform_driver at91_adc_driver = {
|
||||
.probe = at91_adc_probe,
|
||||
.remove = __devexit_p(at91_adc_remove),
|
||||
.driver = {
|
||||
.name = "at91_adc",
|
||||
.of_match_table = of_match_ptr(at91_adc_dt_ids),
|
||||
},
|
||||
};
|
||||
|
||||
module_platform_driver(at91_adc_driver);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_DESCRIPTION("Atmel AT91 ADC Driver");
|
||||
MODULE_AUTHOR("Maxime Ripard <maxime.ripard@free-electrons.com>");
|
|
@ -0,0 +1,17 @@
|
|||
#
|
||||
# Gain Amplifiers, etc.
|
||||
#
|
||||
menu "Amplifiers"
|
||||
|
||||
config AD8366
|
||||
tristate "Analog Devices AD8366 VGA"
|
||||
depends on SPI
|
||||
select BITREVERSE
|
||||
help
|
||||
Say yes here to build support for Analog Devices AD8366
|
||||
SPI Dual-Digital Variable Gain Amplifier (VGA).
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called ad8366.
|
||||
|
||||
endmenu
|
|
@ -0,0 +1,5 @@
|
|||
#
|
||||
# Makefile iio/amplifiers
|
||||
#
|
||||
|
||||
obj-$(CONFIG_AD8366) += ad8366.o
|
|
@ -0,0 +1,222 @@
|
|||
/*
|
||||
* AD8366 SPI Dual-Digital Variable Gain Amplifier (VGA)
|
||||
*
|
||||
* Copyright 2012 Analog Devices Inc.
|
||||
*
|
||||
* Licensed under the GPL-2.
|
||||
*/
|
||||
|
||||
#include <linux/device.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/sysfs.h>
|
||||
#include <linux/spi/spi.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/bitrev.h>
|
||||
|
||||
#include <linux/iio/iio.h>
|
||||
#include <linux/iio/sysfs.h>
|
||||
|
||||
struct ad8366_state {
|
||||
struct spi_device *spi;
|
||||
struct regulator *reg;
|
||||
unsigned char ch[2];
|
||||
/*
|
||||
* DMA (thus cache coherency maintenance) requires the
|
||||
* transfer buffers to live in their own cache lines.
|
||||
*/
|
||||
unsigned char data[2] ____cacheline_aligned;
|
||||
};
|
||||
|
||||
static int ad8366_write(struct iio_dev *indio_dev,
|
||||
unsigned char ch_a, char unsigned ch_b)
|
||||
{
|
||||
struct ad8366_state *st = iio_priv(indio_dev);
|
||||
int ret;
|
||||
|
||||
ch_a = bitrev8(ch_a & 0x3F);
|
||||
ch_b = bitrev8(ch_b & 0x3F);
|
||||
|
||||
st->data[0] = ch_b >> 4;
|
||||
st->data[1] = (ch_b << 4) | (ch_a >> 2);
|
||||
|
||||
ret = spi_write(st->spi, st->data, ARRAY_SIZE(st->data));
|
||||
if (ret < 0)
|
||||
dev_err(&indio_dev->dev, "write failed (%d)", ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ad8366_read_raw(struct iio_dev *indio_dev,
|
||||
struct iio_chan_spec const *chan,
|
||||
int *val,
|
||||
int *val2,
|
||||
long m)
|
||||
{
|
||||
struct ad8366_state *st = iio_priv(indio_dev);
|
||||
int ret;
|
||||
unsigned code;
|
||||
|
||||
mutex_lock(&indio_dev->mlock);
|
||||
switch (m) {
|
||||
case IIO_CHAN_INFO_HARDWAREGAIN:
|
||||
code = st->ch[chan->channel];
|
||||
|
||||
/* Values in dB */
|
||||
code = code * 253 + 4500;
|
||||
*val = code / 1000;
|
||||
*val2 = (code % 1000) * 1000;
|
||||
|
||||
ret = IIO_VAL_INT_PLUS_MICRO_DB;
|
||||
break;
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
}
|
||||
mutex_unlock(&indio_dev->mlock);
|
||||
|
||||
return ret;
|
||||
};
|
||||
|
||||
static int ad8366_write_raw(struct iio_dev *indio_dev,
|
||||
struct iio_chan_spec const *chan,
|
||||
int val,
|
||||
int val2,
|
||||
long mask)
|
||||
{
|
||||
struct ad8366_state *st = iio_priv(indio_dev);
|
||||
unsigned code;
|
||||
int ret;
|
||||
|
||||
if (val < 0 || val2 < 0)
|
||||
return -EINVAL;
|
||||
|
||||
/* Values in dB */
|
||||
code = (((u8)val * 1000) + ((u32)val2 / 1000));
|
||||
|
||||
if (code > 20500 || code < 4500)
|
||||
return -EINVAL;
|
||||
|
||||
code = (code - 4500) / 253;
|
||||
|
||||
mutex_lock(&indio_dev->mlock);
|
||||
switch (mask) {
|
||||
case IIO_CHAN_INFO_HARDWAREGAIN:
|
||||
st->ch[chan->channel] = code;
|
||||
ret = ad8366_write(indio_dev, st->ch[0], st->ch[1]);
|
||||
break;
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
}
|
||||
mutex_unlock(&indio_dev->mlock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct iio_info ad8366_info = {
|
||||
.read_raw = &ad8366_read_raw,
|
||||
.write_raw = &ad8366_write_raw,
|
||||
.driver_module = THIS_MODULE,
|
||||
};
|
||||
|
||||
#define AD8366_CHAN(_channel) { \
|
||||
.type = IIO_VOLTAGE, \
|
||||
.output = 1, \
|
||||
.indexed = 1, \
|
||||
.channel = _channel, \
|
||||
.info_mask = IIO_CHAN_INFO_HARDWAREGAIN_SEPARATE_BIT,\
|
||||
}
|
||||
|
||||
static const struct iio_chan_spec ad8366_channels[] = {
|
||||
AD8366_CHAN(0),
|
||||
AD8366_CHAN(1),
|
||||
};
|
||||
|
||||
static int __devinit ad8366_probe(struct spi_device *spi)
|
||||
{
|
||||
struct iio_dev *indio_dev;
|
||||
struct ad8366_state *st;
|
||||
int ret;
|
||||
|
||||
indio_dev = iio_device_alloc(sizeof(*st));
|
||||
if (indio_dev == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
st = iio_priv(indio_dev);
|
||||
|
||||
st->reg = regulator_get(&spi->dev, "vcc");
|
||||
if (!IS_ERR(st->reg)) {
|
||||
ret = regulator_enable(st->reg);
|
||||
if (ret)
|
||||
goto error_put_reg;
|
||||
}
|
||||
|
||||
spi_set_drvdata(spi, indio_dev);
|
||||
st->spi = spi;
|
||||
|
||||
indio_dev->dev.parent = &spi->dev;
|
||||
indio_dev->name = spi_get_device_id(spi)->name;
|
||||
indio_dev->info = &ad8366_info;
|
||||
indio_dev->modes = INDIO_DIRECT_MODE;
|
||||
indio_dev->channels = ad8366_channels;
|
||||
indio_dev->num_channels = ARRAY_SIZE(ad8366_channels);
|
||||
|
||||
ret = iio_device_register(indio_dev);
|
||||
if (ret)
|
||||
goto error_disable_reg;
|
||||
|
||||
ad8366_write(indio_dev, 0 , 0);
|
||||
|
||||
return 0;
|
||||
|
||||
error_disable_reg:
|
||||
if (!IS_ERR(st->reg))
|
||||
regulator_disable(st->reg);
|
||||
error_put_reg:
|
||||
if (!IS_ERR(st->reg))
|
||||
regulator_put(st->reg);
|
||||
|
||||
iio_device_free(indio_dev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int __devexit ad8366_remove(struct spi_device *spi)
|
||||
{
|
||||
struct iio_dev *indio_dev = spi_get_drvdata(spi);
|
||||
struct ad8366_state *st = iio_priv(indio_dev);
|
||||
struct regulator *reg = st->reg;
|
||||
|
||||
iio_device_unregister(indio_dev);
|
||||
|
||||
if (!IS_ERR(reg)) {
|
||||
regulator_disable(reg);
|
||||
regulator_put(reg);
|
||||
}
|
||||
|
||||
iio_device_free(indio_dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct spi_device_id ad8366_id[] = {
|
||||
{"ad8366", 0},
|
||||
{}
|
||||
};
|
||||
|
||||
static struct spi_driver ad8366_driver = {
|
||||
.driver = {
|
||||
.name = KBUILD_MODNAME,
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.probe = ad8366_probe,
|
||||
.remove = __devexit_p(ad8366_remove),
|
||||
.id_table = ad8366_id,
|
||||
};
|
||||
|
||||
module_spi_driver(ad8366_driver);
|
||||
|
||||
MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>");
|
||||
MODULE_DESCRIPTION("Analog Devices AD8366 VGA");
|
||||
MODULE_LICENSE("GPL v2");
|
|
@ -12,6 +12,12 @@
|
|||
|
||||
#ifndef _IIO_CORE_H_
|
||||
#define _IIO_CORE_H_
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/device.h>
|
||||
|
||||
struct iio_chan_spec;
|
||||
struct iio_dev;
|
||||
|
||||
|
||||
int __iio_add_chan_devattr(const char *postfix,
|
||||
struct iio_chan_spec const *chan,
|
|
@ -21,10 +21,10 @@
|
|||
#include <linux/slab.h>
|
||||
#include <linux/poll.h>
|
||||
|
||||
#include "iio.h"
|
||||
#include <linux/iio/iio.h>
|
||||
#include "iio_core.h"
|
||||
#include "sysfs.h"
|
||||
#include "buffer.h"
|
||||
#include <linux/iio/sysfs.h>
|
||||
#include <linux/iio/buffer.h>
|
||||
|
||||
static const char * const iio_endian_prefix[] = {
|
||||
[IIO_BE] = "be",
|
||||
|
@ -105,7 +105,7 @@ static ssize_t iio_scan_el_show(struct device *dev,
|
|||
char *buf)
|
||||
{
|
||||
int ret;
|
||||
struct iio_dev *indio_dev = dev_get_drvdata(dev);
|
||||
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
|
||||
|
||||
ret = test_bit(to_iio_dev_attr(attr)->address,
|
||||
indio_dev->buffer->scan_mask);
|
||||
|
@ -124,13 +124,15 @@ static ssize_t iio_scan_el_store(struct device *dev,
|
|||
const char *buf,
|
||||
size_t len)
|
||||
{
|
||||
int ret = 0;
|
||||
int ret;
|
||||
bool state;
|
||||
struct iio_dev *indio_dev = dev_get_drvdata(dev);
|
||||
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
|
||||
struct iio_buffer *buffer = indio_dev->buffer;
|
||||
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
|
||||
|
||||
state = !(buf[0] == '0');
|
||||
ret = strtobool(buf, &state);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
mutex_lock(&indio_dev->mlock);
|
||||
if (iio_buffer_enabled(indio_dev)) {
|
||||
ret = -EBUSY;
|
||||
|
@ -160,7 +162,7 @@ static ssize_t iio_scan_el_ts_show(struct device *dev,
|
|||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct iio_dev *indio_dev = dev_get_drvdata(dev);
|
||||
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
|
||||
return sprintf(buf, "%d\n", indio_dev->buffer->scan_timestamp);
|
||||
}
|
||||
|
||||
|
@ -169,17 +171,21 @@ static ssize_t iio_scan_el_ts_store(struct device *dev,
|
|||
const char *buf,
|
||||
size_t len)
|
||||
{
|
||||
int ret = 0;
|
||||
struct iio_dev *indio_dev = dev_get_drvdata(dev);
|
||||
int ret;
|
||||
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
|
||||
bool state;
|
||||
|
||||
state = !(buf[0] == '0');
|
||||
ret = strtobool(buf, &state);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
mutex_lock(&indio_dev->mlock);
|
||||
if (iio_buffer_enabled(indio_dev)) {
|
||||
ret = -EBUSY;
|
||||
goto error_ret;
|
||||
}
|
||||
indio_dev->buffer->scan_timestamp = state;
|
||||
indio_dev->scan_timestamp = state;
|
||||
error_ret:
|
||||
mutex_unlock(&indio_dev->mlock);
|
||||
|
||||
|
@ -291,7 +297,7 @@ int iio_buffer_register(struct iio_dev *indio_dev,
|
|||
goto error_cleanup_dynamic;
|
||||
attrcount += ret;
|
||||
if (channels[i].type == IIO_TIMESTAMP)
|
||||
buffer->scan_index_timestamp =
|
||||
indio_dev->scan_index_timestamp =
|
||||
channels[i].scan_index;
|
||||
}
|
||||
if (indio_dev->masklength && buffer->scan_mask == NULL) {
|
||||
|
@ -346,7 +352,7 @@ ssize_t iio_buffer_read_length(struct device *dev,
|
|||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct iio_dev *indio_dev = dev_get_drvdata(dev);
|
||||
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
|
||||
struct iio_buffer *buffer = indio_dev->buffer;
|
||||
|
||||
if (buffer->access->get_length)
|
||||
|
@ -364,7 +370,7 @@ ssize_t iio_buffer_write_length(struct device *dev,
|
|||
{
|
||||
int ret;
|
||||
ulong val;
|
||||
struct iio_dev *indio_dev = dev_get_drvdata(dev);
|
||||
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
|
||||
struct iio_buffer *buffer = indio_dev->buffer;
|
||||
|
||||
ret = strict_strtoul(buf, 10, &val);
|
||||
|
@ -397,7 +403,7 @@ ssize_t iio_buffer_store_enable(struct device *dev,
|
|||
int ret;
|
||||
bool requested_state, current_state;
|
||||
int previous_mode;
|
||||
struct iio_dev *indio_dev = dev_get_drvdata(dev);
|
||||
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
|
||||
struct iio_buffer *buffer = indio_dev->buffer;
|
||||
|
||||
mutex_lock(&indio_dev->mlock);
|
||||
|
@ -483,7 +489,7 @@ ssize_t iio_buffer_show_enable(struct device *dev,
|
|||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct iio_dev *indio_dev = dev_get_drvdata(dev);
|
||||
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
|
||||
return sprintf(buf, "%d\n", iio_buffer_enabled(indio_dev));
|
||||
}
|
||||
EXPORT_SYMBOL(iio_buffer_show_enable);
|
||||
|
@ -503,30 +509,41 @@ static const unsigned long *iio_scan_mask_match(const unsigned long *av_masks,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
int iio_sw_buffer_preenable(struct iio_dev *indio_dev)
|
||||
static int iio_compute_scan_bytes(struct iio_dev *indio_dev, const long *mask,
|
||||
bool timestamp)
|
||||
{
|
||||
struct iio_buffer *buffer = indio_dev->buffer;
|
||||
const struct iio_chan_spec *ch;
|
||||
unsigned bytes = 0;
|
||||
int length, i;
|
||||
|
||||
/* How much space will the demuxed element take? */
|
||||
for_each_set_bit(i, mask,
|
||||
indio_dev->masklength) {
|
||||
ch = iio_find_channel_from_si(indio_dev, i);
|
||||
length = ch->scan_type.storagebits / 8;
|
||||
bytes = ALIGN(bytes, length);
|
||||
bytes += length;
|
||||
}
|
||||
if (timestamp) {
|
||||
ch = iio_find_channel_from_si(indio_dev,
|
||||
indio_dev->scan_index_timestamp);
|
||||
length = ch->scan_type.storagebits / 8;
|
||||
bytes = ALIGN(bytes, length);
|
||||
bytes += length;
|
||||
}
|
||||
return bytes;
|
||||
}
|
||||
|
||||
int iio_sw_buffer_preenable(struct iio_dev *indio_dev)
|
||||
{
|
||||
struct iio_buffer *buffer = indio_dev->buffer;
|
||||
dev_dbg(&indio_dev->dev, "%s\n", __func__);
|
||||
|
||||
/* How much space will the demuxed element take? */
|
||||
for_each_set_bit(i, buffer->scan_mask,
|
||||
indio_dev->masklength) {
|
||||
ch = iio_find_channel_from_si(indio_dev, i);
|
||||
length = ch->scan_type.storagebits/8;
|
||||
bytes = ALIGN(bytes, length);
|
||||
bytes += length;
|
||||
}
|
||||
if (buffer->scan_timestamp) {
|
||||
ch = iio_find_channel_from_si(indio_dev,
|
||||
buffer->scan_index_timestamp);
|
||||
length = ch->scan_type.storagebits/8;
|
||||
bytes = ALIGN(bytes, length);
|
||||
bytes += length;
|
||||
}
|
||||
buffer->access->set_bytes_per_datum(buffer, bytes);
|
||||
indio_dev->scan_bytes =
|
||||
iio_compute_scan_bytes(indio_dev, buffer->scan_mask,
|
||||
buffer->scan_timestamp);
|
||||
buffer->access->set_bytes_per_datum(buffer, indio_dev->scan_bytes);
|
||||
|
||||
/* What scan mask do we actually have ?*/
|
||||
if (indio_dev->available_scan_masks)
|
||||
|
@ -638,19 +655,25 @@ int iio_push_to_buffer(struct iio_buffer *buffer, unsigned char *data,
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(iio_push_to_buffer);
|
||||
|
||||
static void iio_buffer_demux_free(struct iio_buffer *buffer)
|
||||
{
|
||||
struct iio_demux_table *p, *q;
|
||||
list_for_each_entry_safe(p, q, &buffer->demux_list, l) {
|
||||
list_del(&p->l);
|
||||
kfree(p);
|
||||
}
|
||||
}
|
||||
|
||||
int iio_update_demux(struct iio_dev *indio_dev)
|
||||
{
|
||||
const struct iio_chan_spec *ch;
|
||||
struct iio_buffer *buffer = indio_dev->buffer;
|
||||
int ret, in_ind = -1, out_ind, length;
|
||||
unsigned in_loc = 0, out_loc = 0;
|
||||
struct iio_demux_table *p, *q;
|
||||
struct iio_demux_table *p;
|
||||
|
||||
/* Clear out any old demux */
|
||||
list_for_each_entry_safe(p, q, &buffer->demux_list, l) {
|
||||
list_del(&p->l);
|
||||
kfree(p);
|
||||
}
|
||||
iio_buffer_demux_free(buffer);
|
||||
kfree(buffer->demux_bounce);
|
||||
buffer->demux_bounce = NULL;
|
||||
|
||||
|
@ -704,7 +727,7 @@ int iio_update_demux(struct iio_dev *indio_dev)
|
|||
goto error_clear_mux_table;
|
||||
}
|
||||
ch = iio_find_channel_from_si(indio_dev,
|
||||
buffer->scan_index_timestamp);
|
||||
indio_dev->scan_index_timestamp);
|
||||
length = ch->scan_type.storagebits/8;
|
||||
if (out_loc % length)
|
||||
out_loc += length - out_loc % length;
|
||||
|
@ -725,10 +748,8 @@ int iio_update_demux(struct iio_dev *indio_dev)
|
|||
return 0;
|
||||
|
||||
error_clear_mux_table:
|
||||
list_for_each_entry_safe(p, q, &buffer->demux_list, l) {
|
||||
list_del(&p->l);
|
||||
kfree(p);
|
||||
}
|
||||
iio_buffer_demux_free(buffer);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(iio_update_demux);
|
|
@ -23,11 +23,11 @@
|
|||
#include <linux/slab.h>
|
||||
#include <linux/anon_inodes.h>
|
||||
#include <linux/debugfs.h>
|
||||
#include "iio.h"
|
||||
#include <linux/iio/iio.h>
|
||||
#include "iio_core.h"
|
||||
#include "iio_core_trigger.h"
|
||||
#include "sysfs.h"
|
||||
#include "events.h"
|
||||
#include <linux/iio/sysfs.h>
|
||||
#include <linux/iio/events.h>
|
||||
|
||||
/* IDA to assign each registered device a unique id*/
|
||||
static DEFINE_IDA(iio_ida);
|
||||
|
@ -42,11 +42,6 @@ EXPORT_SYMBOL(iio_bus_type);
|
|||
|
||||
static struct dentry *iio_debugfs_dentry;
|
||||
|
||||
static const char * const iio_data_type_name[] = {
|
||||
[IIO_RAW] = "raw",
|
||||
[IIO_PROCESSED] = "input",
|
||||
};
|
||||
|
||||
static const char * const iio_direction[] = {
|
||||
[0] = "in",
|
||||
[1] = "out",
|
||||
|
@ -68,6 +63,7 @@ static const char * const iio_chan_type_name_spec[] = {
|
|||
[IIO_ANGL] = "angl",
|
||||
[IIO_TIMESTAMP] = "timestamp",
|
||||
[IIO_CAPACITANCE] = "capacitance",
|
||||
[IIO_ALTVOLTAGE] = "altvoltage",
|
||||
};
|
||||
|
||||
static const char * const iio_modifier_names[] = {
|
||||
|
@ -80,6 +76,8 @@ static const char * const iio_modifier_names[] = {
|
|||
|
||||
/* relies on pairs of these shared then separate */
|
||||
static const char * const iio_chan_info_postfix[] = {
|
||||
[IIO_CHAN_INFO_RAW] = "raw",
|
||||
[IIO_CHAN_INFO_PROCESSED] = "input",
|
||||
[IIO_CHAN_INFO_SCALE] = "scale",
|
||||
[IIO_CHAN_INFO_OFFSET] = "offset",
|
||||
[IIO_CHAN_INFO_CALIBSCALE] = "calibscale",
|
||||
|
@ -90,6 +88,10 @@ static const char * const iio_chan_info_postfix[] = {
|
|||
[IIO_CHAN_INFO_AVERAGE_RAW] = "mean_raw",
|
||||
[IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY]
|
||||
= "filter_low_pass_3db_frequency",
|
||||
[IIO_CHAN_INFO_SAMP_FREQ] = "sampling_frequency",
|
||||
[IIO_CHAN_INFO_FREQUENCY] = "frequency",
|
||||
[IIO_CHAN_INFO_PHASE] = "phase",
|
||||
[IIO_CHAN_INFO_HARDWAREGAIN] = "hardwaregain",
|
||||
};
|
||||
|
||||
const struct iio_chan_spec
|
||||
|
@ -151,14 +153,6 @@ static void __exit iio_exit(void)
|
|||
}
|
||||
|
||||
#if defined(CONFIG_DEBUG_FS)
|
||||
static int iio_debugfs_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
if (inode->i_private)
|
||||
file->private_data = inode->i_private;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ssize_t iio_debugfs_read_reg(struct file *file, char __user *userbuf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
|
@ -217,7 +211,7 @@ static ssize_t iio_debugfs_write_reg(struct file *file,
|
|||
}
|
||||
|
||||
static const struct file_operations iio_debugfs_reg_fops = {
|
||||
.open = iio_debugfs_open,
|
||||
.open = simple_open,
|
||||
.read = iio_debugfs_read_reg,
|
||||
.write = iio_debugfs_write_reg,
|
||||
};
|
||||
|
@ -234,15 +228,12 @@ static int iio_device_register_debugfs(struct iio_dev *indio_dev)
|
|||
if (indio_dev->info->debugfs_reg_access == NULL)
|
||||
return 0;
|
||||
|
||||
if (IS_ERR(iio_debugfs_dentry))
|
||||
if (!iio_debugfs_dentry)
|
||||
return 0;
|
||||
|
||||
indio_dev->debugfs_dentry =
|
||||
debugfs_create_dir(dev_name(&indio_dev->dev),
|
||||
iio_debugfs_dentry);
|
||||
if (IS_ERR(indio_dev->debugfs_dentry))
|
||||
return PTR_ERR(indio_dev->debugfs_dentry);
|
||||
|
||||
if (indio_dev->debugfs_dentry == NULL) {
|
||||
dev_warn(indio_dev->dev.parent,
|
||||
"Failed to create debugfs directory\n");
|
||||
|
@ -274,13 +265,13 @@ static ssize_t iio_read_channel_ext_info(struct device *dev,
|
|||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct iio_dev *indio_dev = dev_get_drvdata(dev);
|
||||
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
|
||||
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
|
||||
const struct iio_chan_spec_ext_info *ext_info;
|
||||
|
||||
ext_info = &this_attr->c->ext_info[this_attr->address];
|
||||
|
||||
return ext_info->read(indio_dev, this_attr->c, buf);
|
||||
return ext_info->read(indio_dev, ext_info->private, this_attr->c, buf);
|
||||
}
|
||||
|
||||
static ssize_t iio_write_channel_ext_info(struct device *dev,
|
||||
|
@ -288,42 +279,50 @@ static ssize_t iio_write_channel_ext_info(struct device *dev,
|
|||
const char *buf,
|
||||
size_t len)
|
||||
{
|
||||
struct iio_dev *indio_dev = dev_get_drvdata(dev);
|
||||
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
|
||||
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
|
||||
const struct iio_chan_spec_ext_info *ext_info;
|
||||
|
||||
ext_info = &this_attr->c->ext_info[this_attr->address];
|
||||
|
||||
return ext_info->write(indio_dev, this_attr->c, buf, len);
|
||||
return ext_info->write(indio_dev, ext_info->private,
|
||||
this_attr->c, buf, len);
|
||||
}
|
||||
|
||||
static ssize_t iio_read_channel_info(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct iio_dev *indio_dev = dev_get_drvdata(dev);
|
||||
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
|
||||
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
|
||||
int val, val2;
|
||||
bool scale_db = false;
|
||||
int ret = indio_dev->info->read_raw(indio_dev, this_attr->c,
|
||||
&val, &val2, this_attr->address);
|
||||
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (ret == IIO_VAL_INT)
|
||||
switch (ret) {
|
||||
case IIO_VAL_INT:
|
||||
return sprintf(buf, "%d\n", val);
|
||||
else if (ret == IIO_VAL_INT_PLUS_MICRO) {
|
||||
case IIO_VAL_INT_PLUS_MICRO_DB:
|
||||
scale_db = true;
|
||||
case IIO_VAL_INT_PLUS_MICRO:
|
||||
if (val2 < 0)
|
||||
return sprintf(buf, "-%d.%06u\n", val, -val2);
|
||||
return sprintf(buf, "-%d.%06u%s\n", val, -val2,
|
||||
scale_db ? " dB" : "");
|
||||
else
|
||||
return sprintf(buf, "%d.%06u\n", val, val2);
|
||||
} else if (ret == IIO_VAL_INT_PLUS_NANO) {
|
||||
return sprintf(buf, "%d.%06u%s\n", val, val2,
|
||||
scale_db ? " dB" : "");
|
||||
case IIO_VAL_INT_PLUS_NANO:
|
||||
if (val2 < 0)
|
||||
return sprintf(buf, "-%d.%09u\n", val, -val2);
|
||||
else
|
||||
return sprintf(buf, "%d.%09u\n", val, val2);
|
||||
} else
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static ssize_t iio_write_channel_info(struct device *dev,
|
||||
|
@ -331,7 +330,7 @@ static ssize_t iio_write_channel_info(struct device *dev,
|
|||
const char *buf,
|
||||
size_t len)
|
||||
{
|
||||
struct iio_dev *indio_dev = dev_get_drvdata(dev);
|
||||
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
|
||||
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
|
||||
int ret, integer = 0, fract = 0, fract_mult = 100000;
|
||||
bool integer_part = true, negative = false;
|
||||
|
@ -575,25 +574,12 @@ error_ret:
|
|||
static int iio_device_add_channel_sysfs(struct iio_dev *indio_dev,
|
||||
struct iio_chan_spec const *chan)
|
||||
{
|
||||
int ret, i, attrcount = 0;
|
||||
int ret, attrcount = 0;
|
||||
int i;
|
||||
const struct iio_chan_spec_ext_info *ext_info;
|
||||
|
||||
if (chan->channel < 0)
|
||||
return 0;
|
||||
|
||||
ret = __iio_add_chan_devattr(iio_data_type_name[chan->processed_val],
|
||||
chan,
|
||||
&iio_read_channel_info,
|
||||
(chan->output ?
|
||||
&iio_write_channel_info : NULL),
|
||||
0,
|
||||
0,
|
||||
&indio_dev->dev,
|
||||
&indio_dev->channel_attr_list);
|
||||
if (ret)
|
||||
goto error_ret;
|
||||
attrcount++;
|
||||
|
||||
for_each_set_bit(i, &chan->info_mask, sizeof(long)*8) {
|
||||
ret = __iio_add_chan_devattr(iio_chan_info_postfix[i/2],
|
||||
chan,
|
||||
|
@ -652,7 +638,7 @@ static ssize_t iio_show_dev_name(struct device *dev,
|
|||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct iio_dev *indio_dev = dev_get_drvdata(dev);
|
||||
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
|
||||
return sprintf(buf, "%s\n", indio_dev->name);
|
||||
}
|
||||
|
||||
|
@ -738,7 +724,7 @@ static void iio_device_unregister_sysfs(struct iio_dev *indio_dev)
|
|||
|
||||
static void iio_dev_release(struct device *device)
|
||||
{
|
||||
struct iio_dev *indio_dev = container_of(device, struct iio_dev, dev);
|
||||
struct iio_dev *indio_dev = dev_to_iio_dev(device);
|
||||
cdev_del(&indio_dev->chrdev);
|
||||
if (indio_dev->modes & INDIO_BUFFER_TRIGGERED)
|
||||
iio_device_unregister_trigger_consumer(indio_dev);
|
||||
|
@ -752,7 +738,7 @@ static struct device_type iio_dev_type = {
|
|||
.release = iio_dev_release,
|
||||
};
|
||||
|
||||
struct iio_dev *iio_allocate_device(int sizeof_priv)
|
||||
struct iio_dev *iio_device_alloc(int sizeof_priv)
|
||||
{
|
||||
struct iio_dev *dev;
|
||||
size_t alloc_size;
|
||||
|
@ -788,16 +774,16 @@ struct iio_dev *iio_allocate_device(int sizeof_priv)
|
|||
|
||||
return dev;
|
||||
}
|
||||
EXPORT_SYMBOL(iio_allocate_device);
|
||||
EXPORT_SYMBOL(iio_device_alloc);
|
||||
|
||||
void iio_free_device(struct iio_dev *dev)
|
||||
void iio_device_free(struct iio_dev *dev)
|
||||
{
|
||||
if (dev) {
|
||||
ida_simple_remove(&iio_ida, dev->id);
|
||||
kfree(dev);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(iio_free_device);
|
||||
EXPORT_SYMBOL(iio_device_free);
|
||||
|
||||
/**
|
||||
* iio_chrdev_open() - chrdev file open for buffer access and ioctls
|
|
@ -20,10 +20,10 @@
|
|||
#include <linux/slab.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/wait.h>
|
||||
#include "iio.h"
|
||||
#include <linux/iio/iio.h>
|
||||
#include "iio_core.h"
|
||||
#include "sysfs.h"
|
||||
#include "events.h"
|
||||
#include <linux/iio/sysfs.h>
|
||||
#include <linux/iio/events.h>
|
||||
|
||||
/**
|
||||
* struct iio_event_interface - chrdev interface for an event line
|
||||
|
@ -186,7 +186,7 @@ static ssize_t iio_ev_state_store(struct device *dev,
|
|||
const char *buf,
|
||||
size_t len)
|
||||
{
|
||||
struct iio_dev *indio_dev = dev_get_drvdata(dev);
|
||||
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
|
||||
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
|
||||
int ret;
|
||||
bool val;
|
||||
|
@ -205,7 +205,7 @@ static ssize_t iio_ev_state_show(struct device *dev,
|
|||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct iio_dev *indio_dev = dev_get_drvdata(dev);
|
||||
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
|
||||
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
|
||||
int val = indio_dev->info->read_event_config(indio_dev,
|
||||
this_attr->address);
|
||||
|
@ -220,7 +220,7 @@ static ssize_t iio_ev_value_show(struct device *dev,
|
|||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct iio_dev *indio_dev = dev_get_drvdata(dev);
|
||||
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
|
||||
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
|
||||
int val, ret;
|
||||
|
||||
|
@ -237,7 +237,7 @@ static ssize_t iio_ev_value_store(struct device *dev,
|
|||
const char *buf,
|
||||
size_t len)
|
||||
{
|
||||
struct iio_dev *indio_dev = dev_get_drvdata(dev);
|
||||
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
|
||||
struct iio_dev_attr *this_attr = to_iio_dev_attr(attr);
|
||||
unsigned long val;
|
||||
int ret;
|
|
@ -15,11 +15,11 @@
|
|||
#include <linux/list.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include "iio.h"
|
||||
#include "trigger.h"
|
||||
#include <linux/iio/iio.h>
|
||||
#include <linux/iio/trigger.h>
|
||||
#include "iio_core.h"
|
||||
#include "iio_core_trigger.h"
|
||||
#include "trigger_consumer.h"
|
||||
#include <linux/iio/trigger_consumer.h>
|
||||
|
||||
/* RFC - Question of approach
|
||||
* Make the common case (single sensor single trigger)
|
||||
|
@ -310,7 +310,7 @@ static ssize_t iio_trigger_read_current(struct device *dev,
|
|||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct iio_dev *indio_dev = dev_get_drvdata(dev);
|
||||
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
|
||||
|
||||
if (indio_dev->trig)
|
||||
return sprintf(buf, "%s\n", indio_dev->trig->name);
|
||||
|
@ -329,7 +329,7 @@ static ssize_t iio_trigger_write_current(struct device *dev,
|
|||
const char *buf,
|
||||
size_t len)
|
||||
{
|
||||
struct iio_dev *indio_dev = dev_get_drvdata(dev);
|
||||
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
|
||||
struct iio_trigger *oldtrig = indio_dev->trig;
|
||||
struct iio_trigger *trig;
|
||||
int ret;
|
||||
|
@ -360,9 +360,9 @@ static ssize_t iio_trigger_write_current(struct device *dev,
|
|||
indio_dev->trig = trig;
|
||||
|
||||
if (oldtrig && indio_dev->trig != oldtrig)
|
||||
iio_put_trigger(oldtrig);
|
||||
iio_trigger_put(oldtrig);
|
||||
if (indio_dev->trig)
|
||||
iio_get_trigger(indio_dev->trig);
|
||||
iio_trigger_get(indio_dev->trig);
|
||||
|
||||
return len;
|
||||
}
|
||||
|
@ -426,7 +426,7 @@ static void iio_trig_subirqunmask(struct irq_data *d)
|
|||
trig->subirqs[d->irq - trig->subirq_base].enabled = true;
|
||||
}
|
||||
|
||||
struct iio_trigger *iio_allocate_trigger(const char *fmt, ...)
|
||||
struct iio_trigger *iio_trigger_alloc(const char *fmt, ...)
|
||||
{
|
||||
va_list vargs;
|
||||
struct iio_trigger *trig;
|
||||
|
@ -472,14 +472,14 @@ struct iio_trigger *iio_allocate_trigger(const char *fmt, ...)
|
|||
}
|
||||
return trig;
|
||||
}
|
||||
EXPORT_SYMBOL(iio_allocate_trigger);
|
||||
EXPORT_SYMBOL(iio_trigger_alloc);
|
||||
|
||||
void iio_free_trigger(struct iio_trigger *trig)
|
||||
void iio_trigger_free(struct iio_trigger *trig)
|
||||
{
|
||||
if (trig)
|
||||
put_device(&trig->dev);
|
||||
}
|
||||
EXPORT_SYMBOL(iio_free_trigger);
|
||||
EXPORT_SYMBOL(iio_trigger_free);
|
||||
|
||||
void iio_device_register_trigger_consumer(struct iio_dev *indio_dev)
|
||||
{
|
||||
|
@ -491,7 +491,7 @@ void iio_device_unregister_trigger_consumer(struct iio_dev *indio_dev)
|
|||
{
|
||||
/* Clean up and associated but not attached triggers references */
|
||||
if (indio_dev->trig)
|
||||
iio_put_trigger(indio_dev->trig);
|
||||
iio_trigger_put(indio_dev->trig);
|
||||
}
|
||||
|
||||
int iio_triggered_buffer_postenable(struct iio_dev *indio_dev)
|
|
@ -11,11 +11,11 @@
|
|||
#include <linux/slab.h>
|
||||
#include <linux/mutex.h>
|
||||
|
||||
#include "iio.h"
|
||||
#include <linux/iio/iio.h>
|
||||
#include "iio_core.h"
|
||||
#include "machine.h"
|
||||
#include "driver.h"
|
||||
#include "consumer.h"
|
||||
#include <linux/iio/machine.h>
|
||||
#include <linux/iio/driver.h>
|
||||
#include <linux/iio/consumer.h>
|
||||
|
||||
struct iio_map_internal {
|
||||
struct iio_dev *indio_dev;
|
|
@ -5,8 +5,7 @@
|
|||
#include <linux/workqueue.h>
|
||||
#include <linux/kfifo.h>
|
||||
#include <linux/mutex.h>
|
||||
|
||||
#include "kfifo_buf.h"
|
||||
#include <linux/iio/kfifo_buf.h>
|
||||
|
||||
struct iio_kfifo {
|
||||
struct iio_buffer buffer;
|
|
@ -516,4 +516,5 @@ source "drivers/misc/ti-st/Kconfig"
|
|||
source "drivers/misc/lis3lv02d/Kconfig"
|
||||
source "drivers/misc/carma/Kconfig"
|
||||
source "drivers/misc/altera-stapl/Kconfig"
|
||||
source "drivers/misc/mei/Kconfig"
|
||||
endmenu
|
||||
|
|
|
@ -50,3 +50,4 @@ obj-y += lis3lv02d/
|
|||
obj-y += carma/
|
||||
obj-$(CONFIG_USB_SWITCH_FSA9480) += fsa9480.o
|
||||
obj-$(CONFIG_ALTERA_STAPL) +=altera-stapl/
|
||||
obj-$(CONFIG_INTEL_MEI) += mei/
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
#include "mei_dev.h"
|
||||
#include "hw.h"
|
||||
#include "interface.h"
|
||||
#include "mei.h"
|
||||
#include <linux/mei.h>
|
||||
|
||||
const uuid_le mei_amthi_guid = UUID_LE(0x12f80028, 0xb4b7, 0x4b2d, 0xac,
|
||||
0xa8, 0x46, 0xe0, 0xff, 0x65,
|
||||
|
@ -200,7 +200,7 @@ int mei_hw_init(struct mei_device *dev)
|
|||
if (!(dev->me_hw_state & ME_RDY_HRA))
|
||||
dev_dbg(&dev->pdev->dev, "ME turn off ME_RDY.\n");
|
||||
|
||||
printk(KERN_ERR "mei: link layer initialization failed.\n");
|
||||
dev_err(&dev->pdev->dev, "link layer initialization failed.\n");
|
||||
ret = -ENODEV;
|
||||
goto out;
|
||||
}
|
|
@ -16,7 +16,7 @@
|
|||
|
||||
#include <linux/pci.h>
|
||||
#include "mei_dev.h"
|
||||
#include "mei.h"
|
||||
#include <linux/mei.h>
|
||||
#include "interface.h"
|
||||
|
||||
|
|
@ -19,7 +19,7 @@
|
|||
#ifndef _MEI_INTERFACE_H_
|
||||
#define _MEI_INTERFACE_H_
|
||||
|
||||
#include "mei.h"
|
||||
#include <linux/mei.h>
|
||||
#include "mei_dev.h"
|
||||
|
||||
|
||||
|
@ -51,8 +51,7 @@ int mei_flow_ctrl_creds(struct mei_device *dev, struct mei_cl *cl);
|
|||
|
||||
int mei_wd_send(struct mei_device *dev);
|
||||
int mei_wd_stop(struct mei_device *dev, bool preserve);
|
||||
bool mei_wd_host_init(struct mei_device *dev);
|
||||
void mei_wd_set_start_timeout(struct mei_device *dev, u16 timeout);
|
||||
int mei_wd_host_init(struct mei_device *dev);
|
||||
/*
|
||||
* mei_watchdog_register - Registering watchdog interface
|
||||
* once we got connection to the WD Client
|
|
@ -22,7 +22,7 @@
|
|||
#include <linux/jiffies.h>
|
||||
|
||||
#include "mei_dev.h"
|
||||
#include "mei.h"
|
||||
#include <linux/mei.h>
|
||||
#include "hw.h"
|
||||
#include "interface.h"
|
||||
|
|
@ -35,7 +35,7 @@
|
|||
|
||||
#include "mei_dev.h"
|
||||
#include "hw.h"
|
||||
#include "mei.h"
|
||||
#include <linux/mei.h>
|
||||
#include "interface.h"
|
||||
|
||||
|
|
@ -14,6 +14,8 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/kernel.h>
|
||||
|
@ -36,19 +38,10 @@
|
|||
#include <linux/miscdevice.h>
|
||||
|
||||
#include "mei_dev.h"
|
||||
#include "mei.h"
|
||||
#include <linux/mei.h>
|
||||
#include "interface.h"
|
||||
|
||||
|
||||
#define MEI_READ_TIMEOUT 45
|
||||
#define MEI_DRIVER_NAME "mei"
|
||||
#define MEI_DEV_NAME "mei"
|
||||
|
||||
/*
|
||||
* mei driver strings
|
||||
*/
|
||||
static char mei_driver_name[] = MEI_DRIVER_NAME;
|
||||
static const char mei_driver_string[] = "Intel(R) Management Engine Interface";
|
||||
static const char mei_driver_name[] = "mei";
|
||||
|
||||
/* The device pointer */
|
||||
/* Currently this driver works as long as there is only a single AMT device. */
|
||||
|
@ -931,7 +924,7 @@ static const struct file_operations mei_fops = {
|
|||
* Misc Device Struct
|
||||
*/
|
||||
static struct miscdevice mei_misc_device = {
|
||||
.name = MEI_DRIVER_NAME,
|
||||
.name = "mei",
|
||||
.fops = &mei_fops,
|
||||
.minor = MISC_DYNAMIC_MINOR,
|
||||
};
|
||||
|
@ -958,7 +951,7 @@ static int __devinit mei_probe(struct pci_dev *pdev,
|
|||
/* enable pci dev */
|
||||
err = pci_enable_device(pdev);
|
||||
if (err) {
|
||||
printk(KERN_ERR "mei: Failed to enable pci device.\n");
|
||||
dev_err(&pdev->dev, "failed to enable pci device.\n");
|
||||
goto end;
|
||||
}
|
||||
/* set PCI host mastering */
|
||||
|
@ -966,7 +959,7 @@ static int __devinit mei_probe(struct pci_dev *pdev,
|
|||
/* pci request regions for mei driver */
|
||||
err = pci_request_regions(pdev, mei_driver_name);
|
||||
if (err) {
|
||||
printk(KERN_ERR "mei: Failed to get pci regions.\n");
|
||||
dev_err(&pdev->dev, "failed to get pci regions.\n");
|
||||
goto disable_device;
|
||||
}
|
||||
/* allocates and initializes the mei dev structure */
|
||||
|
@ -978,7 +971,7 @@ static int __devinit mei_probe(struct pci_dev *pdev,
|
|||
/* mapping IO device memory */
|
||||
dev->mem_addr = pci_iomap(pdev, 0, 0);
|
||||
if (!dev->mem_addr) {
|
||||
printk(KERN_ERR "mei: mapping I/O device memory failure.\n");
|
||||
dev_err(&pdev->dev, "mapping I/O device memory failure.\n");
|
||||
err = -ENOMEM;
|
||||
goto free_device;
|
||||
}
|
||||
|
@ -997,13 +990,13 @@ static int __devinit mei_probe(struct pci_dev *pdev,
|
|||
IRQF_SHARED, mei_driver_name, dev);
|
||||
|
||||
if (err) {
|
||||
printk(KERN_ERR "mei: request_threaded_irq failure. irq = %d\n",
|
||||
dev_err(&pdev->dev, "request_threaded_irq failure. irq = %d\n",
|
||||
pdev->irq);
|
||||
goto unmap_memory;
|
||||
}
|
||||
INIT_DELAYED_WORK(&dev->timer_work, mei_timer);
|
||||
if (mei_hw_init(dev)) {
|
||||
printk(KERN_ERR "mei: Init hw failure.\n");
|
||||
dev_err(&pdev->dev, "init hw failure.\n");
|
||||
err = -ENODEV;
|
||||
goto release_irq;
|
||||
}
|
||||
|
@ -1020,7 +1013,7 @@ static int __devinit mei_probe(struct pci_dev *pdev,
|
|||
|
||||
mutex_unlock(&mei_mutex);
|
||||
|
||||
pr_debug("mei: Driver initialization successful.\n");
|
||||
pr_debug("initialization successful.\n");
|
||||
|
||||
return 0;
|
||||
|
||||
|
@ -1041,7 +1034,7 @@ disable_device:
|
|||
pci_disable_device(pdev);
|
||||
end:
|
||||
mutex_unlock(&mei_mutex);
|
||||
printk(KERN_ERR "mei: Driver initialization failed.\n");
|
||||
dev_err(&pdev->dev, "initialization failed.\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
|
@ -1160,8 +1153,8 @@ static int mei_pci_resume(struct device *device)
|
|||
IRQF_SHARED, mei_driver_name, dev);
|
||||
|
||||
if (err) {
|
||||
printk(KERN_ERR "mei: Request_irq failure. irq = %d\n",
|
||||
pdev->irq);
|
||||
dev_err(&pdev->dev, "request_threaded_irq failed: irq = %d.\n",
|
||||
pdev->irq);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
@ -1204,11 +1197,11 @@ static int __init mei_init_module(void)
|
|||
{
|
||||
int ret;
|
||||
|
||||
pr_debug("mei: %s\n", mei_driver_string);
|
||||
pr_debug("loading.\n");
|
||||
/* init pci module */
|
||||
ret = pci_register_driver(&mei_driver);
|
||||
if (ret < 0)
|
||||
printk(KERN_ERR "mei: Error registering driver.\n");
|
||||
pr_err("error registering driver.\n");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -1226,7 +1219,7 @@ static void __exit mei_exit_module(void)
|
|||
misc_deregister(&mei_misc_device);
|
||||
pci_unregister_driver(&mei_driver);
|
||||
|
||||
pr_debug("mei: Driver unloaded successfully.\n");
|
||||
pr_debug("unloaded successfully.\n");
|
||||
}
|
||||
|
||||
module_exit(mei_exit_module);
|
|
@ -19,7 +19,7 @@
|
|||
|
||||
#include <linux/types.h>
|
||||
#include <linux/watchdog.h>
|
||||
#include "mei.h"
|
||||
#include <linux/mei.h>
|
||||
#include "hw.h"
|
||||
|
||||
/*
|
|
@ -24,7 +24,7 @@
|
|||
#include "mei_dev.h"
|
||||
#include "hw.h"
|
||||
#include "interface.h"
|
||||
#include "mei.h"
|
||||
#include <linux/mei.h>
|
||||
|
||||
static const u8 mei_start_wd_params[] = { 0x02, 0x12, 0x13, 0x10 };
|
||||
static const u8 mei_stop_wd_params[] = { 0x02, 0x02, 0x14, 0x10 };
|
||||
|
@ -45,23 +45,22 @@ const uuid_le mei_wd_guid = UUID_LE(0x05B79A6F, 0x4628, 0x4D7F, 0x89,
|
|||
0x9D, 0xA9, 0x15, 0x14, 0xCB,
|
||||
0x32, 0xAB);
|
||||
|
||||
void mei_wd_set_start_timeout(struct mei_device *dev, u16 timeout)
|
||||
static void mei_wd_set_start_timeout(struct mei_device *dev, u16 timeout)
|
||||
{
|
||||
dev_dbg(&dev->pdev->dev, "timeout=%d.\n", timeout);
|
||||
dev_dbg(&dev->pdev->dev, "wd: set timeout=%d.\n", timeout);
|
||||
memcpy(dev->wd_data, mei_start_wd_params, MEI_WD_PARAMS_SIZE);
|
||||
memcpy(dev->wd_data + MEI_WD_PARAMS_SIZE,
|
||||
&timeout, sizeof(u16));
|
||||
memcpy(dev->wd_data + MEI_WD_PARAMS_SIZE, &timeout, sizeof(u16));
|
||||
}
|
||||
|
||||
/**
|
||||
* host_init_wd - mei initialization wd.
|
||||
*
|
||||
* @dev: the device structure
|
||||
* returns -ENENT if wd client cannot be found
|
||||
* -EIO if write has failed
|
||||
*/
|
||||
bool mei_wd_host_init(struct mei_device *dev)
|
||||
int mei_wd_host_init(struct mei_device *dev)
|
||||
{
|
||||
bool ret = false;
|
||||
|
||||
mei_cl_init(&dev->wd_cl, dev);
|
||||
|
||||
/* look for WD client and connect to it */
|
||||
|
@ -72,25 +71,21 @@ bool mei_wd_host_init(struct mei_device *dev)
|
|||
mei_find_me_client_update_filext(dev, &dev->wd_cl,
|
||||
&mei_wd_guid, MEI_WD_HOST_CLIENT_ID);
|
||||
|
||||
dev_dbg(&dev->pdev->dev, "check wd_cl\n");
|
||||
if (MEI_FILE_CONNECTING == dev->wd_cl.state) {
|
||||
if (mei_connect(dev, &dev->wd_cl)) {
|
||||
dev_dbg(&dev->pdev->dev, "Failed to connect to WD client\n");
|
||||
dev->wd_cl.state = MEI_FILE_DISCONNECTED;
|
||||
dev->wd_cl.host_client_id = 0;
|
||||
ret = false;
|
||||
goto end;
|
||||
} else {
|
||||
dev->wd_cl.timer_count = CONNECT_TIMEOUT;
|
||||
}
|
||||
} else {
|
||||
dev_dbg(&dev->pdev->dev, "Failed to find WD client\n");
|
||||
ret = false;
|
||||
goto end;
|
||||
dev_dbg(&dev->pdev->dev, "wd: check client\n");
|
||||
if (MEI_FILE_CONNECTING != dev->wd_cl.state) {
|
||||
dev_info(&dev->pdev->dev, "wd: failed to find the client\n");
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
end:
|
||||
return ret;
|
||||
if (mei_connect(dev, &dev->wd_cl)) {
|
||||
dev_err(&dev->pdev->dev, "wd: failed to connect to the client\n");
|
||||
dev->wd_cl.state = MEI_FILE_DISCONNECTED;
|
||||
dev->wd_cl.host_client_id = 0;
|
||||
return -EIO;
|
||||
}
|
||||
dev->wd_cl.timer_count = CONNECT_TIMEOUT;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -159,7 +154,7 @@ int mei_wd_stop(struct mei_device *dev, bool preserve)
|
|||
if (ret)
|
||||
goto out;
|
||||
} else {
|
||||
dev_dbg(&dev->pdev->dev, "send stop WD failed\n");
|
||||
dev_err(&dev->pdev->dev, "wd: send stop failed\n");
|
||||
}
|
||||
|
||||
dev->wd_pending = false;
|
||||
|
@ -173,13 +168,13 @@ int mei_wd_stop(struct mei_device *dev, bool preserve)
|
|||
dev->wd_stopped, 10 * HZ);
|
||||
mutex_lock(&dev->device_lock);
|
||||
if (dev->wd_stopped) {
|
||||
dev_dbg(&dev->pdev->dev, "stop wd complete ret=%d.\n", ret);
|
||||
dev_dbg(&dev->pdev->dev, "wd: stop completed ret=%d.\n", ret);
|
||||
ret = 0;
|
||||
} else {
|
||||
if (!ret)
|
||||
ret = -ETIMEDOUT;
|
||||
dev_warn(&dev->pdev->dev,
|
||||
"stop wd failed to complete ret=%d.\n", ret);
|
||||
"wd: stop failed to complete ret=%d.\n", ret);
|
||||
}
|
||||
|
||||
if (preserve)
|
||||
|
@ -208,13 +203,15 @@ static int mei_wd_ops_start(struct watchdog_device *wd_dev)
|
|||
mutex_lock(&dev->device_lock);
|
||||
|
||||
if (dev->mei_state != MEI_ENABLED) {
|
||||
dev_dbg(&dev->pdev->dev, "mei_state != MEI_ENABLED mei_state= %d\n",
|
||||
dev->mei_state);
|
||||
dev_dbg(&dev->pdev->dev,
|
||||
"wd: mei_state != MEI_ENABLED mei_state = %d\n",
|
||||
dev->mei_state);
|
||||
goto end_unlock;
|
||||
}
|
||||
|
||||
if (dev->wd_cl.state != MEI_FILE_CONNECTED) {
|
||||
dev_dbg(&dev->pdev->dev, "MEI Driver is not connected to Watchdog Client\n");
|
||||
dev_dbg(&dev->pdev->dev,
|
||||
"MEI Driver is not connected to Watchdog Client\n");
|
||||
goto end_unlock;
|
||||
}
|
||||
|
||||
|
@ -267,7 +264,7 @@ static int mei_wd_ops_ping(struct watchdog_device *wd_dev)
|
|||
mutex_lock(&dev->device_lock);
|
||||
|
||||
if (dev->wd_cl.state != MEI_FILE_CONNECTED) {
|
||||
dev_dbg(&dev->pdev->dev, "wd is not connected.\n");
|
||||
dev_err(&dev->pdev->dev, "wd: not connected.\n");
|
||||
ret = -ENODEV;
|
||||
goto end;
|
||||
}
|
||||
|
@ -277,16 +274,17 @@ static int mei_wd_ops_ping(struct watchdog_device *wd_dev)
|
|||
mei_flow_ctrl_creds(dev, &dev->wd_cl) > 0) {
|
||||
|
||||
dev->mei_host_buffer_is_empty = false;
|
||||
dev_dbg(&dev->pdev->dev, "sending watchdog ping\n");
|
||||
dev_dbg(&dev->pdev->dev, "wd: sending ping\n");
|
||||
|
||||
if (mei_wd_send(dev)) {
|
||||
dev_dbg(&dev->pdev->dev, "wd send failed.\n");
|
||||
dev_err(&dev->pdev->dev, "wd: send failed.\n");
|
||||
ret = -EIO;
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (mei_flow_ctrl_reduce(dev, &dev->wd_cl)) {
|
||||
dev_dbg(&dev->pdev->dev, "mei_flow_ctrl_reduce() failed.\n");
|
||||
dev_err(&dev->pdev->dev,
|
||||
"wd: mei_flow_ctrl_reduce() failed.\n");
|
||||
ret = -EIO;
|
||||
goto end;
|
||||
}
|
||||
|
@ -346,7 +344,7 @@ static const struct watchdog_info wd_info = {
|
|||
.options = WDIOF_KEEPALIVEPING,
|
||||
};
|
||||
|
||||
struct watchdog_device amt_wd_dev = {
|
||||
static struct watchdog_device amt_wd_dev = {
|
||||
.info = &wd_info,
|
||||
.ops = &wd_ops,
|
||||
.timeout = AMT_WD_DEFAULT_TIMEOUT,
|
||||
|
@ -362,10 +360,12 @@ void mei_watchdog_register(struct mei_device *dev)
|
|||
dev->wd_due_counter = !!dev->wd_timeout;
|
||||
|
||||
if (watchdog_register_device(&amt_wd_dev)) {
|
||||
dev_err(&dev->pdev->dev, "unable to register watchdog device.\n");
|
||||
dev_err(&dev->pdev->dev,
|
||||
"wd: unable to register watchdog device.\n");
|
||||
dev->wd_interface_reg = false;
|
||||
} else {
|
||||
dev_dbg(&dev->pdev->dev, "successfully register watchdog interface.\n");
|
||||
dev_dbg(&dev->pdev->dev,
|
||||
"wd: successfully register watchdog interface.\n");
|
||||
dev->wd_interface_reg = true;
|
||||
}
|
||||
}
|
|
@ -203,37 +203,6 @@ config WANXL_BUILD_FIRMWARE
|
|||
|
||||
You should never need this option, say N.
|
||||
|
||||
config PC300
|
||||
tristate "Cyclades-PC300 support (RS-232/V.35, X.21, T1/E1 boards)"
|
||||
depends on HDLC && PCI && BROKEN
|
||||
---help---
|
||||
This driver is broken because of struct tty_driver change.
|
||||
|
||||
Driver for the Cyclades-PC300 synchronous communication boards.
|
||||
|
||||
These boards provide synchronous serial interfaces to your
|
||||
Linux box (interfaces currently available are RS-232/V.35, X.21 and
|
||||
T1/E1). If you wish to support Multilink PPP, please select the
|
||||
option later and read the file README.mlppp provided by PC300
|
||||
package.
|
||||
|
||||
To compile this as a module, choose M here: the module
|
||||
will be called pc300.
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
config PC300_MLPPP
|
||||
bool "Cyclades-PC300 MLPPP support"
|
||||
depends on PC300 && PPP_MULTILINK && PPP_SYNC_TTY && HDLC_PPP
|
||||
help
|
||||
Multilink PPP over the PC300 synchronous communication boards.
|
||||
|
||||
comment "Cyclades-PC300 MLPPP support is disabled."
|
||||
depends on HDLC && PC300 && (PPP=n || !PPP_MULTILINK || PPP_SYNC_TTY=n || !HDLC_PPP)
|
||||
|
||||
comment "Refer to the file README.mlppp, provided by PC300 package."
|
||||
depends on HDLC && PC300 && (PPP=n || !PPP_MULTILINK || PPP_SYNC_TTY=n || !HDLC_PPP)
|
||||
|
||||
config PC300TOO
|
||||
tristate "Cyclades PC300 RSV/X21 alternative support"
|
||||
depends on HDLC && PCI
|
||||
|
|
|
@ -17,10 +17,6 @@ obj-$(CONFIG_HDLC_FR) += hdlc_fr.o
|
|||
obj-$(CONFIG_HDLC_PPP) += hdlc_ppp.o
|
||||
obj-$(CONFIG_HDLC_X25) += hdlc_x25.o
|
||||
|
||||
pc300-y := pc300_drv.o
|
||||
pc300-$(CONFIG_PC300_MLPPP) += pc300_tty.o
|
||||
pc300-objs := $(pc300-y)
|
||||
|
||||
obj-$(CONFIG_HOSTESS_SV11) += z85230.o hostess_sv11.o
|
||||
obj-$(CONFIG_SEALEVEL_4021) += z85230.o sealevel.o
|
||||
obj-$(CONFIG_COSA) += cosa.o
|
||||
|
@ -35,7 +31,6 @@ obj-$(CONFIG_SDLA) += sdla.o
|
|||
obj-$(CONFIG_CYCLADES_SYNC) += cycx_drv.o cyclomx.o
|
||||
obj-$(CONFIG_LAPBETHER) += lapbether.o
|
||||
obj-$(CONFIG_SBNI) += sbni.o
|
||||
obj-$(CONFIG_PC300) += pc300.o
|
||||
obj-$(CONFIG_N2) += n2.o
|
||||
obj-$(CONFIG_C101) += c101.o
|
||||
obj-$(CONFIG_WANXL) += wanxl.o
|
||||
|
|
|
@ -24,8 +24,6 @@ menuconfig STAGING
|
|||
|
||||
if STAGING
|
||||
|
||||
source "drivers/staging/serial/Kconfig"
|
||||
|
||||
source "drivers/staging/et131x/Kconfig"
|
||||
|
||||
source "drivers/staging/slicoss/Kconfig"
|
||||
|
@ -72,8 +70,6 @@ source "drivers/staging/vt6655/Kconfig"
|
|||
|
||||
source "drivers/staging/vt6656/Kconfig"
|
||||
|
||||
source "drivers/staging/vme/Kconfig"
|
||||
|
||||
source "drivers/staging/sep/Kconfig"
|
||||
|
||||
source "drivers/staging/iio/Kconfig"
|
||||
|
@ -114,12 +110,12 @@ source "drivers/staging/cptm1217/Kconfig"
|
|||
|
||||
source "drivers/staging/ste_rmi4/Kconfig"
|
||||
|
||||
source "drivers/staging/mei/Kconfig"
|
||||
|
||||
source "drivers/staging/nvec/Kconfig"
|
||||
|
||||
source "drivers/staging/media/Kconfig"
|
||||
|
||||
source "drivers/staging/net/Kconfig"
|
||||
|
||||
source "drivers/staging/omapdrm/Kconfig"
|
||||
|
||||
source "drivers/staging/android/Kconfig"
|
||||
|
@ -132,4 +128,8 @@ source "drivers/staging/ozwpan/Kconfig"
|
|||
|
||||
source "drivers/staging/ccg/Kconfig"
|
||||
|
||||
source "drivers/staging/ipack/Kconfig"
|
||||
|
||||
source "drivers/staging/gdm72xx/Kconfig"
|
||||
|
||||
endif # STAGING
|
||||
|
|
|
@ -3,8 +3,8 @@
|
|||
# fix for build system bug...
|
||||
obj-$(CONFIG_STAGING) += staging.o
|
||||
|
||||
obj-y += serial/
|
||||
obj-y += media/
|
||||
obj-y += net/
|
||||
obj-$(CONFIG_ET131X) += et131x/
|
||||
obj-$(CONFIG_SLICOSS) += slicoss/
|
||||
obj-$(CONFIG_USBIP_CORE) += usbip/
|
||||
|
@ -29,6 +29,7 @@ obj-$(CONFIG_OCTEON_ETHERNET) += octeon/
|
|||
obj-$(CONFIG_VT6655) += vt6655/
|
||||
obj-$(CONFIG_VT6656) += vt6656/
|
||||
obj-$(CONFIG_VME_BUS) += vme/
|
||||
obj-$(CONFIG_IPACK_BUS) += ipack/
|
||||
obj-$(CONFIG_DX_SEP) += sep/
|
||||
obj-$(CONFIG_IIO) += iio/
|
||||
obj-$(CONFIG_ZRAM) += zram/
|
||||
|
@ -49,7 +50,6 @@ obj-$(CONFIG_FT1000) += ft1000/
|
|||
obj-$(CONFIG_SPEAKUP) += speakup/
|
||||
obj-$(CONFIG_TOUCHSCREEN_CLEARPAD_TM1217) += cptm1217/
|
||||
obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4) += ste_rmi4/
|
||||
obj-$(CONFIG_INTEL_MEI) += mei/
|
||||
obj-$(CONFIG_MFD_NVEC) += nvec/
|
||||
obj-$(CONFIG_DRM_OMAP) += omapdrm/
|
||||
obj-$(CONFIG_ANDROID) += android/
|
||||
|
@ -57,3 +57,4 @@ obj-$(CONFIG_PHONE) += telephony/
|
|||
obj-$(CONFIG_RAMSTER) += ramster/
|
||||
obj-$(CONFIG_USB_WPAN_HCD) += ozwpan/
|
||||
obj-$(CONFIG_USB_G_CCG) += ccg/
|
||||
obj-$(CONFIG_WIMAX_GDM72XX) += gdm72xx/
|
||||
|
|
|
@ -25,17 +25,9 @@ config ANDROID_LOGGER
|
|||
tristate "Android log driver"
|
||||
default n
|
||||
|
||||
config ANDROID_PERSISTENT_RAM
|
||||
bool
|
||||
depends on HAVE_MEMBLOCK
|
||||
select REED_SOLOMON
|
||||
select REED_SOLOMON_ENC8
|
||||
select REED_SOLOMON_DEC8
|
||||
|
||||
config ANDROID_RAM_CONSOLE
|
||||
bool "Android RAM buffer console"
|
||||
depends on !S390 && !UML && HAVE_MEMBLOCK
|
||||
select ANDROID_PERSISTENT_RAM
|
||||
depends on !S390 && !UML && HAVE_MEMBLOCK && PSTORE_RAM=y
|
||||
default n
|
||||
|
||||
config ANDROID_TIMED_OUTPUT
|
||||
|
@ -53,31 +45,15 @@ config ANDROID_LOW_MEMORY_KILLER
|
|||
---help---
|
||||
Register processes to be killed when memory is low
|
||||
|
||||
config ANDROID_INTF_ALARM
|
||||
config ANDROID_INTF_ALARM_DEV
|
||||
bool "Android alarm driver"
|
||||
depends on RTC_CLASS
|
||||
default n
|
||||
help
|
||||
Provides non-wakeup and rtc backed wakeup alarms based on rtc or
|
||||
elapsed realtime, and a non-wakeup alarm on the monotonic clock.
|
||||
Also provides an interface to set the wall time which must be used
|
||||
for elapsed realtime to work.
|
||||
Also exports the alarm interface to user-space.
|
||||
|
||||
config ANDROID_INTF_ALARM_DEV
|
||||
bool "Android alarm device"
|
||||
depends on ANDROID_INTF_ALARM
|
||||
default y
|
||||
help
|
||||
Exports the alarm interface to user-space.
|
||||
|
||||
config ANDROID_ALARM_OLDDRV_COMPAT
|
||||
bool "Android Alarm compatability with old drivers"
|
||||
depends on ANDROID_INTF_ALARM
|
||||
default n
|
||||
help
|
||||
Provides preprocessor alias to aid compatability with
|
||||
older out-of-tree drivers that use the Android Alarm
|
||||
in-kernel API. This will be removed eventually.
|
||||
endif # if ANDROID
|
||||
|
||||
endmenu
|
||||
|
|
|
@ -1,10 +1,8 @@
|
|||
obj-$(CONFIG_ANDROID_BINDER_IPC) += binder.o
|
||||
obj-$(CONFIG_ASHMEM) += ashmem.o
|
||||
obj-$(CONFIG_ANDROID_LOGGER) += logger.o
|
||||
obj-$(CONFIG_ANDROID_PERSISTENT_RAM) += persistent_ram.o
|
||||
obj-$(CONFIG_ANDROID_RAM_CONSOLE) += ram_console.o
|
||||
obj-$(CONFIG_ANDROID_TIMED_OUTPUT) += timed_output.o
|
||||
obj-$(CONFIG_ANDROID_TIMED_GPIO) += timed_gpio.o
|
||||
obj-$(CONFIG_ANDROID_LOW_MEMORY_KILLER) += lowmemorykiller.o
|
||||
obj-$(CONFIG_ANDROID_INTF_ALARM) += alarm.o
|
||||
obj-$(CONFIG_ANDROID_INTF_ALARM_DEV) += alarm-dev.o
|
||||
|
|
|
@ -22,19 +22,9 @@
|
|||
#include <linux/sched.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/alarmtimer.h>
|
||||
#include "android_alarm.h"
|
||||
|
||||
/* XXX - Hack out wakelocks, while they are out of tree */
|
||||
struct wake_lock {
|
||||
int i;
|
||||
};
|
||||
#define wake_lock(x)
|
||||
#define wake_lock_timeout(x, y)
|
||||
#define wake_unlock(x)
|
||||
#define WAKE_LOCK_SUSPEND 0
|
||||
#define wake_lock_init(x, y, z) ((x)->i = 1)
|
||||
#define wake_lock_destroy(x)
|
||||
|
||||
#define ANDROID_ALARM_PRINT_INFO (1U << 0)
|
||||
#define ANDROID_ALARM_PRINT_IO (1U << 1)
|
||||
#define ANDROID_ALARM_PRINT_INT (1U << 2)
|
||||
|
@ -54,19 +44,65 @@ module_param_named(debug_mask, debug_mask, int, S_IRUGO | S_IWUSR | S_IWGRP);
|
|||
ANDROID_ALARM_RTC_WAKEUP_MASK | \
|
||||
ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP_MASK)
|
||||
|
||||
/* support old usespace code */
|
||||
/* support old userspace code */
|
||||
#define ANDROID_ALARM_SET_OLD _IOW('a', 2, time_t) /* set alarm */
|
||||
#define ANDROID_ALARM_SET_AND_WAIT_OLD _IOW('a', 3, time_t)
|
||||
|
||||
static int alarm_opened;
|
||||
static DEFINE_SPINLOCK(alarm_slock);
|
||||
static struct wake_lock alarm_wake_lock;
|
||||
static struct wakeup_source alarm_wake_lock;
|
||||
static DECLARE_WAIT_QUEUE_HEAD(alarm_wait_queue);
|
||||
static uint32_t alarm_pending;
|
||||
static uint32_t alarm_enabled;
|
||||
static uint32_t wait_pending;
|
||||
|
||||
static struct android_alarm alarms[ANDROID_ALARM_TYPE_COUNT];
|
||||
struct devalarm {
|
||||
union {
|
||||
struct hrtimer hrt;
|
||||
struct alarm alrm;
|
||||
} u;
|
||||
enum android_alarm_type type;
|
||||
};
|
||||
|
||||
static struct devalarm alarms[ANDROID_ALARM_TYPE_COUNT];
|
||||
|
||||
|
||||
static int is_wakeup(enum android_alarm_type type)
|
||||
{
|
||||
if (type == ANDROID_ALARM_RTC_WAKEUP ||
|
||||
type == ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void devalarm_start(struct devalarm *alrm, ktime_t exp)
|
||||
{
|
||||
if (is_wakeup(alrm->type))
|
||||
alarm_start(&alrm->u.alrm, exp);
|
||||
else
|
||||
hrtimer_start(&alrm->u.hrt, exp, HRTIMER_MODE_ABS);
|
||||
}
|
||||
|
||||
|
||||
static int devalarm_try_to_cancel(struct devalarm *alrm)
|
||||
{
|
||||
int ret;
|
||||
if (is_wakeup(alrm->type))
|
||||
ret = alarm_try_to_cancel(&alrm->u.alrm);
|
||||
else
|
||||
ret = hrtimer_try_to_cancel(&alrm->u.hrt);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void devalarm_cancel(struct devalarm *alrm)
|
||||
{
|
||||
if (is_wakeup(alrm->type))
|
||||
alarm_cancel(&alrm->u.alrm);
|
||||
else
|
||||
hrtimer_cancel(&alrm->u.hrt);
|
||||
}
|
||||
|
||||
|
||||
static long alarm_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
|
@ -75,6 +111,8 @@ static long alarm_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
|||
struct timespec new_alarm_time;
|
||||
struct timespec new_rtc_time;
|
||||
struct timespec tmp_time;
|
||||
struct rtc_time new_rtc_tm;
|
||||
struct rtc_device *rtc_dev;
|
||||
enum android_alarm_type alarm_type = ANDROID_ALARM_IOCTL_TO_TYPE(cmd);
|
||||
uint32_t alarm_type_mask = 1U << alarm_type;
|
||||
|
||||
|
@ -101,11 +139,11 @@ static long alarm_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
|||
case ANDROID_ALARM_CLEAR(0):
|
||||
spin_lock_irqsave(&alarm_slock, flags);
|
||||
pr_alarm(IO, "alarm %d clear\n", alarm_type);
|
||||
android_alarm_try_to_cancel(&alarms[alarm_type]);
|
||||
devalarm_try_to_cancel(&alarms[alarm_type]);
|
||||
if (alarm_pending) {
|
||||
alarm_pending &= ~alarm_type_mask;
|
||||
if (!alarm_pending && !wait_pending)
|
||||
wake_unlock(&alarm_wake_lock);
|
||||
__pm_relax(&alarm_wake_lock);
|
||||
}
|
||||
alarm_enabled &= ~alarm_type_mask;
|
||||
spin_unlock_irqrestore(&alarm_slock, flags);
|
||||
|
@ -132,8 +170,7 @@ from_old_alarm_set:
|
|||
pr_alarm(IO, "alarm %d set %ld.%09ld\n", alarm_type,
|
||||
new_alarm_time.tv_sec, new_alarm_time.tv_nsec);
|
||||
alarm_enabled |= alarm_type_mask;
|
||||
android_alarm_start_range(&alarms[alarm_type],
|
||||
timespec_to_ktime(new_alarm_time),
|
||||
devalarm_start(&alarms[alarm_type],
|
||||
timespec_to_ktime(new_alarm_time));
|
||||
spin_unlock_irqrestore(&alarm_slock, flags);
|
||||
if (ANDROID_ALARM_BASE_CMD(cmd) != ANDROID_ALARM_SET_AND_WAIT(0)
|
||||
|
@ -144,7 +181,7 @@ from_old_alarm_set:
|
|||
spin_lock_irqsave(&alarm_slock, flags);
|
||||
pr_alarm(IO, "alarm wait\n");
|
||||
if (!alarm_pending && wait_pending) {
|
||||
wake_unlock(&alarm_wake_lock);
|
||||
__pm_relax(&alarm_wake_lock);
|
||||
wait_pending = 0;
|
||||
}
|
||||
spin_unlock_irqrestore(&alarm_slock, flags);
|
||||
|
@ -163,7 +200,13 @@ from_old_alarm_set:
|
|||
rv = -EFAULT;
|
||||
goto err1;
|
||||
}
|
||||
rv = android_alarm_set_rtc(new_rtc_time);
|
||||
rtc_time_to_tm(new_rtc_time.tv_sec, &new_rtc_tm);
|
||||
rtc_dev = alarmtimer_get_rtcdev();
|
||||
rv = do_settimeofday(&new_rtc_time);
|
||||
if (rv < 0)
|
||||
goto err1;
|
||||
if (rtc_dev)
|
||||
rv = rtc_set_time(rtc_dev, &new_rtc_tm);
|
||||
spin_lock_irqsave(&alarm_slock, flags);
|
||||
alarm_pending |= ANDROID_ALARM_TIME_CHANGE_MASK;
|
||||
wake_up(&alarm_wait_queue);
|
||||
|
@ -179,8 +222,7 @@ from_old_alarm_set:
|
|||
break;
|
||||
case ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP:
|
||||
case ANDROID_ALARM_ELAPSED_REALTIME:
|
||||
tmp_time =
|
||||
ktime_to_timespec(alarm_get_elapsed_realtime());
|
||||
get_monotonic_boottime(&tmp_time);
|
||||
break;
|
||||
case ANDROID_ALARM_TYPE_COUNT:
|
||||
case ANDROID_ALARM_SYSTEMTIME:
|
||||
|
@ -224,14 +266,14 @@ static int alarm_release(struct inode *inode, struct file *file)
|
|||
alarm_enabled &= ~alarm_type_mask;
|
||||
}
|
||||
spin_unlock_irqrestore(&alarm_slock, flags);
|
||||
android_alarm_cancel(&alarms[i]);
|
||||
devalarm_cancel(&alarms[i]);
|
||||
spin_lock_irqsave(&alarm_slock, flags);
|
||||
}
|
||||
if (alarm_pending | wait_pending) {
|
||||
if (alarm_pending)
|
||||
pr_alarm(INFO, "alarm_release: clear "
|
||||
"pending alarms %x\n", alarm_pending);
|
||||
wake_unlock(&alarm_wake_lock);
|
||||
__pm_relax(&alarm_wake_lock);
|
||||
wait_pending = 0;
|
||||
alarm_pending = 0;
|
||||
}
|
||||
|
@ -241,15 +283,15 @@ static int alarm_release(struct inode *inode, struct file *file)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void alarm_triggered(struct android_alarm *alarm)
|
||||
static void devalarm_triggered(struct devalarm *alarm)
|
||||
{
|
||||
unsigned long flags;
|
||||
uint32_t alarm_type_mask = 1U << alarm->type;
|
||||
|
||||
pr_alarm(INT, "alarm_triggered type %d\n", alarm->type);
|
||||
pr_alarm(INT, "devalarm_triggered type %d\n", alarm->type);
|
||||
spin_lock_irqsave(&alarm_slock, flags);
|
||||
if (alarm_enabled & alarm_type_mask) {
|
||||
wake_lock_timeout(&alarm_wake_lock, 5 * HZ);
|
||||
__pm_wakeup_event(&alarm_wake_lock, 5000); /* 5secs */
|
||||
alarm_enabled &= ~alarm_type_mask;
|
||||
alarm_pending |= alarm_type_mask;
|
||||
wake_up(&alarm_wait_queue);
|
||||
|
@ -257,6 +299,25 @@ static void alarm_triggered(struct android_alarm *alarm)
|
|||
spin_unlock_irqrestore(&alarm_slock, flags);
|
||||
}
|
||||
|
||||
|
||||
static enum hrtimer_restart devalarm_hrthandler(struct hrtimer *hrt)
|
||||
{
|
||||
struct devalarm *devalrm = container_of(hrt, struct devalarm, u.hrt);
|
||||
|
||||
devalarm_triggered(devalrm);
|
||||
return HRTIMER_NORESTART;
|
||||
}
|
||||
|
||||
static enum alarmtimer_restart devalarm_alarmhandler(struct alarm *alrm,
|
||||
ktime_t now)
|
||||
{
|
||||
struct devalarm *devalrm = container_of(alrm, struct devalarm, u.alrm);
|
||||
|
||||
devalarm_triggered(devalrm);
|
||||
return ALARMTIMER_NORESTART;
|
||||
}
|
||||
|
||||
|
||||
static const struct file_operations alarm_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.unlocked_ioctl = alarm_ioctl,
|
||||
|
@ -279,17 +340,31 @@ static int __init alarm_dev_init(void)
|
|||
if (err)
|
||||
return err;
|
||||
|
||||
for (i = 0; i < ANDROID_ALARM_TYPE_COUNT; i++)
|
||||
android_alarm_init(&alarms[i], i, alarm_triggered);
|
||||
wake_lock_init(&alarm_wake_lock, WAKE_LOCK_SUSPEND, "alarm");
|
||||
alarm_init(&alarms[ANDROID_ALARM_RTC_WAKEUP].u.alrm,
|
||||
ALARM_REALTIME, devalarm_alarmhandler);
|
||||
hrtimer_init(&alarms[ANDROID_ALARM_RTC].u.hrt,
|
||||
CLOCK_REALTIME, HRTIMER_MODE_ABS);
|
||||
alarm_init(&alarms[ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP].u.alrm,
|
||||
ALARM_BOOTTIME, devalarm_alarmhandler);
|
||||
hrtimer_init(&alarms[ANDROID_ALARM_ELAPSED_REALTIME].u.hrt,
|
||||
CLOCK_BOOTTIME, HRTIMER_MODE_ABS);
|
||||
hrtimer_init(&alarms[ANDROID_ALARM_SYSTEMTIME].u.hrt,
|
||||
CLOCK_MONOTONIC, HRTIMER_MODE_ABS);
|
||||
|
||||
for (i = 0; i < ANDROID_ALARM_TYPE_COUNT; i++) {
|
||||
alarms[i].type = i;
|
||||
if (!is_wakeup(i))
|
||||
alarms[i].u.hrt.function = devalarm_hrthandler;
|
||||
}
|
||||
|
||||
wakeup_source_init(&alarm_wake_lock, "alarm");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit alarm_dev_exit(void)
|
||||
{
|
||||
misc_deregister(&alarm_device);
|
||||
wake_lock_destroy(&alarm_wake_lock);
|
||||
wakeup_source_trash(&alarm_wake_lock);
|
||||
}
|
||||
|
||||
module_init(alarm_dev_init);
|
||||
|
|
|
@ -1,601 +0,0 @@
|
|||
/* drivers/rtc/alarm.c
|
||||
*
|
||||
* Copyright (C) 2007-2009 Google, Inc.
|
||||
*
|
||||
* This software is licensed under the terms of the GNU General Public
|
||||
* License version 2, as published by the Free Software Foundation, and
|
||||
* may be copied, distributed, and modified under those terms.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/time.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/miscdevice.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/rtc.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include "android_alarm.h"
|
||||
|
||||
/* XXX - Hack out wakelocks, while they are out of tree */
|
||||
struct wake_lock {
|
||||
int i;
|
||||
};
|
||||
#define wake_lock(x)
|
||||
#define wake_lock_timeout(x, y)
|
||||
#define wake_unlock(x)
|
||||
#define WAKE_LOCK_SUSPEND 0
|
||||
#define wake_lock_init(x, y, z) ((x)->i = 1)
|
||||
#define wake_lock_destroy(x)
|
||||
|
||||
#define ANDROID_ALARM_PRINT_ERROR (1U << 0)
|
||||
#define ANDROID_ALARM_PRINT_INIT_STATUS (1U << 1)
|
||||
#define ANDROID_ALARM_PRINT_TSET (1U << 2)
|
||||
#define ANDROID_ALARM_PRINT_CALL (1U << 3)
|
||||
#define ANDROID_ALARM_PRINT_SUSPEND (1U << 4)
|
||||
#define ANDROID_ALARM_PRINT_INT (1U << 5)
|
||||
#define ANDROID_ALARM_PRINT_FLOW (1U << 6)
|
||||
|
||||
static int debug_mask = ANDROID_ALARM_PRINT_ERROR | \
|
||||
ANDROID_ALARM_PRINT_INIT_STATUS;
|
||||
module_param_named(debug_mask, debug_mask, int, S_IRUGO | S_IWUSR | S_IWGRP);
|
||||
|
||||
#define pr_alarm(debug_level_mask, args...) \
|
||||
do { \
|
||||
if (debug_mask & ANDROID_ALARM_PRINT_##debug_level_mask) { \
|
||||
pr_info(args); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define ANDROID_ALARM_WAKEUP_MASK ( \
|
||||
ANDROID_ALARM_RTC_WAKEUP_MASK | \
|
||||
ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP_MASK)
|
||||
|
||||
/* support old usespace code */
|
||||
#define ANDROID_ALARM_SET_OLD _IOW('a', 2, time_t) /* set alarm */
|
||||
#define ANDROID_ALARM_SET_AND_WAIT_OLD _IOW('a', 3, time_t)
|
||||
|
||||
struct alarm_queue {
|
||||
struct rb_root alarms;
|
||||
struct rb_node *first;
|
||||
struct hrtimer timer;
|
||||
ktime_t delta;
|
||||
bool stopped;
|
||||
ktime_t stopped_time;
|
||||
};
|
||||
|
||||
static struct rtc_device *alarm_rtc_dev;
|
||||
static DEFINE_SPINLOCK(alarm_slock);
|
||||
static DEFINE_MUTEX(alarm_setrtc_mutex);
|
||||
static struct wake_lock alarm_rtc_wake_lock;
|
||||
static struct platform_device *alarm_platform_dev;
|
||||
struct alarm_queue alarms[ANDROID_ALARM_TYPE_COUNT];
|
||||
static bool suspended;
|
||||
|
||||
static void update_timer_locked(struct alarm_queue *base, bool head_removed)
|
||||
{
|
||||
struct android_alarm *alarm;
|
||||
bool is_wakeup = base == &alarms[ANDROID_ALARM_RTC_WAKEUP] ||
|
||||
base == &alarms[ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP];
|
||||
|
||||
if (base->stopped) {
|
||||
pr_alarm(FLOW, "changed alarm while setting the wall time\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (is_wakeup && !suspended && head_removed)
|
||||
wake_unlock(&alarm_rtc_wake_lock);
|
||||
|
||||
if (!base->first)
|
||||
return;
|
||||
|
||||
alarm = container_of(base->first, struct android_alarm, node);
|
||||
|
||||
pr_alarm(FLOW, "selected alarm, type %d, func %pF at %lld\n",
|
||||
alarm->type, alarm->function, ktime_to_ns(alarm->expires));
|
||||
|
||||
if (is_wakeup && suspended) {
|
||||
pr_alarm(FLOW, "changed alarm while suspened\n");
|
||||
wake_lock_timeout(&alarm_rtc_wake_lock, 1 * HZ);
|
||||
return;
|
||||
}
|
||||
|
||||
hrtimer_try_to_cancel(&base->timer);
|
||||
base->timer.node.expires = ktime_add(base->delta, alarm->expires);
|
||||
base->timer._softexpires = ktime_add(base->delta, alarm->softexpires);
|
||||
hrtimer_start_expires(&base->timer, HRTIMER_MODE_ABS);
|
||||
}
|
||||
|
||||
static void alarm_enqueue_locked(struct android_alarm *alarm)
|
||||
{
|
||||
struct alarm_queue *base = &alarms[alarm->type];
|
||||
struct rb_node **link = &base->alarms.rb_node;
|
||||
struct rb_node *parent = NULL;
|
||||
struct android_alarm *entry;
|
||||
int leftmost = 1;
|
||||
bool was_first = false;
|
||||
|
||||
pr_alarm(FLOW, "added alarm, type %d, func %pF at %lld\n",
|
||||
alarm->type, alarm->function, ktime_to_ns(alarm->expires));
|
||||
|
||||
if (base->first == &alarm->node) {
|
||||
base->first = rb_next(&alarm->node);
|
||||
was_first = true;
|
||||
}
|
||||
if (!RB_EMPTY_NODE(&alarm->node)) {
|
||||
rb_erase(&alarm->node, &base->alarms);
|
||||
RB_CLEAR_NODE(&alarm->node);
|
||||
}
|
||||
|
||||
while (*link) {
|
||||
parent = *link;
|
||||
entry = rb_entry(parent, struct android_alarm, node);
|
||||
/*
|
||||
* We dont care about collisions. Nodes with
|
||||
* the same expiry time stay together.
|
||||
*/
|
||||
if (alarm->expires.tv64 < entry->expires.tv64) {
|
||||
link = &(*link)->rb_left;
|
||||
} else {
|
||||
link = &(*link)->rb_right;
|
||||
leftmost = 0;
|
||||
}
|
||||
}
|
||||
if (leftmost)
|
||||
base->first = &alarm->node;
|
||||
if (leftmost || was_first)
|
||||
update_timer_locked(base, was_first);
|
||||
|
||||
rb_link_node(&alarm->node, parent, link);
|
||||
rb_insert_color(&alarm->node, &base->alarms);
|
||||
}
|
||||
|
||||
/**
|
||||
* android_alarm_init - initialize an alarm
|
||||
* @alarm: the alarm to be initialized
|
||||
* @type: the alarm type to be used
|
||||
* @function: alarm callback function
|
||||
*/
|
||||
void android_alarm_init(struct android_alarm *alarm,
|
||||
enum android_alarm_type type, void (*function)(struct android_alarm *))
|
||||
{
|
||||
RB_CLEAR_NODE(&alarm->node);
|
||||
alarm->type = type;
|
||||
alarm->function = function;
|
||||
|
||||
pr_alarm(FLOW, "created alarm, type %d, func %pF\n", type, function);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* android_alarm_start_range - (re)start an alarm
|
||||
* @alarm: the alarm to be added
|
||||
* @start: earliest expiry time
|
||||
* @end: expiry time
|
||||
*/
|
||||
void android_alarm_start_range(struct android_alarm *alarm, ktime_t start,
|
||||
ktime_t end)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&alarm_slock, flags);
|
||||
alarm->softexpires = start;
|
||||
alarm->expires = end;
|
||||
alarm_enqueue_locked(alarm);
|
||||
spin_unlock_irqrestore(&alarm_slock, flags);
|
||||
}
|
||||
|
||||
/**
|
||||
* android_alarm_try_to_cancel - try to deactivate an alarm
|
||||
* @alarm: alarm to stop
|
||||
*
|
||||
* Returns:
|
||||
* 0 when the alarm was not active
|
||||
* 1 when the alarm was active
|
||||
* -1 when the alarm may currently be excuting the callback function and
|
||||
* cannot be stopped (it may also be inactive)
|
||||
*/
|
||||
int android_alarm_try_to_cancel(struct android_alarm *alarm)
|
||||
{
|
||||
struct alarm_queue *base = &alarms[alarm->type];
|
||||
unsigned long flags;
|
||||
bool first = false;
|
||||
int ret = 0;
|
||||
|
||||
spin_lock_irqsave(&alarm_slock, flags);
|
||||
if (!RB_EMPTY_NODE(&alarm->node)) {
|
||||
pr_alarm(FLOW, "canceled alarm, type %d, func %pF at %lld\n",
|
||||
alarm->type, alarm->function,
|
||||
ktime_to_ns(alarm->expires));
|
||||
ret = 1;
|
||||
if (base->first == &alarm->node) {
|
||||
base->first = rb_next(&alarm->node);
|
||||
first = true;
|
||||
}
|
||||
rb_erase(&alarm->node, &base->alarms);
|
||||
RB_CLEAR_NODE(&alarm->node);
|
||||
if (first)
|
||||
update_timer_locked(base, true);
|
||||
} else
|
||||
pr_alarm(FLOW, "tried to cancel alarm, type %d, func %pF\n",
|
||||
alarm->type, alarm->function);
|
||||
spin_unlock_irqrestore(&alarm_slock, flags);
|
||||
if (!ret && hrtimer_callback_running(&base->timer))
|
||||
ret = -1;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* android_alarm_cancel - cancel an alarm and wait for the handler to finish.
|
||||
* @alarm: the alarm to be cancelled
|
||||
*
|
||||
* Returns:
|
||||
* 0 when the alarm was not active
|
||||
* 1 when the alarm was active
|
||||
*/
|
||||
int android_alarm_cancel(struct android_alarm *alarm)
|
||||
{
|
||||
for (;;) {
|
||||
int ret = android_alarm_try_to_cancel(alarm);
|
||||
if (ret >= 0)
|
||||
return ret;
|
||||
cpu_relax();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* alarm_set_rtc - set the kernel and rtc walltime
|
||||
* @new_time: timespec value containing the new time
|
||||
*/
|
||||
int android_alarm_set_rtc(struct timespec new_time)
|
||||
{
|
||||
int i;
|
||||
int ret;
|
||||
unsigned long flags;
|
||||
struct rtc_time rtc_new_rtc_time;
|
||||
struct timespec tmp_time;
|
||||
|
||||
rtc_time_to_tm(new_time.tv_sec, &rtc_new_rtc_time);
|
||||
|
||||
pr_alarm(TSET, "set rtc %ld %ld - rtc %02d:%02d:%02d %02d/%02d/%04d\n",
|
||||
new_time.tv_sec, new_time.tv_nsec,
|
||||
rtc_new_rtc_time.tm_hour, rtc_new_rtc_time.tm_min,
|
||||
rtc_new_rtc_time.tm_sec, rtc_new_rtc_time.tm_mon + 1,
|
||||
rtc_new_rtc_time.tm_mday,
|
||||
rtc_new_rtc_time.tm_year + 1900);
|
||||
|
||||
mutex_lock(&alarm_setrtc_mutex);
|
||||
spin_lock_irqsave(&alarm_slock, flags);
|
||||
wake_lock(&alarm_rtc_wake_lock);
|
||||
getnstimeofday(&tmp_time);
|
||||
for (i = 0; i < ANDROID_ALARM_SYSTEMTIME; i++) {
|
||||
hrtimer_try_to_cancel(&alarms[i].timer);
|
||||
alarms[i].stopped = true;
|
||||
alarms[i].stopped_time = timespec_to_ktime(tmp_time);
|
||||
}
|
||||
alarms[ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP].delta =
|
||||
alarms[ANDROID_ALARM_ELAPSED_REALTIME].delta =
|
||||
ktime_sub(alarms[ANDROID_ALARM_ELAPSED_REALTIME].delta,
|
||||
timespec_to_ktime(timespec_sub(tmp_time, new_time)));
|
||||
spin_unlock_irqrestore(&alarm_slock, flags);
|
||||
ret = do_settimeofday(&new_time);
|
||||
spin_lock_irqsave(&alarm_slock, flags);
|
||||
for (i = 0; i < ANDROID_ALARM_SYSTEMTIME; i++) {
|
||||
alarms[i].stopped = false;
|
||||
update_timer_locked(&alarms[i], false);
|
||||
}
|
||||
spin_unlock_irqrestore(&alarm_slock, flags);
|
||||
if (ret < 0) {
|
||||
pr_alarm(ERROR, "alarm_set_rtc: Failed to set time\n");
|
||||
goto err;
|
||||
}
|
||||
if (!alarm_rtc_dev) {
|
||||
pr_alarm(ERROR,
|
||||
"alarm_set_rtc: no RTC, time will be lost on reboot\n");
|
||||
goto err;
|
||||
}
|
||||
ret = rtc_set_time(alarm_rtc_dev, &rtc_new_rtc_time);
|
||||
if (ret < 0)
|
||||
pr_alarm(ERROR, "alarm_set_rtc: "
|
||||
"Failed to set RTC, time will be lost on reboot\n");
|
||||
err:
|
||||
wake_unlock(&alarm_rtc_wake_lock);
|
||||
mutex_unlock(&alarm_setrtc_mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* alarm_get_elapsed_realtime - get the elapsed real time in ktime_t format
|
||||
*
|
||||
* returns the time in ktime_t format
|
||||
*/
|
||||
ktime_t alarm_get_elapsed_realtime(void)
|
||||
{
|
||||
ktime_t now;
|
||||
unsigned long flags;
|
||||
struct alarm_queue *base = &alarms[ANDROID_ALARM_ELAPSED_REALTIME];
|
||||
|
||||
spin_lock_irqsave(&alarm_slock, flags);
|
||||
now = base->stopped ? base->stopped_time : ktime_get_real();
|
||||
now = ktime_sub(now, base->delta);
|
||||
spin_unlock_irqrestore(&alarm_slock, flags);
|
||||
return now;
|
||||
}
|
||||
|
||||
static enum hrtimer_restart alarm_timer_triggered(struct hrtimer *timer)
|
||||
{
|
||||
struct alarm_queue *base;
|
||||
struct android_alarm *alarm;
|
||||
unsigned long flags;
|
||||
ktime_t now;
|
||||
|
||||
spin_lock_irqsave(&alarm_slock, flags);
|
||||
|
||||
base = container_of(timer, struct alarm_queue, timer);
|
||||
now = base->stopped ? base->stopped_time : hrtimer_cb_get_time(timer);
|
||||
now = ktime_sub(now, base->delta);
|
||||
|
||||
pr_alarm(INT, "alarm_timer_triggered type %ld at %lld\n",
|
||||
base - alarms, ktime_to_ns(now));
|
||||
|
||||
while (base->first) {
|
||||
alarm = container_of(base->first, struct android_alarm, node);
|
||||
if (alarm->softexpires.tv64 > now.tv64) {
|
||||
pr_alarm(FLOW, "don't call alarm, %pF, %lld (s %lld)\n",
|
||||
alarm->function, ktime_to_ns(alarm->expires),
|
||||
ktime_to_ns(alarm->softexpires));
|
||||
break;
|
||||
}
|
||||
base->first = rb_next(&alarm->node);
|
||||
rb_erase(&alarm->node, &base->alarms);
|
||||
RB_CLEAR_NODE(&alarm->node);
|
||||
pr_alarm(CALL, "call alarm, type %d, func %pF, %lld (s %lld)\n",
|
||||
alarm->type, alarm->function,
|
||||
ktime_to_ns(alarm->expires),
|
||||
ktime_to_ns(alarm->softexpires));
|
||||
spin_unlock_irqrestore(&alarm_slock, flags);
|
||||
alarm->function(alarm);
|
||||
spin_lock_irqsave(&alarm_slock, flags);
|
||||
}
|
||||
if (!base->first)
|
||||
pr_alarm(FLOW, "no more alarms of type %ld\n", base - alarms);
|
||||
update_timer_locked(base, true);
|
||||
spin_unlock_irqrestore(&alarm_slock, flags);
|
||||
return HRTIMER_NORESTART;
|
||||
}
|
||||
|
||||
static void alarm_triggered_func(void *p)
|
||||
{
|
||||
struct rtc_device *rtc = alarm_rtc_dev;
|
||||
if (!(rtc->irq_data & RTC_AF))
|
||||
return;
|
||||
pr_alarm(INT, "rtc alarm triggered\n");
|
||||
wake_lock_timeout(&alarm_rtc_wake_lock, 1 * HZ);
|
||||
}
|
||||
|
||||
static int alarm_suspend(struct platform_device *pdev, pm_message_t state)
|
||||
{
|
||||
int err = 0;
|
||||
unsigned long flags;
|
||||
struct rtc_wkalrm rtc_alarm;
|
||||
struct rtc_time rtc_current_rtc_time;
|
||||
unsigned long rtc_current_time;
|
||||
unsigned long rtc_alarm_time;
|
||||
struct timespec rtc_delta;
|
||||
struct timespec wall_time;
|
||||
struct alarm_queue *wakeup_queue = NULL;
|
||||
struct alarm_queue *tmp_queue = NULL;
|
||||
|
||||
pr_alarm(SUSPEND, "alarm_suspend(%p, %d)\n", pdev, state.event);
|
||||
|
||||
spin_lock_irqsave(&alarm_slock, flags);
|
||||
suspended = true;
|
||||
spin_unlock_irqrestore(&alarm_slock, flags);
|
||||
|
||||
hrtimer_cancel(&alarms[ANDROID_ALARM_RTC_WAKEUP].timer);
|
||||
hrtimer_cancel(&alarms[
|
||||
ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP].timer);
|
||||
|
||||
tmp_queue = &alarms[ANDROID_ALARM_RTC_WAKEUP];
|
||||
if (tmp_queue->first)
|
||||
wakeup_queue = tmp_queue;
|
||||
tmp_queue = &alarms[ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP];
|
||||
if (tmp_queue->first && (!wakeup_queue ||
|
||||
hrtimer_get_expires(&tmp_queue->timer).tv64 <
|
||||
hrtimer_get_expires(&wakeup_queue->timer).tv64))
|
||||
wakeup_queue = tmp_queue;
|
||||
if (wakeup_queue) {
|
||||
rtc_read_time(alarm_rtc_dev, &rtc_current_rtc_time);
|
||||
getnstimeofday(&wall_time);
|
||||
rtc_tm_to_time(&rtc_current_rtc_time, &rtc_current_time);
|
||||
set_normalized_timespec(&rtc_delta,
|
||||
wall_time.tv_sec - rtc_current_time,
|
||||
wall_time.tv_nsec);
|
||||
|
||||
rtc_alarm_time = timespec_sub(ktime_to_timespec(
|
||||
hrtimer_get_expires(&wakeup_queue->timer)),
|
||||
rtc_delta).tv_sec;
|
||||
|
||||
rtc_time_to_tm(rtc_alarm_time, &rtc_alarm.time);
|
||||
rtc_alarm.enabled = 1;
|
||||
rtc_set_alarm(alarm_rtc_dev, &rtc_alarm);
|
||||
rtc_read_time(alarm_rtc_dev, &rtc_current_rtc_time);
|
||||
rtc_tm_to_time(&rtc_current_rtc_time, &rtc_current_time);
|
||||
pr_alarm(SUSPEND,
|
||||
"rtc alarm set at %ld, now %ld, rtc delta %ld.%09ld\n",
|
||||
rtc_alarm_time, rtc_current_time,
|
||||
rtc_delta.tv_sec, rtc_delta.tv_nsec);
|
||||
if (rtc_current_time + 1 >= rtc_alarm_time) {
|
||||
pr_alarm(SUSPEND, "alarm about to go off\n");
|
||||
memset(&rtc_alarm, 0, sizeof(rtc_alarm));
|
||||
rtc_alarm.enabled = 0;
|
||||
rtc_set_alarm(alarm_rtc_dev, &rtc_alarm);
|
||||
|
||||
spin_lock_irqsave(&alarm_slock, flags);
|
||||
suspended = false;
|
||||
wake_lock_timeout(&alarm_rtc_wake_lock, 2 * HZ);
|
||||
update_timer_locked(&alarms[ANDROID_ALARM_RTC_WAKEUP],
|
||||
false);
|
||||
update_timer_locked(&alarms[
|
||||
ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP], false);
|
||||
err = -EBUSY;
|
||||
spin_unlock_irqrestore(&alarm_slock, flags);
|
||||
}
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
static int alarm_resume(struct platform_device *pdev)
|
||||
{
|
||||
struct rtc_wkalrm alarm;
|
||||
unsigned long flags;
|
||||
|
||||
pr_alarm(SUSPEND, "alarm_resume(%p)\n", pdev);
|
||||
|
||||
memset(&alarm, 0, sizeof(alarm));
|
||||
alarm.enabled = 0;
|
||||
rtc_set_alarm(alarm_rtc_dev, &alarm);
|
||||
|
||||
spin_lock_irqsave(&alarm_slock, flags);
|
||||
suspended = false;
|
||||
update_timer_locked(&alarms[ANDROID_ALARM_RTC_WAKEUP], false);
|
||||
update_timer_locked(&alarms[ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP],
|
||||
false);
|
||||
spin_unlock_irqrestore(&alarm_slock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct rtc_task alarm_rtc_task = {
|
||||
.func = alarm_triggered_func
|
||||
};
|
||||
|
||||
static int rtc_alarm_add_device(struct device *dev,
|
||||
struct class_interface *class_intf)
|
||||
{
|
||||
int err;
|
||||
struct rtc_device *rtc = to_rtc_device(dev);
|
||||
|
||||
mutex_lock(&alarm_setrtc_mutex);
|
||||
|
||||
if (alarm_rtc_dev) {
|
||||
err = -EBUSY;
|
||||
goto err1;
|
||||
}
|
||||
|
||||
alarm_platform_dev =
|
||||
platform_device_register_simple("alarm", -1, NULL, 0);
|
||||
if (IS_ERR(alarm_platform_dev)) {
|
||||
err = PTR_ERR(alarm_platform_dev);
|
||||
goto err2;
|
||||
}
|
||||
err = rtc_irq_register(rtc, &alarm_rtc_task);
|
||||
if (err)
|
||||
goto err3;
|
||||
alarm_rtc_dev = rtc;
|
||||
pr_alarm(INIT_STATUS, "using rtc device, %s, for alarms", rtc->name);
|
||||
mutex_unlock(&alarm_setrtc_mutex);
|
||||
|
||||
return 0;
|
||||
|
||||
err3:
|
||||
platform_device_unregister(alarm_platform_dev);
|
||||
err2:
|
||||
err1:
|
||||
mutex_unlock(&alarm_setrtc_mutex);
|
||||
return err;
|
||||
}
|
||||
|
||||
static void rtc_alarm_remove_device(struct device *dev,
|
||||
struct class_interface *class_intf)
|
||||
{
|
||||
if (dev == &alarm_rtc_dev->dev) {
|
||||
pr_alarm(INIT_STATUS, "lost rtc device for alarms");
|
||||
rtc_irq_unregister(alarm_rtc_dev, &alarm_rtc_task);
|
||||
platform_device_unregister(alarm_platform_dev);
|
||||
alarm_rtc_dev = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static struct class_interface rtc_alarm_interface = {
|
||||
.add_dev = &rtc_alarm_add_device,
|
||||
.remove_dev = &rtc_alarm_remove_device,
|
||||
};
|
||||
|
||||
static struct platform_driver alarm_driver = {
|
||||
.suspend = alarm_suspend,
|
||||
.resume = alarm_resume,
|
||||
.driver = {
|
||||
.name = "alarm"
|
||||
}
|
||||
};
|
||||
|
||||
static int __init alarm_late_init(void)
|
||||
{
|
||||
unsigned long flags;
|
||||
struct timespec tmp_time, system_time;
|
||||
|
||||
/* this needs to run after the rtc is read at boot */
|
||||
spin_lock_irqsave(&alarm_slock, flags);
|
||||
/* We read the current rtc and system time so we can later calulate
|
||||
* elasped realtime to be (boot_systemtime + rtc - boot_rtc) ==
|
||||
* (rtc - (boot_rtc - boot_systemtime))
|
||||
*/
|
||||
getnstimeofday(&tmp_time);
|
||||
ktime_get_ts(&system_time);
|
||||
alarms[ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP].delta =
|
||||
alarms[ANDROID_ALARM_ELAPSED_REALTIME].delta =
|
||||
timespec_to_ktime(timespec_sub(tmp_time, system_time));
|
||||
|
||||
spin_unlock_irqrestore(&alarm_slock, flags);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __init alarm_driver_init(void)
|
||||
{
|
||||
int err;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ANDROID_ALARM_SYSTEMTIME; i++) {
|
||||
hrtimer_init(&alarms[i].timer,
|
||||
CLOCK_REALTIME, HRTIMER_MODE_ABS);
|
||||
alarms[i].timer.function = alarm_timer_triggered;
|
||||
}
|
||||
hrtimer_init(&alarms[ANDROID_ALARM_SYSTEMTIME].timer,
|
||||
CLOCK_MONOTONIC, HRTIMER_MODE_ABS);
|
||||
alarms[ANDROID_ALARM_SYSTEMTIME].timer.function = alarm_timer_triggered;
|
||||
err = platform_driver_register(&alarm_driver);
|
||||
if (err < 0)
|
||||
goto err1;
|
||||
wake_lock_init(&alarm_rtc_wake_lock, WAKE_LOCK_SUSPEND, "alarm_rtc");
|
||||
rtc_alarm_interface.class = rtc_class;
|
||||
err = class_interface_register(&rtc_alarm_interface);
|
||||
if (err < 0)
|
||||
goto err2;
|
||||
|
||||
return 0;
|
||||
|
||||
err2:
|
||||
wake_lock_destroy(&alarm_rtc_wake_lock);
|
||||
platform_driver_unregister(&alarm_driver);
|
||||
err1:
|
||||
return err;
|
||||
}
|
||||
|
||||
static void __exit alarm_exit(void)
|
||||
{
|
||||
class_interface_unregister(&rtc_alarm_interface);
|
||||
wake_lock_destroy(&alarm_rtc_wake_lock);
|
||||
platform_driver_unregister(&alarm_driver);
|
||||
}
|
||||
|
||||
late_initcall(alarm_late_init);
|
||||
module_init(alarm_driver_init);
|
||||
module_exit(alarm_exit);
|
||||
|
|
@ -33,65 +33,6 @@ enum android_alarm_type {
|
|||
/* ANDROID_ALARM_TIME_CHANGE = 16 */
|
||||
};
|
||||
|
||||
#ifdef __KERNEL__
|
||||
|
||||
#include <linux/ktime.h>
|
||||
#include <linux/rbtree.h>
|
||||
|
||||
/*
|
||||
* The alarm interface is similar to the hrtimer interface but adds support
|
||||
* for wakeup from suspend. It also adds an elapsed realtime clock that can
|
||||
* be used for periodic timers that need to keep runing while the system is
|
||||
* suspended and not be disrupted when the wall time is set.
|
||||
*/
|
||||
|
||||
/**
|
||||
* struct alarm - the basic alarm structure
|
||||
* @node: red black tree node for time ordered insertion
|
||||
* @type: alarm type. rtc/elapsed-realtime/systemtime, wakeup/non-wakeup.
|
||||
* @softexpires: the absolute earliest expiry time of the alarm.
|
||||
* @expires: the absolute expiry time.
|
||||
* @function: alarm expiry callback function
|
||||
*
|
||||
* The alarm structure must be initialized by alarm_init()
|
||||
*
|
||||
*/
|
||||
|
||||
struct android_alarm {
|
||||
struct rb_node node;
|
||||
enum android_alarm_type type;
|
||||
ktime_t softexpires;
|
||||
ktime_t expires;
|
||||
void (*function)(struct android_alarm *);
|
||||
};
|
||||
|
||||
void android_alarm_init(struct android_alarm *alarm,
|
||||
enum android_alarm_type type, void (*function)(struct android_alarm *));
|
||||
void android_alarm_start_range(struct android_alarm *alarm, ktime_t start,
|
||||
ktime_t end);
|
||||
int android_alarm_try_to_cancel(struct android_alarm *alarm);
|
||||
int android_alarm_cancel(struct android_alarm *alarm);
|
||||
ktime_t alarm_get_elapsed_realtime(void);
|
||||
|
||||
/* set rtc while preserving elapsed realtime */
|
||||
int android_alarm_set_rtc(const struct timespec ts);
|
||||
|
||||
#ifdef CONFIG_ANDROID_ALARM_OLDDRV_COMPAT
|
||||
/*
|
||||
* Some older drivers depend on the old API,
|
||||
* so provide compatability macros for now.
|
||||
*/
|
||||
#define alarm android_alarm
|
||||
#define alarm_init(x, y, z) android_alarm_init(x, y, z)
|
||||
#define alarm_start_range(x, y, z) android_alarm_start_range(x, y, z)
|
||||
#define alarm_try_to_cancel(x) android_alarm_try_to_cancel(x)
|
||||
#define alarm_cancel(x) android_alarm_cancel(x)
|
||||
#define alarm_set_rtc(x) android_alarm_set_rtc(x)
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
enum android_alarm_return_flags {
|
||||
ANDROID_ALARM_RTC_WAKEUP_MASK = 1U << ANDROID_ALARM_RTC_WAKEUP,
|
||||
ANDROID_ALARM_RTC_MASK = 1U << ANDROID_ALARM_RTC,
|
||||
|
|
|
@ -53,17 +53,17 @@ struct flat_binder_object {
|
|||
|
||||
/* 8 bytes of data. */
|
||||
union {
|
||||
void *binder; /* local object */
|
||||
void __user *binder; /* local object */
|
||||
signed long handle; /* remote object */
|
||||
};
|
||||
|
||||
/* extra data associated with local object */
|
||||
void *cookie;
|
||||
void __user *cookie;
|
||||
};
|
||||
|
||||
/*
|
||||
* On 64-bit platforms where user code may run in 32-bits the driver must
|
||||
* translate the buffer (and local binder) addresses apropriately.
|
||||
* translate the buffer (and local binder) addresses appropriately.
|
||||
*/
|
||||
|
||||
struct binder_write_read {
|
||||
|
@ -139,9 +139,9 @@ struct binder_transaction_data {
|
|||
union {
|
||||
struct {
|
||||
/* transaction data */
|
||||
const void *buffer;
|
||||
const void __user *buffer;
|
||||
/* offsets from buffer to flat_binder_object structs */
|
||||
const void *offsets;
|
||||
const void __user *offsets;
|
||||
} ptr;
|
||||
uint8_t buf[8];
|
||||
} data;
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include <linux/poll.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/time.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include "logger.h"
|
||||
|
||||
#include <asm/ioctls.h>
|
||||
|
@ -45,8 +46,12 @@ struct logger_log {
|
|||
size_t w_off; /* current write head offset */
|
||||
size_t head; /* new readers start here */
|
||||
size_t size; /* size of the log */
|
||||
struct list_head logs; /* list of log channels (myself)*/
|
||||
};
|
||||
|
||||
static LIST_HEAD(log_list);
|
||||
|
||||
|
||||
/*
|
||||
* struct logger_reader - a logging device open for reading
|
||||
*
|
||||
|
@ -60,9 +65,9 @@ struct logger_reader {
|
|||
};
|
||||
|
||||
/* logger_offset - returns index 'n' into the log via (optimized) modulus */
|
||||
size_t logger_offset(struct logger_log *log, size_t n)
|
||||
static size_t logger_offset(struct logger_log *log, size_t n)
|
||||
{
|
||||
return n & (log->size-1);
|
||||
return n & (log->size - 1);
|
||||
}
|
||||
|
||||
|
||||
|
@ -348,7 +353,7 @@ static ssize_t do_write_log_from_user(struct logger_log *log,
|
|||
* writev(), and aio_write(). Writes are our fast path, and we try to optimize
|
||||
* them above all else.
|
||||
*/
|
||||
ssize_t logger_aio_write(struct kiocb *iocb, const struct iovec *iov,
|
||||
static ssize_t logger_aio_write(struct kiocb *iocb, const struct iovec *iov,
|
||||
unsigned long nr_segs, loff_t ppos)
|
||||
{
|
||||
struct logger_log *log = file_get_log(iocb->ki_filp);
|
||||
|
@ -408,7 +413,15 @@ ssize_t logger_aio_write(struct kiocb *iocb, const struct iovec *iov,
|
|||
return ret;
|
||||
}
|
||||
|
||||
static struct logger_log *get_log_from_minor(int);
|
||||
static struct logger_log *get_log_from_minor(int minor)
|
||||
{
|
||||
struct logger_log *log;
|
||||
|
||||
list_for_each_entry(log, &log_list, logs)
|
||||
if (log->misc.minor == minor)
|
||||
return log;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* logger_open - the log's open() file operation
|
||||
|
@ -565,80 +578,84 @@ static const struct file_operations logger_fops = {
|
|||
};
|
||||
|
||||
/*
|
||||
* Defines a log structure with name 'NAME' and a size of 'SIZE' bytes, which
|
||||
* must be a power of two, greater than LOGGER_ENTRY_MAX_LEN, and less than
|
||||
* LONG_MAX minus LOGGER_ENTRY_MAX_LEN.
|
||||
* Log size must be a power of two, greater than LOGGER_ENTRY_MAX_LEN,
|
||||
* and less than LONG_MAX minus LOGGER_ENTRY_MAX_LEN.
|
||||
*/
|
||||
#define DEFINE_LOGGER_DEVICE(VAR, NAME, SIZE) \
|
||||
static unsigned char _buf_ ## VAR[SIZE]; \
|
||||
static struct logger_log VAR = { \
|
||||
.buffer = _buf_ ## VAR, \
|
||||
.misc = { \
|
||||
.minor = MISC_DYNAMIC_MINOR, \
|
||||
.name = NAME, \
|
||||
.fops = &logger_fops, \
|
||||
.parent = NULL, \
|
||||
}, \
|
||||
.wq = __WAIT_QUEUE_HEAD_INITIALIZER(VAR .wq), \
|
||||
.readers = LIST_HEAD_INIT(VAR .readers), \
|
||||
.mutex = __MUTEX_INITIALIZER(VAR .mutex), \
|
||||
.w_off = 0, \
|
||||
.head = 0, \
|
||||
.size = SIZE, \
|
||||
};
|
||||
|
||||
DEFINE_LOGGER_DEVICE(log_main, LOGGER_LOG_MAIN, 256*1024)
|
||||
DEFINE_LOGGER_DEVICE(log_events, LOGGER_LOG_EVENTS, 256*1024)
|
||||
DEFINE_LOGGER_DEVICE(log_radio, LOGGER_LOG_RADIO, 256*1024)
|
||||
DEFINE_LOGGER_DEVICE(log_system, LOGGER_LOG_SYSTEM, 256*1024)
|
||||
|
||||
static struct logger_log *get_log_from_minor(int minor)
|
||||
static int __init create_log(char *log_name, int size)
|
||||
{
|
||||
if (log_main.misc.minor == minor)
|
||||
return &log_main;
|
||||
if (log_events.misc.minor == minor)
|
||||
return &log_events;
|
||||
if (log_radio.misc.minor == minor)
|
||||
return &log_radio;
|
||||
if (log_system.misc.minor == minor)
|
||||
return &log_system;
|
||||
return NULL;
|
||||
}
|
||||
int ret = 0;
|
||||
struct logger_log *log;
|
||||
unsigned char *buffer;
|
||||
|
||||
static int __init init_log(struct logger_log *log)
|
||||
{
|
||||
int ret;
|
||||
buffer = vmalloc(size);
|
||||
if (buffer == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
log = kzalloc(sizeof(struct logger_log), GFP_KERNEL);
|
||||
if (log == NULL) {
|
||||
ret = -ENOMEM;
|
||||
goto out_free_buffer;
|
||||
}
|
||||
log->buffer = buffer;
|
||||
|
||||
log->misc.minor = MISC_DYNAMIC_MINOR;
|
||||
log->misc.name = kstrdup(log_name, GFP_KERNEL);
|
||||
if (log->misc.name == NULL) {
|
||||
ret = -ENOMEM;
|
||||
goto out_free_log;
|
||||
}
|
||||
|
||||
log->misc.fops = &logger_fops;
|
||||
log->misc.parent = NULL;
|
||||
|
||||
init_waitqueue_head(&log->wq);
|
||||
INIT_LIST_HEAD(&log->readers);
|
||||
mutex_init(&log->mutex);
|
||||
log->w_off = 0;
|
||||
log->head = 0;
|
||||
log->size = size;
|
||||
|
||||
INIT_LIST_HEAD(&log->logs);
|
||||
list_add_tail(&log->logs, &log_list);
|
||||
|
||||
/* finally, initialize the misc device for this log */
|
||||
ret = misc_register(&log->misc);
|
||||
if (unlikely(ret)) {
|
||||
printk(KERN_ERR "logger: failed to register misc "
|
||||
"device for log '%s'!\n", log->misc.name);
|
||||
return ret;
|
||||
goto out_free_log;
|
||||
}
|
||||
|
||||
printk(KERN_INFO "logger: created %luK log '%s'\n",
|
||||
(unsigned long) log->size >> 10, log->misc.name);
|
||||
|
||||
return 0;
|
||||
|
||||
out_free_log:
|
||||
kfree(log);
|
||||
|
||||
out_free_buffer:
|
||||
vfree(buffer);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int __init logger_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = init_log(&log_main);
|
||||
ret = create_log(LOGGER_LOG_MAIN, 256*1024);
|
||||
if (unlikely(ret))
|
||||
goto out;
|
||||
|
||||
ret = init_log(&log_events);
|
||||
ret = create_log(LOGGER_LOG_EVENTS, 256*1024);
|
||||
if (unlikely(ret))
|
||||
goto out;
|
||||
|
||||
ret = init_log(&log_radio);
|
||||
ret = create_log(LOGGER_LOG_RADIO, 256*1024);
|
||||
if (unlikely(ret))
|
||||
goto out;
|
||||
|
||||
ret = init_log(&log_system);
|
||||
ret = create_log(LOGGER_LOG_SYSTEM, 256*1024);
|
||||
if (unlikely(ret))
|
||||
goto out;
|
||||
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
#include <linux/string.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/io.h>
|
||||
#include "persistent_ram.h"
|
||||
#include <linux/pstore_ram.h>
|
||||
#include "ram_console.h"
|
||||
|
||||
static struct persistent_ram_zone *ram_console_zone;
|
||||
|
|
|
@ -99,6 +99,7 @@ EXPORT_SYMBOL_GPL(timed_output_dev_register);
|
|||
|
||||
void timed_output_dev_unregister(struct timed_output_dev *tdev)
|
||||
{
|
||||
tdev->enable(tdev, 0);
|
||||
device_remove_file(tdev->dev, &dev_attr_enable);
|
||||
device_destroy(timed_output_class, MKDEV(0, tdev->index));
|
||||
dev_set_drvdata(tdev->dev, NULL);
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1115,20 +1115,20 @@ int download_ddr_settings(PMINI_ADAPTER Adapter)
|
|||
{
|
||||
case DDR_80_MHZ:
|
||||
psDDRSetting = asT3LP_DDRSetting80MHz;
|
||||
RegCount = (sizeof(asT3LP_DDRSetting80MHz)/sizeof(DDR_SET_NODE));
|
||||
RegCount = ARRAY_SIZE(asT3LP_DDRSetting80MHz);
|
||||
RegCount -= T3LP_SKIP_CLOCK_PROGRAM_DUMP_80MHZ ;
|
||||
psDDRSetting += T3LP_SKIP_CLOCK_PROGRAM_DUMP_80MHZ;
|
||||
break;
|
||||
case DDR_100_MHZ:
|
||||
psDDRSetting = asT3LP_DDRSetting100MHz;
|
||||
RegCount = (sizeof(asT3LP_DDRSetting100MHz)/sizeof(DDR_SET_NODE));
|
||||
RegCount = ARRAY_SIZE(asT3LP_DDRSetting100MHz);
|
||||
RegCount -= T3LP_SKIP_CLOCK_PROGRAM_DUMP_100MHZ ;
|
||||
psDDRSetting += T3LP_SKIP_CLOCK_PROGRAM_DUMP_100MHZ;
|
||||
break;
|
||||
case DDR_133_MHZ:
|
||||
bOverrideSelfRefresh = TRUE;
|
||||
psDDRSetting = asT3LP_DDRSetting133MHz;
|
||||
RegCount = (sizeof(asT3LP_DDRSetting133MHz)/sizeof(DDR_SET_NODE));
|
||||
RegCount = ARRAY_SIZE(asT3LP_DDRSetting133MHz);
|
||||
RegCount -= T3LP_SKIP_CLOCK_PROGRAM_DUMP_133MHZ ;
|
||||
psDDRSetting += T3LP_SKIP_CLOCK_PROGRAM_DUMP_133MHZ;
|
||||
break;
|
||||
|
@ -1146,20 +1146,20 @@ int download_ddr_settings(PMINI_ADAPTER Adapter)
|
|||
{
|
||||
case DDR_80_MHZ:
|
||||
psDDRSetting = asT3LPB_DDRSetting80MHz;
|
||||
RegCount=(sizeof(asT3LPB_DDRSetting80MHz)/sizeof(DDR_SET_NODE));
|
||||
RegCount=ARRAY_SIZE(asT3LPB_DDRSetting80MHz);
|
||||
RegCount -= T3LPB_SKIP_CLOCK_PROGRAM_DUMP_80MHZ ;
|
||||
psDDRSetting += T3LPB_SKIP_CLOCK_PROGRAM_DUMP_80MHZ;
|
||||
break;
|
||||
case DDR_100_MHZ:
|
||||
psDDRSetting = asT3LPB_DDRSetting100MHz;
|
||||
RegCount = (sizeof(asT3LPB_DDRSetting100MHz)/sizeof(DDR_SET_NODE));
|
||||
RegCount = ARRAY_SIZE(asT3LPB_DDRSetting100MHz);
|
||||
RegCount -= T3LPB_SKIP_CLOCK_PROGRAM_DUMP_100MHZ ;
|
||||
psDDRSetting += T3LPB_SKIP_CLOCK_PROGRAM_DUMP_100MHZ;
|
||||
break;
|
||||
case DDR_133_MHZ:
|
||||
bOverrideSelfRefresh = TRUE;
|
||||
psDDRSetting = asT3LPB_DDRSetting133MHz;
|
||||
RegCount = (sizeof(asT3LPB_DDRSetting133MHz)/sizeof(DDR_SET_NODE));
|
||||
RegCount = ARRAY_SIZE(asT3LPB_DDRSetting133MHz);
|
||||
RegCount -= T3LPB_SKIP_CLOCK_PROGRAM_DUMP_133MHZ ;
|
||||
psDDRSetting += T3LPB_SKIP_CLOCK_PROGRAM_DUMP_133MHZ;
|
||||
break;
|
||||
|
@ -1167,7 +1167,7 @@ int download_ddr_settings(PMINI_ADAPTER Adapter)
|
|||
case DDR_160_MHZ:
|
||||
bOverrideSelfRefresh = TRUE;
|
||||
psDDRSetting = asT3LPB_DDRSetting160MHz;
|
||||
RegCount = sizeof(asT3LPB_DDRSetting160MHz)/sizeof(DDR_SET_NODE);
|
||||
RegCount = ARRAY_SIZE(asT3LPB_DDRSetting160MHz);
|
||||
RegCount -= T3LPB_SKIP_CLOCK_PROGRAM_DUMP_160MHZ;
|
||||
psDDRSetting += T3LPB_SKIP_CLOCK_PROGRAM_DUMP_160MHZ;
|
||||
|
||||
|
@ -1181,19 +1181,19 @@ int download_ddr_settings(PMINI_ADAPTER Adapter)
|
|||
{
|
||||
case DDR_80_MHZ:
|
||||
psDDRSetting = asT3_DDRSetting80MHz;
|
||||
RegCount = (sizeof(asT3_DDRSetting80MHz)/sizeof(DDR_SET_NODE));
|
||||
RegCount = ARRAY_SIZE(asT3_DDRSetting80MHz);
|
||||
RegCount-=T3_SKIP_CLOCK_PROGRAM_DUMP_80MHZ ;
|
||||
psDDRSetting += T3_SKIP_CLOCK_PROGRAM_DUMP_80MHZ;
|
||||
break;
|
||||
case DDR_100_MHZ:
|
||||
psDDRSetting = asT3_DDRSetting100MHz;
|
||||
RegCount = (sizeof(asT3_DDRSetting100MHz)/sizeof(DDR_SET_NODE));
|
||||
RegCount = ARRAY_SIZE(asT3_DDRSetting100MHz);
|
||||
RegCount-=T3_SKIP_CLOCK_PROGRAM_DUMP_100MHZ ;
|
||||
psDDRSetting += T3_SKIP_CLOCK_PROGRAM_DUMP_100MHZ;
|
||||
break;
|
||||
case DDR_133_MHZ:
|
||||
psDDRSetting = asT3_DDRSetting133MHz;
|
||||
RegCount = (sizeof(asT3_DDRSetting133MHz)/sizeof(DDR_SET_NODE));
|
||||
RegCount = ARRAY_SIZE(asT3_DDRSetting133MHz);
|
||||
RegCount-=T3_SKIP_CLOCK_PROGRAM_DUMP_133MHZ ;
|
||||
psDDRSetting += T3_SKIP_CLOCK_PROGRAM_DUMP_133MHZ ;
|
||||
break;
|
||||
|
@ -1207,20 +1207,20 @@ int download_ddr_settings(PMINI_ADAPTER Adapter)
|
|||
{
|
||||
case DDR_80_MHZ:
|
||||
psDDRSetting = asT3B_DDRSetting80MHz;
|
||||
RegCount = (sizeof(asT3B_DDRSetting80MHz)/sizeof(DDR_SET_NODE));
|
||||
RegCount = ARRAY_SIZE(asT3B_DDRSetting80MHz);
|
||||
RegCount -= T3B_SKIP_CLOCK_PROGRAM_DUMP_80MHZ ;
|
||||
psDDRSetting += T3B_SKIP_CLOCK_PROGRAM_DUMP_80MHZ;
|
||||
break;
|
||||
case DDR_100_MHZ:
|
||||
psDDRSetting = asT3B_DDRSetting100MHz;
|
||||
RegCount = (sizeof(asT3B_DDRSetting100MHz)/sizeof(DDR_SET_NODE));
|
||||
RegCount = ARRAY_SIZE(asT3B_DDRSetting100MHz);
|
||||
RegCount -= T3B_SKIP_CLOCK_PROGRAM_DUMP_100MHZ ;
|
||||
psDDRSetting += T3B_SKIP_CLOCK_PROGRAM_DUMP_100MHZ;
|
||||
break;
|
||||
case DDR_133_MHZ:
|
||||
bOverrideSelfRefresh = TRUE;
|
||||
psDDRSetting = asT3B_DDRSetting133MHz;
|
||||
RegCount = (sizeof(asT3B_DDRSetting133MHz)/sizeof(DDR_SET_NODE));
|
||||
RegCount = ARRAY_SIZE(asT3B_DDRSetting133MHz);
|
||||
RegCount -= T3B_SKIP_CLOCK_PROGRAM_DUMP_133MHZ ;
|
||||
psDDRSetting += T3B_SKIP_CLOCK_PROGRAM_DUMP_133MHZ;
|
||||
break;
|
||||
|
|
|
@ -1,51 +1,52 @@
|
|||
#include "headers.h"
|
||||
|
||||
static BOOLEAN MatchSrcIpv6Address(S_CLASSIFIER_RULE *pstClassifierRule,IPV6Header *pstIpv6Header);
|
||||
static BOOLEAN MatchDestIpv6Address(S_CLASSIFIER_RULE *pstClassifierRule,IPV6Header *pstIpv6Header);
|
||||
static BOOLEAN MatchSrcIpv6Address(S_CLASSIFIER_RULE *pstClassifierRule,
|
||||
IPV6Header *pstIpv6Header);
|
||||
static BOOLEAN MatchDestIpv6Address(S_CLASSIFIER_RULE *pstClassifierRule,
|
||||
IPV6Header *pstIpv6Header);
|
||||
static VOID DumpIpv6Header(IPV6Header *pstIpv6Header);
|
||||
|
||||
static UCHAR * GetNextIPV6ChainedHeader(UCHAR **ppucPayload,UCHAR *pucNextHeader,BOOLEAN *bParseDone,USHORT *pusPayloadLength)
|
||||
static UCHAR *GetNextIPV6ChainedHeader(UCHAR **ppucPayload,
|
||||
UCHAR *pucNextHeader, BOOLEAN *bParseDone, USHORT *pusPayloadLength)
|
||||
{
|
||||
UCHAR *pucRetHeaderPtr = NULL;
|
||||
UCHAR *pucPayloadPtr = NULL;
|
||||
USHORT usNextHeaderOffset = 0 ;
|
||||
PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev);
|
||||
PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev);
|
||||
|
||||
if((NULL == ppucPayload) || (*pusPayloadLength == 0) || (*bParseDone))
|
||||
{
|
||||
if ((ppucPayload == NULL) || (*pusPayloadLength == 0) ||
|
||||
(*bParseDone)) {
|
||||
*bParseDone = TRUE;
|
||||
return NULL;
|
||||
|
||||
}
|
||||
|
||||
pucRetHeaderPtr = *ppucPayload;
|
||||
pucPayloadPtr = *ppucPayload;
|
||||
|
||||
if(!pucRetHeaderPtr || !pucPayloadPtr)
|
||||
{
|
||||
if (!pucRetHeaderPtr || !pucPayloadPtr) {
|
||||
*bParseDone = TRUE;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//Get the Nextt Header Type
|
||||
/* Get the Nextt Header Type */
|
||||
*bParseDone = FALSE;
|
||||
|
||||
|
||||
|
||||
switch(*pucNextHeader)
|
||||
{
|
||||
switch (*pucNextHeader) {
|
||||
case IPV6HDR_TYPE_HOPBYHOP:
|
||||
{
|
||||
|
||||
BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, "\nIPv6 HopByHop Header");
|
||||
usNextHeaderOffset+=sizeof(IPV6HopByHopOptionsHeader);
|
||||
BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG,
|
||||
DBG_LVL_ALL, "\nIPv6 HopByHop Header");
|
||||
usNextHeaderOffset += sizeof(IPV6HopByHopOptionsHeader);
|
||||
}
|
||||
break;
|
||||
|
||||
case IPV6HDR_TYPE_ROUTING:
|
||||
{
|
||||
IPV6RoutingHeader *pstIpv6RoutingHeader;
|
||||
BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, "\nIPv6 Routing Header");
|
||||
BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG,
|
||||
DBG_LVL_ALL, "\nIPv6 Routing Header");
|
||||
pstIpv6RoutingHeader = (IPV6RoutingHeader *)pucPayloadPtr;
|
||||
usNextHeaderOffset += sizeof(IPV6RoutingHeader);
|
||||
usNextHeaderOffset += pstIpv6RoutingHeader->ucNumAddresses * IPV6_ADDRESS_SIZEINBYTES;
|
||||
|
@ -54,8 +55,10 @@ static UCHAR * GetNextIPV6ChainedHeader(UCHAR **ppucPayload,UCHAR *pucNextHeader
|
|||
break;
|
||||
case IPV6HDR_TYPE_FRAGMENTATION:
|
||||
{
|
||||
BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, "\nIPv6 Fragmentation Header");
|
||||
usNextHeaderOffset+= sizeof(IPV6FragmentHeader);
|
||||
BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG,
|
||||
DBG_LVL_ALL,
|
||||
"\nIPv6 Fragmentation Header");
|
||||
usNextHeaderOffset += sizeof(IPV6FragmentHeader);
|
||||
|
||||
}
|
||||
break;
|
||||
|
@ -63,9 +66,11 @@ static UCHAR * GetNextIPV6ChainedHeader(UCHAR **ppucPayload,UCHAR *pucNextHeader
|
|||
{
|
||||
IPV6DestOptionsHeader *pstIpv6DestOptsHdr = (IPV6DestOptionsHeader *)pucPayloadPtr;
|
||||
int nTotalOptions = pstIpv6DestOptsHdr->ucHdrExtLen;
|
||||
BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, "\nIPv6 DestOpts Header Header");
|
||||
usNextHeaderOffset+= sizeof(IPV6DestOptionsHeader);
|
||||
usNextHeaderOffset+= nTotalOptions * IPV6_DESTOPTS_HDR_OPTIONSIZE ;
|
||||
BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG,
|
||||
DBG_LVL_ALL,
|
||||
"\nIPv6 DestOpts Header Header");
|
||||
usNextHeaderOffset += sizeof(IPV6DestOptionsHeader);
|
||||
usNextHeaderOffset += nTotalOptions * IPV6_DESTOPTS_HDR_OPTIONSIZE ;
|
||||
|
||||
}
|
||||
break;
|
||||
|
@ -73,36 +78,43 @@ static UCHAR * GetNextIPV6ChainedHeader(UCHAR **ppucPayload,UCHAR *pucNextHeader
|
|||
{
|
||||
IPV6AuthenticationHeader *pstIpv6AuthHdr = (IPV6AuthenticationHeader *)pucPayloadPtr;
|
||||
int nHdrLen = pstIpv6AuthHdr->ucLength;
|
||||
BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, "\nIPv6 Authentication Header");
|
||||
usNextHeaderOffset+= nHdrLen * 4;
|
||||
BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG,
|
||||
DBG_LVL_ALL,
|
||||
"\nIPv6 Authentication Header");
|
||||
usNextHeaderOffset += nHdrLen * 4;
|
||||
}
|
||||
break;
|
||||
case IPV6HDR_TYPE_ENCRYPTEDSECURITYPAYLOAD:
|
||||
{
|
||||
BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, "\nIPv6 Encrypted Security Payload Header");
|
||||
BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG,
|
||||
DBG_LVL_ALL,
|
||||
"\nIPv6 Encrypted Security Payload Header");
|
||||
*bParseDone = TRUE;
|
||||
|
||||
}
|
||||
break;
|
||||
case IPV6_ICMP_HDR_TYPE:
|
||||
{
|
||||
BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, " ICMP Header");
|
||||
BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG,
|
||||
DBG_LVL_ALL, "\nICMP Header");
|
||||
*bParseDone = TRUE;
|
||||
}
|
||||
break;
|
||||
case TCP_HEADER_TYPE:
|
||||
{
|
||||
BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, " \nTCP Header");
|
||||
BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG,
|
||||
DBG_LVL_ALL, "\nTCP Header");
|
||||
*bParseDone = TRUE;
|
||||
}
|
||||
break;
|
||||
case UDP_HEADER_TYPE:
|
||||
{
|
||||
BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, " \nUDP Header");
|
||||
BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG,
|
||||
DBG_LVL_ALL, "\nUDP Header");
|
||||
*bParseDone = TRUE;
|
||||
}
|
||||
break;
|
||||
default :
|
||||
default:
|
||||
{
|
||||
*bParseDone = TRUE;
|
||||
|
||||
|
@ -112,53 +124,49 @@ static UCHAR * GetNextIPV6ChainedHeader(UCHAR **ppucPayload,UCHAR *pucNextHeader
|
|||
|
||||
}
|
||||
|
||||
if(*bParseDone == FALSE)
|
||||
{
|
||||
if(*pusPayloadLength <= usNextHeaderOffset)
|
||||
{
|
||||
if (*bParseDone == FALSE) {
|
||||
if (*pusPayloadLength <= usNextHeaderOffset) {
|
||||
*bParseDone = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
*pucNextHeader = *pucPayloadPtr;
|
||||
pucPayloadPtr+=usNextHeaderOffset;
|
||||
(*pusPayloadLength)-=usNextHeaderOffset;
|
||||
pucPayloadPtr += usNextHeaderOffset;
|
||||
(*pusPayloadLength) -= usNextHeaderOffset;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
*ppucPayload = pucPayloadPtr;
|
||||
return pucRetHeaderPtr;
|
||||
}
|
||||
|
||||
|
||||
static UCHAR GetIpv6ProtocolPorts(UCHAR *pucPayload,USHORT *pusSrcPort,USHORT *pusDestPort,USHORT usPayloadLength,UCHAR ucNextHeader)
|
||||
static UCHAR GetIpv6ProtocolPorts(UCHAR *pucPayload, USHORT *pusSrcPort,
|
||||
USHORT *pusDestPort, USHORT usPayloadLength, UCHAR ucNextHeader)
|
||||
{
|
||||
UCHAR *pIpv6HdrScanContext = pucPayload;
|
||||
BOOLEAN bDone = FALSE;
|
||||
UCHAR ucHeaderType =0;
|
||||
UCHAR ucHeaderType = 0;
|
||||
UCHAR *pucNextHeader = NULL;
|
||||
PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev);
|
||||
PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev);
|
||||
|
||||
if( !pucPayload || (usPayloadLength == 0))
|
||||
{
|
||||
if (!pucPayload || (usPayloadLength == 0))
|
||||
return 0;
|
||||
}
|
||||
|
||||
*pusSrcPort = *pusDestPort = 0;
|
||||
ucHeaderType = ucNextHeader;
|
||||
while(!bDone)
|
||||
{
|
||||
pucNextHeader = GetNextIPV6ChainedHeader(&pIpv6HdrScanContext,&ucHeaderType,&bDone,&usPayloadLength);
|
||||
if(bDone)
|
||||
{
|
||||
if((ucHeaderType==TCP_HEADER_TYPE) || (ucHeaderType == UDP_HEADER_TYPE))
|
||||
{
|
||||
*pusSrcPort=*((PUSHORT)(pucNextHeader));
|
||||
*pusDestPort=*((PUSHORT)(pucNextHeader+2));
|
||||
BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, " \nProtocol Ports - Src Port :0x%x Dest Port : 0x%x",ntohs(*pusSrcPort),ntohs(*pusDestPort));
|
||||
while (!bDone) {
|
||||
pucNextHeader = GetNextIPV6ChainedHeader(&pIpv6HdrScanContext,
|
||||
&ucHeaderType, &bDone, &usPayloadLength);
|
||||
if (bDone) {
|
||||
if ((ucHeaderType == TCP_HEADER_TYPE) ||
|
||||
(ucHeaderType == UDP_HEADER_TYPE)) {
|
||||
*pusSrcPort = *((PUSHORT)(pucNextHeader));
|
||||
*pusDestPort = *((PUSHORT)(pucNextHeader+2));
|
||||
BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG,
|
||||
DBG_LVL_ALL,
|
||||
"\nProtocol Ports - Src Port :0x%x Dest Port : 0x%x",
|
||||
ntohs(*pusSrcPort),
|
||||
ntohs(*pusDestPort));
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -168,92 +176,111 @@ static UCHAR GetIpv6ProtocolPorts(UCHAR *pucPayload,USHORT *pusSrcPort,USHORT *p
|
|||
}
|
||||
|
||||
|
||||
|
||||
USHORT IpVersion6(PMINI_ADAPTER Adapter, /**< Pointer to the driver control structure */
|
||||
PVOID pcIpHeader, /**<Pointer to the IP Hdr of the packet*/
|
||||
S_CLASSIFIER_RULE *pstClassifierRule )
|
||||
/*
|
||||
* Arg 1 PMINI_ADAPTER Adapter is a pointer ot the driver contorl structure
|
||||
* Arg 2 PVOID pcIpHeader is a pointer to the IP header of the packet
|
||||
*/
|
||||
USHORT IpVersion6(PMINI_ADAPTER Adapter, PVOID pcIpHeader,
|
||||
S_CLASSIFIER_RULE *pstClassifierRule)
|
||||
{
|
||||
USHORT ushDestPort = 0;
|
||||
USHORT ushSrcPort = 0;
|
||||
UCHAR ucNextProtocolAboveIP =0;
|
||||
UCHAR ucNextProtocolAboveIP = 0;
|
||||
IPV6Header *pstIpv6Header = NULL;
|
||||
BOOLEAN bClassificationSucceed = FALSE;
|
||||
|
||||
BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, "IpVersion6 ==========>\n");
|
||||
BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG,
|
||||
DBG_LVL_ALL, "IpVersion6 ==========>\n");
|
||||
|
||||
pstIpv6Header = (IPV6Header *)pcIpHeader;
|
||||
|
||||
DumpIpv6Header(pstIpv6Header);
|
||||
|
||||
//Try to get the next higher layer protocol and the Ports Nos if TCP or UDP
|
||||
/*
|
||||
* Try to get the next higher layer protocol
|
||||
* and the Ports Nos if TCP or UDP
|
||||
*/
|
||||
ucNextProtocolAboveIP = GetIpv6ProtocolPorts((UCHAR *)(pcIpHeader + sizeof(IPV6Header)),
|
||||
&ushSrcPort,
|
||||
&ushDestPort,
|
||||
pstIpv6Header->usPayloadLength,
|
||||
pstIpv6Header->ucNextHeader);
|
||||
|
||||
do
|
||||
{
|
||||
if(0 == pstClassifierRule->ucDirection)
|
||||
{
|
||||
//cannot be processed for classification.
|
||||
// it is a down link connection
|
||||
do {
|
||||
if (pstClassifierRule->ucDirection == 0) {
|
||||
/*
|
||||
* cannot be processed for classification.
|
||||
* it is a down link connection
|
||||
*/
|
||||
break;
|
||||
}
|
||||
|
||||
if(!pstClassifierRule->bIpv6Protocol)
|
||||
{
|
||||
//We are looking for Ipv6 Classifiers . Lets ignore this classifier and try the next one.
|
||||
if (!pstClassifierRule->bIpv6Protocol) {
|
||||
/*
|
||||
* We are looking for Ipv6 Classifiers
|
||||
* Lets ignore this classifier and try the next one
|
||||
*/
|
||||
break;
|
||||
}
|
||||
|
||||
bClassificationSucceed=MatchSrcIpv6Address(pstClassifierRule,pstIpv6Header);
|
||||
if(!bClassificationSucceed)
|
||||
break;
|
||||
bClassificationSucceed = MatchSrcIpv6Address(pstClassifierRule,
|
||||
pstIpv6Header);
|
||||
if (!bClassificationSucceed)
|
||||
break;
|
||||
|
||||
bClassificationSucceed=MatchDestIpv6Address(pstClassifierRule,pstIpv6Header);
|
||||
if(!bClassificationSucceed)
|
||||
break;
|
||||
bClassificationSucceed = MatchDestIpv6Address(pstClassifierRule,
|
||||
pstIpv6Header);
|
||||
if (!bClassificationSucceed)
|
||||
break;
|
||||
|
||||
//Match the protocol type.For IPv6 the next protocol at end of Chain of IPv6 prot headers
|
||||
bClassificationSucceed=MatchProtocol(pstClassifierRule,ucNextProtocolAboveIP);
|
||||
if(!bClassificationSucceed)
|
||||
break;
|
||||
BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, "\nIPv6 Protocol Matched");
|
||||
/*
|
||||
* Match the protocol type.
|
||||
* For IPv6 the next protocol at end of
|
||||
* Chain of IPv6 prot headers
|
||||
*/
|
||||
bClassificationSucceed = MatchProtocol(pstClassifierRule,
|
||||
ucNextProtocolAboveIP);
|
||||
if (!bClassificationSucceed)
|
||||
break;
|
||||
|
||||
if((ucNextProtocolAboveIP == TCP_HEADER_TYPE) || (ucNextProtocolAboveIP == UDP_HEADER_TYPE))
|
||||
{
|
||||
//Match Src Port
|
||||
BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, "\nIPv6 Source Port:%x\n",ntohs(ushSrcPort));
|
||||
bClassificationSucceed=MatchSrcPort(pstClassifierRule,ntohs(ushSrcPort));
|
||||
if(!bClassificationSucceed)
|
||||
BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG,
|
||||
DBG_LVL_ALL, "\nIPv6 Protocol Matched");
|
||||
|
||||
if ((ucNextProtocolAboveIP == TCP_HEADER_TYPE) ||
|
||||
(ucNextProtocolAboveIP == UDP_HEADER_TYPE)) {
|
||||
/* Match Src Port */
|
||||
BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG,
|
||||
DBG_LVL_ALL, "\nIPv6 Source Port:%x\n",
|
||||
ntohs(ushSrcPort));
|
||||
bClassificationSucceed = MatchSrcPort(pstClassifierRule,
|
||||
ntohs(ushSrcPort));
|
||||
if (!bClassificationSucceed)
|
||||
break;
|
||||
|
||||
BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, "\nIPv6 Src Port Matched");
|
||||
BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG,
|
||||
DBG_LVL_ALL, "\nIPv6 Src Port Matched");
|
||||
|
||||
//Match Dest Port
|
||||
BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, "\nIPv6 Destination Port:%x\n",ntohs(ushDestPort));
|
||||
bClassificationSucceed=MatchDestPort(pstClassifierRule,ntohs(ushDestPort));
|
||||
if(!bClassificationSucceed)
|
||||
/* Match Dest Port */
|
||||
BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG,
|
||||
DBG_LVL_ALL, "\nIPv6 Destination Port:%x\n",
|
||||
ntohs(ushDestPort));
|
||||
bClassificationSucceed = MatchDestPort(pstClassifierRule,
|
||||
ntohs(ushDestPort));
|
||||
if (!bClassificationSucceed)
|
||||
break;
|
||||
BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, "\nIPv6 Dest Port Matched");
|
||||
BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG,
|
||||
DBG_LVL_ALL, "\nIPv6 Dest Port Matched");
|
||||
}
|
||||
}while(0);
|
||||
} while (0);
|
||||
|
||||
if(TRUE==bClassificationSucceed)
|
||||
{
|
||||
if (bClassificationSucceed == TRUE) {
|
||||
INT iMatchedSFQueueIndex = 0;
|
||||
iMatchedSFQueueIndex = SearchSfid(Adapter,pstClassifierRule->ulSFID);
|
||||
if(iMatchedSFQueueIndex >= NO_OF_QUEUES)
|
||||
{
|
||||
iMatchedSFQueueIndex = SearchSfid(Adapter, pstClassifierRule->ulSFID);
|
||||
if (iMatchedSFQueueIndex >= NO_OF_QUEUES) {
|
||||
bClassificationSucceed = FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(FALSE == Adapter->PackInfo[iMatchedSFQueueIndex].bActive)
|
||||
{
|
||||
} else {
|
||||
if (Adapter->PackInfo[iMatchedSFQueueIndex].bActive == FALSE)
|
||||
bClassificationSucceed = FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -261,52 +288,55 @@ USHORT IpVersion6(PMINI_ADAPTER Adapter, /**< Pointer to the driver control stru
|
|||
}
|
||||
|
||||
|
||||
static BOOLEAN MatchSrcIpv6Address(S_CLASSIFIER_RULE *pstClassifierRule,IPV6Header *pstIpv6Header)
|
||||
static BOOLEAN MatchSrcIpv6Address(S_CLASSIFIER_RULE *pstClassifierRule,
|
||||
IPV6Header *pstIpv6Header)
|
||||
{
|
||||
UINT uiLoopIndex=0;
|
||||
UINT uiIpv6AddIndex=0;
|
||||
UINT uiIpv6AddrNoLongWords = 4;
|
||||
UINT uiLoopIndex = 0;
|
||||
UINT uiIpv6AddIndex = 0;
|
||||
UINT uiIpv6AddrNoLongWords = 4;
|
||||
ULONG aulSrcIP[4];
|
||||
PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev);
|
||||
PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev);
|
||||
/*
|
||||
//This is the no. of Src Addresses ie Range of IP Addresses contained
|
||||
//in the classifier rule for which we need to match
|
||||
*/
|
||||
* This is the no. of Src Addresses ie Range of IP Addresses contained
|
||||
* in the classifier rule for which we need to match
|
||||
*/
|
||||
UINT uiCountIPSrcAddresses = (UINT)pstClassifierRule->ucIPSourceAddressLength;
|
||||
|
||||
|
||||
if(0 == uiCountIPSrcAddresses)
|
||||
if (uiCountIPSrcAddresses == 0)
|
||||
return TRUE;
|
||||
|
||||
|
||||
//First Convert the Ip Address in the packet to Host Endian order
|
||||
for(uiIpv6AddIndex=0;uiIpv6AddIndex<uiIpv6AddrNoLongWords;uiIpv6AddIndex++)
|
||||
{
|
||||
aulSrcIP[uiIpv6AddIndex]=ntohl(pstIpv6Header->ulSrcIpAddress[uiIpv6AddIndex]);
|
||||
}
|
||||
/* First Convert the Ip Address in the packet to Host Endian order */
|
||||
for (uiIpv6AddIndex = 0; uiIpv6AddIndex < uiIpv6AddrNoLongWords; uiIpv6AddIndex++)
|
||||
aulSrcIP[uiIpv6AddIndex] = ntohl(pstIpv6Header->ulSrcIpAddress[uiIpv6AddIndex]);
|
||||
|
||||
for(uiLoopIndex=0;uiLoopIndex<uiCountIPSrcAddresses;uiLoopIndex+=uiIpv6AddrNoLongWords)
|
||||
{
|
||||
BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, "\n Src Ipv6 Address In Received Packet : \n ");
|
||||
for (uiLoopIndex = 0; uiLoopIndex < uiCountIPSrcAddresses; uiLoopIndex += uiIpv6AddrNoLongWords) {
|
||||
BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL,
|
||||
"\n Src Ipv6 Address In Received Packet :\n ");
|
||||
DumpIpv6Address(aulSrcIP);
|
||||
BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, "\n Src Ipv6 Mask In Classifier Rule: \n");
|
||||
BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL,
|
||||
"\n Src Ipv6 Mask In Classifier Rule:\n");
|
||||
DumpIpv6Address(&pstClassifierRule->stSrcIpAddress.ulIpv6Mask[uiLoopIndex]);
|
||||
BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, "\n Src Ipv6 Address In Classifier Rule : \n");
|
||||
BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL,
|
||||
"\n Src Ipv6 Address In Classifier Rule :\n");
|
||||
DumpIpv6Address(&pstClassifierRule->stSrcIpAddress.ulIpv6Addr[uiLoopIndex]);
|
||||
|
||||
for(uiIpv6AddIndex=0;uiIpv6AddIndex<uiIpv6AddrNoLongWords;uiIpv6AddIndex++)
|
||||
{
|
||||
if((pstClassifierRule->stSrcIpAddress.ulIpv6Mask[uiLoopIndex+uiIpv6AddIndex] & aulSrcIP[uiIpv6AddIndex])
|
||||
!= pstClassifierRule->stSrcIpAddress.ulIpv6Addr[uiLoopIndex+uiIpv6AddIndex])
|
||||
{
|
||||
//Match failed for current Ipv6 Address.Try next Ipv6 Address
|
||||
for (uiIpv6AddIndex = 0; uiIpv6AddIndex < uiIpv6AddrNoLongWords; uiIpv6AddIndex++) {
|
||||
if ((pstClassifierRule->stSrcIpAddress.ulIpv6Mask[uiLoopIndex+uiIpv6AddIndex] & aulSrcIP[uiIpv6AddIndex])
|
||||
!= pstClassifierRule->stSrcIpAddress.ulIpv6Addr[uiLoopIndex+uiIpv6AddIndex]) {
|
||||
/*
|
||||
* Match failed for current Ipv6 Address
|
||||
* Try next Ipv6 Address
|
||||
*/
|
||||
break;
|
||||
}
|
||||
|
||||
if(uiIpv6AddIndex == uiIpv6AddrNoLongWords-1)
|
||||
{
|
||||
//Match Found
|
||||
BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, "Ipv6 Src Ip Address Matched\n");
|
||||
if (uiIpv6AddIndex == uiIpv6AddrNoLongWords-1) {
|
||||
/* Match Found */
|
||||
BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG,
|
||||
DBG_LVL_ALL,
|
||||
"Ipv6 Src Ip Address Matched\n");
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
@ -314,52 +344,56 @@ static BOOLEAN MatchSrcIpv6Address(S_CLASSIFIER_RULE *pstClassifierRule,IPV6Head
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
static BOOLEAN MatchDestIpv6Address(S_CLASSIFIER_RULE *pstClassifierRule,IPV6Header *pstIpv6Header)
|
||||
static BOOLEAN MatchDestIpv6Address(S_CLASSIFIER_RULE *pstClassifierRule,
|
||||
IPV6Header *pstIpv6Header)
|
||||
{
|
||||
UINT uiLoopIndex=0;
|
||||
UINT uiIpv6AddIndex=0;
|
||||
UINT uiIpv6AddrNoLongWords = 4;
|
||||
UINT uiLoopIndex = 0;
|
||||
UINT uiIpv6AddIndex = 0;
|
||||
UINT uiIpv6AddrNoLongWords = 4;
|
||||
ULONG aulDestIP[4];
|
||||
PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev);
|
||||
PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev);
|
||||
/*
|
||||
//This is the no. of Destination Addresses ie Range of IP Addresses contained
|
||||
//in the classifier rule for which we need to match
|
||||
*/
|
||||
* This is the no. of Destination Addresses
|
||||
* ie Range of IP Addresses contained in the classifier rule
|
||||
* for which we need to match
|
||||
*/
|
||||
UINT uiCountIPDestinationAddresses = (UINT)pstClassifierRule->ucIPDestinationAddressLength;
|
||||
|
||||
|
||||
if(0 == uiCountIPDestinationAddresses)
|
||||
if (uiCountIPDestinationAddresses == 0)
|
||||
return TRUE;
|
||||
|
||||
|
||||
//First Convert the Ip Address in the packet to Host Endian order
|
||||
for(uiIpv6AddIndex=0;uiIpv6AddIndex<uiIpv6AddrNoLongWords;uiIpv6AddIndex++)
|
||||
{
|
||||
aulDestIP[uiIpv6AddIndex]=ntohl(pstIpv6Header->ulDestIpAddress[uiIpv6AddIndex]);
|
||||
}
|
||||
/* First Convert the Ip Address in the packet to Host Endian order */
|
||||
for (uiIpv6AddIndex = 0; uiIpv6AddIndex < uiIpv6AddrNoLongWords; uiIpv6AddIndex++)
|
||||
aulDestIP[uiIpv6AddIndex] = ntohl(pstIpv6Header->ulDestIpAddress[uiIpv6AddIndex]);
|
||||
|
||||
for(uiLoopIndex=0;uiLoopIndex<uiCountIPDestinationAddresses;uiLoopIndex+=uiIpv6AddrNoLongWords)
|
||||
{
|
||||
BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, "\n Destination Ipv6 Address In Received Packet : \n ");
|
||||
for (uiLoopIndex = 0; uiLoopIndex < uiCountIPDestinationAddresses; uiLoopIndex += uiIpv6AddrNoLongWords) {
|
||||
BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL,
|
||||
"\n Destination Ipv6 Address In Received Packet :\n ");
|
||||
DumpIpv6Address(aulDestIP);
|
||||
BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, "\n Destination Ipv6 Mask In Classifier Rule: \n");
|
||||
BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL,
|
||||
"\n Destination Ipv6 Mask In Classifier Rule :\n");
|
||||
DumpIpv6Address(&pstClassifierRule->stDestIpAddress.ulIpv6Mask[uiLoopIndex]);
|
||||
BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, "\n Destination Ipv6 Address In Classifier Rule : \n");
|
||||
BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL,
|
||||
"\n Destination Ipv6 Address In Classifier Rule :\n");
|
||||
DumpIpv6Address(&pstClassifierRule->stDestIpAddress.ulIpv6Addr[uiLoopIndex]);
|
||||
|
||||
for(uiIpv6AddIndex=0;uiIpv6AddIndex<uiIpv6AddrNoLongWords;uiIpv6AddIndex++)
|
||||
{
|
||||
if((pstClassifierRule->stDestIpAddress.ulIpv6Mask[uiLoopIndex+uiIpv6AddIndex] & aulDestIP[uiIpv6AddIndex])
|
||||
!= pstClassifierRule->stDestIpAddress.ulIpv6Addr[uiLoopIndex+uiIpv6AddIndex])
|
||||
{
|
||||
//Match failed for current Ipv6 Address.Try next Ipv6 Address
|
||||
for (uiIpv6AddIndex = 0; uiIpv6AddIndex < uiIpv6AddrNoLongWords; uiIpv6AddIndex++) {
|
||||
if ((pstClassifierRule->stDestIpAddress.ulIpv6Mask[uiLoopIndex+uiIpv6AddIndex] & aulDestIP[uiIpv6AddIndex])
|
||||
!= pstClassifierRule->stDestIpAddress.ulIpv6Addr[uiLoopIndex+uiIpv6AddIndex]) {
|
||||
/*
|
||||
* Match failed for current Ipv6 Address.
|
||||
* Try next Ipv6 Address
|
||||
*/
|
||||
break;
|
||||
}
|
||||
|
||||
if(uiIpv6AddIndex == uiIpv6AddrNoLongWords-1)
|
||||
{
|
||||
//Match Found
|
||||
BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, "Ipv6 Destination Ip Address Matched\n");
|
||||
if (uiIpv6AddIndex == uiIpv6AddrNoLongWords-1) {
|
||||
/* Match Found */
|
||||
BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG,
|
||||
DBG_LVL_ALL,
|
||||
"Ipv6 Destination Ip Address Matched\n");
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
@ -371,11 +405,11 @@ static BOOLEAN MatchDestIpv6Address(S_CLASSIFIER_RULE *pstClassifierRule,IPV6Hea
|
|||
VOID DumpIpv6Address(ULONG *puIpv6Address)
|
||||
{
|
||||
UINT uiIpv6AddrNoLongWords = 4;
|
||||
UINT uiIpv6AddIndex=0;
|
||||
PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev);
|
||||
for(uiIpv6AddIndex=0;uiIpv6AddIndex<uiIpv6AddrNoLongWords;uiIpv6AddIndex++)
|
||||
{
|
||||
BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, ":%lx",puIpv6Address[uiIpv6AddIndex]);
|
||||
UINT uiIpv6AddIndex = 0;
|
||||
PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev);
|
||||
for (uiIpv6AddIndex = 0; uiIpv6AddIndex < uiIpv6AddrNoLongWords; uiIpv6AddIndex++) {
|
||||
BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL,
|
||||
":%lx", puIpv6Address[uiIpv6AddIndex]);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -383,22 +417,35 @@ VOID DumpIpv6Address(ULONG *puIpv6Address)
|
|||
static VOID DumpIpv6Header(IPV6Header *pstIpv6Header)
|
||||
{
|
||||
UCHAR ucVersion;
|
||||
UCHAR ucPrio ;
|
||||
PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev);
|
||||
BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, "----Ipv6 Header---");
|
||||
UCHAR ucPrio;
|
||||
PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev);
|
||||
BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL,
|
||||
"----Ipv6 Header---");
|
||||
ucVersion = pstIpv6Header->ucVersionPrio & 0xf0;
|
||||
BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, "Version : %x \n",ucVersion);
|
||||
BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL,
|
||||
"Version : %x\n", ucVersion);
|
||||
ucPrio = pstIpv6Header->ucVersionPrio & 0x0f;
|
||||
BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, "Priority : %x \n",ucPrio);
|
||||
//BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, "Flow Label : %x \n",(pstIpv6Header->ucVersionPrio &0xf0);
|
||||
BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, "Payload Length : %x \n",ntohs(pstIpv6Header->usPayloadLength));
|
||||
BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, "Next Header : %x \n",pstIpv6Header->ucNextHeader);
|
||||
BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, "Hop Limit : %x \n",pstIpv6Header->ucHopLimit);
|
||||
BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, "Src Address :\n");
|
||||
BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL,
|
||||
"Priority : %x\n", ucPrio);
|
||||
/*
|
||||
* BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL,
|
||||
* "Flow Label : %x\n",(pstIpv6Header->ucVersionPrio &0xf0);
|
||||
*/
|
||||
BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL,
|
||||
"Payload Length : %x\n",
|
||||
ntohs(pstIpv6Header->usPayloadLength));
|
||||
BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL,
|
||||
"Next Header : %x\n", pstIpv6Header->ucNextHeader);
|
||||
BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL,
|
||||
"Hop Limit : %x\n", pstIpv6Header->ucHopLimit);
|
||||
BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL,
|
||||
"Src Address :\n");
|
||||
DumpIpv6Address(pstIpv6Header->ulSrcIpAddress);
|
||||
BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, "Dest Address :\n");
|
||||
BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL,
|
||||
"Dest Address :\n");
|
||||
DumpIpv6Address(pstIpv6Header->ulDestIpAddress);
|
||||
BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, "----Ipv6 Header End---");
|
||||
BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL,
|
||||
"----Ipv6 Header End---");
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -835,7 +835,7 @@ int reset_card_proc(PMINI_ADAPTER ps_adapter)
|
|||
Bcm_kill_all_URBs(psIntfAdapter);
|
||||
/* Reset the UMA-B Device */
|
||||
if (ps_adapter->chip_id >= T3LPB) {
|
||||
BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Reseting UMA-B\n");
|
||||
BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Resetting UMA-B\n");
|
||||
retval = usb_reset_device(psIntfAdapter->udev);
|
||||
psIntfAdapter->psAdapter->StopAllXaction = FALSE;
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -465,7 +465,7 @@
|
|||
/* only relevant to kernel modules. */
|
||||
|
||||
#define COMEDI_CB_EOS 1 /* end of scan */
|
||||
#define COMEDI_CB_EOA 2 /* end of acquisition */
|
||||
#define COMEDI_CB_EOA 2 /* end of acquisition/output */
|
||||
#define COMEDI_CB_BLOCK 4 /* data has arrived:
|
||||
* wakes up read() / write() */
|
||||
#define COMEDI_CB_EOBUF 8 /* DEPRECATED: end of buffer */
|
||||
|
|
|
@ -58,14 +58,35 @@ MODULE_LICENSE("GPL");
|
|||
#ifdef CONFIG_COMEDI_DEBUG
|
||||
int comedi_debug;
|
||||
EXPORT_SYMBOL(comedi_debug);
|
||||
module_param(comedi_debug, int, 0644);
|
||||
module_param(comedi_debug, int, S_IRUGO | S_IWUSR);
|
||||
MODULE_PARM_DESC(comedi_debug,
|
||||
"enable comedi core and driver debugging if non-zero (default 0)"
|
||||
);
|
||||
#endif
|
||||
|
||||
bool comedi_autoconfig = 1;
|
||||
module_param(comedi_autoconfig, bool, 0444);
|
||||
module_param(comedi_autoconfig, bool, S_IRUGO);
|
||||
MODULE_PARM_DESC(comedi_autoconfig,
|
||||
"enable drivers to auto-configure comedi devices (default 1)");
|
||||
|
||||
static int comedi_num_legacy_minors;
|
||||
module_param(comedi_num_legacy_minors, int, 0444);
|
||||
module_param(comedi_num_legacy_minors, int, S_IRUGO);
|
||||
MODULE_PARM_DESC(comedi_num_legacy_minors,
|
||||
"number of comedi minor devices to reserve for non-auto-configured devices (default 0)"
|
||||
);
|
||||
|
||||
unsigned int comedi_default_buf_size_kb = CONFIG_COMEDI_DEFAULT_BUF_SIZE_KB;
|
||||
module_param(comedi_default_buf_size_kb, uint, S_IRUGO | S_IWUSR);
|
||||
MODULE_PARM_DESC(comedi_default_buf_size_kb,
|
||||
"default asynchronous buffer size in KiB (default "
|
||||
__MODULE_STRING(CONFIG_COMEDI_DEFAULT_BUF_SIZE_KB) ")");
|
||||
|
||||
unsigned int comedi_default_buf_maxsize_kb
|
||||
= CONFIG_COMEDI_DEFAULT_BUF_MAXSIZE_KB;
|
||||
module_param(comedi_default_buf_maxsize_kb, uint, S_IRUGO | S_IWUSR);
|
||||
MODULE_PARM_DESC(comedi_default_buf_maxsize_kb,
|
||||
"default maximum size of asynchronous buffer in KiB (default "
|
||||
__MODULE_STRING(CONFIG_COMEDI_DEFAULT_BUF_MAXSIZE_KB) ")");
|
||||
|
||||
static DEFINE_SPINLOCK(comedi_file_info_table_lock);
|
||||
static struct comedi_device_file_info
|
||||
|
@ -108,15 +129,283 @@ static int do_cancel(struct comedi_device *dev, struct comedi_subdevice *s);
|
|||
static int comedi_fasync(int fd, struct file *file, int on);
|
||||
|
||||
static int is_device_busy(struct comedi_device *dev);
|
||||
|
||||
static int resize_async_buffer(struct comedi_device *dev,
|
||||
struct comedi_subdevice *s,
|
||||
struct comedi_async *async, unsigned new_size);
|
||||
struct comedi_async *async, unsigned new_size)
|
||||
{
|
||||
int retval;
|
||||
|
||||
/* declarations for sysfs attribute files */
|
||||
static struct device_attribute dev_attr_max_read_buffer_kb;
|
||||
static struct device_attribute dev_attr_read_buffer_kb;
|
||||
static struct device_attribute dev_attr_max_write_buffer_kb;
|
||||
static struct device_attribute dev_attr_write_buffer_kb;
|
||||
if (new_size > async->max_bufsize)
|
||||
return -EPERM;
|
||||
|
||||
if (s->busy) {
|
||||
DPRINTK("subdevice is busy, cannot resize buffer\n");
|
||||
return -EBUSY;
|
||||
}
|
||||
if (async->mmap_count) {
|
||||
DPRINTK("subdevice is mmapped, cannot resize buffer\n");
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
if (!async->prealloc_buf)
|
||||
return -EINVAL;
|
||||
|
||||
/* make sure buffer is an integral number of pages
|
||||
* (we round up) */
|
||||
new_size = (new_size + PAGE_SIZE - 1) & PAGE_MASK;
|
||||
|
||||
retval = comedi_buf_alloc(dev, s, new_size);
|
||||
if (retval < 0)
|
||||
return retval;
|
||||
|
||||
if (s->buf_change) {
|
||||
retval = s->buf_change(dev, s, new_size);
|
||||
if (retval < 0)
|
||||
return retval;
|
||||
}
|
||||
|
||||
DPRINTK("comedi%i subd %d buffer resized to %i bytes\n",
|
||||
dev->minor, (int)(s - dev->subdevices), async->prealloc_bufsz);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* sysfs attribute files */
|
||||
|
||||
static const unsigned bytes_per_kibi = 1024;
|
||||
|
||||
static ssize_t show_max_read_buffer_kb(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
ssize_t retval;
|
||||
struct comedi_device_file_info *info = dev_get_drvdata(dev);
|
||||
unsigned max_buffer_size_kb = 0;
|
||||
struct comedi_subdevice *const read_subdevice =
|
||||
comedi_get_read_subdevice(info);
|
||||
|
||||
mutex_lock(&info->device->mutex);
|
||||
if (read_subdevice &&
|
||||
(read_subdevice->subdev_flags & SDF_CMD_READ) &&
|
||||
read_subdevice->async) {
|
||||
max_buffer_size_kb = read_subdevice->async->max_bufsize /
|
||||
bytes_per_kibi;
|
||||
}
|
||||
retval = snprintf(buf, PAGE_SIZE, "%i\n", max_buffer_size_kb);
|
||||
mutex_unlock(&info->device->mutex);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
static ssize_t store_max_read_buffer_kb(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct comedi_device_file_info *info = dev_get_drvdata(dev);
|
||||
unsigned int new_max_size_kb;
|
||||
unsigned int new_max_size;
|
||||
int ret;
|
||||
struct comedi_subdevice *const read_subdevice =
|
||||
comedi_get_read_subdevice(info);
|
||||
|
||||
ret = kstrtouint(buf, 10, &new_max_size_kb);
|
||||
if (ret)
|
||||
return ret;
|
||||
if (new_max_size_kb > (UINT_MAX / bytes_per_kibi))
|
||||
return -EINVAL;
|
||||
new_max_size = new_max_size_kb * bytes_per_kibi;
|
||||
|
||||
mutex_lock(&info->device->mutex);
|
||||
if (read_subdevice == NULL ||
|
||||
(read_subdevice->subdev_flags & SDF_CMD_READ) == 0 ||
|
||||
read_subdevice->async == NULL) {
|
||||
mutex_unlock(&info->device->mutex);
|
||||
return -EINVAL;
|
||||
}
|
||||
read_subdevice->async->max_bufsize = new_max_size;
|
||||
mutex_unlock(&info->device->mutex);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static ssize_t show_read_buffer_kb(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
ssize_t retval;
|
||||
struct comedi_device_file_info *info = dev_get_drvdata(dev);
|
||||
unsigned buffer_size_kb = 0;
|
||||
struct comedi_subdevice *const read_subdevice =
|
||||
comedi_get_read_subdevice(info);
|
||||
|
||||
mutex_lock(&info->device->mutex);
|
||||
if (read_subdevice &&
|
||||
(read_subdevice->subdev_flags & SDF_CMD_READ) &&
|
||||
read_subdevice->async) {
|
||||
buffer_size_kb = read_subdevice->async->prealloc_bufsz /
|
||||
bytes_per_kibi;
|
||||
}
|
||||
retval = snprintf(buf, PAGE_SIZE, "%i\n", buffer_size_kb);
|
||||
mutex_unlock(&info->device->mutex);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
static ssize_t store_read_buffer_kb(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct comedi_device_file_info *info = dev_get_drvdata(dev);
|
||||
unsigned int new_size_kb;
|
||||
unsigned int new_size;
|
||||
int retval;
|
||||
int ret;
|
||||
struct comedi_subdevice *const read_subdevice =
|
||||
comedi_get_read_subdevice(info);
|
||||
|
||||
ret = kstrtouint(buf, 10, &new_size_kb);
|
||||
if (ret)
|
||||
return ret;
|
||||
if (new_size_kb > (UINT_MAX / bytes_per_kibi))
|
||||
return -EINVAL;
|
||||
new_size = new_size_kb * bytes_per_kibi;
|
||||
|
||||
mutex_lock(&info->device->mutex);
|
||||
if (read_subdevice == NULL ||
|
||||
(read_subdevice->subdev_flags & SDF_CMD_READ) == 0 ||
|
||||
read_subdevice->async == NULL) {
|
||||
mutex_unlock(&info->device->mutex);
|
||||
return -EINVAL;
|
||||
}
|
||||
retval = resize_async_buffer(info->device, read_subdevice,
|
||||
read_subdevice->async, new_size);
|
||||
mutex_unlock(&info->device->mutex);
|
||||
|
||||
if (retval < 0)
|
||||
return retval;
|
||||
return count;
|
||||
}
|
||||
|
||||
static ssize_t show_max_write_buffer_kb(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
ssize_t retval;
|
||||
struct comedi_device_file_info *info = dev_get_drvdata(dev);
|
||||
unsigned max_buffer_size_kb = 0;
|
||||
struct comedi_subdevice *const write_subdevice =
|
||||
comedi_get_write_subdevice(info);
|
||||
|
||||
mutex_lock(&info->device->mutex);
|
||||
if (write_subdevice &&
|
||||
(write_subdevice->subdev_flags & SDF_CMD_WRITE) &&
|
||||
write_subdevice->async) {
|
||||
max_buffer_size_kb = write_subdevice->async->max_bufsize /
|
||||
bytes_per_kibi;
|
||||
}
|
||||
retval = snprintf(buf, PAGE_SIZE, "%i\n", max_buffer_size_kb);
|
||||
mutex_unlock(&info->device->mutex);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
static ssize_t store_max_write_buffer_kb(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct comedi_device_file_info *info = dev_get_drvdata(dev);
|
||||
unsigned int new_max_size_kb;
|
||||
unsigned int new_max_size;
|
||||
int ret;
|
||||
struct comedi_subdevice *const write_subdevice =
|
||||
comedi_get_write_subdevice(info);
|
||||
|
||||
ret = kstrtouint(buf, 10, &new_max_size_kb);
|
||||
if (ret)
|
||||
return ret;
|
||||
if (new_max_size_kb > (UINT_MAX / bytes_per_kibi))
|
||||
return -EINVAL;
|
||||
new_max_size = new_max_size_kb * bytes_per_kibi;
|
||||
|
||||
mutex_lock(&info->device->mutex);
|
||||
if (write_subdevice == NULL ||
|
||||
(write_subdevice->subdev_flags & SDF_CMD_WRITE) == 0 ||
|
||||
write_subdevice->async == NULL) {
|
||||
mutex_unlock(&info->device->mutex);
|
||||
return -EINVAL;
|
||||
}
|
||||
write_subdevice->async->max_bufsize = new_max_size;
|
||||
mutex_unlock(&info->device->mutex);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static ssize_t show_write_buffer_kb(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
ssize_t retval;
|
||||
struct comedi_device_file_info *info = dev_get_drvdata(dev);
|
||||
unsigned buffer_size_kb = 0;
|
||||
struct comedi_subdevice *const write_subdevice =
|
||||
comedi_get_write_subdevice(info);
|
||||
|
||||
mutex_lock(&info->device->mutex);
|
||||
if (write_subdevice &&
|
||||
(write_subdevice->subdev_flags & SDF_CMD_WRITE) &&
|
||||
write_subdevice->async) {
|
||||
buffer_size_kb = write_subdevice->async->prealloc_bufsz /
|
||||
bytes_per_kibi;
|
||||
}
|
||||
retval = snprintf(buf, PAGE_SIZE, "%i\n", buffer_size_kb);
|
||||
mutex_unlock(&info->device->mutex);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
static ssize_t store_write_buffer_kb(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct comedi_device_file_info *info = dev_get_drvdata(dev);
|
||||
unsigned int new_size_kb;
|
||||
unsigned int new_size;
|
||||
int retval;
|
||||
int ret;
|
||||
struct comedi_subdevice *const write_subdevice =
|
||||
comedi_get_write_subdevice(info);
|
||||
|
||||
ret = kstrtouint(buf, 10, &new_size_kb);
|
||||
if (ret)
|
||||
return ret;
|
||||
if (new_size_kb > (UINT_MAX / bytes_per_kibi))
|
||||
return -EINVAL;
|
||||
new_size = ((uint64_t) new_size_kb) * bytes_per_kibi;
|
||||
|
||||
mutex_lock(&info->device->mutex);
|
||||
if (write_subdevice == NULL ||
|
||||
(write_subdevice->subdev_flags & SDF_CMD_WRITE) == 0 ||
|
||||
write_subdevice->async == NULL) {
|
||||
mutex_unlock(&info->device->mutex);
|
||||
return -EINVAL;
|
||||
}
|
||||
retval = resize_async_buffer(info->device, write_subdevice,
|
||||
write_subdevice->async, new_size);
|
||||
mutex_unlock(&info->device->mutex);
|
||||
|
||||
if (retval < 0)
|
||||
return retval;
|
||||
return count;
|
||||
}
|
||||
|
||||
static struct device_attribute comedi_dev_attrs[] = {
|
||||
__ATTR(max_read_buffer_kb, S_IRUGO | S_IWUSR,
|
||||
show_max_read_buffer_kb, store_max_read_buffer_kb),
|
||||
__ATTR(read_buffer_kb, S_IRUGO | S_IWUSR | S_IWGRP,
|
||||
show_read_buffer_kb, store_read_buffer_kb),
|
||||
__ATTR(max_write_buffer_kb, S_IRUGO | S_IWUSR,
|
||||
show_max_write_buffer_kb, store_max_write_buffer_kb),
|
||||
__ATTR(write_buffer_kb, S_IRUGO | S_IWUSR | S_IWGRP,
|
||||
show_write_buffer_kb, store_write_buffer_kb),
|
||||
__ATTR_NULL
|
||||
};
|
||||
|
||||
static long comedi_unlocked_ioctl(struct file *file, unsigned int cmd,
|
||||
unsigned long arg)
|
||||
|
@ -280,7 +569,7 @@ static int do_devconfig_ioctl(struct comedi_device *dev,
|
|||
if (ret == 0) {
|
||||
if (!try_module_get(dev->driver->module)) {
|
||||
comedi_device_detach(dev);
|
||||
return -ENOSYS;
|
||||
ret = -ENOSYS;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1545,7 +1834,7 @@ done:
|
|||
return retval;
|
||||
}
|
||||
|
||||
static unsigned int comedi_poll(struct file *file, poll_table * wait)
|
||||
static unsigned int comedi_poll(struct file *file, poll_table *wait)
|
||||
{
|
||||
unsigned int mask = 0;
|
||||
const unsigned minor = iminor(file->f_dentry->d_inode);
|
||||
|
@ -2054,6 +2343,8 @@ static int __init comedi_init(void)
|
|||
return PTR_ERR(comedi_class);
|
||||
}
|
||||
|
||||
comedi_class->dev_attrs = comedi_dev_attrs;
|
||||
|
||||
/* XXX requires /proc interface */
|
||||
comedi_proc_init();
|
||||
|
||||
|
@ -2192,11 +2483,9 @@ static void comedi_device_cleanup(struct comedi_device *dev)
|
|||
|
||||
int comedi_alloc_board_minor(struct device *hardware_device)
|
||||
{
|
||||
unsigned long flags;
|
||||
struct comedi_device_file_info *info;
|
||||
struct device *csdev;
|
||||
unsigned i;
|
||||
int retval;
|
||||
|
||||
info = kzalloc(sizeof(struct comedi_device_file_info), GFP_KERNEL);
|
||||
if (info == NULL)
|
||||
|
@ -2206,15 +2495,16 @@ int comedi_alloc_board_minor(struct device *hardware_device)
|
|||
kfree(info);
|
||||
return -ENOMEM;
|
||||
}
|
||||
info->hardware_device = hardware_device;
|
||||
comedi_device_init(info->device);
|
||||
spin_lock_irqsave(&comedi_file_info_table_lock, flags);
|
||||
spin_lock(&comedi_file_info_table_lock);
|
||||
for (i = 0; i < COMEDI_NUM_BOARD_MINORS; ++i) {
|
||||
if (comedi_file_info_table[i] == NULL) {
|
||||
comedi_file_info_table[i] = info;
|
||||
break;
|
||||
}
|
||||
}
|
||||
spin_unlock_irqrestore(&comedi_file_info_table_lock, flags);
|
||||
spin_unlock(&comedi_file_info_table_lock);
|
||||
if (i == COMEDI_NUM_BOARD_MINORS) {
|
||||
comedi_device_cleanup(info->device);
|
||||
kfree(info->device);
|
||||
|
@ -2230,55 +2520,19 @@ int comedi_alloc_board_minor(struct device *hardware_device)
|
|||
if (!IS_ERR(csdev))
|
||||
info->device->class_dev = csdev;
|
||||
dev_set_drvdata(csdev, info);
|
||||
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",
|
||||
dev_attr_max_read_buffer_kb.attr.name);
|
||||
comedi_free_board_minor(i);
|
||||
return retval;
|
||||
}
|
||||
retval = device_create_file(csdev, &dev_attr_read_buffer_kb);
|
||||
if (retval) {
|
||||
printk(KERN_ERR
|
||||
"comedi: "
|
||||
"failed to create sysfs attribute file \"%s\".\n",
|
||||
dev_attr_read_buffer_kb.attr.name);
|
||||
comedi_free_board_minor(i);
|
||||
return retval;
|
||||
}
|
||||
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",
|
||||
dev_attr_max_write_buffer_kb.attr.name);
|
||||
comedi_free_board_minor(i);
|
||||
return retval;
|
||||
}
|
||||
retval = device_create_file(csdev, &dev_attr_write_buffer_kb);
|
||||
if (retval) {
|
||||
printk(KERN_ERR
|
||||
"comedi: "
|
||||
"failed to create sysfs attribute file \"%s\".\n",
|
||||
dev_attr_write_buffer_kb.attr.name);
|
||||
comedi_free_board_minor(i);
|
||||
return retval;
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
void comedi_free_board_minor(unsigned minor)
|
||||
{
|
||||
unsigned long flags;
|
||||
struct comedi_device_file_info *info;
|
||||
|
||||
BUG_ON(minor >= COMEDI_NUM_BOARD_MINORS);
|
||||
spin_lock_irqsave(&comedi_file_info_table_lock, flags);
|
||||
spin_lock(&comedi_file_info_table_lock);
|
||||
info = comedi_file_info_table[minor];
|
||||
comedi_file_info_table[minor] = NULL;
|
||||
spin_unlock_irqrestore(&comedi_file_info_table_lock, flags);
|
||||
spin_unlock(&comedi_file_info_table_lock);
|
||||
|
||||
if (info) {
|
||||
struct comedi_device *dev = info->device;
|
||||
|
@ -2294,14 +2548,29 @@ void comedi_free_board_minor(unsigned minor)
|
|||
}
|
||||
}
|
||||
|
||||
int comedi_find_board_minor(struct device *hardware_device)
|
||||
{
|
||||
int minor;
|
||||
struct comedi_device_file_info *info;
|
||||
|
||||
for (minor = 0; minor < COMEDI_NUM_BOARD_MINORS; minor++) {
|
||||
spin_lock(&comedi_file_info_table_lock);
|
||||
info = comedi_file_info_table[minor];
|
||||
if (info && info->hardware_device == hardware_device) {
|
||||
spin_unlock(&comedi_file_info_table_lock);
|
||||
return minor;
|
||||
}
|
||||
spin_unlock(&comedi_file_info_table_lock);
|
||||
}
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
int comedi_alloc_subdevice_minor(struct comedi_device *dev,
|
||||
struct comedi_subdevice *s)
|
||||
{
|
||||
unsigned long flags;
|
||||
struct comedi_device_file_info *info;
|
||||
struct device *csdev;
|
||||
unsigned i;
|
||||
int retval;
|
||||
|
||||
info = kmalloc(sizeof(struct comedi_device_file_info), GFP_KERNEL);
|
||||
if (info == NULL)
|
||||
|
@ -2309,14 +2578,14 @@ int comedi_alloc_subdevice_minor(struct comedi_device *dev,
|
|||
info->device = dev;
|
||||
info->read_subdevice = s;
|
||||
info->write_subdevice = s;
|
||||
spin_lock_irqsave(&comedi_file_info_table_lock, flags);
|
||||
spin_lock(&comedi_file_info_table_lock);
|
||||
for (i = COMEDI_FIRST_SUBDEVICE_MINOR; i < COMEDI_NUM_MINORS; ++i) {
|
||||
if (comedi_file_info_table[i] == NULL) {
|
||||
comedi_file_info_table[i] = info;
|
||||
break;
|
||||
}
|
||||
}
|
||||
spin_unlock_irqrestore(&comedi_file_info_table_lock, flags);
|
||||
spin_unlock(&comedi_file_info_table_lock);
|
||||
if (i == COMEDI_NUM_MINORS) {
|
||||
kfree(info);
|
||||
printk(KERN_ERR
|
||||
|
@ -2331,48 +2600,12 @@ int comedi_alloc_subdevice_minor(struct comedi_device *dev,
|
|||
if (!IS_ERR(csdev))
|
||||
s->class_dev = csdev;
|
||||
dev_set_drvdata(csdev, info);
|
||||
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",
|
||||
dev_attr_max_read_buffer_kb.attr.name);
|
||||
comedi_free_subdevice_minor(s);
|
||||
return retval;
|
||||
}
|
||||
retval = device_create_file(csdev, &dev_attr_read_buffer_kb);
|
||||
if (retval) {
|
||||
printk(KERN_ERR
|
||||
"comedi: "
|
||||
"failed to create sysfs attribute file \"%s\".\n",
|
||||
dev_attr_read_buffer_kb.attr.name);
|
||||
comedi_free_subdevice_minor(s);
|
||||
return retval;
|
||||
}
|
||||
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",
|
||||
dev_attr_max_write_buffer_kb.attr.name);
|
||||
comedi_free_subdevice_minor(s);
|
||||
return retval;
|
||||
}
|
||||
retval = device_create_file(csdev, &dev_attr_write_buffer_kb);
|
||||
if (retval) {
|
||||
printk(KERN_ERR
|
||||
"comedi: "
|
||||
"failed to create sysfs attribute file \"%s\".\n",
|
||||
dev_attr_write_buffer_kb.attr.name);
|
||||
comedi_free_subdevice_minor(s);
|
||||
return retval;
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
void comedi_free_subdevice_minor(struct comedi_subdevice *s)
|
||||
{
|
||||
unsigned long flags;
|
||||
struct comedi_device_file_info *info;
|
||||
|
||||
if (s == NULL)
|
||||
|
@ -2383,10 +2616,10 @@ void comedi_free_subdevice_minor(struct comedi_subdevice *s)
|
|||
BUG_ON(s->minor >= COMEDI_NUM_MINORS);
|
||||
BUG_ON(s->minor < COMEDI_FIRST_SUBDEVICE_MINOR);
|
||||
|
||||
spin_lock_irqsave(&comedi_file_info_table_lock, flags);
|
||||
spin_lock(&comedi_file_info_table_lock);
|
||||
info = comedi_file_info_table[s->minor];
|
||||
comedi_file_info_table[s->minor] = NULL;
|
||||
spin_unlock_irqrestore(&comedi_file_info_table_lock, flags);
|
||||
spin_unlock(&comedi_file_info_table_lock);
|
||||
|
||||
if (s->class_dev) {
|
||||
device_destroy(comedi_class, MKDEV(COMEDI_MAJOR, s->minor));
|
||||
|
@ -2397,310 +2630,12 @@ void comedi_free_subdevice_minor(struct comedi_subdevice *s)
|
|||
|
||||
struct comedi_device_file_info *comedi_get_device_file_info(unsigned minor)
|
||||
{
|
||||
unsigned long flags;
|
||||
struct comedi_device_file_info *info;
|
||||
|
||||
BUG_ON(minor >= COMEDI_NUM_MINORS);
|
||||
spin_lock_irqsave(&comedi_file_info_table_lock, flags);
|
||||
spin_lock(&comedi_file_info_table_lock);
|
||||
info = comedi_file_info_table[minor];
|
||||
spin_unlock_irqrestore(&comedi_file_info_table_lock, flags);
|
||||
spin_unlock(&comedi_file_info_table_lock);
|
||||
return info;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(comedi_get_device_file_info);
|
||||
|
||||
static int resize_async_buffer(struct comedi_device *dev,
|
||||
struct comedi_subdevice *s,
|
||||
struct comedi_async *async, unsigned new_size)
|
||||
{
|
||||
int retval;
|
||||
|
||||
if (new_size > async->max_bufsize)
|
||||
return -EPERM;
|
||||
|
||||
if (s->busy) {
|
||||
DPRINTK("subdevice is busy, cannot resize buffer\n");
|
||||
return -EBUSY;
|
||||
}
|
||||
if (async->mmap_count) {
|
||||
DPRINTK("subdevice is mmapped, cannot resize buffer\n");
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
if (!async->prealloc_buf)
|
||||
return -EINVAL;
|
||||
|
||||
/* make sure buffer is an integral number of pages
|
||||
* (we round up) */
|
||||
new_size = (new_size + PAGE_SIZE - 1) & PAGE_MASK;
|
||||
|
||||
retval = comedi_buf_alloc(dev, s, new_size);
|
||||
if (retval < 0)
|
||||
return retval;
|
||||
|
||||
if (s->buf_change) {
|
||||
retval = s->buf_change(dev, s, new_size);
|
||||
if (retval < 0)
|
||||
return retval;
|
||||
}
|
||||
|
||||
DPRINTK("comedi%i subd %d buffer resized to %i bytes\n",
|
||||
dev->minor, (int)(s - dev->subdevices), async->prealloc_bufsz);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* sysfs attribute files */
|
||||
|
||||
static const unsigned bytes_per_kibi = 1024;
|
||||
|
||||
static ssize_t show_max_read_buffer_kb(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
ssize_t retval;
|
||||
struct comedi_device_file_info *info = dev_get_drvdata(dev);
|
||||
unsigned max_buffer_size_kb = 0;
|
||||
struct comedi_subdevice *const read_subdevice =
|
||||
comedi_get_read_subdevice(info);
|
||||
|
||||
mutex_lock(&info->device->mutex);
|
||||
if (read_subdevice &&
|
||||
(read_subdevice->subdev_flags & SDF_CMD_READ) &&
|
||||
read_subdevice->async) {
|
||||
max_buffer_size_kb = read_subdevice->async->max_bufsize /
|
||||
bytes_per_kibi;
|
||||
}
|
||||
retval = snprintf(buf, PAGE_SIZE, "%i\n", max_buffer_size_kb);
|
||||
mutex_unlock(&info->device->mutex);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
static ssize_t store_max_read_buffer_kb(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct comedi_device_file_info *info = dev_get_drvdata(dev);
|
||||
unsigned int new_max_size_kb;
|
||||
unsigned int new_max_size;
|
||||
int ret;
|
||||
struct comedi_subdevice *const read_subdevice =
|
||||
comedi_get_read_subdevice(info);
|
||||
|
||||
ret = kstrtouint(buf, 10, &new_max_size_kb);
|
||||
if (ret)
|
||||
return ret;
|
||||
if (new_max_size_kb > (UINT_MAX / bytes_per_kibi))
|
||||
return -EINVAL;
|
||||
new_max_size = new_max_size_kb * bytes_per_kibi;
|
||||
|
||||
mutex_lock(&info->device->mutex);
|
||||
if (read_subdevice == NULL ||
|
||||
(read_subdevice->subdev_flags & SDF_CMD_READ) == 0 ||
|
||||
read_subdevice->async == NULL) {
|
||||
mutex_unlock(&info->device->mutex);
|
||||
return -EINVAL;
|
||||
}
|
||||
read_subdevice->async->max_bufsize = new_max_size;
|
||||
mutex_unlock(&info->device->mutex);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static struct device_attribute dev_attr_max_read_buffer_kb = {
|
||||
.attr = {
|
||||
.name = "max_read_buffer_kb",
|
||||
.mode = S_IRUGO | S_IWUSR},
|
||||
.show = &show_max_read_buffer_kb,
|
||||
.store = &store_max_read_buffer_kb
|
||||
};
|
||||
|
||||
static ssize_t show_read_buffer_kb(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
ssize_t retval;
|
||||
struct comedi_device_file_info *info = dev_get_drvdata(dev);
|
||||
unsigned buffer_size_kb = 0;
|
||||
struct comedi_subdevice *const read_subdevice =
|
||||
comedi_get_read_subdevice(info);
|
||||
|
||||
mutex_lock(&info->device->mutex);
|
||||
if (read_subdevice &&
|
||||
(read_subdevice->subdev_flags & SDF_CMD_READ) &&
|
||||
read_subdevice->async) {
|
||||
buffer_size_kb = read_subdevice->async->prealloc_bufsz /
|
||||
bytes_per_kibi;
|
||||
}
|
||||
retval = snprintf(buf, PAGE_SIZE, "%i\n", buffer_size_kb);
|
||||
mutex_unlock(&info->device->mutex);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
static ssize_t store_read_buffer_kb(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct comedi_device_file_info *info = dev_get_drvdata(dev);
|
||||
unsigned int new_size_kb;
|
||||
unsigned int new_size;
|
||||
int retval;
|
||||
int ret;
|
||||
struct comedi_subdevice *const read_subdevice =
|
||||
comedi_get_read_subdevice(info);
|
||||
|
||||
ret = kstrtouint(buf, 10, &new_size_kb);
|
||||
if (ret)
|
||||
return ret;
|
||||
if (new_size_kb > (UINT_MAX / bytes_per_kibi))
|
||||
return -EINVAL;
|
||||
new_size = new_size_kb * bytes_per_kibi;
|
||||
|
||||
mutex_lock(&info->device->mutex);
|
||||
if (read_subdevice == NULL ||
|
||||
(read_subdevice->subdev_flags & SDF_CMD_READ) == 0 ||
|
||||
read_subdevice->async == NULL) {
|
||||
mutex_unlock(&info->device->mutex);
|
||||
return -EINVAL;
|
||||
}
|
||||
retval = resize_async_buffer(info->device, read_subdevice,
|
||||
read_subdevice->async, new_size);
|
||||
mutex_unlock(&info->device->mutex);
|
||||
|
||||
if (retval < 0)
|
||||
return retval;
|
||||
return count;
|
||||
}
|
||||
|
||||
static struct device_attribute dev_attr_read_buffer_kb = {
|
||||
.attr = {
|
||||
.name = "read_buffer_kb",
|
||||
.mode = S_IRUGO | S_IWUSR | S_IWGRP},
|
||||
.show = &show_read_buffer_kb,
|
||||
.store = &store_read_buffer_kb
|
||||
};
|
||||
|
||||
static ssize_t show_max_write_buffer_kb(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
ssize_t retval;
|
||||
struct comedi_device_file_info *info = dev_get_drvdata(dev);
|
||||
unsigned max_buffer_size_kb = 0;
|
||||
struct comedi_subdevice *const write_subdevice =
|
||||
comedi_get_write_subdevice(info);
|
||||
|
||||
mutex_lock(&info->device->mutex);
|
||||
if (write_subdevice &&
|
||||
(write_subdevice->subdev_flags & SDF_CMD_WRITE) &&
|
||||
write_subdevice->async) {
|
||||
max_buffer_size_kb = write_subdevice->async->max_bufsize /
|
||||
bytes_per_kibi;
|
||||
}
|
||||
retval = snprintf(buf, PAGE_SIZE, "%i\n", max_buffer_size_kb);
|
||||
mutex_unlock(&info->device->mutex);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
static ssize_t store_max_write_buffer_kb(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct comedi_device_file_info *info = dev_get_drvdata(dev);
|
||||
unsigned int new_max_size_kb;
|
||||
unsigned int new_max_size;
|
||||
int ret;
|
||||
struct comedi_subdevice *const write_subdevice =
|
||||
comedi_get_write_subdevice(info);
|
||||
|
||||
ret = kstrtouint(buf, 10, &new_max_size_kb);
|
||||
if (ret)
|
||||
return ret;
|
||||
if (new_max_size_kb > (UINT_MAX / bytes_per_kibi))
|
||||
return -EINVAL;
|
||||
new_max_size = new_max_size_kb * bytes_per_kibi;
|
||||
|
||||
mutex_lock(&info->device->mutex);
|
||||
if (write_subdevice == NULL ||
|
||||
(write_subdevice->subdev_flags & SDF_CMD_WRITE) == 0 ||
|
||||
write_subdevice->async == NULL) {
|
||||
mutex_unlock(&info->device->mutex);
|
||||
return -EINVAL;
|
||||
}
|
||||
write_subdevice->async->max_bufsize = new_max_size;
|
||||
mutex_unlock(&info->device->mutex);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static struct device_attribute dev_attr_max_write_buffer_kb = {
|
||||
.attr = {
|
||||
.name = "max_write_buffer_kb",
|
||||
.mode = S_IRUGO | S_IWUSR},
|
||||
.show = &show_max_write_buffer_kb,
|
||||
.store = &store_max_write_buffer_kb
|
||||
};
|
||||
|
||||
static ssize_t show_write_buffer_kb(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
ssize_t retval;
|
||||
struct comedi_device_file_info *info = dev_get_drvdata(dev);
|
||||
unsigned buffer_size_kb = 0;
|
||||
struct comedi_subdevice *const write_subdevice =
|
||||
comedi_get_write_subdevice(info);
|
||||
|
||||
mutex_lock(&info->device->mutex);
|
||||
if (write_subdevice &&
|
||||
(write_subdevice->subdev_flags & SDF_CMD_WRITE) &&
|
||||
write_subdevice->async) {
|
||||
buffer_size_kb = write_subdevice->async->prealloc_bufsz /
|
||||
bytes_per_kibi;
|
||||
}
|
||||
retval = snprintf(buf, PAGE_SIZE, "%i\n", buffer_size_kb);
|
||||
mutex_unlock(&info->device->mutex);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
static ssize_t store_write_buffer_kb(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct comedi_device_file_info *info = dev_get_drvdata(dev);
|
||||
unsigned int new_size_kb;
|
||||
unsigned int new_size;
|
||||
int retval;
|
||||
int ret;
|
||||
struct comedi_subdevice *const write_subdevice =
|
||||
comedi_get_write_subdevice(info);
|
||||
|
||||
ret = kstrtouint(buf, 10, &new_size_kb);
|
||||
if (ret)
|
||||
return ret;
|
||||
if (new_size_kb > (UINT_MAX / bytes_per_kibi))
|
||||
return -EINVAL;
|
||||
new_size = ((uint64_t) new_size_kb) * bytes_per_kibi;
|
||||
|
||||
mutex_lock(&info->device->mutex);
|
||||
if (write_subdevice == NULL ||
|
||||
(write_subdevice->subdev_flags & SDF_CMD_WRITE) == 0 ||
|
||||
write_subdevice->async == NULL) {
|
||||
mutex_unlock(&info->device->mutex);
|
||||
return -EINVAL;
|
||||
}
|
||||
retval = resize_async_buffer(info->device, write_subdevice,
|
||||
write_subdevice->async, new_size);
|
||||
mutex_unlock(&info->device->mutex);
|
||||
|
||||
if (retval < 0)
|
||||
return retval;
|
||||
return count;
|
||||
}
|
||||
|
||||
static struct device_attribute dev_attr_write_buffer_kb = {
|
||||
.attr = {
|
||||
.name = "write_buffer_kb",
|
||||
.mode = S_IRUGO | S_IWUSR | S_IWGRP},
|
||||
.show = &show_write_buffer_kb,
|
||||
.store = &store_write_buffer_kb
|
||||
};
|
||||
|
|
|
@ -180,13 +180,18 @@ struct comedi_async {
|
|||
unsigned int x);
|
||||
};
|
||||
|
||||
struct pci_dev;
|
||||
struct usb_interface;
|
||||
|
||||
struct comedi_driver {
|
||||
struct comedi_driver *next;
|
||||
|
||||
const char *driver_name;
|
||||
struct module *module;
|
||||
int (*attach) (struct comedi_device *, struct comedi_devconfig *);
|
||||
int (*detach) (struct comedi_device *);
|
||||
void (*detach) (struct comedi_device *);
|
||||
int (*attach_pci) (struct comedi_device *, struct pci_dev *);
|
||||
int (*attach_usb) (struct comedi_device *, struct usb_interface *);
|
||||
|
||||
/* number of elements in board_name and board_id arrays */
|
||||
unsigned int num_names;
|
||||
|
@ -230,10 +235,16 @@ struct comedi_device {
|
|||
void (*close) (struct comedi_device *dev);
|
||||
};
|
||||
|
||||
static inline const void *comedi_board(struct comedi_device *dev)
|
||||
{
|
||||
return dev->board_ptr;
|
||||
}
|
||||
|
||||
struct comedi_device_file_info {
|
||||
struct comedi_device *device;
|
||||
struct comedi_subdevice *read_subdevice;
|
||||
struct comedi_subdevice *write_subdevice;
|
||||
struct device *hardware_device;
|
||||
};
|
||||
|
||||
#ifdef CONFIG_COMEDI_DEBUG
|
||||
|
@ -287,6 +298,56 @@ int comedi_device_attach(struct comedi_device *dev,
|
|||
int comedi_driver_register(struct comedi_driver *);
|
||||
int comedi_driver_unregister(struct comedi_driver *);
|
||||
|
||||
/**
|
||||
* module_comedi_driver() - Helper macro for registering a comedi driver
|
||||
* @__comedi_driver: comedi_driver struct
|
||||
*
|
||||
* Helper macro for comedi drivers which do not do anything special in module
|
||||
* init/exit. This eliminates a lot of boilerplate. Each module may only use
|
||||
* this macro once, and calling it replaces module_init() and module_exit().
|
||||
*/
|
||||
#define module_comedi_driver(__comedi_driver) \
|
||||
module_driver(__comedi_driver, comedi_driver_register, \
|
||||
comedi_driver_unregister)
|
||||
|
||||
struct pci_driver;
|
||||
|
||||
int comedi_pci_driver_register(struct comedi_driver *, struct pci_driver *);
|
||||
void comedi_pci_driver_unregister(struct comedi_driver *, struct pci_driver *);
|
||||
|
||||
/**
|
||||
* module_comedi_pci_driver() - Helper macro for registering a comedi PCI driver
|
||||
* @__comedi_driver: comedi_driver struct
|
||||
* @__pci_driver: pci_driver struct
|
||||
*
|
||||
* Helper macro for comedi PCI drivers which do not do anything special
|
||||
* in module init/exit. This eliminates a lot of boilerplate. Each
|
||||
* module may only use this macro once, and calling it replaces
|
||||
* module_init() and module_exit()
|
||||
*/
|
||||
#define module_comedi_pci_driver(__comedi_driver, __pci_driver) \
|
||||
module_driver(__comedi_driver, comedi_pci_driver_register, \
|
||||
comedi_pci_driver_unregister, &(__pci_driver))
|
||||
|
||||
struct usb_driver;
|
||||
|
||||
int comedi_usb_driver_register(struct comedi_driver *, struct usb_driver *);
|
||||
void comedi_usb_driver_unregister(struct comedi_driver *, struct usb_driver *);
|
||||
|
||||
/**
|
||||
* module_comedi_usb_driver() - Helper macro for registering a comedi USB driver
|
||||
* @__comedi_driver: comedi_driver struct
|
||||
* @__usb_driver: usb_driver struct
|
||||
*
|
||||
* Helper macro for comedi USB drivers which do not do anything special
|
||||
* in module init/exit. This eliminates a lot of boilerplate. Each
|
||||
* module may only use this macro once, and calling it replaces
|
||||
* module_init() and module_exit()
|
||||
*/
|
||||
#define module_comedi_usb_driver(__comedi_driver, __usb_driver) \
|
||||
module_driver(__comedi_driver, comedi_usb_driver_register, \
|
||||
comedi_usb_driver_unregister, &(__usb_driver))
|
||||
|
||||
void init_polling(void);
|
||||
void cleanup_polling(void);
|
||||
void start_polling(struct comedi_device *);
|
||||
|
@ -456,11 +517,12 @@ static inline void *comedi_aux_data(int options[], int n)
|
|||
int comedi_alloc_subdevice_minor(struct comedi_device *dev,
|
||||
struct comedi_subdevice *s);
|
||||
void comedi_free_subdevice_minor(struct comedi_subdevice *s);
|
||||
int comedi_pci_auto_config(struct pci_dev *pcidev, const char *board_name);
|
||||
int comedi_pci_auto_config(struct pci_dev *pcidev,
|
||||
struct comedi_driver *driver);
|
||||
void comedi_pci_auto_unconfig(struct pci_dev *pcidev);
|
||||
struct usb_device; /* forward declaration */
|
||||
int comedi_usb_auto_config(struct usb_device *usbdev, const char *board_name);
|
||||
void comedi_usb_auto_unconfig(struct usb_device *usbdev);
|
||||
int comedi_usb_auto_config(struct usb_interface *intf,
|
||||
struct comedi_driver *driver);
|
||||
void comedi_usb_auto_unconfig(struct usb_interface *intf);
|
||||
|
||||
#ifdef CONFIG_COMEDI_PCI_DRIVERS
|
||||
#define CONFIG_COMEDI_PCI
|
||||
|
|
|
@ -106,6 +106,26 @@ void comedi_device_detach(struct comedi_device *dev)
|
|||
__comedi_device_detach(dev);
|
||||
}
|
||||
|
||||
/* do a little post-config cleanup */
|
||||
/* called with module refcount incremented, decrements it */
|
||||
static int comedi_device_postconfig(struct comedi_device *dev)
|
||||
{
|
||||
int ret = postconfig(dev);
|
||||
module_put(dev->driver->module);
|
||||
if (ret < 0) {
|
||||
__comedi_device_detach(dev);
|
||||
return ret;
|
||||
}
|
||||
if (!dev->board_name) {
|
||||
printk(KERN_WARNING "BUG: dev->board_name=<%p>\n",
|
||||
dev->board_name);
|
||||
dev->board_name = "BUG";
|
||||
}
|
||||
smp_wmb();
|
||||
dev->attached = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int comedi_device_attach(struct comedi_device *dev, struct comedi_devconfig *it)
|
||||
{
|
||||
struct comedi_driver *driv;
|
||||
|
@ -121,59 +141,36 @@ int comedi_device_attach(struct comedi_device *dev, struct comedi_devconfig *it)
|
|||
}
|
||||
if (driv->num_names) {
|
||||
dev->board_ptr = comedi_recognize(driv, it->board_name);
|
||||
if (dev->board_ptr == NULL) {
|
||||
module_put(driv->module);
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
if (strcmp(driv->driver_name, it->board_name)) {
|
||||
module_put(driv->module);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
/* initialize dev->driver here so
|
||||
* comedi_error() can be called from attach */
|
||||
dev->driver = driv;
|
||||
ret = driv->attach(dev, it);
|
||||
if (ret < 0) {
|
||||
module_put(dev->driver->module);
|
||||
__comedi_device_detach(dev);
|
||||
return ret;
|
||||
}
|
||||
goto attached;
|
||||
}
|
||||
|
||||
/* recognize has failed if we get here */
|
||||
/* report valid board names before returning error */
|
||||
for (driv = comedi_drivers; driv; driv = driv->next) {
|
||||
if (!try_module_get(driv->module)) {
|
||||
printk(KERN_INFO
|
||||
"comedi: failed to increment module count\n");
|
||||
continue;
|
||||
}
|
||||
comedi_report_boards(driv);
|
||||
if (dev->board_ptr)
|
||||
break;
|
||||
} else if (strcmp(driv->driver_name, it->board_name))
|
||||
break;
|
||||
module_put(driv->module);
|
||||
}
|
||||
return -EIO;
|
||||
|
||||
attached:
|
||||
/* do a little post-config cleanup */
|
||||
ret = postconfig(dev);
|
||||
module_put(dev->driver->module);
|
||||
if (driv == NULL) {
|
||||
/* recognize has failed if we get here */
|
||||
/* report valid board names before returning error */
|
||||
for (driv = comedi_drivers; driv; driv = driv->next) {
|
||||
if (!try_module_get(driv->module)) {
|
||||
printk(KERN_INFO
|
||||
"comedi: failed to increment module count\n");
|
||||
continue;
|
||||
}
|
||||
comedi_report_boards(driv);
|
||||
module_put(driv->module);
|
||||
}
|
||||
return -EIO;
|
||||
}
|
||||
/* initialize dev->driver here so
|
||||
* comedi_error() can be called from attach */
|
||||
dev->driver = driv;
|
||||
ret = driv->attach(dev, it);
|
||||
if (ret < 0) {
|
||||
module_put(dev->driver->module);
|
||||
__comedi_device_detach(dev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (!dev->board_name) {
|
||||
printk(KERN_WARNING "BUG: dev->board_name=<%p>\n",
|
||||
dev->board_name);
|
||||
dev->board_name = "BUG";
|
||||
}
|
||||
smp_wmb();
|
||||
dev->attached = 1;
|
||||
|
||||
return 0;
|
||||
return comedi_device_postconfig(dev);
|
||||
}
|
||||
|
||||
int comedi_driver_register(struct comedi_driver *driver)
|
||||
|
@ -242,6 +239,8 @@ static int postconfig(struct comedi_device *dev)
|
|||
s->len_chanlist = 1;
|
||||
|
||||
if (s->do_cmd) {
|
||||
unsigned int buf_size;
|
||||
|
||||
BUG_ON((s->subdev_flags & (SDF_CMD_READ |
|
||||
SDF_CMD_WRITE)) == 0);
|
||||
BUG_ON(!s->do_cmdtest);
|
||||
|
@ -257,19 +256,20 @@ static int postconfig(struct comedi_device *dev)
|
|||
async->subdevice = s;
|
||||
s->async = async;
|
||||
|
||||
#define DEFAULT_BUF_MAXSIZE (64*1024)
|
||||
#define DEFAULT_BUF_SIZE (64*1024)
|
||||
|
||||
async->max_bufsize = DEFAULT_BUF_MAXSIZE;
|
||||
async->max_bufsize =
|
||||
comedi_default_buf_maxsize_kb * 1024;
|
||||
buf_size = comedi_default_buf_size_kb * 1024;
|
||||
if (buf_size > async->max_bufsize)
|
||||
buf_size = async->max_bufsize;
|
||||
|
||||
async->prealloc_buf = NULL;
|
||||
async->prealloc_bufsz = 0;
|
||||
if (comedi_buf_alloc(dev, s, DEFAULT_BUF_SIZE) < 0) {
|
||||
if (comedi_buf_alloc(dev, s, buf_size) < 0) {
|
||||
printk(KERN_INFO "Buffer allocation failed\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
if (s->buf_change) {
|
||||
ret = s->buf_change(dev, s, DEFAULT_BUF_SIZE);
|
||||
ret = s->buf_change(dev, s, buf_size);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
|
@ -814,67 +814,102 @@ void comedi_reset_async_buf(struct comedi_async *async)
|
|||
async->events = 0;
|
||||
}
|
||||
|
||||
static int comedi_auto_config(struct device *hardware_device,
|
||||
const char *board_name, const int *options,
|
||||
unsigned num_options)
|
||||
static int
|
||||
comedi_auto_config_helper(struct device *hardware_device,
|
||||
struct comedi_driver *driver,
|
||||
int (*attach_wrapper) (struct comedi_device *,
|
||||
void *), void *context)
|
||||
{
|
||||
struct comedi_devconfig it;
|
||||
int minor;
|
||||
struct comedi_device_file_info *dev_file_info;
|
||||
int retval;
|
||||
unsigned *private_data = NULL;
|
||||
struct comedi_device *comedi_dev;
|
||||
int ret;
|
||||
|
||||
if (!comedi_autoconfig) {
|
||||
dev_set_drvdata(hardware_device, NULL);
|
||||
if (!comedi_autoconfig)
|
||||
return 0;
|
||||
}
|
||||
|
||||
minor = comedi_alloc_board_minor(hardware_device);
|
||||
if (minor < 0)
|
||||
return minor;
|
||||
|
||||
private_data = kmalloc(sizeof(unsigned), GFP_KERNEL);
|
||||
if (private_data == NULL) {
|
||||
retval = -ENOMEM;
|
||||
goto cleanup;
|
||||
}
|
||||
*private_data = minor;
|
||||
dev_set_drvdata(hardware_device, private_data);
|
||||
|
||||
dev_file_info = comedi_get_device_file_info(minor);
|
||||
comedi_dev = dev_file_info->device;
|
||||
|
||||
mutex_lock(&comedi_dev->mutex);
|
||||
if (comedi_dev->attached)
|
||||
ret = -EBUSY;
|
||||
else if (!try_module_get(driver->module)) {
|
||||
printk(KERN_INFO "comedi: failed to increment module count\n");
|
||||
ret = -EIO;
|
||||
} else {
|
||||
/* set comedi_dev->driver here for attach wrapper */
|
||||
comedi_dev->driver = driver;
|
||||
ret = (*attach_wrapper)(comedi_dev, context);
|
||||
if (ret < 0) {
|
||||
module_put(driver->module);
|
||||
__comedi_device_detach(comedi_dev);
|
||||
} else {
|
||||
ret = comedi_device_postconfig(comedi_dev);
|
||||
}
|
||||
}
|
||||
mutex_unlock(&comedi_dev->mutex);
|
||||
|
||||
if (ret < 0)
|
||||
comedi_free_board_minor(minor);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int comedi_auto_config_wrapper(struct comedi_device *dev, void *context)
|
||||
{
|
||||
struct comedi_devconfig *it = context;
|
||||
struct comedi_driver *driv = dev->driver;
|
||||
|
||||
if (driv->num_names) {
|
||||
/* look for generic board entry matching driver name, which
|
||||
* has already been copied to it->board_name */
|
||||
dev->board_ptr = comedi_recognize(driv, it->board_name);
|
||||
if (dev->board_ptr == NULL) {
|
||||
printk(KERN_WARNING
|
||||
"comedi: auto config failed to find board entry"
|
||||
" '%s' for driver '%s'\n", it->board_name,
|
||||
driv->driver_name);
|
||||
comedi_report_boards(driv);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
return driv->attach(dev, it);
|
||||
}
|
||||
|
||||
static int comedi_auto_config(struct device *hardware_device,
|
||||
struct comedi_driver *driver, const int *options,
|
||||
unsigned num_options)
|
||||
{
|
||||
struct comedi_devconfig it;
|
||||
|
||||
memset(&it, 0, sizeof(it));
|
||||
strncpy(it.board_name, board_name, COMEDI_NAMELEN);
|
||||
strncpy(it.board_name, driver->driver_name, COMEDI_NAMELEN);
|
||||
it.board_name[COMEDI_NAMELEN - 1] = '\0';
|
||||
BUG_ON(num_options > COMEDI_NDEVCONFOPTS);
|
||||
memcpy(it.options, options, num_options * sizeof(int));
|
||||
|
||||
mutex_lock(&dev_file_info->device->mutex);
|
||||
retval = comedi_device_attach(dev_file_info->device, &it);
|
||||
mutex_unlock(&dev_file_info->device->mutex);
|
||||
|
||||
cleanup:
|
||||
if (retval < 0) {
|
||||
kfree(private_data);
|
||||
comedi_free_board_minor(minor);
|
||||
}
|
||||
return retval;
|
||||
return comedi_auto_config_helper(hardware_device, driver,
|
||||
comedi_auto_config_wrapper, &it);
|
||||
}
|
||||
|
||||
static void comedi_auto_unconfig(struct device *hardware_device)
|
||||
{
|
||||
unsigned *minor = (unsigned *)dev_get_drvdata(hardware_device);
|
||||
if (minor == NULL)
|
||||
int minor;
|
||||
|
||||
if (hardware_device == NULL)
|
||||
return;
|
||||
|
||||
BUG_ON(*minor >= COMEDI_NUM_BOARD_MINORS);
|
||||
|
||||
comedi_free_board_minor(*minor);
|
||||
dev_set_drvdata(hardware_device, NULL);
|
||||
kfree(minor);
|
||||
minor = comedi_find_board_minor(hardware_device);
|
||||
if (minor < 0)
|
||||
return;
|
||||
BUG_ON(minor >= COMEDI_NUM_BOARD_MINORS);
|
||||
comedi_free_board_minor(minor);
|
||||
}
|
||||
|
||||
int comedi_pci_auto_config(struct pci_dev *pcidev, const char *board_name)
|
||||
static int comedi_old_pci_auto_config(struct pci_dev *pcidev,
|
||||
struct comedi_driver *driver)
|
||||
{
|
||||
int options[2];
|
||||
|
||||
|
@ -883,9 +918,30 @@ int comedi_pci_auto_config(struct pci_dev *pcidev, const char *board_name)
|
|||
/* pci slot */
|
||||
options[1] = PCI_SLOT(pcidev->devfn);
|
||||
|
||||
return comedi_auto_config(&pcidev->dev, board_name,
|
||||
return comedi_auto_config(&pcidev->dev, driver,
|
||||
options, ARRAY_SIZE(options));
|
||||
}
|
||||
|
||||
static int comedi_pci_attach_wrapper(struct comedi_device *dev, void *pcidev)
|
||||
{
|
||||
return dev->driver->attach_pci(dev, pcidev);
|
||||
}
|
||||
|
||||
static int comedi_new_pci_auto_config(struct pci_dev *pcidev,
|
||||
struct comedi_driver *driver)
|
||||
{
|
||||
return comedi_auto_config_helper(&pcidev->dev, driver,
|
||||
comedi_pci_attach_wrapper, pcidev);
|
||||
}
|
||||
|
||||
int comedi_pci_auto_config(struct pci_dev *pcidev, struct comedi_driver *driver)
|
||||
{
|
||||
|
||||
if (driver->attach_pci)
|
||||
return comedi_new_pci_auto_config(pcidev, driver);
|
||||
else
|
||||
return comedi_old_pci_auto_config(pcidev, driver);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(comedi_pci_auto_config);
|
||||
|
||||
void comedi_pci_auto_unconfig(struct pci_dev *pcidev)
|
||||
|
@ -894,16 +950,96 @@ void comedi_pci_auto_unconfig(struct pci_dev *pcidev)
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(comedi_pci_auto_unconfig);
|
||||
|
||||
int comedi_usb_auto_config(struct usb_device *usbdev, const char *board_name)
|
||||
int comedi_pci_driver_register(struct comedi_driver *comedi_driver,
|
||||
struct pci_driver *pci_driver)
|
||||
{
|
||||
BUG_ON(usbdev == NULL);
|
||||
return comedi_auto_config(&usbdev->dev, board_name, NULL, 0);
|
||||
int ret;
|
||||
|
||||
ret = comedi_driver_register(comedi_driver);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* FIXME: Remove this test after auditing all comedi pci drivers */
|
||||
if (!pci_driver->name)
|
||||
pci_driver->name = comedi_driver->driver_name;
|
||||
|
||||
ret = pci_register_driver(pci_driver);
|
||||
if (ret < 0) {
|
||||
comedi_driver_unregister(comedi_driver);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(comedi_pci_driver_register);
|
||||
|
||||
void comedi_pci_driver_unregister(struct comedi_driver *comedi_driver,
|
||||
struct pci_driver *pci_driver)
|
||||
{
|
||||
pci_unregister_driver(pci_driver);
|
||||
comedi_driver_unregister(comedi_driver);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(comedi_pci_driver_unregister);
|
||||
|
||||
static int comedi_old_usb_auto_config(struct usb_interface *intf,
|
||||
struct comedi_driver *driver)
|
||||
{
|
||||
return comedi_auto_config(&intf->dev, driver, NULL, 0);
|
||||
}
|
||||
|
||||
static int comedi_usb_attach_wrapper(struct comedi_device *dev, void *intf)
|
||||
{
|
||||
return dev->driver->attach_usb(dev, intf);
|
||||
}
|
||||
|
||||
static int comedi_new_usb_auto_config(struct usb_interface *intf,
|
||||
struct comedi_driver *driver)
|
||||
{
|
||||
return comedi_auto_config_helper(&intf->dev, driver,
|
||||
comedi_usb_attach_wrapper, intf);
|
||||
}
|
||||
|
||||
int comedi_usb_auto_config(struct usb_interface *intf,
|
||||
struct comedi_driver *driver)
|
||||
{
|
||||
BUG_ON(intf == NULL);
|
||||
if (driver->attach_usb)
|
||||
return comedi_new_usb_auto_config(intf, driver);
|
||||
else
|
||||
return comedi_old_usb_auto_config(intf, driver);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(comedi_usb_auto_config);
|
||||
|
||||
void comedi_usb_auto_unconfig(struct usb_device *usbdev)
|
||||
void comedi_usb_auto_unconfig(struct usb_interface *intf)
|
||||
{
|
||||
BUG_ON(usbdev == NULL);
|
||||
comedi_auto_unconfig(&usbdev->dev);
|
||||
BUG_ON(intf == NULL);
|
||||
comedi_auto_unconfig(&intf->dev);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(comedi_usb_auto_unconfig);
|
||||
|
||||
int comedi_usb_driver_register(struct comedi_driver *comedi_driver,
|
||||
struct usb_driver *usb_driver)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = comedi_driver_register(comedi_driver);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = usb_register(usb_driver);
|
||||
if (ret < 0) {
|
||||
comedi_driver_unregister(comedi_driver);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(comedi_usb_driver_register);
|
||||
|
||||
void comedi_usb_driver_unregister(struct comedi_driver *comedi_driver,
|
||||
struct usb_driver *usb_driver)
|
||||
{
|
||||
usb_deregister(usb_driver);
|
||||
comedi_driver_unregister(comedi_driver);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(comedi_usb_driver_unregister);
|
||||
|
|
|
@ -107,31 +107,6 @@ struct subdev_8255_struct {
|
|||
#define CALLBACK_FUNC (((struct subdev_8255_struct *)s->private)->cb_func)
|
||||
#define subdevpriv ((struct subdev_8255_struct *)s->private)
|
||||
|
||||
static int dev_8255_attach(struct comedi_device *dev,
|
||||
struct comedi_devconfig *it);
|
||||
static int dev_8255_detach(struct comedi_device *dev);
|
||||
static struct comedi_driver driver_8255 = {
|
||||
.driver_name = "8255",
|
||||
.module = THIS_MODULE,
|
||||
.attach = dev_8255_attach,
|
||||
.detach = dev_8255_detach,
|
||||
};
|
||||
|
||||
static int __init driver_8255_init_module(void)
|
||||
{
|
||||
return comedi_driver_register(&driver_8255);
|
||||
}
|
||||
|
||||
static void __exit driver_8255_cleanup_module(void)
|
||||
{
|
||||
comedi_driver_unregister(&driver_8255);
|
||||
}
|
||||
|
||||
module_init(driver_8255_init_module);
|
||||
module_exit(driver_8255_cleanup_module);
|
||||
|
||||
static void do_config(struct comedi_device *dev, struct comedi_subdevice *s);
|
||||
|
||||
void subdev_8255_interrupt(struct comedi_device *dev,
|
||||
struct comedi_subdevice *s)
|
||||
{
|
||||
|
@ -185,6 +160,23 @@ static int subdev_8255_insn(struct comedi_device *dev,
|
|||
return 2;
|
||||
}
|
||||
|
||||
static void do_config(struct comedi_device *dev, struct comedi_subdevice *s)
|
||||
{
|
||||
int config;
|
||||
|
||||
config = CR_CW;
|
||||
/* 1 in io_bits indicates output, 1 in config indicates input */
|
||||
if (!(s->io_bits & 0x0000ff))
|
||||
config |= CR_A_IO;
|
||||
if (!(s->io_bits & 0x00ff00))
|
||||
config |= CR_B_IO;
|
||||
if (!(s->io_bits & 0x0f0000))
|
||||
config |= CR_C_LO_IO;
|
||||
if (!(s->io_bits & 0xf00000))
|
||||
config |= CR_C_HI_IO;
|
||||
CALLBACK_FUNC(1, _8255_CR, config, CALLBACK_ARG);
|
||||
}
|
||||
|
||||
static int subdev_8255_insn_config(struct comedi_device *dev,
|
||||
struct comedi_subdevice *s,
|
||||
struct comedi_insn *insn, unsigned int *data)
|
||||
|
@ -222,23 +214,6 @@ static int subdev_8255_insn_config(struct comedi_device *dev,
|
|||
return 1;
|
||||
}
|
||||
|
||||
static void do_config(struct comedi_device *dev, struct comedi_subdevice *s)
|
||||
{
|
||||
int config;
|
||||
|
||||
config = CR_CW;
|
||||
/* 1 in io_bits indicates output, 1 in config indicates input */
|
||||
if (!(s->io_bits & 0x0000ff))
|
||||
config |= CR_A_IO;
|
||||
if (!(s->io_bits & 0x00ff00))
|
||||
config |= CR_B_IO;
|
||||
if (!(s->io_bits & 0x0f0000))
|
||||
config |= CR_C_LO_IO;
|
||||
if (!(s->io_bits & 0xf00000))
|
||||
config |= CR_C_HI_IO;
|
||||
CALLBACK_FUNC(1, _8255_CR, config, CALLBACK_ARG);
|
||||
}
|
||||
|
||||
static int subdev_8255_cmdtest(struct comedi_device *dev,
|
||||
struct comedi_subdevice *s,
|
||||
struct comedi_cmd *cmd)
|
||||
|
@ -442,14 +417,12 @@ static int dev_8255_attach(struct comedi_device *dev,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int dev_8255_detach(struct comedi_device *dev)
|
||||
static void dev_8255_detach(struct comedi_device *dev)
|
||||
{
|
||||
int i;
|
||||
unsigned long iobase;
|
||||
struct comedi_subdevice *s;
|
||||
|
||||
printk(KERN_INFO "comedi%d: 8255: remove\n", dev->minor);
|
||||
|
||||
for (i = 0; i < dev->n_subdevices; i++) {
|
||||
s = dev->subdevices + i;
|
||||
if (s->type != COMEDI_SUBD_UNUSED) {
|
||||
|
@ -458,10 +431,16 @@ static int dev_8255_detach(struct comedi_device *dev)
|
|||
}
|
||||
subdev_8255_cleanup(dev, s);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct comedi_driver dev_8255_driver = {
|
||||
.driver_name = "8255",
|
||||
.module = THIS_MODULE,
|
||||
.attach = dev_8255_attach,
|
||||
.detach = dev_8255_detach,
|
||||
};
|
||||
module_comedi_driver(dev_8255_driver);
|
||||
|
||||
MODULE_AUTHOR("Comedi http://www.comedi.org");
|
||||
MODULE_DESCRIPTION("Comedi low-level driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
|
|
@ -22,46 +22,13 @@ Devices: [Adlink] ACL-7225b (acl7225b), [ICP] P16R16DIO (p16r16dio)
|
|||
#define ACL7225_DI_LO 2 /* Digital input low byte (DI0-DI7) */
|
||||
#define ACL7225_DI_HI 3 /* Digital input high byte (DI8-DI15) */
|
||||
|
||||
static int acl7225b_attach(struct comedi_device *dev,
|
||||
struct comedi_devconfig *it);
|
||||
static int acl7225b_detach(struct comedi_device *dev);
|
||||
|
||||
struct boardtype {
|
||||
const char *name; /* driver name */
|
||||
int io_range; /* len of I/O space */
|
||||
};
|
||||
|
||||
static const struct boardtype boardtypes[] = {
|
||||
{"acl7225b", ACL7225_SIZE,},
|
||||
{"p16r16dio", P16R16DIO_SIZE,},
|
||||
};
|
||||
|
||||
#define n_boardtypes (sizeof(boardtypes)/sizeof(struct boardtype))
|
||||
#define this_board ((const struct boardtype *)dev->board_ptr)
|
||||
|
||||
static struct comedi_driver driver_acl7225b = {
|
||||
.driver_name = "acl7225b",
|
||||
.module = THIS_MODULE,
|
||||
.attach = acl7225b_attach,
|
||||
.detach = acl7225b_detach,
|
||||
.board_name = &boardtypes[0].name,
|
||||
.num_names = n_boardtypes,
|
||||
.offset = sizeof(struct boardtype),
|
||||
};
|
||||
|
||||
static int __init driver_acl7225b_init_module(void)
|
||||
{
|
||||
return comedi_driver_register(&driver_acl7225b);
|
||||
}
|
||||
|
||||
static void __exit driver_acl7225b_cleanup_module(void)
|
||||
{
|
||||
comedi_driver_unregister(&driver_acl7225b);
|
||||
}
|
||||
|
||||
module_init(driver_acl7225b_init_module);
|
||||
module_exit(driver_acl7225b_cleanup_module);
|
||||
|
||||
static int acl7225b_do_insn(struct comedi_device *dev,
|
||||
struct comedi_subdevice *s,
|
||||
struct comedi_insn *insn, unsigned int *data)
|
||||
|
@ -152,16 +119,28 @@ static int acl7225b_attach(struct comedi_device *dev,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int acl7225b_detach(struct comedi_device *dev)
|
||||
static void acl7225b_detach(struct comedi_device *dev)
|
||||
{
|
||||
printk(KERN_INFO "comedi%d: acl7225b: remove\n", dev->minor);
|
||||
|
||||
if (dev->iobase)
|
||||
release_region(dev->iobase, this_board->io_range);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct boardtype boardtypes[] = {
|
||||
{ "acl7225b", ACL7225_SIZE, },
|
||||
{ "p16r16dio", P16R16DIO_SIZE, },
|
||||
};
|
||||
|
||||
static struct comedi_driver acl7225b_driver = {
|
||||
.driver_name = "acl7225b",
|
||||
.module = THIS_MODULE,
|
||||
.attach = acl7225b_attach,
|
||||
.detach = acl7225b_detach,
|
||||
.board_name = &boardtypes[0].name,
|
||||
.num_names = ARRAY_SIZE(boardtypes),
|
||||
.offset = sizeof(struct boardtype),
|
||||
};
|
||||
module_comedi_driver(acl7225b_driver);
|
||||
|
||||
MODULE_AUTHOR("Comedi http://www.comedi.org");
|
||||
MODULE_DESCRIPTION("Comedi low-level driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -94,111 +94,72 @@ struct addi_board {
|
|||
unsigned int ui_MinDelaytimeNs; /* Minimum Delay in Nano secs */
|
||||
|
||||
/* interrupt and reset */
|
||||
void (*v_hwdrv_Interrupt)(int irq, void *d);
|
||||
int (*i_hwdrv_Reset)(struct comedi_device *dev);
|
||||
void (*interrupt)(int irq, void *d);
|
||||
int (*reset)(struct comedi_device *);
|
||||
|
||||
/* Subdevice functions */
|
||||
|
||||
/* ANALOG INPUT */
|
||||
int (*i_hwdrv_InsnConfigAnalogInput)(struct comedi_device *dev,
|
||||
struct comedi_subdevice *s,
|
||||
struct comedi_insn *insn,
|
||||
unsigned int *data);
|
||||
int (*i_hwdrv_InsnReadAnalogInput)(struct comedi_device *dev,
|
||||
struct comedi_subdevice *s,
|
||||
struct comedi_insn *insn,
|
||||
unsigned int *data);
|
||||
int (*i_hwdrv_InsnWriteAnalogInput)(struct comedi_device *dev,
|
||||
struct comedi_subdevice *s,
|
||||
struct comedi_insn *insn,
|
||||
unsigned int *data);
|
||||
int (*i_hwdrv_InsnBitsAnalogInput)(struct comedi_device *dev,
|
||||
struct comedi_subdevice *s,
|
||||
struct comedi_insn *insn,
|
||||
unsigned int *data);
|
||||
int (*i_hwdrv_CommandTestAnalogInput)(struct comedi_device *dev,
|
||||
struct comedi_subdevice *s,
|
||||
struct comedi_cmd *cmd);
|
||||
int (*i_hwdrv_CommandAnalogInput)(struct comedi_device *dev,
|
||||
struct comedi_subdevice *s);
|
||||
int (*i_hwdrv_CancelAnalogInput)(struct comedi_device *dev,
|
||||
struct comedi_subdevice *s);
|
||||
int (*ai_config)(struct comedi_device *, struct comedi_subdevice *,
|
||||
struct comedi_insn *, unsigned int *);
|
||||
int (*ai_read)(struct comedi_device *, struct comedi_subdevice *,
|
||||
struct comedi_insn *, unsigned int *);
|
||||
int (*ai_write)(struct comedi_device *, struct comedi_subdevice *,
|
||||
struct comedi_insn *, unsigned int *);
|
||||
int (*ai_bits)(struct comedi_device *, struct comedi_subdevice *,
|
||||
struct comedi_insn *, unsigned int *);
|
||||
int (*ai_cmdtest)(struct comedi_device *, struct comedi_subdevice *,
|
||||
struct comedi_cmd *);
|
||||
int (*ai_cmd)(struct comedi_device *, struct comedi_subdevice *);
|
||||
int (*ai_cancel)(struct comedi_device *, struct comedi_subdevice *);
|
||||
|
||||
/* Analog Output */
|
||||
int (*i_hwdrv_InsnConfigAnalogOutput)(struct comedi_device *dev,
|
||||
struct comedi_subdevice *s,
|
||||
struct comedi_insn *insn,
|
||||
unsigned int *data);
|
||||
int (*i_hwdrv_InsnWriteAnalogOutput)(struct comedi_device *dev,
|
||||
struct comedi_subdevice *s,
|
||||
struct comedi_insn *insn,
|
||||
unsigned int *data);
|
||||
int (*i_hwdrv_InsnBitsAnalogOutput)(struct comedi_device *dev,
|
||||
struct comedi_subdevice *s,
|
||||
struct comedi_insn *insn,
|
||||
unsigned int *data);
|
||||
int (*ao_config)(struct comedi_device *, struct comedi_subdevice *,
|
||||
struct comedi_insn *, unsigned int *);
|
||||
int (*ao_write)(struct comedi_device *, struct comedi_subdevice *,
|
||||
struct comedi_insn *, unsigned int *);
|
||||
int (*ao_bits)(struct comedi_device *, struct comedi_subdevice *,
|
||||
struct comedi_insn *, unsigned int *);
|
||||
|
||||
/* Digital Input */
|
||||
int (*i_hwdrv_InsnConfigDigitalInput) (struct comedi_device *dev,
|
||||
struct comedi_subdevice *s,
|
||||
struct comedi_insn *insn,
|
||||
unsigned int *data);
|
||||
int (*i_hwdrv_InsnReadDigitalInput) (struct comedi_device *dev,
|
||||
struct comedi_subdevice *s,
|
||||
struct comedi_insn *insn,
|
||||
unsigned int *data);
|
||||
int (*i_hwdrv_InsnWriteDigitalInput) (struct comedi_device *dev,
|
||||
struct comedi_subdevice *s,
|
||||
struct comedi_insn *insn,
|
||||
unsigned int *data);
|
||||
int (*i_hwdrv_InsnBitsDigitalInput) (struct comedi_device *dev,
|
||||
struct comedi_subdevice *s,
|
||||
struct comedi_insn *insn,
|
||||
unsigned int *data);
|
||||
int (*di_config)(struct comedi_device *, struct comedi_subdevice *,
|
||||
struct comedi_insn *, unsigned int *);
|
||||
int (*di_read)(struct comedi_device *, struct comedi_subdevice *,
|
||||
struct comedi_insn *, unsigned int *);
|
||||
int (*di_write)(struct comedi_device *, struct comedi_subdevice *,
|
||||
struct comedi_insn *, unsigned int *);
|
||||
int (*di_bits)(struct comedi_device *, struct comedi_subdevice *,
|
||||
struct comedi_insn *, unsigned int *);
|
||||
|
||||
/* Digital Output */
|
||||
int (*i_hwdrv_InsnConfigDigitalOutput)(struct comedi_device *dev,
|
||||
struct comedi_subdevice *s,
|
||||
struct comedi_insn *insn,
|
||||
unsigned int *data);
|
||||
int (*i_hwdrv_InsnWriteDigitalOutput)(struct comedi_device *dev,
|
||||
struct comedi_subdevice *s,
|
||||
struct comedi_insn *insn,
|
||||
unsigned int *data);
|
||||
int (*i_hwdrv_InsnBitsDigitalOutput)(struct comedi_device *dev,
|
||||
struct comedi_subdevice *s,
|
||||
struct comedi_insn *insn,
|
||||
unsigned int *data);
|
||||
int (*i_hwdrv_InsnReadDigitalOutput)(struct comedi_device *dev,
|
||||
struct comedi_subdevice *s,
|
||||
struct comedi_insn *insn,
|
||||
unsigned int *data);
|
||||
int (*do_config)(struct comedi_device *, struct comedi_subdevice *,
|
||||
struct comedi_insn *, unsigned int *);
|
||||
int (*do_write)(struct comedi_device *, struct comedi_subdevice *,
|
||||
struct comedi_insn *, unsigned int *);
|
||||
int (*do_bits)(struct comedi_device *, struct comedi_subdevice *,
|
||||
struct comedi_insn *, unsigned int *);
|
||||
int (*do_read)(struct comedi_device *, struct comedi_subdevice *,
|
||||
struct comedi_insn *, unsigned int *);
|
||||
|
||||
/* TIMER */
|
||||
int (*i_hwdrv_InsnConfigTimer)(struct comedi_device *dev,
|
||||
struct comedi_subdevice *s,
|
||||
struct comedi_insn *insn, unsigned int *data);
|
||||
int (*i_hwdrv_InsnWriteTimer)(struct comedi_device *dev,
|
||||
struct comedi_subdevice *s, struct comedi_insn *insn,
|
||||
unsigned int *data);
|
||||
int (*i_hwdrv_InsnReadTimer)(struct comedi_device *dev, struct comedi_subdevice *s,
|
||||
struct comedi_insn *insn, unsigned int *data);
|
||||
int (*i_hwdrv_InsnBitsTimer)(struct comedi_device *dev, struct comedi_subdevice *s,
|
||||
struct comedi_insn *insn, unsigned int *data);
|
||||
int (*timer_config)(struct comedi_device *, struct comedi_subdevice *,
|
||||
struct comedi_insn *, unsigned int *);
|
||||
int (*timer_write)(struct comedi_device *, struct comedi_subdevice *,
|
||||
struct comedi_insn *, unsigned int *);
|
||||
int (*timer_read)(struct comedi_device *, struct comedi_subdevice *,
|
||||
struct comedi_insn *, unsigned int *);
|
||||
int (*timer_bits)(struct comedi_device *, struct comedi_subdevice *,
|
||||
struct comedi_insn *, unsigned int *);
|
||||
|
||||
/* TTL IO */
|
||||
int (*i_hwdr_ConfigInitTTLIO)(struct comedi_device *dev,
|
||||
struct comedi_subdevice *s, struct comedi_insn *insn,
|
||||
unsigned int *data);
|
||||
int (*i_hwdr_ReadTTLIOBits)(struct comedi_device *dev, struct comedi_subdevice *s,
|
||||
struct comedi_insn *insn, unsigned int *data);
|
||||
int (*i_hwdr_ReadTTLIOAllPortValue)(struct comedi_device *dev,
|
||||
struct comedi_subdevice *s,
|
||||
struct comedi_insn *insn,
|
||||
unsigned int *data);
|
||||
int (*i_hwdr_WriteTTLIOChlOnOff)(struct comedi_device *dev,
|
||||
struct comedi_subdevice *s,
|
||||
struct comedi_insn *insn, unsigned int *data);
|
||||
int (*ttl_config)(struct comedi_device *, struct comedi_subdevice *,
|
||||
struct comedi_insn *, unsigned int *);
|
||||
int (*ttl_bits)(struct comedi_device *, struct comedi_subdevice *,
|
||||
struct comedi_insn *, unsigned int *);
|
||||
int (*ttl_read)(struct comedi_device *, struct comedi_subdevice *,
|
||||
struct comedi_insn *, unsigned int *);
|
||||
int (*ttl_write)(struct comedi_device *, struct comedi_subdevice *,
|
||||
struct comedi_insn *, unsigned int *);
|
||||
};
|
||||
|
||||
/* MODULE INFO STRUCTURE */
|
||||
|
@ -455,7 +416,7 @@ static unsigned short pci_list_builded; /* set to 1 when list of card is known *
|
|||
|
||||
/* Function declarations */
|
||||
static int i_ADDI_Attach(struct comedi_device *dev, struct comedi_devconfig *it);
|
||||
static int i_ADDI_Detach(struct comedi_device *dev);
|
||||
static void i_ADDI_Detach(struct comedi_device *dev);
|
||||
static int i_ADDI_Reset(struct comedi_device *dev);
|
||||
|
||||
static irqreturn_t v_ADDI_Interrupt(int irq, void *d);
|
||||
|
|
|
@ -156,7 +156,7 @@ int i_APCI3120_InsnReadAnalogInput(struct comedi_device *dev, struct comedi_subd
|
|||
} else
|
||||
us_ConvertTiming = (unsigned short) (devpriv->ui_EocEosConversionTime / 1000); /* nano to useconds */
|
||||
|
||||
/* this_board->i_hwdrv_InsnReadAnalogInput(dev,us_ConvertTiming,insn->n,&insn->chanspec,data,insn->unused[0]); */
|
||||
/* this_board->ai_read(dev,us_ConvertTiming,insn->n,&insn->chanspec,data,insn->unused[0]); */
|
||||
|
||||
/* Clear software registers */
|
||||
devpriv->b_TimerSelectMode = 0;
|
||||
|
@ -670,7 +670,7 @@ int i_APCI3120_CommandAnalogInput(struct comedi_device *dev, struct comedi_subde
|
|||
/* mode 1 */
|
||||
|
||||
devpriv->ui_AiTimer0 = cmd->convert_arg; /* timer constant in nano seconds */
|
||||
/* return this_board->i_hwdrv_CommandAnalogInput(1,dev,s); */
|
||||
/* return this_board->ai_cmd(1,dev,s); */
|
||||
return i_APCI3120_CyclicAnalogInput(1, dev, s);
|
||||
}
|
||||
|
||||
|
@ -680,7 +680,7 @@ int i_APCI3120_CommandAnalogInput(struct comedi_device *dev, struct comedi_subde
|
|||
/* mode 2 */
|
||||
devpriv->ui_AiTimer1 = cmd->scan_begin_arg;
|
||||
devpriv->ui_AiTimer0 = cmd->convert_arg; /* variable changed timer2 to timer0 */
|
||||
/* return this_board->i_hwdrv_CommandAnalogInput(2,dev,s); */
|
||||
/* return this_board->ai_cmd(2,dev,s); */
|
||||
return i_APCI3120_CyclicAnalogInput(2, dev, s);
|
||||
}
|
||||
return -1;
|
||||
|
@ -1922,7 +1922,7 @@ int i_APCI3120_InsnConfigTimer(struct comedi_device *dev, struct comedi_subdevic
|
|||
|
||||
ui_Timervalue2 = data[1] / 1000; /* convert nano seconds to u seconds */
|
||||
|
||||
/* this_board->i_hwdrv_InsnConfigTimer(dev, ui_Timervalue2,(unsigned char)data[0]); */
|
||||
/* this_board->timer_config(dev, ui_Timervalue2,(unsigned char)data[0]); */
|
||||
us_TmpValue = (unsigned short) inw(devpriv->iobase + APCI3120_RD_STATUS);
|
||||
|
||||
/*
|
||||
|
@ -2092,7 +2092,7 @@ int i_APCI3120_InsnWriteTimer(struct comedi_device *dev, struct comedi_subdevice
|
|||
ui_Timervalue2 = 0;
|
||||
}
|
||||
|
||||
/* this_board->i_hwdrv_InsnWriteTimer(dev,data[0],ui_Timervalue2); */
|
||||
/* this_board->timer_write(dev,data[0],ui_Timervalue2); */
|
||||
|
||||
switch (data[0]) {
|
||||
case APCI3120_START:
|
||||
|
@ -2260,7 +2260,7 @@ int i_APCI3120_InsnReadTimer(struct comedi_device *dev, struct comedi_subdevice
|
|||
comedi_error(dev, "\nread:timer2 not configured ");
|
||||
}
|
||||
|
||||
/* this_board->i_hwdrv_InsnReadTimer(dev,data); */
|
||||
/* this_board->timer_read(dev,data); */
|
||||
if (devpriv->b_Timer2Mode == APCI3120_TIMER) {
|
||||
|
||||
/* Read the LOW unsigned short of Timer 2 register */
|
||||
|
@ -2331,7 +2331,7 @@ int i_APCI3120_InsnReadDigitalInput(struct comedi_device *dev,
|
|||
|
||||
ui_Chan = CR_CHAN(insn->chanspec); /* channel specified */
|
||||
|
||||
/* this_board->i_hwdrv_InsnReadDigitalInput(dev,ui_Chan,data); */
|
||||
/* this_board->di_read(dev,ui_Chan,data); */
|
||||
if (ui_Chan <= 3) {
|
||||
ui_TmpValue = (unsigned int) inw(devpriv->iobase + APCI3120_RD_STATUS);
|
||||
|
||||
|
@ -2379,7 +2379,7 @@ int i_APCI3120_InsnBitsDigitalInput(struct comedi_device *dev, struct comedi_sub
|
|||
*****/
|
||||
|
||||
*data = (ui_TmpValue >> 8) & 0xf;
|
||||
/* this_board->i_hwdrv_InsnBitsDigitalInput(dev,data); */
|
||||
/* this_board->di_bits(dev,data); */
|
||||
return insn->n;
|
||||
}
|
||||
|
||||
|
@ -2595,7 +2595,7 @@ int i_APCI3120_InsnWriteAnalogOutput(struct comedi_device *dev,
|
|||
ui_Range = CR_RANGE(insn->chanspec);
|
||||
ui_Channel = CR_CHAN(insn->chanspec);
|
||||
|
||||
/* this_board->i_hwdrv_InsnWriteAnalogOutput(dev, ui_Range, ui_Channel,data[0]); */
|
||||
/* this_board->ao_write(dev, ui_Range, ui_Channel,data[0]); */
|
||||
if (ui_Range) { /* if 1 then unipolar */
|
||||
|
||||
if (data[0] != 0)
|
||||
|
|
|
@ -54,8 +54,6 @@ References:
|
|||
#include "../comedidev.h"
|
||||
#include "comedi_pci.h"
|
||||
|
||||
#define PCI6208_DRIVER_NAME "adl_pci6208"
|
||||
|
||||
/* Board descriptions */
|
||||
struct pci6208_board {
|
||||
const char *name;
|
||||
|
@ -85,17 +83,6 @@ static const struct pci6208_board pci6208_boards[] = {
|
|||
}
|
||||
};
|
||||
|
||||
/* 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(pci6208_pci_table) = {
|
||||
/* { PCI_VENDOR_ID_ADLINK, 0x6208, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, */
|
||||
/* { PCI_VENDOR_ID_ADLINK, 0x6208, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, */
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_ADLINK, 0x6208) },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(pci, pci6208_pci_table);
|
||||
|
||||
/* Will be initialized in pci6208_find device(). */
|
||||
#define thisboard ((const struct pci6208_board *)dev->board_ptr)
|
||||
|
||||
|
@ -107,157 +94,6 @@ struct pci6208_private {
|
|||
|
||||
#define devpriv ((struct pci6208_private *)dev->private)
|
||||
|
||||
static int pci6208_attach(struct comedi_device *dev,
|
||||
struct comedi_devconfig *it);
|
||||
static int pci6208_detach(struct comedi_device *dev);
|
||||
|
||||
static struct comedi_driver driver_pci6208 = {
|
||||
.driver_name = PCI6208_DRIVER_NAME,
|
||||
.module = THIS_MODULE,
|
||||
.attach = pci6208_attach,
|
||||
.detach = pci6208_detach,
|
||||
};
|
||||
|
||||
static int __devinit driver_pci6208_pci_probe(struct pci_dev *dev,
|
||||
const struct pci_device_id *ent)
|
||||
{
|
||||
return comedi_pci_auto_config(dev, driver_pci6208.driver_name);
|
||||
}
|
||||
|
||||
static void __devexit driver_pci6208_pci_remove(struct pci_dev *dev)
|
||||
{
|
||||
comedi_pci_auto_unconfig(dev);
|
||||
}
|
||||
|
||||
static struct pci_driver driver_pci6208_pci_driver = {
|
||||
.id_table = pci6208_pci_table,
|
||||
.probe = &driver_pci6208_pci_probe,
|
||||
.remove = __devexit_p(&driver_pci6208_pci_remove)
|
||||
};
|
||||
|
||||
static int __init driver_pci6208_init_module(void)
|
||||
{
|
||||
int retval;
|
||||
|
||||
retval = comedi_driver_register(&driver_pci6208);
|
||||
if (retval < 0)
|
||||
return retval;
|
||||
|
||||
driver_pci6208_pci_driver.name = (char *)driver_pci6208.driver_name;
|
||||
return pci_register_driver(&driver_pci6208_pci_driver);
|
||||
}
|
||||
|
||||
static void __exit driver_pci6208_cleanup_module(void)
|
||||
{
|
||||
pci_unregister_driver(&driver_pci6208_pci_driver);
|
||||
comedi_driver_unregister(&driver_pci6208);
|
||||
}
|
||||
|
||||
module_init(driver_pci6208_init_module);
|
||||
module_exit(driver_pci6208_cleanup_module);
|
||||
|
||||
static int pci6208_find_device(struct comedi_device *dev, int bus, int slot);
|
||||
static int
|
||||
pci6208_pci_setup(struct pci_dev *pci_dev, unsigned long *io_base_ptr,
|
||||
int dev_minor);
|
||||
|
||||
/*read/write functions*/
|
||||
static int pci6208_ao_winsn(struct comedi_device *dev,
|
||||
struct comedi_subdevice *s,
|
||||
struct comedi_insn *insn, unsigned int *data);
|
||||
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_insn *insn,unsigned int *data); */
|
||||
/* static int pci6208_dio_insn_config(struct comedi_device *dev,
|
||||
* struct comedi_subdevice *s, */
|
||||
/* struct comedi_insn *insn,unsigned int *data); */
|
||||
|
||||
/*
|
||||
* Attach is called by the Comedi core to configure the driver
|
||||
* for a particular board. If you specified a board_name array
|
||||
* in the driver structure, dev->board_ptr contains that
|
||||
* address.
|
||||
*/
|
||||
static int pci6208_attach(struct comedi_device *dev,
|
||||
struct comedi_devconfig *it)
|
||||
{
|
||||
struct comedi_subdevice *s;
|
||||
int retval;
|
||||
unsigned long io_base;
|
||||
|
||||
printk(KERN_INFO "comedi%d: pci6208: ", dev->minor);
|
||||
|
||||
retval = alloc_private(dev, sizeof(struct pci6208_private));
|
||||
if (retval < 0)
|
||||
return retval;
|
||||
|
||||
retval = pci6208_find_device(dev, it->options[0], it->options[1]);
|
||||
if (retval < 0)
|
||||
return retval;
|
||||
|
||||
retval = pci6208_pci_setup(devpriv->pci_dev, &io_base, dev->minor);
|
||||
if (retval < 0)
|
||||
return retval;
|
||||
|
||||
dev->iobase = io_base;
|
||||
dev->board_name = thisboard->name;
|
||||
|
||||
/*
|
||||
* Allocate the subdevice structures. alloc_subdevice() is a
|
||||
* convenient macro defined in comedidev.h.
|
||||
*/
|
||||
if (alloc_subdevices(dev, 2) < 0)
|
||||
return -ENOMEM;
|
||||
|
||||
s = dev->subdevices + 0;
|
||||
/* analog output subdevice */
|
||||
s->type = COMEDI_SUBD_AO;
|
||||
s->subdev_flags = SDF_WRITABLE; /* anything else to add here?? */
|
||||
s->n_chan = thisboard->ao_chans;
|
||||
s->maxdata = 0xffff; /* 16-bit DAC */
|
||||
s->range_table = &range_bipolar10; /* this needs to be checked. */
|
||||
s->insn_write = pci6208_ao_winsn;
|
||||
s->insn_read = pci6208_ao_rinsn;
|
||||
|
||||
/* s=dev->subdevices+1; */
|
||||
/* digital i/o subdevice */
|
||||
/* s->type=COMEDI_SUBD_DIO; */
|
||||
/* s->subdev_flags=SDF_READABLE|SDF_WRITABLE; */
|
||||
/* s->n_chan=16; */
|
||||
/* s->maxdata=1; */
|
||||
/* s->range_table=&range_digital; */
|
||||
/* s->insn_bits = pci6208_dio_insn_bits; */
|
||||
/* s->insn_config = pci6208_dio_insn_config; */
|
||||
|
||||
printk(KERN_INFO "attached\n");
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* _detach is called to deconfigure a device. It should deallocate
|
||||
* resources.
|
||||
* This function is also called when _attach() fails, so it should be
|
||||
* careful not to release resources that were not necessarily
|
||||
* allocated by _attach(). dev->private and dev->subdevices are
|
||||
* deallocated automatically by the core.
|
||||
*/
|
||||
static int pci6208_detach(struct comedi_device *dev)
|
||||
{
|
||||
printk(KERN_INFO "comedi%d: pci6208: 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 pci6208_ao_winsn(struct comedi_device *dev,
|
||||
struct comedi_subdevice *s,
|
||||
struct comedi_insn *insn, unsigned int *data)
|
||||
|
@ -410,7 +246,7 @@ pci6208_pci_setup(struct pci_dev *pci_dev, unsigned long *io_base_ptr,
|
|||
unsigned long io_base, io_range, lcr_io_base, lcr_io_range;
|
||||
|
||||
/* Enable PCI device and request regions */
|
||||
if (comedi_pci_enable(pci_dev, PCI6208_DRIVER_NAME) < 0) {
|
||||
if (comedi_pci_enable(pci_dev, "adl_pci6208") < 0) {
|
||||
printk(KERN_ERR "comedi%d: Failed to enable PCI device "
|
||||
"and request regions\n",
|
||||
dev_minor);
|
||||
|
@ -442,6 +278,103 @@ pci6208_pci_setup(struct pci_dev *pci_dev, unsigned long *io_base_ptr,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int pci6208_attach(struct comedi_device *dev,
|
||||
struct comedi_devconfig *it)
|
||||
{
|
||||
struct comedi_subdevice *s;
|
||||
int retval;
|
||||
unsigned long io_base;
|
||||
|
||||
printk(KERN_INFO "comedi%d: pci6208: ", dev->minor);
|
||||
|
||||
retval = alloc_private(dev, sizeof(struct pci6208_private));
|
||||
if (retval < 0)
|
||||
return retval;
|
||||
|
||||
retval = pci6208_find_device(dev, it->options[0], it->options[1]);
|
||||
if (retval < 0)
|
||||
return retval;
|
||||
|
||||
retval = pci6208_pci_setup(devpriv->pci_dev, &io_base, dev->minor);
|
||||
if (retval < 0)
|
||||
return retval;
|
||||
|
||||
dev->iobase = io_base;
|
||||
dev->board_name = thisboard->name;
|
||||
|
||||
if (alloc_subdevices(dev, 2) < 0)
|
||||
return -ENOMEM;
|
||||
|
||||
s = dev->subdevices + 0;
|
||||
/* analog output subdevice */
|
||||
s->type = COMEDI_SUBD_AO;
|
||||
s->subdev_flags = SDF_WRITABLE; /* anything else to add here?? */
|
||||
s->n_chan = thisboard->ao_chans;
|
||||
s->maxdata = 0xffff; /* 16-bit DAC */
|
||||
s->range_table = &range_bipolar10; /* this needs to be checked. */
|
||||
s->insn_write = pci6208_ao_winsn;
|
||||
s->insn_read = pci6208_ao_rinsn;
|
||||
|
||||
/* s=dev->subdevices+1; */
|
||||
/* digital i/o subdevice */
|
||||
/* s->type=COMEDI_SUBD_DIO; */
|
||||
/* s->subdev_flags=SDF_READABLE|SDF_WRITABLE; */
|
||||
/* s->n_chan=16; */
|
||||
/* s->maxdata=1; */
|
||||
/* s->range_table=&range_digital; */
|
||||
/* s->insn_bits = pci6208_dio_insn_bits; */
|
||||
/* s->insn_config = pci6208_dio_insn_config; */
|
||||
|
||||
printk(KERN_INFO "attached\n");
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void pci6208_detach(struct comedi_device *dev)
|
||||
{
|
||||
if (devpriv && devpriv->pci_dev) {
|
||||
if (dev->iobase)
|
||||
comedi_pci_disable(devpriv->pci_dev);
|
||||
pci_dev_put(devpriv->pci_dev);
|
||||
}
|
||||
}
|
||||
|
||||
static struct comedi_driver adl_pci6208_driver = {
|
||||
.driver_name = "adl_pci6208",
|
||||
.module = THIS_MODULE,
|
||||
.attach = pci6208_attach,
|
||||
.detach = pci6208_detach,
|
||||
};
|
||||
|
||||
static int __devinit adl_pci6208_pci_probe(struct pci_dev *dev,
|
||||
const struct pci_device_id *ent)
|
||||
{
|
||||
return comedi_pci_auto_config(dev, &adl_pci6208_driver);
|
||||
}
|
||||
|
||||
static void __devexit adl_pci6208_pci_remove(struct pci_dev *dev)
|
||||
{
|
||||
comedi_pci_auto_unconfig(dev);
|
||||
}
|
||||
|
||||
/* 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(adl_pci6208_pci_table) = {
|
||||
/* { PCI_VENDOR_ID_ADLINK, 0x6208, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, */
|
||||
/* { PCI_VENDOR_ID_ADLINK, 0x6208, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, */
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_ADLINK, 0x6208) },
|
||||
{ 0 }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(pci, adl_pci6208_pci_table);
|
||||
|
||||
static struct pci_driver adl_pci6208_pci_driver = {
|
||||
.name = "adl_pci6208",
|
||||
.id_table = adl_pci6208_pci_table,
|
||||
.probe = adl_pci6208_pci_probe,
|
||||
.remove = __devexit_p(adl_pci6208_pci_remove),
|
||||
};
|
||||
module_comedi_pci_driver(adl_pci6208_driver, adl_pci6208_pci_driver);
|
||||
|
||||
MODULE_AUTHOR("Comedi http://www.comedi.org");
|
||||
MODULE_DESCRIPTION("Comedi low-level driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
|
|
@ -43,13 +43,6 @@ Configuration Options:
|
|||
|
||||
#define PCI_DEVICE_ID_PCI7230 0x7230
|
||||
|
||||
static DEFINE_PCI_DEVICE_TABLE(adl_pci7230_pci_table) = {
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_ADLINK, PCI_DEVICE_ID_PCI7230) },
|
||||
{0}
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(pci, adl_pci7230_pci_table);
|
||||
|
||||
struct adl_pci7230_private {
|
||||
int data;
|
||||
struct pci_dev *pci_dev;
|
||||
|
@ -57,27 +50,36 @@ struct adl_pci7230_private {
|
|||
|
||||
#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,
|
||||
};
|
||||
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;
|
||||
|
||||
/* Digital IO */
|
||||
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);
|
||||
unsigned int *data)
|
||||
{
|
||||
if (insn->n != 2)
|
||||
return -EINVAL;
|
||||
|
||||
static int adl_pci7230_do_insn_bits(struct comedi_device *dev,
|
||||
struct comedi_subdevice *s,
|
||||
struct comedi_insn *insn,
|
||||
unsigned int *data);
|
||||
data[1] = inl(dev->iobase + PCI7230_DI) & 0xffffffff;
|
||||
|
||||
return 2;
|
||||
}
|
||||
|
||||
static int adl_pci7230_attach(struct comedi_device *dev,
|
||||
struct comedi_devconfig *it)
|
||||
|
@ -148,89 +150,46 @@ static int adl_pci7230_attach(struct comedi_device *dev,
|
|||
return 1;
|
||||
}
|
||||
|
||||
static int adl_pci7230_detach(struct comedi_device *dev)
|
||||
static void 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)
|
||||
static struct comedi_driver adl_pci7230_driver = {
|
||||
.driver_name = "adl_pci7230",
|
||||
.module = THIS_MODULE,
|
||||
.attach = adl_pci7230_attach,
|
||||
.detach = adl_pci7230_detach,
|
||||
};
|
||||
|
||||
static int __devinit adl_pci7230_pci_probe(struct pci_dev *dev,
|
||||
const struct pci_device_id *ent)
|
||||
{
|
||||
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;
|
||||
return comedi_pci_auto_config(dev, &adl_pci7230_driver);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
static int __devinit driver_adl_pci7230_pci_probe(struct pci_dev *dev,
|
||||
const struct pci_device_id
|
||||
*ent)
|
||||
{
|
||||
return comedi_pci_auto_config(dev, driver_adl_pci7230.driver_name);
|
||||
}
|
||||
|
||||
static void __devexit driver_adl_pci7230_pci_remove(struct pci_dev *dev)
|
||||
static void __devexit adl_pci7230_pci_remove(struct pci_dev *dev)
|
||||
{
|
||||
comedi_pci_auto_unconfig(dev);
|
||||
}
|
||||
|
||||
static struct pci_driver driver_adl_pci7230_pci_driver = {
|
||||
.id_table = adl_pci7230_pci_table,
|
||||
.probe = &driver_adl_pci7230_pci_probe,
|
||||
.remove = __devexit_p(&driver_adl_pci7230_pci_remove)
|
||||
static DEFINE_PCI_DEVICE_TABLE(adl_pci7230_pci_table) = {
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_ADLINK, PCI_DEVICE_ID_PCI7230) },
|
||||
{ 0 }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(pci, adl_pci7230_pci_table);
|
||||
|
||||
static int __init driver_adl_pci7230_init_module(void)
|
||||
{
|
||||
int retval;
|
||||
|
||||
retval = comedi_driver_register(&driver_adl_pci7230);
|
||||
if (retval < 0)
|
||||
return retval;
|
||||
|
||||
driver_adl_pci7230_pci_driver.name =
|
||||
(char *)driver_adl_pci7230.driver_name;
|
||||
return pci_register_driver(&driver_adl_pci7230_pci_driver);
|
||||
}
|
||||
|
||||
static void __exit driver_adl_pci7230_cleanup_module(void)
|
||||
{
|
||||
pci_unregister_driver(&driver_adl_pci7230_pci_driver);
|
||||
comedi_driver_unregister(&driver_adl_pci7230);
|
||||
}
|
||||
|
||||
module_init(driver_adl_pci7230_init_module);
|
||||
module_exit(driver_adl_pci7230_cleanup_module);
|
||||
static struct pci_driver adl_pci7230_pci_driver = {
|
||||
.name = "adl_pci7230",
|
||||
.id_table = adl_pci7230_pci_table,
|
||||
.probe = adl_pci7230_pci_probe,
|
||||
.remove = __devexit_p(adl_pci7230_pci_remove),
|
||||
};
|
||||
module_comedi_pci_driver(adl_pci7230_driver, adl_pci7230_pci_driver);
|
||||
|
||||
MODULE_AUTHOR("Comedi http://www.comedi.org");
|
||||
MODULE_DESCRIPTION("Comedi low-level driver");
|
||||
|
|
|
@ -48,13 +48,6 @@ Configuration Options:
|
|||
|
||||
#define PCI_DEVICE_ID_PCI7296 0x7296
|
||||
|
||||
static DEFINE_PCI_DEVICE_TABLE(adl_pci7296_pci_table) = {
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_ADLINK, PCI_DEVICE_ID_PCI7296) },
|
||||
{0}
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(pci, adl_pci7296_pci_table);
|
||||
|
||||
struct adl_pci7296_private {
|
||||
int data;
|
||||
struct pci_dev *pci_dev;
|
||||
|
@ -62,16 +55,6 @@ struct adl_pci7296_private {
|
|||
|
||||
#define devpriv ((struct adl_pci7296_private *)dev->private)
|
||||
|
||||
static int adl_pci7296_attach(struct comedi_device *dev,
|
||||
struct comedi_devconfig *it);
|
||||
static int adl_pci7296_detach(struct comedi_device *dev);
|
||||
static struct comedi_driver driver_adl_pci7296 = {
|
||||
.driver_name = "adl_pci7296",
|
||||
.module = THIS_MODULE,
|
||||
.attach = adl_pci7296_attach,
|
||||
.detach = adl_pci7296_detach,
|
||||
};
|
||||
|
||||
static int adl_pci7296_attach(struct comedi_device *dev,
|
||||
struct comedi_devconfig *it)
|
||||
{
|
||||
|
@ -151,66 +134,52 @@ static int adl_pci7296_attach(struct comedi_device *dev,
|
|||
return -EIO;
|
||||
}
|
||||
|
||||
static int adl_pci7296_detach(struct comedi_device *dev)
|
||||
static void adl_pci7296_detach(struct comedi_device *dev)
|
||||
{
|
||||
printk(KERN_INFO "comedi%d: pci7432: remove\n", dev->minor);
|
||||
|
||||
if (devpriv && devpriv->pci_dev) {
|
||||
if (dev->iobase)
|
||||
comedi_pci_disable(devpriv->pci_dev);
|
||||
pci_dev_put(devpriv->pci_dev);
|
||||
}
|
||||
/* detach four 8255 digital io subdevices */
|
||||
if (dev->subdevices) {
|
||||
subdev_8255_cleanup(dev, dev->subdevices + 0);
|
||||
subdev_8255_cleanup(dev, dev->subdevices + 1);
|
||||
subdev_8255_cleanup(dev, dev->subdevices + 2);
|
||||
subdev_8255_cleanup(dev, dev->subdevices + 3);
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __devinit driver_adl_pci7296_pci_probe(struct pci_dev *dev,
|
||||
const struct pci_device_id
|
||||
*ent)
|
||||
static struct comedi_driver adl_pci7296_driver = {
|
||||
.driver_name = "adl_pci7296",
|
||||
.module = THIS_MODULE,
|
||||
.attach = adl_pci7296_attach,
|
||||
.detach = adl_pci7296_detach,
|
||||
};
|
||||
|
||||
static int __devinit adl_pci7296_pci_probe(struct pci_dev *dev,
|
||||
const struct pci_device_id *ent)
|
||||
{
|
||||
return comedi_pci_auto_config(dev, driver_adl_pci7296.driver_name);
|
||||
return comedi_pci_auto_config(dev, &adl_pci7296_driver);
|
||||
}
|
||||
|
||||
static void __devexit driver_adl_pci7296_pci_remove(struct pci_dev *dev)
|
||||
static void __devexit adl_pci7296_pci_remove(struct pci_dev *dev)
|
||||
{
|
||||
comedi_pci_auto_unconfig(dev);
|
||||
}
|
||||
|
||||
static struct pci_driver driver_adl_pci7296_pci_driver = {
|
||||
.id_table = adl_pci7296_pci_table,
|
||||
.probe = &driver_adl_pci7296_pci_probe,
|
||||
.remove = __devexit_p(&driver_adl_pci7296_pci_remove)
|
||||
static DEFINE_PCI_DEVICE_TABLE(adl_pci7296_pci_table) = {
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_ADLINK, PCI_DEVICE_ID_PCI7296) },
|
||||
{ 0 }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(pci, adl_pci7296_pci_table);
|
||||
|
||||
static int __init driver_adl_pci7296_init_module(void)
|
||||
{
|
||||
int retval;
|
||||
|
||||
retval = comedi_driver_register(&driver_adl_pci7296);
|
||||
if (retval < 0)
|
||||
return retval;
|
||||
|
||||
driver_adl_pci7296_pci_driver.name =
|
||||
(char *)driver_adl_pci7296.driver_name;
|
||||
return pci_register_driver(&driver_adl_pci7296_pci_driver);
|
||||
}
|
||||
|
||||
static void __exit driver_adl_pci7296_cleanup_module(void)
|
||||
{
|
||||
pci_unregister_driver(&driver_adl_pci7296_pci_driver);
|
||||
comedi_driver_unregister(&driver_adl_pci7296);
|
||||
}
|
||||
|
||||
module_init(driver_adl_pci7296_init_module);
|
||||
module_exit(driver_adl_pci7296_cleanup_module);
|
||||
static struct pci_driver adl_pci7296_pci_driver = {
|
||||
.name = "adl_pci7296",
|
||||
.id_table = adl_pci7296_pci_table,
|
||||
.probe = adl_pci7296_pci_probe,
|
||||
.remove = __devexit_p(adl_pci7296_pci_remove),
|
||||
};
|
||||
module_comedi_pci_driver(adl_pci7296_driver, adl_pci7296_pci_driver);
|
||||
|
||||
MODULE_AUTHOR("Comedi http://www.comedi.org");
|
||||
MODULE_DESCRIPTION("Comedi low-level driver");
|
||||
|
|
|
@ -43,13 +43,6 @@ Configuration Options:
|
|||
|
||||
#define PCI_DEVICE_ID_PCI7432 0x7432
|
||||
|
||||
static DEFINE_PCI_DEVICE_TABLE(adl_pci7432_pci_table) = {
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_ADLINK, PCI_DEVICE_ID_PCI7432) },
|
||||
{0}
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(pci, adl_pci7432_pci_table);
|
||||
|
||||
struct adl_pci7432_private {
|
||||
int data;
|
||||
struct pci_dev *pci_dev;
|
||||
|
@ -57,29 +50,44 @@ struct adl_pci7432_private {
|
|||
|
||||
#define devpriv ((struct adl_pci7432_private *)dev->private)
|
||||
|
||||
static int adl_pci7432_attach(struct comedi_device *dev,
|
||||
struct comedi_devconfig *it);
|
||||
static int adl_pci7432_detach(struct comedi_device *dev);
|
||||
static struct comedi_driver driver_adl_pci7432 = {
|
||||
.driver_name = "adl_pci7432",
|
||||
.module = THIS_MODULE,
|
||||
.attach = adl_pci7432_attach,
|
||||
.detach = adl_pci7432_detach,
|
||||
};
|
||||
static int adl_pci7432_do_insn_bits(struct comedi_device *dev,
|
||||
struct comedi_subdevice *s,
|
||||
struct comedi_insn *insn,
|
||||
unsigned int *data)
|
||||
{
|
||||
printk(KERN_DEBUG "comedi: pci7432_do_insn_bits called\n");
|
||||
printk(KERN_DEBUG "comedi: data0: %8x data1: %8x\n", data[0], data[1]);
|
||||
|
||||
/* Digital IO */
|
||||
if (insn->n != 2)
|
||||
return -EINVAL;
|
||||
|
||||
if (data[0]) {
|
||||
s->state &= ~data[0];
|
||||
s->state |= (data[0] & data[1]);
|
||||
|
||||
printk(KERN_DEBUG "comedi: out: %8x on iobase %4lx\n", s->state,
|
||||
dev->iobase + PCI7432_DO);
|
||||
outl(s->state & 0xffffffff, dev->iobase + PCI7432_DO);
|
||||
}
|
||||
return 2;
|
||||
}
|
||||
|
||||
static int adl_pci7432_di_insn_bits(struct comedi_device *dev,
|
||||
struct comedi_subdevice *s,
|
||||
struct comedi_insn *insn,
|
||||
unsigned int *data);
|
||||
unsigned int *data)
|
||||
{
|
||||
printk(KERN_DEBUG "comedi: pci7432_di_insn_bits called\n");
|
||||
printk(KERN_DEBUG "comedi: data0: %8x data1: %8x\n", data[0], data[1]);
|
||||
|
||||
static int adl_pci7432_do_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 + PCI7432_DI) & 0xffffffff;
|
||||
printk(KERN_DEBUG "comedi: data1 %8x\n", data[1]);
|
||||
|
||||
return 2;
|
||||
}
|
||||
|
||||
static int adl_pci7432_attach(struct comedi_device *dev,
|
||||
struct comedi_devconfig *it)
|
||||
|
@ -153,97 +161,46 @@ static int adl_pci7432_attach(struct comedi_device *dev,
|
|||
return -EIO;
|
||||
}
|
||||
|
||||
static int adl_pci7432_detach(struct comedi_device *dev)
|
||||
static void adl_pci7432_detach(struct comedi_device *dev)
|
||||
{
|
||||
printk(KERN_INFO "comedi%d: pci7432: 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_pci7432_do_insn_bits(struct comedi_device *dev,
|
||||
struct comedi_subdevice *s,
|
||||
struct comedi_insn *insn,
|
||||
unsigned int *data)
|
||||
static struct comedi_driver adl_pci7432_driver = {
|
||||
.driver_name = "adl_pci7432",
|
||||
.module = THIS_MODULE,
|
||||
.attach = adl_pci7432_attach,
|
||||
.detach = adl_pci7432_detach,
|
||||
};
|
||||
|
||||
static int __devinit adl_pci7432_pci_probe(struct pci_dev *dev,
|
||||
const struct pci_device_id *ent)
|
||||
{
|
||||
printk(KERN_DEBUG "comedi: pci7432_do_insn_bits called\n");
|
||||
printk(KERN_DEBUG "comedi: data0: %8x data1: %8x\n", data[0], data[1]);
|
||||
|
||||
if (insn->n != 2)
|
||||
return -EINVAL;
|
||||
|
||||
if (data[0]) {
|
||||
s->state &= ~data[0];
|
||||
s->state |= (data[0] & data[1]);
|
||||
|
||||
printk(KERN_DEBUG "comedi: out: %8x on iobase %4lx\n", s->state,
|
||||
dev->iobase + PCI7432_DO);
|
||||
outl(s->state & 0xffffffff, dev->iobase + PCI7432_DO);
|
||||
}
|
||||
return 2;
|
||||
return comedi_pci_auto_config(dev, &adl_pci7432_driver);
|
||||
}
|
||||
|
||||
static int adl_pci7432_di_insn_bits(struct comedi_device *dev,
|
||||
struct comedi_subdevice *s,
|
||||
struct comedi_insn *insn,
|
||||
unsigned int *data)
|
||||
{
|
||||
printk(KERN_DEBUG "comedi: pci7432_di_insn_bits called\n");
|
||||
printk(KERN_DEBUG "comedi: data0: %8x data1: %8x\n", data[0], data[1]);
|
||||
|
||||
if (insn->n != 2)
|
||||
return -EINVAL;
|
||||
|
||||
data[1] = inl(dev->iobase + PCI7432_DI) & 0xffffffff;
|
||||
printk(KERN_DEBUG "comedi: data1 %8x\n", data[1]);
|
||||
|
||||
return 2;
|
||||
}
|
||||
|
||||
static int __devinit driver_adl_pci7432_pci_probe(struct pci_dev *dev,
|
||||
const struct pci_device_id
|
||||
*ent)
|
||||
{
|
||||
return comedi_pci_auto_config(dev, driver_adl_pci7432.driver_name);
|
||||
}
|
||||
|
||||
static void __devexit driver_adl_pci7432_pci_remove(struct pci_dev *dev)
|
||||
static void __devexit adl_pci7432_pci_remove(struct pci_dev *dev)
|
||||
{
|
||||
comedi_pci_auto_unconfig(dev);
|
||||
}
|
||||
|
||||
static struct pci_driver driver_adl_pci7432_pci_driver = {
|
||||
.id_table = adl_pci7432_pci_table,
|
||||
.probe = &driver_adl_pci7432_pci_probe,
|
||||
.remove = __devexit_p(&driver_adl_pci7432_pci_remove)
|
||||
static DEFINE_PCI_DEVICE_TABLE(adl_pci7432_pci_table) = {
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_ADLINK, PCI_DEVICE_ID_PCI7432) },
|
||||
{ 0 }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(pci, adl_pci7432_pci_table);
|
||||
|
||||
static int __init driver_adl_pci7432_init_module(void)
|
||||
{
|
||||
int retval;
|
||||
|
||||
retval = comedi_driver_register(&driver_adl_pci7432);
|
||||
if (retval < 0)
|
||||
return retval;
|
||||
|
||||
driver_adl_pci7432_pci_driver.name =
|
||||
(char *)driver_adl_pci7432.driver_name;
|
||||
return pci_register_driver(&driver_adl_pci7432_pci_driver);
|
||||
}
|
||||
|
||||
static void __exit driver_adl_pci7432_cleanup_module(void)
|
||||
{
|
||||
pci_unregister_driver(&driver_adl_pci7432_pci_driver);
|
||||
comedi_driver_unregister(&driver_adl_pci7432);
|
||||
}
|
||||
|
||||
module_init(driver_adl_pci7432_init_module);
|
||||
module_exit(driver_adl_pci7432_cleanup_module);
|
||||
static struct pci_driver adl_pci7432_pci_driver = {
|
||||
.name = "adl_pci7432",
|
||||
.id_table = adl_pci7432_pci_table,
|
||||
.probe = adl_pci7432_pci_probe,
|
||||
.remove = __devexit_p(adl_pci7432_pci_remove),
|
||||
};
|
||||
module_comedi_pci_driver(adl_pci7432_driver, adl_pci7432_pci_driver);
|
||||
|
||||
MODULE_AUTHOR("Comedi http://www.comedi.org");
|
||||
MODULE_DESCRIPTION("Comedi low-level driver");
|
||||
|
|
|
@ -56,13 +56,6 @@ Configuration Options:
|
|||
|
||||
#define PCI_DEVICE_ID_PCI8164 0x8164
|
||||
|
||||
static DEFINE_PCI_DEVICE_TABLE(adl_pci8164_pci_table) = {
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_ADLINK, PCI_DEVICE_ID_PCI8164) },
|
||||
{0}
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(pci, adl_pci8164_pci_table);
|
||||
|
||||
struct adl_pci8164_private {
|
||||
int data;
|
||||
struct pci_dev *pci_dev;
|
||||
|
@ -70,159 +63,6 @@ struct adl_pci8164_private {
|
|||
|
||||
#define devpriv ((struct adl_pci8164_private *)dev->private)
|
||||
|
||||
static int adl_pci8164_attach(struct comedi_device *dev,
|
||||
struct comedi_devconfig *it);
|
||||
static int adl_pci8164_detach(struct comedi_device *dev);
|
||||
static struct comedi_driver driver_adl_pci8164 = {
|
||||
.driver_name = "adl_pci8164",
|
||||
.module = THIS_MODULE,
|
||||
.attach = adl_pci8164_attach,
|
||||
.detach = adl_pci8164_detach,
|
||||
};
|
||||
|
||||
static int adl_pci8164_insn_read_msts(struct comedi_device *dev,
|
||||
struct comedi_subdevice *s,
|
||||
struct comedi_insn *insn,
|
||||
unsigned int *data);
|
||||
|
||||
static int adl_pci8164_insn_read_ssts(struct comedi_device *dev,
|
||||
struct comedi_subdevice *s,
|
||||
struct comedi_insn *insn,
|
||||
unsigned int *data);
|
||||
|
||||
static int adl_pci8164_insn_read_buf0(struct comedi_device *dev,
|
||||
struct comedi_subdevice *s,
|
||||
struct comedi_insn *insn,
|
||||
unsigned int *data);
|
||||
|
||||
static int adl_pci8164_insn_read_buf1(struct comedi_device *dev,
|
||||
struct comedi_subdevice *s,
|
||||
struct comedi_insn *insn,
|
||||
unsigned int *data);
|
||||
|
||||
static int adl_pci8164_insn_write_cmd(struct comedi_device *dev,
|
||||
struct comedi_subdevice *s,
|
||||
struct comedi_insn *insn,
|
||||
unsigned int *data);
|
||||
|
||||
static int adl_pci8164_insn_write_otp(struct comedi_device *dev,
|
||||
struct comedi_subdevice *s,
|
||||
struct comedi_insn *insn,
|
||||
unsigned int *data);
|
||||
|
||||
static int adl_pci8164_insn_write_buf0(struct comedi_device *dev,
|
||||
struct comedi_subdevice *s,
|
||||
struct comedi_insn *insn,
|
||||
unsigned int *data);
|
||||
|
||||
static int adl_pci8164_insn_write_buf1(struct comedi_device *dev,
|
||||
struct comedi_subdevice *s,
|
||||
struct comedi_insn *insn,
|
||||
unsigned int *data);
|
||||
|
||||
static int adl_pci8164_attach(struct comedi_device *dev,
|
||||
struct comedi_devconfig *it)
|
||||
{
|
||||
struct pci_dev *pcidev = NULL;
|
||||
struct comedi_subdevice *s;
|
||||
int bus, slot;
|
||||
|
||||
printk(KERN_INFO "comedi: attempt to attach...\n");
|
||||
printk(KERN_INFO "comedi%d: adl_pci8164\n", dev->minor);
|
||||
|
||||
dev->board_name = "pci8164";
|
||||
bus = it->options[0];
|
||||
slot = it->options[1];
|
||||
|
||||
if (alloc_private(dev, sizeof(struct adl_pci8164_private)) < 0)
|
||||
return -ENOMEM;
|
||||
|
||||
if (alloc_subdevices(dev, 4) < 0)
|
||||
return -ENOMEM;
|
||||
|
||||
for_each_pci_dev(pcidev) {
|
||||
if (pcidev->vendor == PCI_VENDOR_ID_ADLINK &&
|
||||
pcidev->device == PCI_DEVICE_ID_PCI8164) {
|
||||
if (bus || slot) {
|
||||
/* requested particular bus/slot */
|
||||
if (pcidev->bus->number != bus
|
||||
|| PCI_SLOT(pcidev->devfn) != slot)
|
||||
continue;
|
||||
}
|
||||
devpriv->pci_dev = pcidev;
|
||||
if (comedi_pci_enable(pcidev, "adl_pci8164") < 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;
|
||||
s->type = COMEDI_SUBD_PROC;
|
||||
s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
|
||||
s->n_chan = 4;
|
||||
s->maxdata = 0xffff;
|
||||
s->len_chanlist = 4;
|
||||
/* s->range_table = &range_axis; */
|
||||
s->insn_read = adl_pci8164_insn_read_msts;
|
||||
s->insn_write = adl_pci8164_insn_write_cmd;
|
||||
|
||||
s = dev->subdevices + 1;
|
||||
s->type = COMEDI_SUBD_PROC;
|
||||
s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
|
||||
s->n_chan = 4;
|
||||
s->maxdata = 0xffff;
|
||||
s->len_chanlist = 4;
|
||||
/* s->range_table = &range_axis; */
|
||||
s->insn_read = adl_pci8164_insn_read_ssts;
|
||||
s->insn_write = adl_pci8164_insn_write_otp;
|
||||
|
||||
s = dev->subdevices + 2;
|
||||
s->type = COMEDI_SUBD_PROC;
|
||||
s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
|
||||
s->n_chan = 4;
|
||||
s->maxdata = 0xffff;
|
||||
s->len_chanlist = 4;
|
||||
/* s->range_table = &range_axis; */
|
||||
s->insn_read = adl_pci8164_insn_read_buf0;
|
||||
s->insn_write = adl_pci8164_insn_write_buf0;
|
||||
|
||||
s = dev->subdevices + 3;
|
||||
s->type = COMEDI_SUBD_PROC;
|
||||
s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
|
||||
s->n_chan = 4;
|
||||
s->maxdata = 0xffff;
|
||||
s->len_chanlist = 4;
|
||||
/* s->range_table = &range_axis; */
|
||||
s->insn_read = adl_pci8164_insn_read_buf1;
|
||||
s->insn_write = adl_pci8164_insn_write_buf1;
|
||||
|
||||
printk(KERN_INFO "comedi: attached\n");
|
||||
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
printk(KERN_ERR "comedi%d: no supported board found!"
|
||||
"(req. bus/slot : %d/%d)\n", dev->minor, bus, slot);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
static int adl_pci8164_detach(struct comedi_device *dev)
|
||||
{
|
||||
printk(KERN_INFO "comedi%d: pci8164: 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;
|
||||
}
|
||||
|
||||
/*
|
||||
all the read commands are the same except for the addition a constant
|
||||
* const to the data for inw()
|
||||
|
@ -384,45 +224,136 @@ static int adl_pci8164_insn_write_buf1(struct comedi_device *dev,
|
|||
return 2;
|
||||
}
|
||||
|
||||
static int __devinit driver_adl_pci8164_pci_probe(struct pci_dev *dev,
|
||||
const struct pci_device_id
|
||||
*ent)
|
||||
static int adl_pci8164_attach(struct comedi_device *dev,
|
||||
struct comedi_devconfig *it)
|
||||
{
|
||||
return comedi_pci_auto_config(dev, driver_adl_pci8164.driver_name);
|
||||
struct pci_dev *pcidev = NULL;
|
||||
struct comedi_subdevice *s;
|
||||
int bus, slot;
|
||||
|
||||
printk(KERN_INFO "comedi: attempt to attach...\n");
|
||||
printk(KERN_INFO "comedi%d: adl_pci8164\n", dev->minor);
|
||||
|
||||
dev->board_name = "pci8164";
|
||||
bus = it->options[0];
|
||||
slot = it->options[1];
|
||||
|
||||
if (alloc_private(dev, sizeof(struct adl_pci8164_private)) < 0)
|
||||
return -ENOMEM;
|
||||
|
||||
if (alloc_subdevices(dev, 4) < 0)
|
||||
return -ENOMEM;
|
||||
|
||||
for_each_pci_dev(pcidev) {
|
||||
if (pcidev->vendor == PCI_VENDOR_ID_ADLINK &&
|
||||
pcidev->device == PCI_DEVICE_ID_PCI8164) {
|
||||
if (bus || slot) {
|
||||
/* requested particular bus/slot */
|
||||
if (pcidev->bus->number != bus
|
||||
|| PCI_SLOT(pcidev->devfn) != slot)
|
||||
continue;
|
||||
}
|
||||
devpriv->pci_dev = pcidev;
|
||||
if (comedi_pci_enable(pcidev, "adl_pci8164") < 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;
|
||||
s->type = COMEDI_SUBD_PROC;
|
||||
s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
|
||||
s->n_chan = 4;
|
||||
s->maxdata = 0xffff;
|
||||
s->len_chanlist = 4;
|
||||
/* s->range_table = &range_axis; */
|
||||
s->insn_read = adl_pci8164_insn_read_msts;
|
||||
s->insn_write = adl_pci8164_insn_write_cmd;
|
||||
|
||||
s = dev->subdevices + 1;
|
||||
s->type = COMEDI_SUBD_PROC;
|
||||
s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
|
||||
s->n_chan = 4;
|
||||
s->maxdata = 0xffff;
|
||||
s->len_chanlist = 4;
|
||||
/* s->range_table = &range_axis; */
|
||||
s->insn_read = adl_pci8164_insn_read_ssts;
|
||||
s->insn_write = adl_pci8164_insn_write_otp;
|
||||
|
||||
s = dev->subdevices + 2;
|
||||
s->type = COMEDI_SUBD_PROC;
|
||||
s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
|
||||
s->n_chan = 4;
|
||||
s->maxdata = 0xffff;
|
||||
s->len_chanlist = 4;
|
||||
/* s->range_table = &range_axis; */
|
||||
s->insn_read = adl_pci8164_insn_read_buf0;
|
||||
s->insn_write = adl_pci8164_insn_write_buf0;
|
||||
|
||||
s = dev->subdevices + 3;
|
||||
s->type = COMEDI_SUBD_PROC;
|
||||
s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
|
||||
s->n_chan = 4;
|
||||
s->maxdata = 0xffff;
|
||||
s->len_chanlist = 4;
|
||||
/* s->range_table = &range_axis; */
|
||||
s->insn_read = adl_pci8164_insn_read_buf1;
|
||||
s->insn_write = adl_pci8164_insn_write_buf1;
|
||||
|
||||
printk(KERN_INFO "comedi: attached\n");
|
||||
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
printk(KERN_ERR "comedi%d: no supported board found!"
|
||||
"(req. bus/slot : %d/%d)\n", dev->minor, bus, slot);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
static void __devexit driver_adl_pci8164_pci_remove(struct pci_dev *dev)
|
||||
static void adl_pci8164_detach(struct comedi_device *dev)
|
||||
{
|
||||
if (devpriv && devpriv->pci_dev) {
|
||||
if (dev->iobase)
|
||||
comedi_pci_disable(devpriv->pci_dev);
|
||||
pci_dev_put(devpriv->pci_dev);
|
||||
}
|
||||
}
|
||||
|
||||
static struct comedi_driver adl_pci8164_driver = {
|
||||
.driver_name = "adl_pci8164",
|
||||
.module = THIS_MODULE,
|
||||
.attach = adl_pci8164_attach,
|
||||
.detach = adl_pci8164_detach,
|
||||
};
|
||||
|
||||
static int __devinit adl_pci8164_pci_probe(struct pci_dev *dev,
|
||||
const struct pci_device_id *ent)
|
||||
{
|
||||
return comedi_pci_auto_config(dev, &adl_pci8164_driver);
|
||||
}
|
||||
|
||||
static void __devexit adl_pci8164_pci_remove(struct pci_dev *dev)
|
||||
{
|
||||
comedi_pci_auto_unconfig(dev);
|
||||
}
|
||||
|
||||
static struct pci_driver driver_adl_pci8164_pci_driver = {
|
||||
.id_table = adl_pci8164_pci_table,
|
||||
.probe = &driver_adl_pci8164_pci_probe,
|
||||
.remove = __devexit_p(&driver_adl_pci8164_pci_remove)
|
||||
static DEFINE_PCI_DEVICE_TABLE(adl_pci8164_pci_table) = {
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_ADLINK, PCI_DEVICE_ID_PCI8164) },
|
||||
{0}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(pci, adl_pci8164_pci_table);
|
||||
|
||||
static int __init driver_adl_pci8164_init_module(void)
|
||||
{
|
||||
int retval;
|
||||
|
||||
retval = comedi_driver_register(&driver_adl_pci8164);
|
||||
if (retval < 0)
|
||||
return retval;
|
||||
|
||||
driver_adl_pci8164_pci_driver.name =
|
||||
(char *)driver_adl_pci8164.driver_name;
|
||||
return pci_register_driver(&driver_adl_pci8164_pci_driver);
|
||||
}
|
||||
|
||||
static void __exit driver_adl_pci8164_cleanup_module(void)
|
||||
{
|
||||
pci_unregister_driver(&driver_adl_pci8164_pci_driver);
|
||||
comedi_driver_unregister(&driver_adl_pci8164);
|
||||
}
|
||||
|
||||
module_init(driver_adl_pci8164_init_module);
|
||||
module_exit(driver_adl_pci8164_cleanup_module);
|
||||
static struct pci_driver adl_pci8164_pci_driver = {
|
||||
.name = "adl_pci8164",
|
||||
.id_table = adl_pci8164_pci_table,
|
||||
.probe = adl_pci8164_pci_probe,
|
||||
.remove = __devexit_p(adl_pci8164_pci_remove),
|
||||
};
|
||||
module_comedi_pci_driver(adl_pci8164_driver, adl_pci8164_pci_driver);
|
||||
|
||||
MODULE_AUTHOR("Comedi http://www.comedi.org");
|
||||
MODULE_DESCRIPTION("Comedi low-level driver");
|
||||
|
|
|
@ -289,16 +289,6 @@ TODO:
|
|||
PCI9111_IO_BASE+PCI9111_REGISTER_8254_COUNTER_2); \
|
||||
} while (0)
|
||||
|
||||
/* Function prototypes */
|
||||
|
||||
static int pci9111_attach(struct comedi_device *dev,
|
||||
struct comedi_devconfig *it);
|
||||
static int pci9111_detach(struct comedi_device *dev);
|
||||
static void pci9111_ai_munge(struct comedi_device *dev,
|
||||
struct comedi_subdevice *s, void *data,
|
||||
unsigned int num_bytes,
|
||||
unsigned int start_chan_index);
|
||||
|
||||
static const struct comedi_lrange pci9111_hr_ai_range = {
|
||||
5,
|
||||
{
|
||||
|
@ -310,14 +300,6 @@ static const struct comedi_lrange pci9111_hr_ai_range = {
|
|||
}
|
||||
};
|
||||
|
||||
static DEFINE_PCI_DEVICE_TABLE(pci9111_pci_table) = {
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_ADLINK, PCI9111_HR_DEVICE_ID) },
|
||||
/* { PCI_DEVICE(PCI_VENDOR_ID_ADLINK, PCI9111_HG_DEVICE_ID) }, */
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(pci, pci9111_pci_table);
|
||||
|
||||
/* */
|
||||
/* Board specification structure */
|
||||
/* */
|
||||
|
@ -354,51 +336,6 @@ static const struct pci9111_board pci9111_boards[] = {
|
|||
#define pci9111_board_nbr \
|
||||
(sizeof(pci9111_boards)/sizeof(struct pci9111_board))
|
||||
|
||||
static struct comedi_driver pci9111_driver = {
|
||||
.driver_name = PCI9111_DRIVER_NAME,
|
||||
.module = THIS_MODULE,
|
||||
.attach = pci9111_attach,
|
||||
.detach = pci9111_detach,
|
||||
};
|
||||
|
||||
static int __devinit pci9111_driver_pci_probe(struct pci_dev *dev,
|
||||
const struct pci_device_id *ent)
|
||||
{
|
||||
return comedi_pci_auto_config(dev, pci9111_driver.driver_name);
|
||||
}
|
||||
|
||||
static void __devexit pci9111_driver_pci_remove(struct pci_dev *dev)
|
||||
{
|
||||
comedi_pci_auto_unconfig(dev);
|
||||
}
|
||||
|
||||
static struct pci_driver pci9111_driver_pci_driver = {
|
||||
.id_table = pci9111_pci_table,
|
||||
.probe = &pci9111_driver_pci_probe,
|
||||
.remove = __devexit_p(&pci9111_driver_pci_remove)
|
||||
};
|
||||
|
||||
static int __init pci9111_driver_init_module(void)
|
||||
{
|
||||
int retval;
|
||||
|
||||
retval = comedi_driver_register(&pci9111_driver);
|
||||
if (retval < 0)
|
||||
return retval;
|
||||
|
||||
pci9111_driver_pci_driver.name = (char *)pci9111_driver.driver_name;
|
||||
return pci_register_driver(&pci9111_driver_pci_driver);
|
||||
}
|
||||
|
||||
static void __exit pci9111_driver_cleanup_module(void)
|
||||
{
|
||||
pci_unregister_driver(&pci9111_driver_pci_driver);
|
||||
comedi_driver_unregister(&pci9111_driver);
|
||||
}
|
||||
|
||||
module_init(pci9111_driver_init_module);
|
||||
module_exit(pci9111_driver_cleanup_module);
|
||||
|
||||
/* Private data structure */
|
||||
|
||||
struct pci9111_private_data {
|
||||
|
@ -1445,31 +1382,54 @@ found:
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* Detach */
|
||||
|
||||
static int pci9111_detach(struct comedi_device *dev)
|
||||
static void pci9111_detach(struct comedi_device *dev)
|
||||
{
|
||||
/* Reset device */
|
||||
|
||||
if (dev->private != NULL) {
|
||||
if (dev_private->is_valid)
|
||||
pci9111_reset(dev);
|
||||
|
||||
}
|
||||
/* Release previously allocated irq */
|
||||
|
||||
if (dev->irq != 0)
|
||||
free_irq(dev->irq, dev);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct comedi_driver adl_pci9111_driver = {
|
||||
.driver_name = "adl_pci9111",
|
||||
.module = THIS_MODULE,
|
||||
.attach = pci9111_attach,
|
||||
.detach = pci9111_detach,
|
||||
};
|
||||
|
||||
static int __devinit pci9111_pci_probe(struct pci_dev *dev,
|
||||
const struct pci_device_id *ent)
|
||||
{
|
||||
return comedi_pci_auto_config(dev, &adl_pci9111_driver);
|
||||
}
|
||||
|
||||
static void __devexit pci9111_pci_remove(struct pci_dev *dev)
|
||||
{
|
||||
comedi_pci_auto_unconfig(dev);
|
||||
}
|
||||
|
||||
static DEFINE_PCI_DEVICE_TABLE(pci9111_pci_table) = {
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_ADLINK, PCI9111_HR_DEVICE_ID) },
|
||||
/* { PCI_DEVICE(PCI_VENDOR_ID_ADLINK, PCI9111_HG_DEVICE_ID) }, */
|
||||
{ 0 }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(pci, pci9111_pci_table);
|
||||
|
||||
static struct pci_driver adl_pci9111_pci_driver = {
|
||||
.name = "adl_pci9111",
|
||||
.id_table = pci9111_pci_table,
|
||||
.probe = pci9111_pci_probe,
|
||||
.remove = __devexit_p(pci9111_pci_remove),
|
||||
};
|
||||
module_comedi_pci_driver(adl_pci9111_driver, adl_pci9111_pci_driver);
|
||||
|
||||
MODULE_AUTHOR("Comedi http://www.comedi.org");
|
||||
MODULE_DESCRIPTION("Comedi low-level driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
|
|
@ -221,10 +221,6 @@ static const struct comedi_lrange range_pci9118hg = { 8, {
|
|||
* of BIP/UNI ranges
|
||||
*/
|
||||
|
||||
static int pci9118_attach(struct comedi_device *dev,
|
||||
struct comedi_devconfig *it);
|
||||
static int pci9118_detach(struct comedi_device *dev);
|
||||
|
||||
struct boardtype {
|
||||
const char *name; /* board name */
|
||||
int vendor_id; /* PCI vendor a device ID of card */
|
||||
|
@ -252,81 +248,6 @@ struct boardtype {
|
|||
|
||||
};
|
||||
|
||||
static DEFINE_PCI_DEVICE_TABLE(pci9118_pci_table) = {
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_AMCC, 0x80d9) },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(pci, pci9118_pci_table);
|
||||
|
||||
static const struct boardtype boardtypes[] = {
|
||||
{"pci9118dg", PCI_VENDOR_ID_AMCC, 0x80d9,
|
||||
AMCC_OP_REG_SIZE, IORANGE_9118,
|
||||
16, 8, 256, PCI9118_CHANLEN, 2, 0x0fff, 0x0fff,
|
||||
&range_pci9118dg_hr, &range_bipolar10,
|
||||
3000, 12, 512},
|
||||
{"pci9118hg", PCI_VENDOR_ID_AMCC, 0x80d9,
|
||||
AMCC_OP_REG_SIZE, IORANGE_9118,
|
||||
16, 8, 256, PCI9118_CHANLEN, 2, 0x0fff, 0x0fff,
|
||||
&range_pci9118hg, &range_bipolar10,
|
||||
3000, 12, 512},
|
||||
{"pci9118hr", PCI_VENDOR_ID_AMCC, 0x80d9,
|
||||
AMCC_OP_REG_SIZE, IORANGE_9118,
|
||||
16, 8, 256, PCI9118_CHANLEN, 2, 0xffff, 0x0fff,
|
||||
&range_pci9118dg_hr, &range_bipolar10,
|
||||
10000, 40, 512},
|
||||
};
|
||||
|
||||
#define n_boardtypes (sizeof(boardtypes)/sizeof(struct boardtype))
|
||||
|
||||
static struct comedi_driver driver_pci9118 = {
|
||||
.driver_name = "adl_pci9118",
|
||||
.module = THIS_MODULE,
|
||||
.attach = pci9118_attach,
|
||||
.detach = pci9118_detach,
|
||||
.num_names = n_boardtypes,
|
||||
.board_name = &boardtypes[0].name,
|
||||
.offset = sizeof(struct boardtype),
|
||||
};
|
||||
|
||||
static int __devinit driver_pci9118_pci_probe(struct pci_dev *dev,
|
||||
const struct pci_device_id *ent)
|
||||
{
|
||||
return comedi_pci_auto_config(dev, driver_pci9118.driver_name);
|
||||
}
|
||||
|
||||
static void __devexit driver_pci9118_pci_remove(struct pci_dev *dev)
|
||||
{
|
||||
comedi_pci_auto_unconfig(dev);
|
||||
}
|
||||
|
||||
static struct pci_driver driver_pci9118_pci_driver = {
|
||||
.id_table = pci9118_pci_table,
|
||||
.probe = &driver_pci9118_pci_probe,
|
||||
.remove = __devexit_p(&driver_pci9118_pci_remove)
|
||||
};
|
||||
|
||||
static int __init driver_pci9118_init_module(void)
|
||||
{
|
||||
int retval;
|
||||
|
||||
retval = comedi_driver_register(&driver_pci9118);
|
||||
if (retval < 0)
|
||||
return retval;
|
||||
|
||||
driver_pci9118_pci_driver.name = (char *)driver_pci9118.driver_name;
|
||||
return pci_register_driver(&driver_pci9118_pci_driver);
|
||||
}
|
||||
|
||||
static void __exit driver_pci9118_cleanup_module(void)
|
||||
{
|
||||
pci_unregister_driver(&driver_pci9118_pci_driver);
|
||||
comedi_driver_unregister(&driver_pci9118);
|
||||
}
|
||||
|
||||
module_init(driver_pci9118_init_module);
|
||||
module_exit(driver_pci9118_cleanup_module);
|
||||
|
||||
struct pci9118_private {
|
||||
unsigned long iobase_a; /* base+size for AMCC chip */
|
||||
unsigned int master; /* master capable */
|
||||
|
@ -2190,9 +2111,6 @@ static int pci9118_reset(struct comedi_device *dev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
==============================================================================
|
||||
*/
|
||||
static int pci9118_attach(struct comedi_device *dev,
|
||||
struct comedi_devconfig *it)
|
||||
{
|
||||
|
@ -2435,10 +2353,7 @@ static int pci9118_attach(struct comedi_device *dev,
|
|||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
==============================================================================
|
||||
*/
|
||||
static int pci9118_detach(struct comedi_device *dev)
|
||||
static void pci9118_detach(struct comedi_device *dev)
|
||||
{
|
||||
if (dev->private) {
|
||||
if (devpriv->valid)
|
||||
|
@ -2458,13 +2373,100 @@ static int pci9118_detach(struct comedi_device *dev)
|
|||
free_pages((unsigned long)devpriv->dmabuf_virt[1],
|
||||
devpriv->dmabuf_pages[1]);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
==============================================================================
|
||||
*/
|
||||
static const struct boardtype boardtypes[] = {
|
||||
{
|
||||
.name = "pci9118dg",
|
||||
.vendor_id = PCI_VENDOR_ID_AMCC,
|
||||
.device_id = 0x80d9,
|
||||
.iorange_amcc = AMCC_OP_REG_SIZE,
|
||||
.iorange_9118 = IORANGE_9118,
|
||||
.n_aichan = 16,
|
||||
.n_aichand = 8,
|
||||
.mux_aichan = 256,
|
||||
.n_aichanlist = PCI9118_CHANLEN,
|
||||
.n_aochan = 2,
|
||||
.ai_maxdata = 0x0fff,
|
||||
.ao_maxdata = 0x0fff,
|
||||
.rangelist_ai = &range_pci9118dg_hr,
|
||||
.rangelist_ao = &range_bipolar10,
|
||||
.ai_ns_min = 3000,
|
||||
.ai_pacer_min = 12,
|
||||
.half_fifo_size = 512,
|
||||
}, {
|
||||
.name = "pci9118hg",
|
||||
.vendor_id = PCI_VENDOR_ID_AMCC,
|
||||
.device_id = 0x80d9,
|
||||
.iorange_amcc = AMCC_OP_REG_SIZE,
|
||||
.iorange_9118 = IORANGE_9118,
|
||||
.n_aichan = 16,
|
||||
.n_aichand = 8,
|
||||
.mux_aichan = 256,
|
||||
.n_aichanlist = PCI9118_CHANLEN,
|
||||
.n_aochan = 2,
|
||||
.ai_maxdata = 0x0fff,
|
||||
.ao_maxdata = 0x0fff,
|
||||
.rangelist_ai = &range_pci9118hg,
|
||||
.rangelist_ao = &range_bipolar10,
|
||||
.ai_ns_min = 3000,
|
||||
.ai_pacer_min = 12,
|
||||
.half_fifo_size = 512,
|
||||
}, {
|
||||
.name = "pci9118hr",
|
||||
.vendor_id = PCI_VENDOR_ID_AMCC,
|
||||
.device_id = 0x80d9,
|
||||
.iorange_amcc = AMCC_OP_REG_SIZE,
|
||||
.iorange_9118 = IORANGE_9118,
|
||||
.n_aichan = 16,
|
||||
.n_aichand = 8,
|
||||
.mux_aichan = 256,
|
||||
.n_aichanlist = PCI9118_CHANLEN,
|
||||
.n_aochan = 2,
|
||||
.ai_maxdata = 0xffff,
|
||||
.ao_maxdata = 0x0fff,
|
||||
.rangelist_ai = &range_pci9118dg_hr,
|
||||
.rangelist_ao = &range_bipolar10,
|
||||
.ai_ns_min = 10000,
|
||||
.ai_pacer_min = 40,
|
||||
.half_fifo_size = 512,
|
||||
},
|
||||
};
|
||||
|
||||
static struct comedi_driver adl_pci9118_driver = {
|
||||
.driver_name = "adl_pci9118",
|
||||
.module = THIS_MODULE,
|
||||
.attach = pci9118_attach,
|
||||
.detach = pci9118_detach,
|
||||
.num_names = ARRAY_SIZE(boardtypes),
|
||||
.board_name = &boardtypes[0].name,
|
||||
.offset = sizeof(struct boardtype),
|
||||
};
|
||||
|
||||
static int __devinit adl_pci9118_pci_probe(struct pci_dev *dev,
|
||||
const struct pci_device_id *ent)
|
||||
{
|
||||
return comedi_pci_auto_config(dev, &adl_pci9118_driver);
|
||||
}
|
||||
|
||||
static void __devexit adl_pci9118_pci_remove(struct pci_dev *dev)
|
||||
{
|
||||
comedi_pci_auto_unconfig(dev);
|
||||
}
|
||||
|
||||
static DEFINE_PCI_DEVICE_TABLE(adl_pci9118_pci_table) = {
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_AMCC, 0x80d9) },
|
||||
{ 0 }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(pci, adl_pci9118_pci_table);
|
||||
|
||||
static struct pci_driver adl_pci9118_pci_driver = {
|
||||
.name = "adl_pci9118",
|
||||
.id_table = adl_pci9118_pci_table,
|
||||
.probe = adl_pci9118_pci_probe,
|
||||
.remove = __devexit_p(adl_pci9118_pci_remove),
|
||||
};
|
||||
module_comedi_pci_driver(adl_pci9118_driver, adl_pci9118_pci_driver);
|
||||
|
||||
MODULE_AUTHOR("Comedi http://www.comedi.org");
|
||||
MODULE_DESCRIPTION("Comedi low-level driver");
|
||||
|
|
|
@ -125,24 +125,6 @@ struct adq12b_board {
|
|||
int do_chans;
|
||||
};
|
||||
|
||||
static const struct adq12b_board adq12b_boards[] = {
|
||||
{
|
||||
.name = "adq12b",
|
||||
.ai_se_chans = 16,
|
||||
.ai_diff_chans = 8,
|
||||
.ai_bits = 12,
|
||||
.di_chans = 5,
|
||||
.do_chans = 8}
|
||||
/* potentially, more adq-based deviced will be added */
|
||||
/*,
|
||||
.name = "adq12b",
|
||||
.ai_chans = 16, // this is just for reference, hardcoded again later
|
||||
.ai_bits = 12,
|
||||
.di_chans = 8,
|
||||
.do_chans = 5
|
||||
}*/
|
||||
};
|
||||
|
||||
#define thisboard ((const struct adq12b_board *)dev->board_ptr)
|
||||
|
||||
struct adq12b_private {
|
||||
|
@ -156,41 +138,88 @@ struct adq12b_private {
|
|||
#define devpriv ((struct adq12b_private *)dev->private)
|
||||
|
||||
/*
|
||||
* The struct comedi_driver structure tells the Comedi core module
|
||||
* which functions to call to configure/deconfigure (attach/detach)
|
||||
* the board, and also about the kernel module that contains
|
||||
* the device code.
|
||||
* "instructions" read/write data in "one-shot" or "software-triggered"
|
||||
* mode.
|
||||
*/
|
||||
static int adq12b_attach(struct comedi_device *dev,
|
||||
struct comedi_devconfig *it);
|
||||
static int adq12b_detach(struct comedi_device *dev);
|
||||
|
||||
static struct comedi_driver driver_adq12b = {
|
||||
.driver_name = "adq12b",
|
||||
.module = THIS_MODULE,
|
||||
.attach = adq12b_attach,
|
||||
.detach = adq12b_detach,
|
||||
.board_name = &adq12b_boards[0].name,
|
||||
.offset = sizeof(struct adq12b_board),
|
||||
.num_names = ARRAY_SIZE(adq12b_boards),
|
||||
};
|
||||
|
||||
static int adq12b_ai_rinsn(struct comedi_device *dev,
|
||||
struct comedi_subdevice *s, struct comedi_insn *insn,
|
||||
unsigned int *data);
|
||||
unsigned int *data)
|
||||
{
|
||||
int n, i;
|
||||
int range, channel;
|
||||
unsigned char hi, lo, status;
|
||||
|
||||
/* change channel and range only if it is different from the previous */
|
||||
range = CR_RANGE(insn->chanspec);
|
||||
channel = CR_CHAN(insn->chanspec);
|
||||
if (channel != devpriv->last_channel || range != devpriv->last_range) {
|
||||
outb((range << 4) | channel, dev->iobase + ADQ12B_CTREG);
|
||||
udelay(50); /* wait for the mux to settle */
|
||||
}
|
||||
|
||||
/* trigger conversion */
|
||||
status = inb(dev->iobase + ADQ12B_ADLOW);
|
||||
|
||||
/* convert n samples */
|
||||
for (n = 0; n < insn->n; n++) {
|
||||
|
||||
/* wait for end of conversion */
|
||||
i = 0;
|
||||
do {
|
||||
/* udelay(1); */
|
||||
status = inb(dev->iobase + ADQ12B_STINR);
|
||||
status = status & ADQ12B_EOC;
|
||||
} while (status == 0 && ++i < TIMEOUT);
|
||||
/* } while (++i < 10); */
|
||||
|
||||
/* read data */
|
||||
hi = inb(dev->iobase + ADQ12B_ADHIG);
|
||||
lo = inb(dev->iobase + ADQ12B_ADLOW);
|
||||
|
||||
/* printk("debug: chan=%d range=%d status=%d hi=%d lo=%d\n",
|
||||
channel, range, status, hi, lo); */
|
||||
data[n] = (hi << 8) | lo;
|
||||
|
||||
}
|
||||
|
||||
/* return the number of samples read/written */
|
||||
return n;
|
||||
}
|
||||
|
||||
static int adq12b_di_insn_bits(struct comedi_device *dev,
|
||||
struct comedi_subdevice *s,
|
||||
struct comedi_insn *insn, unsigned int *data);
|
||||
struct comedi_insn *insn, unsigned int *data)
|
||||
{
|
||||
|
||||
/* only bits 0-4 have information about digital inputs */
|
||||
data[1] = (inb(dev->iobase + ADQ12B_STINR) & (0x1f));
|
||||
|
||||
return 2;
|
||||
}
|
||||
|
||||
static int adq12b_do_insn_bits(struct comedi_device *dev,
|
||||
struct comedi_subdevice *s,
|
||||
struct comedi_insn *insn, unsigned int *data);
|
||||
struct comedi_insn *insn, unsigned int *data)
|
||||
{
|
||||
int channel;
|
||||
|
||||
for (channel = 0; channel < 8; channel++)
|
||||
if (((data[0] >> channel) & 0x01) != 0)
|
||||
outb((((data[1] >> channel) & 0x01) << 3) | channel,
|
||||
dev->iobase + ADQ12B_OUTBR);
|
||||
|
||||
/* store information to retrieve when asked for reading */
|
||||
if (data[0]) {
|
||||
devpriv->digital_state &= ~data[0];
|
||||
devpriv->digital_state |= (data[0] & data[1]);
|
||||
}
|
||||
|
||||
data[1] = devpriv->digital_state;
|
||||
|
||||
return 2;
|
||||
}
|
||||
|
||||
/*
|
||||
* Attach is called by the Comedi core to configure the driver
|
||||
* for a particular board. If you specified a board_name array
|
||||
* in the driver structure, dev->board_ptr contains that
|
||||
* address.
|
||||
*/
|
||||
static int adq12b_attach(struct comedi_device *dev, struct comedi_devconfig *it)
|
||||
{
|
||||
struct comedi_subdevice *s;
|
||||
|
@ -295,125 +324,34 @@ static int adq12b_attach(struct comedi_device *dev, struct comedi_devconfig *it)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* _detach is called to deconfigure a device. It should deallocate
|
||||
* resources.
|
||||
* This function is also called when _attach() fails, so it should be
|
||||
* careful not to release resources that were not necessarily
|
||||
* allocated by _attach(). dev->private and dev->subdevices are
|
||||
* deallocated automatically by the core.
|
||||
*/
|
||||
static int adq12b_detach(struct comedi_device *dev)
|
||||
static void adq12b_detach(struct comedi_device *dev)
|
||||
{
|
||||
if (dev->iobase)
|
||||
release_region(dev->iobase, ADQ12B_SIZE);
|
||||
|
||||
kfree(devpriv);
|
||||
|
||||
printk(KERN_INFO "comedi%d: adq12b: removed\n", dev->minor);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* "instructions" read/write data in "one-shot" or "software-triggered"
|
||||
* mode.
|
||||
*/
|
||||
static const struct adq12b_board adq12b_boards[] = {
|
||||
{
|
||||
.name = "adq12b",
|
||||
.ai_se_chans = 16,
|
||||
.ai_diff_chans = 8,
|
||||
.ai_bits = 12,
|
||||
.di_chans = 5,
|
||||
.do_chans = 8,
|
||||
},
|
||||
};
|
||||
|
||||
static int adq12b_ai_rinsn(struct comedi_device *dev,
|
||||
struct comedi_subdevice *s, struct comedi_insn *insn,
|
||||
unsigned int *data)
|
||||
{
|
||||
int n, i;
|
||||
int range, channel;
|
||||
unsigned char hi, lo, status;
|
||||
|
||||
/* change channel and range only if it is different from the previous */
|
||||
range = CR_RANGE(insn->chanspec);
|
||||
channel = CR_CHAN(insn->chanspec);
|
||||
if (channel != devpriv->last_channel || range != devpriv->last_range) {
|
||||
outb((range << 4) | channel, dev->iobase + ADQ12B_CTREG);
|
||||
udelay(50); /* wait for the mux to settle */
|
||||
}
|
||||
|
||||
/* trigger conversion */
|
||||
status = inb(dev->iobase + ADQ12B_ADLOW);
|
||||
|
||||
/* convert n samples */
|
||||
for (n = 0; n < insn->n; n++) {
|
||||
|
||||
/* wait for end of conversion */
|
||||
i = 0;
|
||||
do {
|
||||
/* udelay(1); */
|
||||
status = inb(dev->iobase + ADQ12B_STINR);
|
||||
status = status & ADQ12B_EOC;
|
||||
} while (status == 0 && ++i < TIMEOUT);
|
||||
/* } while (++i < 10); */
|
||||
|
||||
/* read data */
|
||||
hi = inb(dev->iobase + ADQ12B_ADHIG);
|
||||
lo = inb(dev->iobase + ADQ12B_ADLOW);
|
||||
|
||||
/* printk("debug: chan=%d range=%d status=%d hi=%d lo=%d\n",
|
||||
channel, range, status, hi, lo); */
|
||||
data[n] = (hi << 8) | lo;
|
||||
|
||||
}
|
||||
|
||||
/* return the number of samples read/written */
|
||||
return n;
|
||||
}
|
||||
|
||||
static int adq12b_di_insn_bits(struct comedi_device *dev,
|
||||
struct comedi_subdevice *s,
|
||||
struct comedi_insn *insn, unsigned int *data)
|
||||
{
|
||||
|
||||
/* only bits 0-4 have information about digital inputs */
|
||||
data[1] = (inb(dev->iobase + ADQ12B_STINR) & (0x1f));
|
||||
|
||||
return 2;
|
||||
}
|
||||
|
||||
static int adq12b_do_insn_bits(struct comedi_device *dev,
|
||||
struct comedi_subdevice *s,
|
||||
struct comedi_insn *insn, unsigned int *data)
|
||||
{
|
||||
int channel;
|
||||
|
||||
for (channel = 0; channel < 8; channel++)
|
||||
if (((data[0] >> channel) & 0x01) != 0)
|
||||
outb((((data[1] >> channel) & 0x01) << 3) | channel,
|
||||
dev->iobase + ADQ12B_OUTBR);
|
||||
|
||||
/* store information to retrieve when asked for reading */
|
||||
if (data[0]) {
|
||||
devpriv->digital_state &= ~data[0];
|
||||
devpriv->digital_state |= (data[0] & data[1]);
|
||||
}
|
||||
|
||||
data[1] = devpriv->digital_state;
|
||||
|
||||
return 2;
|
||||
}
|
||||
|
||||
/*
|
||||
* A convenient macro that defines init_module() and cleanup_module(),
|
||||
* as necessary.
|
||||
*/
|
||||
static int __init driver_adq12b_init_module(void)
|
||||
{
|
||||
return comedi_driver_register(&driver_adq12b);
|
||||
}
|
||||
|
||||
static void __exit driver_adq12b_cleanup_module(void)
|
||||
{
|
||||
comedi_driver_unregister(&driver_adq12b);
|
||||
}
|
||||
|
||||
module_init(driver_adq12b_init_module);
|
||||
module_exit(driver_adq12b_cleanup_module);
|
||||
static struct comedi_driver adq12b_driver = {
|
||||
.driver_name = "adq12b",
|
||||
.module = THIS_MODULE,
|
||||
.attach = adq12b_attach,
|
||||
.detach = adq12b_detach,
|
||||
.board_name = &adq12b_boards[0].name,
|
||||
.offset = sizeof(struct adq12b_board),
|
||||
.num_names = ARRAY_SIZE(adq12b_boards),
|
||||
};
|
||||
module_comedi_driver(adq12b_driver);
|
||||
|
||||
MODULE_AUTHOR("Comedi http://www.comedi.org");
|
||||
MODULE_DESCRIPTION("Comedi low-level driver");
|
||||
|
|
|
@ -191,10 +191,6 @@ static const struct comedi_lrange range_pci171x_da = { 2, {
|
|||
}
|
||||
};
|
||||
|
||||
static int pci1710_attach(struct comedi_device *dev,
|
||||
struct comedi_devconfig *it);
|
||||
static int pci1710_detach(struct comedi_device *dev);
|
||||
|
||||
struct boardtype {
|
||||
const char *name; /* board name */
|
||||
int device_id;
|
||||
|
@ -216,17 +212,6 @@ struct boardtype {
|
|||
unsigned int fifo_half_size; /* size of FIFO/2 */
|
||||
};
|
||||
|
||||
static DEFINE_PCI_DEVICE_TABLE(pci1710_pci_table) = {
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_ADVANTECH, 0x1710) },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_ADVANTECH, 0x1711) },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_ADVANTECH, 0x1713) },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_ADVANTECH, 0x1720) },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_ADVANTECH, 0x1731) },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(pci, pci1710_pci_table);
|
||||
|
||||
static const struct boardtype boardtypes[] = {
|
||||
{"pci1710", 0x1710,
|
||||
IORANGE_171x, 1, TYPE_PCI171X,
|
||||
|
@ -264,18 +249,6 @@ static const struct boardtype boardtypes[] = {
|
|||
{.name = DRV_NAME},
|
||||
};
|
||||
|
||||
#define n_boardtypes (sizeof(boardtypes)/sizeof(struct boardtype))
|
||||
|
||||
static struct comedi_driver driver_pci1710 = {
|
||||
.driver_name = DRV_NAME,
|
||||
.module = THIS_MODULE,
|
||||
.attach = pci1710_attach,
|
||||
.detach = pci1710_detach,
|
||||
.num_names = n_boardtypes,
|
||||
.board_name = &boardtypes[0].name,
|
||||
.offset = sizeof(struct boardtype),
|
||||
};
|
||||
|
||||
struct pci1710_private {
|
||||
struct pci_dev *pcidev; /* ptr to PCI device */
|
||||
char valid; /* card is usable */
|
||||
|
@ -676,7 +649,9 @@ static void interrupt_pci1710_every_sample(void *d)
|
|||
s->async->buf_int_count, s->async->buf_int_ptr,
|
||||
s->async->buf_user_count, s->async->buf_user_ptr);
|
||||
DPRINTK("adv_pci1710 EDBG: EOS2\n");
|
||||
if ((!devpriv->neverending_ai) && (devpriv->ai_act_scan >= devpriv->ai_scans)) { /* all data sampled */
|
||||
if ((!devpriv->neverending_ai) &&
|
||||
(devpriv->ai_act_scan >= devpriv->ai_scans)) {
|
||||
/* all data sampled */
|
||||
pci171x_ai_cancel(dev, s);
|
||||
s->async->events |= COMEDI_CB_EOA;
|
||||
comedi_event(dev, s);
|
||||
|
@ -804,8 +779,8 @@ static irqreturn_t interrupt_service_pci1710(int irq, void *d)
|
|||
irq);
|
||||
if (!dev->attached) /* is device attached? */
|
||||
return IRQ_NONE; /* no, exit */
|
||||
|
||||
if (!(inw(dev->iobase + PCI171x_STATUS) & Status_IRQ)) /* is this interrupt from our board? */
|
||||
/* is this interrupt from our board? */
|
||||
if (!(inw(dev->iobase + PCI171x_STATUS) & Status_IRQ))
|
||||
return IRQ_NONE; /* no, exit */
|
||||
|
||||
DPRINTK("adv_pci1710 EDBG: interrupt_service_pci1710() ST: %4x\n",
|
||||
|
@ -814,7 +789,7 @@ static irqreturn_t interrupt_service_pci1710(int irq, void *d)
|
|||
if (devpriv->ai_et) { /* Switch from initial TRIG_EXT to TRIG_xxx. */
|
||||
devpriv->ai_et = 0;
|
||||
devpriv->CntrlReg &= Control_CNT0;
|
||||
devpriv->CntrlReg |= Control_SW; /* set software trigger */
|
||||
devpriv->CntrlReg |= Control_SW; /* set software trigger */
|
||||
outw(devpriv->CntrlReg, dev->iobase + PCI171x_CONTROL);
|
||||
devpriv->CntrlReg = devpriv->ai_et_CntrlReg;
|
||||
outb(0, dev->iobase + PCI171x_CLRFIFO);
|
||||
|
@ -865,7 +840,8 @@ static int pci171x_ai_docmd_and_mode(int mode, struct comedi_device *dev,
|
|||
devpriv->neverending_ai = 0;
|
||||
|
||||
devpriv->CntrlReg &= Control_CNT0;
|
||||
if ((devpriv->ai_flags & TRIG_WAKE_EOS)) { /* don't we want wake up every scan? devpriv->ai_eos=1; */
|
||||
/* don't we want wake up every scan? devpriv->ai_eos=1; */
|
||||
if ((devpriv->ai_flags & TRIG_WAKE_EOS)) {
|
||||
devpriv->ai_eos = 1;
|
||||
} else {
|
||||
devpriv->CntrlReg |= Control_ONEFH;
|
||||
|
@ -982,13 +958,13 @@ static int pci171x_ai_cmdtest(struct comedi_device *dev,
|
|||
#ifdef PCI171X_EXTDEBUG
|
||||
pci171x_cmdtest_out(1, cmd);
|
||||
#endif
|
||||
DPRINTK
|
||||
("adv_pci1710 EDBG: BGN: pci171x_ai_cmdtest(...) err=%d ret=1\n",
|
||||
err);
|
||||
DPRINTK(
|
||||
"adv_pci1710 EDBG: BGN: pci171x_ai_cmdtest(...) err=%d ret=1\n",
|
||||
err);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* step 2: make sure trigger sources are unique and mutually compatible */
|
||||
/* step2: make sure trigger srcs are unique and mutually compatible */
|
||||
|
||||
if (cmd->start_src != TRIG_NOW && cmd->start_src != TRIG_EXT) {
|
||||
cmd->start_src = TRIG_NOW;
|
||||
|
@ -1015,9 +991,9 @@ static int pci171x_ai_cmdtest(struct comedi_device *dev,
|
|||
#ifdef PCI171X_EXTDEBUG
|
||||
pci171x_cmdtest_out(2, cmd);
|
||||
#endif
|
||||
DPRINTK
|
||||
("adv_pci1710 EDBG: BGN: pci171x_ai_cmdtest(...) err=%d ret=2\n",
|
||||
err);
|
||||
DPRINTK(
|
||||
"adv_pci1710 EDBG: BGN: pci171x_ai_cmdtest(...) err=%d ret=2\n",
|
||||
err);
|
||||
return 2;
|
||||
}
|
||||
|
||||
|
@ -1065,9 +1041,9 @@ static int pci171x_ai_cmdtest(struct comedi_device *dev,
|
|||
#ifdef PCI171X_EXTDEBUG
|
||||
pci171x_cmdtest_out(3, cmd);
|
||||
#endif
|
||||
DPRINTK
|
||||
("adv_pci1710 EDBG: BGN: pci171x_ai_cmdtest(...) err=%d ret=3\n",
|
||||
err);
|
||||
DPRINTK(
|
||||
"adv_pci1710 EDBG: BGN: pci171x_ai_cmdtest(...) err=%d ret=3\n",
|
||||
err);
|
||||
return 3;
|
||||
}
|
||||
|
||||
|
@ -1160,48 +1136,41 @@ static int check_channel_list(struct comedi_device *dev,
|
|||
return 0;
|
||||
}
|
||||
|
||||
if (n_chan > 1) {
|
||||
chansegment[0] = chanlist[0]; /* first channel is every time ok */
|
||||
for (i = 1, seglen = 1; i < n_chan; i++, seglen++) { /* build part of chanlist */
|
||||
/* printk("%d. %d %d\n",i,CR_CHAN(chanlist[i]),CR_RANGE(chanlist[i])); */
|
||||
if (chanlist[0] == chanlist[i])
|
||||
break; /* we detect loop, this must by finish */
|
||||
if (CR_CHAN(chanlist[i]) & 1) /* odd channel cann't by differencial */
|
||||
if (CR_AREF(chanlist[i]) == AREF_DIFF) {
|
||||
comedi_error(dev,
|
||||
"Odd channel can't be differential input!\n");
|
||||
return 0;
|
||||
}
|
||||
nowmustbechan =
|
||||
(CR_CHAN(chansegment[i - 1]) + 1) % s->n_chan;
|
||||
if (CR_AREF(chansegment[i - 1]) == AREF_DIFF)
|
||||
nowmustbechan = (nowmustbechan + 1) % s->n_chan;
|
||||
if (nowmustbechan != CR_CHAN(chanlist[i])) { /* channel list isn't continuous :-( */
|
||||
printk
|
||||
("channel list must be continuous! chanlist[%i]=%d but must be %d or %d!\n",
|
||||
i, CR_CHAN(chanlist[i]), nowmustbechan,
|
||||
CR_CHAN(chanlist[0]));
|
||||
return 0;
|
||||
}
|
||||
chansegment[i] = chanlist[i]; /* well, this is next correct channel in list */
|
||||
}
|
||||
if (n_chan == 1)
|
||||
return 1; /* seglen=1 */
|
||||
|
||||
for (i = 0, segpos = 0; i < n_chan; i++) { /* check whole chanlist */
|
||||
/* printk("%d %d=%d %d\n",CR_CHAN(chansegment[i%seglen]),CR_RANGE(chansegment[i%seglen]),CR_CHAN(chanlist[i]),CR_RANGE(chanlist[i])); */
|
||||
if (chanlist[i] != chansegment[i % seglen]) {
|
||||
printk
|
||||
("bad channel, reference or range number! chanlist[%i]=%d,%d,%d and not %d,%d,%d!\n",
|
||||
i, CR_CHAN(chansegment[i]),
|
||||
CR_RANGE(chansegment[i]),
|
||||
CR_AREF(chansegment[i]),
|
||||
CR_CHAN(chanlist[i % seglen]),
|
||||
CR_RANGE(chanlist[i % seglen]),
|
||||
CR_AREF(chansegment[i % seglen]));
|
||||
return 0; /* chan/gain list is strange */
|
||||
}
|
||||
chansegment[0] = chanlist[0]; /* first channel is every time ok */
|
||||
for (i = 1, seglen = 1; i < n_chan; i++, seglen++) {
|
||||
if (chanlist[0] == chanlist[i])
|
||||
break; /* we detected a loop, stop */
|
||||
if ((CR_CHAN(chanlist[i]) & 1) &&
|
||||
(CR_AREF(chanlist[i]) == AREF_DIFF)) {
|
||||
comedi_error(dev, "Odd channel cannot be differential input!\n");
|
||||
return 0;
|
||||
}
|
||||
nowmustbechan = (CR_CHAN(chansegment[i - 1]) + 1) % s->n_chan;
|
||||
if (CR_AREF(chansegment[i - 1]) == AREF_DIFF)
|
||||
nowmustbechan = (nowmustbechan + 1) % s->n_chan;
|
||||
if (nowmustbechan != CR_CHAN(chanlist[i])) {
|
||||
printk("channel list must be continuous! chanlist[%i]=%d but must be %d or %d!\n",
|
||||
i, CR_CHAN(chanlist[i]), nowmustbechan,
|
||||
CR_CHAN(chanlist[0]));
|
||||
return 0;
|
||||
}
|
||||
chansegment[i] = chanlist[i]; /* next correct channel in list */
|
||||
}
|
||||
|
||||
for (i = 0, segpos = 0; i < n_chan; i++) {
|
||||
if (chanlist[i] != chansegment[i % seglen]) {
|
||||
printk("bad channel, reference or range number! chanlist[%i]=%d,%d,%d and not %d,%d,%d!\n",
|
||||
i, CR_CHAN(chansegment[i]),
|
||||
CR_RANGE(chansegment[i]),
|
||||
CR_AREF(chansegment[i]),
|
||||
CR_CHAN(chanlist[i % seglen]),
|
||||
CR_RANGE(chanlist[i % seglen]),
|
||||
CR_AREF(chansegment[i % seglen]));
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
seglen = 1;
|
||||
}
|
||||
return seglen;
|
||||
}
|
||||
|
@ -1221,14 +1190,14 @@ static void setup_channel_list(struct comedi_device *dev,
|
|||
DPRINTK("SegLen: %d\n", seglen);
|
||||
for (i = 0; i < seglen; i++) { /* store range list to card */
|
||||
chanprog = muxonechan[CR_CHAN(chanlist[i])];
|
||||
outw(chanprog, dev->iobase + PCI171x_MUX); /* select channel */
|
||||
outw(chanprog, dev->iobase + PCI171x_MUX); /* select channel */
|
||||
range = this_board->rangecode_ai[CR_RANGE(chanlist[i])];
|
||||
if (CR_AREF(chanlist[i]) == AREF_DIFF)
|
||||
range |= 0x0020;
|
||||
outw(range, dev->iobase + PCI171x_RANGE); /* select gain */
|
||||
outw(range, dev->iobase + PCI171x_RANGE); /* select gain */
|
||||
#ifdef PCI171x_PARANOIDCHECK
|
||||
devpriv->act_chanlist[i] =
|
||||
(CR_CHAN(chanlist[i]) << 12) & 0xf000;
|
||||
(CR_CHAN(chanlist[i]) << 12) & 0xf000;
|
||||
#endif
|
||||
DPRINTK("GS: %2d. [%4x]=%4x %4x\n", i, chanprog, range,
|
||||
devpriv->act_chanlist[i]);
|
||||
|
@ -1236,13 +1205,14 @@ static void setup_channel_list(struct comedi_device *dev,
|
|||
#ifdef PCI171x_PARANOIDCHECK
|
||||
for ( ; i < n_chan; i++) { /* store remainder of channel list */
|
||||
devpriv->act_chanlist[i] =
|
||||
(CR_CHAN(chanlist[i]) << 12) & 0xf000;
|
||||
(CR_CHAN(chanlist[i]) << 12) & 0xf000;
|
||||
}
|
||||
#endif
|
||||
|
||||
devpriv->ai_et_MuxVal =
|
||||
CR_CHAN(chanlist[0]) | (CR_CHAN(chanlist[seglen - 1]) << 8);
|
||||
outw(devpriv->ai_et_MuxVal, dev->iobase + PCI171x_MUX); /* select channel interval to scan */
|
||||
CR_CHAN(chanlist[0]) | (CR_CHAN(chanlist[seglen - 1]) << 8);
|
||||
/* select channel interval to scan */
|
||||
outw(devpriv->ai_et_MuxVal, dev->iobase + PCI171x_MUX);
|
||||
DPRINTK("MUX: %4x L%4x.H%4x\n",
|
||||
CR_CHAN(chanlist[0]) | (CR_CHAN(chanlist[seglen - 1]) << 8),
|
||||
CR_CHAN(chanlist[0]), CR_CHAN(chanlist[seglen - 1]));
|
||||
|
@ -1365,9 +1335,6 @@ static int pci1710_reset(struct comedi_device *dev)
|
|||
DPRINTK("adv_pci1710 EDBG: END: pci1710_reset(...)\n");
|
||||
}
|
||||
|
||||
/*
|
||||
==============================================================================
|
||||
*/
|
||||
static int pci1710_attach(struct comedi_device *dev,
|
||||
struct comedi_devconfig *it)
|
||||
{
|
||||
|
@ -1398,13 +1365,13 @@ static int pci1710_attach(struct comedi_device *dev,
|
|||
while (NULL != (pcidev = pci_get_device(PCI_VENDOR_ID_ADVANTECH,
|
||||
PCI_ANY_ID, pcidev))) {
|
||||
if (strcmp(this_board->name, DRV_NAME) == 0) {
|
||||
for (i = 0; i < n_boardtypes; ++i) {
|
||||
for (i = 0; i < ARRAY_SIZE(boardtypes); ++i) {
|
||||
if (pcidev->device == boardtypes[i].device_id) {
|
||||
board_index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i == n_boardtypes)
|
||||
if (i == ARRAY_SIZE(boardtypes))
|
||||
continue;
|
||||
} else {
|
||||
if (pcidev->device != boardtypes[board_index].device_id)
|
||||
|
@ -1584,12 +1551,8 @@ static int pci1710_attach(struct comedi_device *dev,
|
|||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
==============================================================================
|
||||
*/
|
||||
static int pci1710_detach(struct comedi_device *dev)
|
||||
static void pci1710_detach(struct comedi_device *dev)
|
||||
{
|
||||
|
||||
if (dev->private) {
|
||||
if (devpriv->valid)
|
||||
pci1710_reset(dev);
|
||||
|
@ -1598,57 +1561,49 @@ static int pci1710_detach(struct comedi_device *dev)
|
|||
if (devpriv->pcidev) {
|
||||
if (dev->iobase)
|
||||
comedi_pci_disable(devpriv->pcidev);
|
||||
|
||||
pci_dev_put(devpriv->pcidev);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
==============================================================================
|
||||
*/
|
||||
static int __devinit driver_pci1710_pci_probe(struct pci_dev *dev,
|
||||
const struct pci_device_id *ent)
|
||||
static struct comedi_driver adv_pci1710_driver = {
|
||||
.driver_name = "adv_pci1710",
|
||||
.module = THIS_MODULE,
|
||||
.attach = pci1710_attach,
|
||||
.detach = pci1710_detach,
|
||||
.num_names = ARRAY_SIZE(boardtypes),
|
||||
.board_name = &boardtypes[0].name,
|
||||
.offset = sizeof(struct boardtype),
|
||||
};
|
||||
|
||||
static int __devinit adv_pci1710_pci_probe(struct pci_dev *dev,
|
||||
const struct pci_device_id *ent)
|
||||
{
|
||||
return comedi_pci_auto_config(dev, driver_pci1710.driver_name);
|
||||
return comedi_pci_auto_config(dev, &adv_pci1710_driver);
|
||||
}
|
||||
|
||||
static void __devexit driver_pci1710_pci_remove(struct pci_dev *dev)
|
||||
static void __devexit adv_pci1710_pci_remove(struct pci_dev *dev)
|
||||
{
|
||||
comedi_pci_auto_unconfig(dev);
|
||||
}
|
||||
|
||||
static struct pci_driver driver_pci1710_pci_driver = {
|
||||
.id_table = pci1710_pci_table,
|
||||
.probe = &driver_pci1710_pci_probe,
|
||||
.remove = __devexit_p(&driver_pci1710_pci_remove)
|
||||
static DEFINE_PCI_DEVICE_TABLE(adv_pci1710_pci_table) = {
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_ADVANTECH, 0x1710) },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_ADVANTECH, 0x1711) },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_ADVANTECH, 0x1713) },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_ADVANTECH, 0x1720) },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_ADVANTECH, 0x1731) },
|
||||
{ 0 }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(pci, adv_pci1710_pci_table);
|
||||
|
||||
static int __init driver_pci1710_init_module(void)
|
||||
{
|
||||
int retval;
|
||||
|
||||
retval = comedi_driver_register(&driver_pci1710);
|
||||
if (retval < 0)
|
||||
return retval;
|
||||
|
||||
driver_pci1710_pci_driver.name = (char *)driver_pci1710.driver_name;
|
||||
return pci_register_driver(&driver_pci1710_pci_driver);
|
||||
}
|
||||
|
||||
static void __exit driver_pci1710_cleanup_module(void)
|
||||
{
|
||||
pci_unregister_driver(&driver_pci1710_pci_driver);
|
||||
comedi_driver_unregister(&driver_pci1710);
|
||||
}
|
||||
|
||||
module_init(driver_pci1710_init_module);
|
||||
module_exit(driver_pci1710_cleanup_module);
|
||||
/*
|
||||
==============================================================================
|
||||
*/
|
||||
static struct pci_driver adv_pci1710_pci_driver = {
|
||||
.name = "adv_pci1710",
|
||||
.id_table = adv_pci1710_pci_table,
|
||||
.probe = adv_pci1710_pci_probe,
|
||||
.remove = __devexit_p(adv_pci1710_pci_remove),
|
||||
};
|
||||
module_comedi_pci_driver(adv_pci1710_driver, adv_pci1710_pci_driver);
|
||||
|
||||
MODULE_AUTHOR("Comedi http://www.comedi.org");
|
||||
MODULE_DESCRIPTION("Comedi low-level driver");
|
||||
|
|
|
@ -150,36 +150,6 @@ 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
|
||||
*/
|
||||
static DEFINE_PCI_DEVICE_TABLE(pci1723_pci_table) = {
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_ADVANTECH, 0x1723) },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(pci, pci1723_pci_table);
|
||||
|
||||
/*
|
||||
* The struct comedi_driver structure tells the Comedi core module
|
||||
* which functions to call to configure/deconfigure (attach/detach)
|
||||
* the board, and also about the kernel module that contains
|
||||
* the device code.
|
||||
*/
|
||||
static int pci1723_attach(struct comedi_device *dev,
|
||||
struct comedi_devconfig *it);
|
||||
static int pci1723_detach(struct comedi_device *dev);
|
||||
|
||||
#define n_boardtypes (sizeof(boardtypes)/sizeof(struct pci1723_board))
|
||||
|
||||
static struct comedi_driver driver_pci1723 = {
|
||||
.driver_name = "adv_pci1723",
|
||||
.module = THIS_MODULE,
|
||||
.attach = pci1723_attach,
|
||||
.detach = pci1723_detach,
|
||||
};
|
||||
|
||||
/* This structure is for data unique to this hardware driver. */
|
||||
struct pci1723_private {
|
||||
int valid; /* card is usable; */
|
||||
|
@ -319,10 +289,6 @@ static int pci1723_dio_insn_bits(struct comedi_device *dev,
|
|||
return 2;
|
||||
}
|
||||
|
||||
/*
|
||||
* Attach is called by the Comedi core to configure the driver
|
||||
* for a pci1723 board.
|
||||
*/
|
||||
static int pci1723_attach(struct comedi_device *dev,
|
||||
struct comedi_devconfig *it)
|
||||
{
|
||||
|
@ -465,73 +431,50 @@ static int pci1723_attach(struct comedi_device *dev,
|
|||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* _detach is called to deconfigure a device. It should deallocate
|
||||
* resources.
|
||||
* This function is also called when _attach() fails, so it should be
|
||||
* careful not to release resources that were not necessarily
|
||||
* allocated by _attach(). dev->private and dev->subdevices are
|
||||
* deallocated automatically by the core.
|
||||
*/
|
||||
static int pci1723_detach(struct comedi_device *dev)
|
||||
static void pci1723_detach(struct comedi_device *dev)
|
||||
{
|
||||
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)
|
||||
comedi_pci_disable(devpriv->pcidev);
|
||||
pci_dev_put(devpriv->pcidev);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* A convenient macro that defines init_module() and cleanup_module(),
|
||||
* as necessary.
|
||||
*/
|
||||
static int __devinit driver_pci1723_pci_probe(struct pci_dev *dev,
|
||||
const struct pci_device_id *ent)
|
||||
static struct comedi_driver adv_pci1723_driver = {
|
||||
.driver_name = "adv_pci1723",
|
||||
.module = THIS_MODULE,
|
||||
.attach = pci1723_attach,
|
||||
.detach = pci1723_detach,
|
||||
};
|
||||
|
||||
static int __devinit adv_pci1723_pci_probe(struct pci_dev *dev,
|
||||
const struct pci_device_id *ent)
|
||||
{
|
||||
return comedi_pci_auto_config(dev, driver_pci1723.driver_name);
|
||||
return comedi_pci_auto_config(dev, &adv_pci1723_driver);
|
||||
}
|
||||
|
||||
static void __devexit driver_pci1723_pci_remove(struct pci_dev *dev)
|
||||
static void __devexit adv_pci1723_pci_remove(struct pci_dev *dev)
|
||||
{
|
||||
comedi_pci_auto_unconfig(dev);
|
||||
}
|
||||
|
||||
static struct pci_driver driver_pci1723_pci_driver = {
|
||||
.id_table = pci1723_pci_table,
|
||||
.probe = &driver_pci1723_pci_probe,
|
||||
.remove = __devexit_p(&driver_pci1723_pci_remove)
|
||||
static DEFINE_PCI_DEVICE_TABLE(adv_pci1723_pci_table) = {
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_ADVANTECH, 0x1723) },
|
||||
{ 0 }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(pci, adv_pci1723_pci_table);
|
||||
|
||||
static int __init driver_pci1723_init_module(void)
|
||||
{
|
||||
int retval;
|
||||
|
||||
retval = comedi_driver_register(&driver_pci1723);
|
||||
if (retval < 0)
|
||||
return retval;
|
||||
|
||||
driver_pci1723_pci_driver.name = (char *)driver_pci1723.driver_name;
|
||||
return pci_register_driver(&driver_pci1723_pci_driver);
|
||||
}
|
||||
|
||||
static void __exit driver_pci1723_cleanup_module(void)
|
||||
{
|
||||
pci_unregister_driver(&driver_pci1723_pci_driver);
|
||||
comedi_driver_unregister(&driver_pci1723);
|
||||
}
|
||||
|
||||
module_init(driver_pci1723_init_module);
|
||||
module_exit(driver_pci1723_cleanup_module);
|
||||
static struct pci_driver adv_pci1723_pci_driver = {
|
||||
.name = "adv_pci1723",
|
||||
.id_table = adv_pci1723_pci_table,
|
||||
.probe = adv_pci1723_pci_probe,
|
||||
.remove = __devexit_p(adv_pci1723_pci_remove),
|
||||
};
|
||||
module_comedi_pci_driver(adv_pci1723_driver, adv_pci1723_pci_driver);
|
||||
|
||||
MODULE_AUTHOR("Comedi http://www.comedi.org");
|
||||
MODULE_DESCRIPTION("Comedi low-level driver");
|
||||
|
|
|
@ -237,10 +237,6 @@ enum hw_io_access {
|
|||
|
||||
#define OMBCMD_RETRY 0x03 /* 3 times try request before error */
|
||||
|
||||
static int pci_dio_attach(struct comedi_device *dev,
|
||||
struct comedi_devconfig *it);
|
||||
static int pci_dio_detach(struct comedi_device *dev);
|
||||
|
||||
struct diosubd_data {
|
||||
int chans; /* num of chans */
|
||||
int addr; /* PCI address ofset */
|
||||
|
@ -263,26 +259,6 @@ struct dio_boardtype {
|
|||
enum hw_io_access io_access;
|
||||
};
|
||||
|
||||
static DEFINE_PCI_DEVICE_TABLE(pci_dio_pci_table) = {
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_ADVANTECH, 0x1730) },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_ADVANTECH, 0x1733) },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_ADVANTECH, 0x1734) },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_ADVANTECH, 0x1735) },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_ADVANTECH, 0x1736) },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_ADVANTECH, 0x1739) },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_ADVANTECH, 0x1750) },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_ADVANTECH, 0x1751) },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_ADVANTECH, 0x1752) },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_ADVANTECH, 0x1753) },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_ADVANTECH, 0x1754) },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_ADVANTECH, 0x1756) },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_ADVANTECH, 0x1760) },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_ADVANTECH, 0x1762) },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(pci, pci_dio_pci_table);
|
||||
|
||||
static const struct dio_boardtype boardtypes[] = {
|
||||
{"pci1730", PCI_VENDOR_ID_ADVANTECH, 0x1730, PCIDIO_MAINREG,
|
||||
TYPE_PCI1730,
|
||||
|
@ -406,15 +382,6 @@ static const struct dio_boardtype boardtypes[] = {
|
|||
IO_16b}
|
||||
};
|
||||
|
||||
#define n_boardtypes (sizeof(boardtypes)/sizeof(struct dio_boardtype))
|
||||
|
||||
static struct comedi_driver driver_pci_dio = {
|
||||
.driver_name = "adv_pci_dio",
|
||||
.module = THIS_MODULE,
|
||||
.attach = pci_dio_attach,
|
||||
.detach = pci_dio_detach
|
||||
};
|
||||
|
||||
struct pci_dio_private {
|
||||
struct pci_dio_private *prev; /* previous private struct */
|
||||
struct pci_dio_private *next; /* next private struct */
|
||||
|
@ -1116,9 +1083,6 @@ static int CheckAndAllocCard(struct comedi_device *dev,
|
|||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
==============================================================================
|
||||
*/
|
||||
static int pci_dio_attach(struct comedi_device *dev,
|
||||
struct comedi_devconfig *it)
|
||||
{
|
||||
|
@ -1134,7 +1098,7 @@ static int pci_dio_attach(struct comedi_device *dev,
|
|||
|
||||
for_each_pci_dev(pcidev) {
|
||||
/* loop through cards supported by this driver */
|
||||
for (i = 0; i < n_boardtypes; ++i) {
|
||||
for (i = 0; i < ARRAY_SIZE(boardtypes); ++i) {
|
||||
if (boardtypes[i].vendor_id != pcidev->vendor)
|
||||
continue;
|
||||
if (boardtypes[i].device_id != pcidev->device)
|
||||
|
@ -1162,7 +1126,7 @@ static int pci_dio_attach(struct comedi_device *dev,
|
|||
return -EIO;
|
||||
}
|
||||
|
||||
if (comedi_pci_enable(pcidev, driver_pci_dio.driver_name)) {
|
||||
if (comedi_pci_enable(pcidev, dev->driver->driver_name)) {
|
||||
dev_err(dev->hw_dev, "Error: Can't enable PCI device and request regions!\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
@ -1246,10 +1210,7 @@ static int pci_dio_attach(struct comedi_device *dev,
|
|||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
==============================================================================
|
||||
*/
|
||||
static int pci_dio_detach(struct comedi_device *dev)
|
||||
static void pci_dio_detach(struct comedi_device *dev)
|
||||
{
|
||||
int i, j;
|
||||
struct comedi_subdevice *s;
|
||||
|
@ -1258,20 +1219,14 @@ static int pci_dio_detach(struct comedi_device *dev)
|
|||
if (dev->private) {
|
||||
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)
|
||||
subdev++;
|
||||
|
||||
}
|
||||
for (i = 0; i < MAX_DO_SUBDEVS; i++) {
|
||||
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++) {
|
||||
|
@ -1280,82 +1235,73 @@ static int pci_dio_detach(struct comedi_device *dev)
|
|||
subdev++;
|
||||
}
|
||||
}
|
||||
|
||||
if (this_board->boardid.chans)
|
||||
subdev++;
|
||||
|
||||
for (i = 0; i < MAX_8254_SUBDEVS; i++)
|
||||
if (this_board->s8254[i].chans)
|
||||
subdev++;
|
||||
|
||||
for (i = 0; i < dev->n_subdevices; i++) {
|
||||
s = dev->subdevices + i;
|
||||
s->private = NULL;
|
||||
}
|
||||
|
||||
if (devpriv->pcidev) {
|
||||
if (dev->iobase)
|
||||
comedi_pci_disable(devpriv->pcidev);
|
||||
|
||||
pci_dev_put(devpriv->pcidev);
|
||||
}
|
||||
|
||||
if (devpriv->prev)
|
||||
devpriv->prev->next = devpriv->next;
|
||||
else
|
||||
pci_priv = devpriv->next;
|
||||
|
||||
if (devpriv->next)
|
||||
devpriv->next->prev = devpriv->prev;
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
==============================================================================
|
||||
*/
|
||||
static int __devinit driver_pci_dio_pci_probe(struct pci_dev *dev,
|
||||
const struct pci_device_id *ent)
|
||||
static struct comedi_driver adv_pci_dio_driver = {
|
||||
.driver_name = "adv_pci_dio",
|
||||
.module = THIS_MODULE,
|
||||
.attach = pci_dio_attach,
|
||||
.detach = pci_dio_detach
|
||||
};
|
||||
|
||||
static int __devinit adv_pci_dio_pci_probe(struct pci_dev *dev,
|
||||
const struct pci_device_id *ent)
|
||||
{
|
||||
return comedi_pci_auto_config(dev, driver_pci_dio.driver_name);
|
||||
return comedi_pci_auto_config(dev, &adv_pci_dio_driver);
|
||||
}
|
||||
|
||||
static void __devexit driver_pci_dio_pci_remove(struct pci_dev *dev)
|
||||
static void __devexit adv_pci_dio_pci_remove(struct pci_dev *dev)
|
||||
{
|
||||
comedi_pci_auto_unconfig(dev);
|
||||
}
|
||||
|
||||
static struct pci_driver driver_pci_dio_pci_driver = {
|
||||
.id_table = pci_dio_pci_table,
|
||||
.probe = &driver_pci_dio_pci_probe,
|
||||
.remove = __devexit_p(&driver_pci_dio_pci_remove)
|
||||
static DEFINE_PCI_DEVICE_TABLE(adv_pci_dio_pci_table) = {
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_ADVANTECH, 0x1730) },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_ADVANTECH, 0x1733) },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_ADVANTECH, 0x1734) },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_ADVANTECH, 0x1735) },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_ADVANTECH, 0x1736) },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_ADVANTECH, 0x1739) },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_ADVANTECH, 0x1750) },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_ADVANTECH, 0x1751) },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_ADVANTECH, 0x1752) },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_ADVANTECH, 0x1753) },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_ADVANTECH, 0x1754) },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_ADVANTECH, 0x1756) },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_ADVANTECH, 0x1760) },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_ADVANTECH, 0x1762) },
|
||||
{ 0 }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(pci, adv_pci_dio_pci_table);
|
||||
|
||||
static int __init driver_pci_dio_init_module(void)
|
||||
{
|
||||
int retval;
|
||||
|
||||
retval = comedi_driver_register(&driver_pci_dio);
|
||||
if (retval < 0)
|
||||
return retval;
|
||||
|
||||
driver_pci_dio_pci_driver.name = (char *)driver_pci_dio.driver_name;
|
||||
return pci_register_driver(&driver_pci_dio_pci_driver);
|
||||
}
|
||||
|
||||
static void __exit driver_pci_dio_cleanup_module(void)
|
||||
{
|
||||
pci_unregister_driver(&driver_pci_dio_pci_driver);
|
||||
comedi_driver_unregister(&driver_pci_dio);
|
||||
}
|
||||
|
||||
module_init(driver_pci_dio_init_module);
|
||||
module_exit(driver_pci_dio_cleanup_module);
|
||||
/*
|
||||
==============================================================================
|
||||
*/
|
||||
static struct pci_driver adv_pci_dio_pci_driver = {
|
||||
.name = "adv_pci_dio",
|
||||
.id_table = adv_pci_dio_pci_table,
|
||||
.probe = adv_pci_dio_pci_probe,
|
||||
.remove = __devexit_p(adv_pci_dio_pci_remove),
|
||||
};
|
||||
module_comedi_pci_driver(adv_pci_dio_driver, adv_pci_dio_pci_driver);
|
||||
|
||||
MODULE_AUTHOR("Comedi http://www.comedi.org");
|
||||
MODULE_DESCRIPTION("Comedi low-level driver");
|
||||
|
|
|
@ -209,36 +209,23 @@ static int aio_aio12_8_attach(struct comedi_device *dev,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int aio_aio12_8_detach(struct comedi_device *dev)
|
||||
static void aio_aio12_8_detach(struct comedi_device *dev)
|
||||
{
|
||||
subdev_8255_cleanup(dev, &dev->subdevices[2]);
|
||||
if (dev->iobase)
|
||||
release_region(dev->iobase, 24);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct comedi_driver driver_aio_aio12_8 = {
|
||||
.driver_name = "aio_aio12_8",
|
||||
.module = THIS_MODULE,
|
||||
.attach = aio_aio12_8_attach,
|
||||
.detach = aio_aio12_8_detach,
|
||||
.board_name = &board_types[0].name,
|
||||
.num_names = 1,
|
||||
.offset = sizeof(struct aio12_8_boardtype),
|
||||
static struct comedi_driver aio_aio12_8_driver = {
|
||||
.driver_name = "aio_aio12_8",
|
||||
.module = THIS_MODULE,
|
||||
.attach = aio_aio12_8_attach,
|
||||
.detach = aio_aio12_8_detach,
|
||||
.board_name = &board_types[0].name,
|
||||
.num_names = ARRAY_SIZE(board_types),
|
||||
.offset = sizeof(struct aio12_8_boardtype),
|
||||
};
|
||||
|
||||
static int __init driver_aio_aio12_8_init_module(void)
|
||||
{
|
||||
return comedi_driver_register(&driver_aio_aio12_8);
|
||||
}
|
||||
|
||||
static void __exit driver_aio_aio12_8_cleanup_module(void)
|
||||
{
|
||||
comedi_driver_unregister(&driver_aio_aio12_8);
|
||||
}
|
||||
|
||||
module_init(driver_aio_aio12_8_init_module);
|
||||
module_exit(driver_aio_aio12_8_cleanup_module);
|
||||
module_comedi_driver(aio_aio12_8_driver);
|
||||
|
||||
MODULE_AUTHOR("Comedi http://www.comedi.org");
|
||||
MODULE_DESCRIPTION("Comedi low-level driver");
|
||||
|
|
|
@ -67,30 +67,41 @@ struct aio_iiro_16_private {
|
|||
|
||||
#define devpriv ((struct aio_iiro_16_private *) dev->private)
|
||||
|
||||
static int aio_iiro_16_attach(struct comedi_device *dev,
|
||||
struct comedi_devconfig *it);
|
||||
static int aio_iiro_16_dio_insn_bits_write(struct comedi_device *dev,
|
||||
struct comedi_subdevice *s,
|
||||
struct comedi_insn *insn,
|
||||
unsigned int *data)
|
||||
{
|
||||
if (insn->n != 2)
|
||||
return -EINVAL;
|
||||
|
||||
static int aio_iiro_16_detach(struct comedi_device *dev);
|
||||
if (data[0]) {
|
||||
s->state &= ~data[0];
|
||||
s->state |= data[0] & data[1];
|
||||
outb(s->state & 0xff, dev->iobase + AIO_IIRO_16_RELAY_0_7);
|
||||
outb((s->state >> 8) & 0xff,
|
||||
dev->iobase + AIO_IIRO_16_RELAY_8_15);
|
||||
}
|
||||
|
||||
static struct comedi_driver driver_aio_iiro_16 = {
|
||||
.driver_name = "aio_iiro_16",
|
||||
.module = THIS_MODULE,
|
||||
.attach = aio_iiro_16_attach,
|
||||
.detach = aio_iiro_16_detach,
|
||||
.board_name = &aio_iiro_16_boards[0].name,
|
||||
.offset = sizeof(struct aio_iiro_16_board),
|
||||
.num_names = ARRAY_SIZE(aio_iiro_16_boards),
|
||||
};
|
||||
data[1] = s->state;
|
||||
|
||||
return 2;
|
||||
}
|
||||
|
||||
static int aio_iiro_16_dio_insn_bits_read(struct comedi_device *dev,
|
||||
struct comedi_subdevice *s,
|
||||
struct comedi_insn *insn,
|
||||
unsigned int *data);
|
||||
unsigned int *data)
|
||||
{
|
||||
if (insn->n != 2)
|
||||
return -EINVAL;
|
||||
|
||||
static int aio_iiro_16_dio_insn_bits_write(struct comedi_device *dev,
|
||||
struct comedi_subdevice *s,
|
||||
struct comedi_insn *insn,
|
||||
unsigned int *data);
|
||||
data[1] = 0;
|
||||
data[1] |= inb(dev->iobase + AIO_IIRO_16_INPUT_0_7);
|
||||
data[1] |= inb(dev->iobase + AIO_IIRO_16_INPUT_8_15) << 8;
|
||||
|
||||
return 2;
|
||||
}
|
||||
|
||||
static int aio_iiro_16_attach(struct comedi_device *dev,
|
||||
struct comedi_devconfig *it)
|
||||
|
@ -138,64 +149,22 @@ static int aio_iiro_16_attach(struct comedi_device *dev,
|
|||
return 1;
|
||||
}
|
||||
|
||||
static int aio_iiro_16_detach(struct comedi_device *dev)
|
||||
static void aio_iiro_16_detach(struct comedi_device *dev)
|
||||
{
|
||||
printk(KERN_INFO "comedi%d: aio_iiro_16: remove\n", dev->minor);
|
||||
|
||||
if (dev->iobase)
|
||||
release_region(dev->iobase, AIO_IIRO_16_SIZE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int aio_iiro_16_dio_insn_bits_write(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];
|
||||
outb(s->state & 0xff, dev->iobase + AIO_IIRO_16_RELAY_0_7);
|
||||
outb((s->state >> 8) & 0xff,
|
||||
dev->iobase + AIO_IIRO_16_RELAY_8_15);
|
||||
}
|
||||
|
||||
data[1] = s->state;
|
||||
|
||||
return 2;
|
||||
}
|
||||
|
||||
static int aio_iiro_16_dio_insn_bits_read(struct comedi_device *dev,
|
||||
struct comedi_subdevice *s,
|
||||
struct comedi_insn *insn,
|
||||
unsigned int *data)
|
||||
{
|
||||
if (insn->n != 2)
|
||||
return -EINVAL;
|
||||
|
||||
data[1] = 0;
|
||||
data[1] |= inb(dev->iobase + AIO_IIRO_16_INPUT_0_7);
|
||||
data[1] |= inb(dev->iobase + AIO_IIRO_16_INPUT_8_15) << 8;
|
||||
|
||||
return 2;
|
||||
}
|
||||
|
||||
static int __init driver_aio_iiro_16_init_module(void)
|
||||
{
|
||||
return comedi_driver_register(&driver_aio_iiro_16);
|
||||
}
|
||||
|
||||
static void __exit driver_aio_iiro_16_cleanup_module(void)
|
||||
{
|
||||
comedi_driver_unregister(&driver_aio_iiro_16);
|
||||
}
|
||||
|
||||
module_init(driver_aio_iiro_16_init_module);
|
||||
module_exit(driver_aio_iiro_16_cleanup_module);
|
||||
static struct comedi_driver aio_iiro_16_driver = {
|
||||
.driver_name = "aio_iiro_16",
|
||||
.module = THIS_MODULE,
|
||||
.attach = aio_iiro_16_attach,
|
||||
.detach = aio_iiro_16_detach,
|
||||
.board_name = &aio_iiro_16_boards[0].name,
|
||||
.offset = sizeof(struct aio_iiro_16_board),
|
||||
.num_names = ARRAY_SIZE(aio_iiro_16_boards),
|
||||
};
|
||||
module_comedi_driver(aio_iiro_16_driver);
|
||||
|
||||
MODULE_AUTHOR("Comedi http://www.comedi.org");
|
||||
MODULE_DESCRIPTION("Comedi low-level driver");
|
||||
|
|
|
@ -217,6 +217,14 @@ order they appear in the channel list.
|
|||
|
||||
#define DIO200_DRIVER_NAME "amplc_dio200"
|
||||
|
||||
#ifdef CONFIG_COMEDI_AMPLC_DIO200_ISA_MODULE
|
||||
#define CONFIG_COMEDI_AMPLC_DIO200_ISA
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_COMEDI_AMPLC_DIO200_PCI_MODULE
|
||||
#define CONFIG_COMEDI_AMPLC_DIO200_PCI
|
||||
#endif
|
||||
|
||||
/* PCI IDs */
|
||||
#define PCI_VENDOR_ID_AMPLICON 0x14dc
|
||||
#define PCI_DEVICE_ID_AMPLICON_PCI272 0x000a
|
||||
|
@ -274,10 +282,14 @@ enum dio200_model {
|
|||
};
|
||||
|
||||
enum dio200_layout {
|
||||
#ifdef CONFIG_COMEDI_AMPLC_DIO200_ISA
|
||||
pc212_layout,
|
||||
pc214_layout,
|
||||
#endif
|
||||
pc215_layout,
|
||||
#ifdef CONFIG_COMEDI_AMPLC_DIO200_ISA
|
||||
pc218_layout,
|
||||
#endif
|
||||
pc272_layout
|
||||
};
|
||||
|
||||
|
@ -290,6 +302,7 @@ struct dio200_board {
|
|||
};
|
||||
|
||||
static const struct dio200_board dio200_boards[] = {
|
||||
#ifdef CONFIG_COMEDI_AMPLC_DIO200_ISA
|
||||
{
|
||||
.name = "pc212e",
|
||||
.bustype = isa_bustype,
|
||||
|
@ -308,15 +321,6 @@ static const struct dio200_board dio200_boards[] = {
|
|||
.model = pc215e_model,
|
||||
.layout = pc215_layout,
|
||||
},
|
||||
#ifdef CONFIG_COMEDI_PCI
|
||||
{
|
||||
.name = "pci215",
|
||||
.devid = PCI_DEVICE_ID_AMPLICON_PCI215,
|
||||
.bustype = pci_bustype,
|
||||
.model = pci215_model,
|
||||
.layout = pc215_layout,
|
||||
},
|
||||
#endif
|
||||
{
|
||||
.name = "pc218e",
|
||||
.bustype = isa_bustype,
|
||||
|
@ -329,7 +333,15 @@ static const struct dio200_board dio200_boards[] = {
|
|||
.model = pc272e_model,
|
||||
.layout = pc272_layout,
|
||||
},
|
||||
#ifdef CONFIG_COMEDI_PCI
|
||||
#endif
|
||||
#ifdef CONFIG_COMEDI_AMPLC_DIO200_PCI
|
||||
{
|
||||
.name = "pci215",
|
||||
.devid = PCI_DEVICE_ID_AMPLICON_PCI215,
|
||||
.bustype = pci_bustype,
|
||||
.model = pci215_model,
|
||||
.layout = pc215_layout,
|
||||
},
|
||||
{
|
||||
.name = "pci272",
|
||||
.devid = PCI_DEVICE_ID_AMPLICON_PCI272,
|
||||
|
@ -337,8 +349,6 @@ static const struct dio200_board dio200_boards[] = {
|
|||
.model = pci272_model,
|
||||
.layout = pc272_layout,
|
||||
},
|
||||
#endif
|
||||
#ifdef CONFIG_COMEDI_PCI
|
||||
{
|
||||
.name = DIO200_DRIVER_NAME,
|
||||
.devid = PCI_DEVICE_ID_INVALID,
|
||||
|
@ -367,6 +377,7 @@ struct dio200_layout_struct {
|
|||
};
|
||||
|
||||
static const struct dio200_layout_struct dio200_layouts[] = {
|
||||
#ifdef CONFIG_COMEDI_AMPLC_DIO200_ISA
|
||||
[pc212_layout] = {
|
||||
.n_subdevs = 6,
|
||||
.sdtype = {sd_8255, sd_8254, sd_8254, sd_8254,
|
||||
|
@ -385,6 +396,7 @@ static const struct dio200_layout_struct dio200_layouts[] = {
|
|||
.has_int_sce = 0,
|
||||
.has_clk_gat_sce = 0,
|
||||
},
|
||||
#endif
|
||||
[pc215_layout] = {
|
||||
.n_subdevs = 5,
|
||||
.sdtype = {sd_8255, sd_8255, sd_8254,
|
||||
|
@ -394,6 +406,7 @@ static const struct dio200_layout_struct dio200_layouts[] = {
|
|||
.has_int_sce = 1,
|
||||
.has_clk_gat_sce = 1,
|
||||
},
|
||||
#ifdef CONFIG_COMEDI_AMPLC_DIO200_ISA
|
||||
[pc218_layout] = {
|
||||
.n_subdevs = 7,
|
||||
.sdtype = {sd_8254, sd_8254, sd_8255, sd_8254,
|
||||
|
@ -405,6 +418,7 @@ static const struct dio200_layout_struct dio200_layouts[] = {
|
|||
.has_int_sce = 1,
|
||||
.has_clk_gat_sce = 1,
|
||||
},
|
||||
#endif
|
||||
[pc272_layout] = {
|
||||
.n_subdevs = 4,
|
||||
.sdtype = {sd_8255, sd_8255, sd_8255,
|
||||
|
@ -419,7 +433,7 @@ static const struct dio200_layout_struct dio200_layouts[] = {
|
|||
* PCI driver table.
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_COMEDI_PCI
|
||||
#ifdef CONFIG_COMEDI_AMPLC_DIO200_PCI
|
||||
static DEFINE_PCI_DEVICE_TABLE(dio200_pci_table) = {
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_AMPLICON, PCI_DEVICE_ID_AMPLICON_PCI215) },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_AMPLICON, PCI_DEVICE_ID_AMPLICON_PCI272) },
|
||||
|
@ -427,7 +441,7 @@ static DEFINE_PCI_DEVICE_TABLE(dio200_pci_table) = {
|
|||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(pci, dio200_pci_table);
|
||||
#endif /* CONFIG_COMEDI_PCI */
|
||||
#endif /* CONFIG_COMEDI_AMPLC_DIO200_PCI */
|
||||
|
||||
/*
|
||||
* Useful for shorthand access to the particular board structure
|
||||
|
@ -441,7 +455,7 @@ MODULE_DEVICE_TABLE(pci, dio200_pci_table);
|
|||
feel free to suggest moving the variable to the struct comedi_device struct.
|
||||
*/
|
||||
struct dio200_private {
|
||||
#ifdef CONFIG_COMEDI_PCI
|
||||
#ifdef CONFIG_COMEDI_AMPLC_DIO200_PCI
|
||||
struct pci_dev *pci_dev; /* PCI device */
|
||||
#endif
|
||||
int intr_sd;
|
||||
|
@ -479,7 +493,7 @@ struct dio200_subdev_intr {
|
|||
*/
|
||||
static int dio200_attach(struct comedi_device *dev,
|
||||
struct comedi_devconfig *it);
|
||||
static int dio200_detach(struct comedi_device *dev);
|
||||
static void dio200_detach(struct comedi_device *dev);
|
||||
static struct comedi_driver driver_amplc_dio200 = {
|
||||
.driver_name = DIO200_DRIVER_NAME,
|
||||
.module = THIS_MODULE,
|
||||
|
@ -490,12 +504,12 @@ static struct comedi_driver driver_amplc_dio200 = {
|
|||
.num_names = ARRAY_SIZE(dio200_boards),
|
||||
};
|
||||
|
||||
#ifdef CONFIG_COMEDI_PCI
|
||||
#ifdef CONFIG_COMEDI_AMPLC_DIO200_PCI
|
||||
static int __devinit driver_amplc_dio200_pci_probe(struct pci_dev *dev,
|
||||
const struct pci_device_id
|
||||
*ent)
|
||||
{
|
||||
return comedi_pci_auto_config(dev, driver_amplc_dio200.driver_name);
|
||||
return comedi_pci_auto_config(dev, &driver_amplc_dio200);
|
||||
}
|
||||
|
||||
static void __devexit driver_amplc_dio200_pci_remove(struct pci_dev *dev)
|
||||
|
@ -549,7 +563,7 @@ module_exit(driver_amplc_dio200_cleanup_module);
|
|||
* This function looks for a PCI device matching the requested board name,
|
||||
* bus and slot.
|
||||
*/
|
||||
#ifdef CONFIG_COMEDI_PCI
|
||||
#ifdef CONFIG_COMEDI_AMPLC_DIO200_PCI
|
||||
static int
|
||||
dio200_find_pci(struct comedi_device *dev, int bus, int slot,
|
||||
struct pci_dev **pci_dev_p)
|
||||
|
@ -611,6 +625,7 @@ dio200_find_pci(struct comedi_device *dev, int bus, int slot,
|
|||
* This function checks and requests an I/O region, reporting an error
|
||||
* if there is a conflict.
|
||||
*/
|
||||
#ifdef CONFIG_COMEDI_AMPLC_DIO200_ISA
|
||||
static int
|
||||
dio200_request_region(unsigned minor, unsigned long from, unsigned long extent)
|
||||
{
|
||||
|
@ -621,6 +636,7 @@ dio200_request_region(unsigned minor, unsigned long from, unsigned long extent)
|
|||
}
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* 'insn_bits' function for an 'INTERRUPT' subdevice.
|
||||
|
@ -1332,7 +1348,7 @@ static int dio200_attach(struct comedi_device *dev, struct comedi_devconfig *it)
|
|||
struct comedi_subdevice *s;
|
||||
unsigned long iobase = 0;
|
||||
unsigned int irq = 0;
|
||||
#ifdef CONFIG_COMEDI_PCI
|
||||
#ifdef CONFIG_COMEDI_AMPLC_DIO200_PCI
|
||||
struct pci_dev *pci_dev = NULL;
|
||||
int bus = 0, slot = 0;
|
||||
#endif
|
||||
|
@ -1354,12 +1370,14 @@ static int dio200_attach(struct comedi_device *dev, struct comedi_devconfig *it)
|
|||
|
||||
/* Process options. */
|
||||
switch (thisboard->bustype) {
|
||||
#ifdef CONFIG_COMEDI_AMPLC_DIO200_ISA
|
||||
case isa_bustype:
|
||||
iobase = it->options[0];
|
||||
irq = it->options[1];
|
||||
share_irq = 0;
|
||||
break;
|
||||
#ifdef CONFIG_COMEDI_PCI
|
||||
#endif
|
||||
#ifdef CONFIG_COMEDI_AMPLC_DIO200_PCI
|
||||
case pci_bustype:
|
||||
bus = it->options[0];
|
||||
slot = it->options[1];
|
||||
|
@ -1382,7 +1400,7 @@ static int dio200_attach(struct comedi_device *dev, struct comedi_devconfig *it)
|
|||
devpriv->intr_sd = -1;
|
||||
|
||||
/* Enable device and reserve I/O spaces. */
|
||||
#ifdef CONFIG_COMEDI_PCI
|
||||
#ifdef CONFIG_COMEDI_AMPLC_DIO200_PCI
|
||||
if (pci_dev) {
|
||||
ret = comedi_pci_enable(pci_dev, DIO200_DRIVER_NAME);
|
||||
if (ret < 0) {
|
||||
|
@ -1396,9 +1414,11 @@ static int dio200_attach(struct comedi_device *dev, struct comedi_devconfig *it)
|
|||
} else
|
||||
#endif
|
||||
{
|
||||
#ifdef CONFIG_COMEDI_AMPLC_DIO200_ISA
|
||||
ret = dio200_request_region(dev->minor, iobase, DIO200_IO_SIZE);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
#endif
|
||||
}
|
||||
dev->iobase = iobase;
|
||||
|
||||
|
@ -1474,12 +1494,19 @@ static int dio200_attach(struct comedi_device *dev, struct comedi_devconfig *it)
|
|||
}
|
||||
|
||||
printk(KERN_INFO "comedi%d: %s ", dev->minor, dev->board_name);
|
||||
if (thisboard->bustype == isa_bustype) {
|
||||
switch (thisboard->bustype) {
|
||||
#ifdef CONFIG_COMEDI_AMPLC_DIO200_ISA
|
||||
case isa_bustype:
|
||||
printk("(base %#lx) ", iobase);
|
||||
} else {
|
||||
#ifdef CONFIG_COMEDI_PCI
|
||||
printk("(pci %s) ", pci_name(pci_dev));
|
||||
break;
|
||||
#endif
|
||||
#ifdef CONFIG_COMEDI_AMPLC_DIO200_PCI
|
||||
case pci_bustype:
|
||||
printk("(pci %s) ", pci_name(pci_dev));
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (irq)
|
||||
printk("(irq %u%s) ", irq, (dev->irq ? "" : " UNAVAILABLE"));
|
||||
|
@ -1491,22 +1518,11 @@ static int dio200_attach(struct comedi_device *dev, struct comedi_devconfig *it)
|
|||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* _detach is called to deconfigure a device. It should deallocate
|
||||
* resources.
|
||||
* This function is also called when _attach() fails, so it should be
|
||||
* careful not to release resources that were not necessarily
|
||||
* allocated by _attach(). dev->private and dev->subdevices are
|
||||
* deallocated automatically by the core.
|
||||
*/
|
||||
static int dio200_detach(struct comedi_device *dev)
|
||||
static void dio200_detach(struct comedi_device *dev)
|
||||
{
|
||||
const struct dio200_layout_struct *layout;
|
||||
unsigned n;
|
||||
|
||||
printk(KERN_DEBUG "comedi%d: %s: detach\n", dev->minor,
|
||||
DIO200_DRIVER_NAME);
|
||||
|
||||
if (dev->irq)
|
||||
free_irq(dev->irq, dev);
|
||||
if (dev->subdevices) {
|
||||
|
@ -1529,7 +1545,7 @@ static int dio200_detach(struct comedi_device *dev)
|
|||
}
|
||||
}
|
||||
if (devpriv) {
|
||||
#ifdef CONFIG_COMEDI_PCI
|
||||
#ifdef CONFIG_COMEDI_AMPLC_DIO200_PCI
|
||||
if (devpriv->pci_dev) {
|
||||
if (dev->iobase)
|
||||
comedi_pci_disable(devpriv->pci_dev);
|
||||
|
@ -1537,15 +1553,12 @@ static int dio200_detach(struct comedi_device *dev)
|
|||
} else
|
||||
#endif
|
||||
{
|
||||
#ifdef CONFIG_COMEDI_AMPLC_DIO200_ISA
|
||||
if (dev->iobase)
|
||||
release_region(dev->iobase, DIO200_IO_SIZE);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
if (dev->board_name)
|
||||
printk(KERN_INFO "comedi%d: %s removed\n",
|
||||
dev->minor, dev->board_name);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
MODULE_AUTHOR("Comedi http://www.comedi.org");
|
||||
|
|
|
@ -63,6 +63,14 @@ unused.
|
|||
|
||||
#define PC236_DRIVER_NAME "amplc_pc236"
|
||||
|
||||
#ifdef CONFIG_COMEDI_AMPLC_PC236_ISA_MODULE
|
||||
#define CONFIG_COMEDI_AMPLC_PC236_ISA
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_COMEDI_AMPLC_PC236_PCI_MODULE
|
||||
#define CONFIG_COMEDI_AMPLC_PC236_PCI
|
||||
#endif
|
||||
|
||||
/* PCI236 PCI configuration register information */
|
||||
#define PCI_VENDOR_ID_AMPLICON 0x14dc
|
||||
#define PCI_DEVICE_ID_AMPLICON_PCI236 0x0009
|
||||
|
@ -106,13 +114,15 @@ struct pc236_board {
|
|||
enum pc236_model model;
|
||||
};
|
||||
static const struct pc236_board pc236_boards[] = {
|
||||
#ifdef CONFIG_COMEDI_AMPLC_PC236_ISA
|
||||
{
|
||||
.name = "pc36at",
|
||||
.fancy_name = "PC36AT",
|
||||
.bustype = isa_bustype,
|
||||
.model = pc36at_model,
|
||||
},
|
||||
#ifdef CONFIG_COMEDI_PCI
|
||||
#endif
|
||||
#ifdef CONFIG_COMEDI_AMPLC_PC236_PCI
|
||||
{
|
||||
.name = "pci236",
|
||||
.fancy_name = "PCI236",
|
||||
|
@ -120,8 +130,6 @@ static const struct pc236_board pc236_boards[] = {
|
|||
.bustype = pci_bustype,
|
||||
.model = pci236_model,
|
||||
},
|
||||
#endif
|
||||
#ifdef CONFIG_COMEDI_PCI
|
||||
{
|
||||
.name = PC236_DRIVER_NAME,
|
||||
.fancy_name = PC236_DRIVER_NAME,
|
||||
|
@ -132,14 +140,14 @@ static const struct pc236_board pc236_boards[] = {
|
|||
#endif
|
||||
};
|
||||
|
||||
#ifdef CONFIG_COMEDI_PCI
|
||||
#ifdef CONFIG_COMEDI_AMPLC_PC236_PCI
|
||||
static DEFINE_PCI_DEVICE_TABLE(pc236_pci_table) = {
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_AMPLICON, PCI_DEVICE_ID_AMPLICON_PCI236) },
|
||||
{0}
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(pci, pc236_pci_table);
|
||||
#endif /* CONFIG_COMEDI_PCI */
|
||||
#endif /* CONFIG_COMEDI_AMPLC_PC236_PCI */
|
||||
|
||||
/*
|
||||
* Useful for shorthand access to the particular board structure
|
||||
|
@ -151,7 +159,7 @@ MODULE_DEVICE_TABLE(pci, pc236_pci_table);
|
|||
feel free to suggest moving the variable to the struct comedi_device struct.
|
||||
*/
|
||||
struct pc236_private {
|
||||
#ifdef CONFIG_COMEDI_PCI
|
||||
#ifdef CONFIG_COMEDI_AMPLC_PC236_PCI
|
||||
/* PCI device */
|
||||
struct pci_dev *pci_dev;
|
||||
unsigned long lcr_iobase; /* PLX PCI9052 config registers in PCIBAR1 */
|
||||
|
@ -168,7 +176,7 @@ struct pc236_private {
|
|||
* the device code.
|
||||
*/
|
||||
static int pc236_attach(struct comedi_device *dev, struct comedi_devconfig *it);
|
||||
static int pc236_detach(struct comedi_device *dev);
|
||||
static void pc236_detach(struct comedi_device *dev);
|
||||
static struct comedi_driver driver_amplc_pc236 = {
|
||||
.driver_name = PC236_DRIVER_NAME,
|
||||
.module = THIS_MODULE,
|
||||
|
@ -179,12 +187,12 @@ static struct comedi_driver driver_amplc_pc236 = {
|
|||
.num_names = ARRAY_SIZE(pc236_boards),
|
||||
};
|
||||
|
||||
#ifdef CONFIG_COMEDI_PCI
|
||||
#ifdef CONFIG_COMEDI_AMPLC_PC236_PCI
|
||||
static int __devinit driver_amplc_pc236_pci_probe(struct pci_dev *dev,
|
||||
const struct pci_device_id
|
||||
*ent)
|
||||
{
|
||||
return comedi_pci_auto_config(dev, driver_amplc_pc236.driver_name);
|
||||
return comedi_pci_auto_config(dev, &driver_amplc_pc236);
|
||||
}
|
||||
|
||||
static void __devexit driver_amplc_pc236_pci_remove(struct pci_dev *dev)
|
||||
|
@ -234,8 +242,10 @@ module_init(driver_amplc_pc236_init_module);
|
|||
module_exit(driver_amplc_pc236_cleanup_module);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_COMEDI_AMPLC_PC236_ISA
|
||||
static int pc236_request_region(unsigned minor, unsigned long from,
|
||||
unsigned long extent);
|
||||
#endif
|
||||
static void pc236_intr_disable(struct comedi_device *dev);
|
||||
static void pc236_intr_enable(struct comedi_device *dev);
|
||||
static int pc236_intr_check(struct comedi_device *dev);
|
||||
|
@ -255,7 +265,7 @@ static irqreturn_t pc236_interrupt(int irq, void *d);
|
|||
* This function looks for a PCI device matching the requested board name,
|
||||
* bus and slot.
|
||||
*/
|
||||
#ifdef CONFIG_COMEDI_PCI
|
||||
#ifdef CONFIG_COMEDI_AMPLC_PC236_PCI
|
||||
static int
|
||||
pc236_find_pci(struct comedi_device *dev, int bus, int slot,
|
||||
struct pci_dev **pci_dev_p)
|
||||
|
@ -324,7 +334,7 @@ static int pc236_attach(struct comedi_device *dev, struct comedi_devconfig *it)
|
|||
struct comedi_subdevice *s;
|
||||
unsigned long iobase = 0;
|
||||
unsigned int irq = 0;
|
||||
#ifdef CONFIG_COMEDI_PCI
|
||||
#ifdef CONFIG_COMEDI_AMPLC_PC236_PCI
|
||||
struct pci_dev *pci_dev = NULL;
|
||||
int bus = 0, slot = 0;
|
||||
#endif
|
||||
|
@ -345,12 +355,14 @@ static int pc236_attach(struct comedi_device *dev, struct comedi_devconfig *it)
|
|||
}
|
||||
/* Process options. */
|
||||
switch (thisboard->bustype) {
|
||||
#ifdef CONFIG_COMEDI_AMPLC_PC236_ISA
|
||||
case isa_bustype:
|
||||
iobase = it->options[0];
|
||||
irq = it->options[1];
|
||||
share_irq = 0;
|
||||
break;
|
||||
#ifdef CONFIG_COMEDI_PCI
|
||||
#endif
|
||||
#ifdef CONFIG_COMEDI_AMPLC_PC236_PCI
|
||||
case pci_bustype:
|
||||
bus = it->options[0];
|
||||
slot = it->options[1];
|
||||
|
@ -361,7 +373,7 @@ static int pc236_attach(struct comedi_device *dev, struct comedi_devconfig *it)
|
|||
return ret;
|
||||
devpriv->pci_dev = pci_dev;
|
||||
break;
|
||||
#endif /* CONFIG_COMEDI_PCI */
|
||||
#endif
|
||||
default:
|
||||
printk(KERN_ERR
|
||||
"comedi%d: %s: BUG! cannot determine board type!\n",
|
||||
|
@ -376,7 +388,7 @@ static int pc236_attach(struct comedi_device *dev, struct comedi_devconfig *it)
|
|||
dev->board_name = thisboard->name;
|
||||
|
||||
/* Enable device and reserve I/O spaces. */
|
||||
#ifdef CONFIG_COMEDI_PCI
|
||||
#ifdef CONFIG_COMEDI_AMPLC_PC236_PCI
|
||||
if (pci_dev) {
|
||||
|
||||
ret = comedi_pci_enable(pci_dev, PC236_DRIVER_NAME);
|
||||
|
@ -392,9 +404,11 @@ static int pc236_attach(struct comedi_device *dev, struct comedi_devconfig *it)
|
|||
} else
|
||||
#endif
|
||||
{
|
||||
#ifdef CONFIG_COMEDI_AMPLC_PC236_ISA
|
||||
ret = pc236_request_region(dev->minor, iobase, PC236_IO_SIZE);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
#endif
|
||||
}
|
||||
dev->iobase = iobase;
|
||||
|
||||
|
@ -439,12 +453,19 @@ static int pc236_attach(struct comedi_device *dev, struct comedi_devconfig *it)
|
|||
}
|
||||
}
|
||||
printk(KERN_INFO "comedi%d: %s ", dev->minor, dev->board_name);
|
||||
if (thisboard->bustype == isa_bustype) {
|
||||
switch (thisboard->bustype) {
|
||||
#ifdef CONFIG_COMEDI_AMPLC_PC236_ISA
|
||||
case isa_bustype:
|
||||
printk("(base %#lx) ", iobase);
|
||||
} else {
|
||||
#ifdef CONFIG_COMEDI_PCI
|
||||
printk("(pci %s) ", pci_name(pci_dev));
|
||||
break;
|
||||
#endif
|
||||
#ifdef CONFIG_COMEDI_AMPLC_PC236_PCI
|
||||
case pci_bustype:
|
||||
printk("(pci %s) ", pci_name(pci_dev));
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (irq)
|
||||
printk("(irq %u%s) ", irq, (dev->irq ? "" : " UNAVAILABLE"));
|
||||
|
@ -456,27 +477,16 @@ static int pc236_attach(struct comedi_device *dev, struct comedi_devconfig *it)
|
|||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* _detach is called to deconfigure a device. It should deallocate
|
||||
* resources.
|
||||
* This function is also called when _attach() fails, so it should be
|
||||
* careful not to release resources that were not necessarily
|
||||
* allocated by _attach(). dev->private and dev->subdevices are
|
||||
* deallocated automatically by the core.
|
||||
*/
|
||||
static int pc236_detach(struct comedi_device *dev)
|
||||
static void pc236_detach(struct comedi_device *dev)
|
||||
{
|
||||
printk(KERN_DEBUG "comedi%d: %s: detach\n", dev->minor,
|
||||
PC236_DRIVER_NAME);
|
||||
if (devpriv)
|
||||
pc236_intr_disable(dev);
|
||||
|
||||
if (dev->irq)
|
||||
free_irq(dev->irq, dev);
|
||||
if (dev->subdevices)
|
||||
subdev_8255_cleanup(dev, dev->subdevices + 0);
|
||||
if (devpriv) {
|
||||
#ifdef CONFIG_COMEDI_PCI
|
||||
#ifdef CONFIG_COMEDI_AMPLC_PC236_PCI
|
||||
if (devpriv->pci_dev) {
|
||||
if (dev->iobase)
|
||||
comedi_pci_disable(devpriv->pci_dev);
|
||||
|
@ -484,21 +494,19 @@ static int pc236_detach(struct comedi_device *dev)
|
|||
} else
|
||||
#endif
|
||||
{
|
||||
#ifdef CONFIG_COMEDI_AMPLC_PC236_ISA
|
||||
if (dev->iobase)
|
||||
release_region(dev->iobase, PC236_IO_SIZE);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
if (dev->board_name) {
|
||||
printk(KERN_INFO "comedi%d: %s removed\n",
|
||||
dev->minor, dev->board_name);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function checks and requests an I/O region, reporting an error
|
||||
* if there is a conflict.
|
||||
*/
|
||||
#ifdef CONFIG_COMEDI_AMPLC_PC236_ISA
|
||||
static int pc236_request_region(unsigned minor, unsigned long from,
|
||||
unsigned long extent)
|
||||
{
|
||||
|
@ -509,6 +517,7 @@ static int pc236_request_region(unsigned minor, unsigned long from,
|
|||
}
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This function is called to mark the interrupt as disabled (no command
|
||||
|
@ -521,7 +530,7 @@ static void pc236_intr_disable(struct comedi_device *dev)
|
|||
|
||||
spin_lock_irqsave(&dev->spinlock, flags);
|
||||
devpriv->enable_irq = 0;
|
||||
#ifdef CONFIG_COMEDI_PCI
|
||||
#ifdef CONFIG_COMEDI_AMPLC_PC236_PCI
|
||||
if (devpriv->lcr_iobase)
|
||||
outl(PCI236_INTR_DISABLE, devpriv->lcr_iobase + PLX9052_INTCSR);
|
||||
#endif
|
||||
|
@ -539,7 +548,7 @@ static void pc236_intr_enable(struct comedi_device *dev)
|
|||
|
||||
spin_lock_irqsave(&dev->spinlock, flags);
|
||||
devpriv->enable_irq = 1;
|
||||
#ifdef CONFIG_COMEDI_PCI
|
||||
#ifdef CONFIG_COMEDI_AMPLC_PC236_PCI
|
||||
if (devpriv->lcr_iobase)
|
||||
outl(PCI236_INTR_ENABLE, devpriv->lcr_iobase + PLX9052_INTCSR);
|
||||
#endif
|
||||
|
@ -561,7 +570,7 @@ static int pc236_intr_check(struct comedi_device *dev)
|
|||
spin_lock_irqsave(&dev->spinlock, flags);
|
||||
if (devpriv->enable_irq) {
|
||||
retval = 1;
|
||||
#ifdef CONFIG_COMEDI_PCI
|
||||
#ifdef CONFIG_COMEDI_AMPLC_PC236_PCI
|
||||
if (devpriv->lcr_iobase) {
|
||||
if ((inl(devpriv->lcr_iobase + PLX9052_INTCSR)
|
||||
& PLX9052_INTCSR_LI1STAT_MASK)
|
||||
|
|
|
@ -50,6 +50,14 @@ The state of the outputs can be read.
|
|||
|
||||
#define PC263_DRIVER_NAME "amplc_pc263"
|
||||
|
||||
#ifdef CONFIG_COMEDI_AMPLC_PC263_ISA_MODULE
|
||||
#define CONFIG_COMEDI_AMPLC_PC263_ISA
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_COMEDI_AMPLC_PC263_PCI_MODULE
|
||||
#define CONFIG_COMEDI_AMPLC_PC263_PCI
|
||||
#endif
|
||||
|
||||
/* PCI263 PCI configuration register information */
|
||||
#define PCI_VENDOR_ID_AMPLICON 0x14dc
|
||||
#define PCI_DEVICE_ID_AMPLICON_PCI263 0x000c
|
||||
|
@ -73,13 +81,15 @@ struct pc263_board {
|
|||
enum pc263_model model;
|
||||
};
|
||||
static const struct pc263_board pc263_boards[] = {
|
||||
#ifdef CONFIG_COMEDI_AMPLC_PC263_ISA
|
||||
{
|
||||
.name = "pc263",
|
||||
.fancy_name = "PC263",
|
||||
.bustype = isa_bustype,
|
||||
.model = pc263_model,
|
||||
},
|
||||
#ifdef CONFIG_COMEDI_PCI
|
||||
#endif
|
||||
#ifdef CONFIG_COMEDI_AMPLC_PC263_PCI
|
||||
{
|
||||
.name = "pci263",
|
||||
.fancy_name = "PCI263",
|
||||
|
@ -87,8 +97,6 @@ static const struct pc263_board pc263_boards[] = {
|
|||
.bustype = pci_bustype,
|
||||
.model = pci263_model,
|
||||
},
|
||||
#endif
|
||||
#ifdef CONFIG_COMEDI_PCI
|
||||
{
|
||||
.name = PC263_DRIVER_NAME,
|
||||
.fancy_name = PC263_DRIVER_NAME,
|
||||
|
@ -99,14 +107,14 @@ static const struct pc263_board pc263_boards[] = {
|
|||
#endif
|
||||
};
|
||||
|
||||
#ifdef CONFIG_COMEDI_PCI
|
||||
#ifdef CONFIG_COMEDI_AMPLC_PC263_PCI
|
||||
static DEFINE_PCI_DEVICE_TABLE(pc263_pci_table) = {
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_AMPLICON, PCI_DEVICE_ID_AMPLICON_PCI263) },
|
||||
{0}
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(pci, pc263_pci_table);
|
||||
#endif /* CONFIG_COMEDI_PCI */
|
||||
#endif /* CONFIG_COMEDI_AMPLC_PC263_PCI */
|
||||
|
||||
/*
|
||||
* Useful for shorthand access to the particular board structure
|
||||
|
@ -117,14 +125,14 @@ MODULE_DEVICE_TABLE(pci, pc263_pci_table);
|
|||
several hardware drivers keep similar information in this structure,
|
||||
feel free to suggest moving the variable to the struct comedi_device struct.
|
||||
*/
|
||||
#ifdef CONFIG_COMEDI_PCI
|
||||
#ifdef CONFIG_COMEDI_AMPLC_PC263_PCI
|
||||
struct pc263_private {
|
||||
/* PCI device. */
|
||||
struct pci_dev *pci_dev;
|
||||
};
|
||||
|
||||
#define devpriv ((struct pc263_private *)dev->private)
|
||||
#endif /* CONFIG_COMEDI_PCI */
|
||||
#endif /* CONFIG_COMEDI_AMPLC_PC263_PCI */
|
||||
|
||||
/*
|
||||
* The struct comedi_driver structure tells the Comedi core module
|
||||
|
@ -133,7 +141,7 @@ struct pc263_private {
|
|||
* the device code.
|
||||
*/
|
||||
static int pc263_attach(struct comedi_device *dev, struct comedi_devconfig *it);
|
||||
static int pc263_detach(struct comedi_device *dev);
|
||||
static void pc263_detach(struct comedi_device *dev);
|
||||
static struct comedi_driver driver_amplc_pc263 = {
|
||||
.driver_name = PC263_DRIVER_NAME,
|
||||
.module = THIS_MODULE,
|
||||
|
@ -144,8 +152,10 @@ static struct comedi_driver driver_amplc_pc263 = {
|
|||
.num_names = ARRAY_SIZE(pc263_boards),
|
||||
};
|
||||
|
||||
#ifdef CONFIG_COMEDI_AMPLC_PC263_ISA
|
||||
static int pc263_request_region(unsigned minor, unsigned long from,
|
||||
unsigned long extent);
|
||||
#endif
|
||||
static int pc263_dio_insn_bits(struct comedi_device *dev,
|
||||
struct comedi_subdevice *s,
|
||||
struct comedi_insn *insn, unsigned int *data);
|
||||
|
@ -157,7 +167,7 @@ static int pc263_dio_insn_config(struct comedi_device *dev,
|
|||
* This function looks for a PCI device matching the requested board name,
|
||||
* bus and slot.
|
||||
*/
|
||||
#ifdef CONFIG_COMEDI_PCI
|
||||
#ifdef CONFIG_COMEDI_AMPLC_PC263_PCI
|
||||
static int
|
||||
pc263_find_pci(struct comedi_device *dev, int bus, int slot,
|
||||
struct pci_dev **pci_dev_p)
|
||||
|
@ -225,7 +235,7 @@ static int pc263_attach(struct comedi_device *dev, struct comedi_devconfig *it)
|
|||
{
|
||||
struct comedi_subdevice *s;
|
||||
unsigned long iobase = 0;
|
||||
#ifdef CONFIG_COMEDI_PCI
|
||||
#ifdef CONFIG_COMEDI_AMPLC_PC263_PCI
|
||||
struct pci_dev *pci_dev = NULL;
|
||||
int bus = 0, slot = 0;
|
||||
#endif
|
||||
|
@ -237,7 +247,7 @@ static int pc263_attach(struct comedi_device *dev, struct comedi_devconfig *it)
|
|||
* Allocate the private structure area. alloc_private() is a
|
||||
* convenient macro defined in comedidev.h.
|
||||
*/
|
||||
#ifdef CONFIG_COMEDI_PCI
|
||||
#ifdef CONFIG_COMEDI_AMPLC_PC263_PCI
|
||||
ret = alloc_private(dev, sizeof(struct pc263_private));
|
||||
if (ret < 0) {
|
||||
printk(KERN_ERR "comedi%d: error! out of memory!\n",
|
||||
|
@ -247,10 +257,12 @@ static int pc263_attach(struct comedi_device *dev, struct comedi_devconfig *it)
|
|||
#endif
|
||||
/* Process options. */
|
||||
switch (thisboard->bustype) {
|
||||
#ifdef CONFIG_COMEDI_AMPLC_PC263_ISA
|
||||
case isa_bustype:
|
||||
iobase = it->options[0];
|
||||
break;
|
||||
#ifdef CONFIG_COMEDI_PCI
|
||||
#endif
|
||||
#ifdef CONFIG_COMEDI_AMPLC_PC263_PCI
|
||||
case pci_bustype:
|
||||
bus = it->options[0];
|
||||
slot = it->options[1];
|
||||
|
@ -260,7 +272,7 @@ static int pc263_attach(struct comedi_device *dev, struct comedi_devconfig *it)
|
|||
return ret;
|
||||
devpriv->pci_dev = pci_dev;
|
||||
break;
|
||||
#endif /* CONFIG_COMEDI_PCI */
|
||||
#endif
|
||||
default:
|
||||
printk(KERN_ERR
|
||||
"comedi%d: %s: BUG! cannot determine board type!\n",
|
||||
|
@ -275,7 +287,7 @@ static int pc263_attach(struct comedi_device *dev, struct comedi_devconfig *it)
|
|||
dev->board_name = thisboard->name;
|
||||
|
||||
/* Enable device and reserve I/O spaces. */
|
||||
#ifdef CONFIG_COMEDI_PCI
|
||||
#ifdef CONFIG_COMEDI_AMPLC_PC263_PCI
|
||||
if (pci_dev) {
|
||||
ret = comedi_pci_enable(pci_dev, PC263_DRIVER_NAME);
|
||||
if (ret < 0) {
|
||||
|
@ -289,9 +301,11 @@ static int pc263_attach(struct comedi_device *dev, struct comedi_devconfig *it)
|
|||
} else
|
||||
#endif
|
||||
{
|
||||
#ifdef CONFIG_COMEDI_AMPLC_PC263_ISA
|
||||
ret = pc263_request_region(dev->minor, iobase, PC263_IO_SIZE);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
#endif
|
||||
}
|
||||
dev->iobase = iobase;
|
||||
|
||||
|
@ -322,12 +336,18 @@ static int pc263_attach(struct comedi_device *dev, struct comedi_devconfig *it)
|
|||
s->state = s->state | (inb(dev->iobase) << 8);
|
||||
|
||||
printk(KERN_INFO "comedi%d: %s ", dev->minor, dev->board_name);
|
||||
if (thisboard->bustype == isa_bustype) {
|
||||
switch (thisboard->bustype) {
|
||||
#ifdef CONFIG_COMEDI_AMPLC_PC263_ISA
|
||||
case isa_bustype:
|
||||
printk("(base %#lx) ", iobase);
|
||||
} else {
|
||||
#ifdef CONFIG_COMEDI_PCI
|
||||
printk("(pci %s) ", pci_name(pci_dev));
|
||||
break;
|
||||
#endif
|
||||
#ifdef CONFIG_COMEDI_AMPLC_PC263_PCI
|
||||
printk("(pci %s) ", pci_name(pci_dev));
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
printk("attached\n");
|
||||
|
@ -335,23 +355,13 @@ static int pc263_attach(struct comedi_device *dev, struct comedi_devconfig *it)
|
|||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* _detach is called to deconfigure a device. It should deallocate
|
||||
* resources.
|
||||
* This function is also called when _attach() fails, so it should be
|
||||
* careful not to release resources that were not necessarily
|
||||
* allocated by _attach(). dev->private and dev->subdevices are
|
||||
* deallocated automatically by the core.
|
||||
*/
|
||||
static int pc263_detach(struct comedi_device *dev)
|
||||
static void pc263_detach(struct comedi_device *dev)
|
||||
{
|
||||
printk(KERN_DEBUG "comedi%d: %s: detach\n", dev->minor,
|
||||
PC263_DRIVER_NAME);
|
||||
|
||||
#ifdef CONFIG_COMEDI_PCI
|
||||
if (devpriv) {
|
||||
#ifdef CONFIG_COMEDI_AMPLC_PC263_PCI
|
||||
if (devpriv)
|
||||
#endif
|
||||
#ifdef CONFIG_COMEDI_PCI
|
||||
{
|
||||
#ifdef CONFIG_COMEDI_AMPLC_PC263_PCI
|
||||
if (devpriv->pci_dev) {
|
||||
if (dev->iobase)
|
||||
comedi_pci_disable(devpriv->pci_dev);
|
||||
|
@ -359,21 +369,19 @@ static int pc263_detach(struct comedi_device *dev)
|
|||
} else
|
||||
#endif
|
||||
{
|
||||
#ifdef CONFIG_COMEDI_AMPLC_PC263_ISA
|
||||
if (dev->iobase)
|
||||
release_region(dev->iobase, PC263_IO_SIZE);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
if (dev->board_name) {
|
||||
printk(KERN_INFO "comedi%d: %s removed\n",
|
||||
dev->minor, dev->board_name);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function checks and requests an I/O region, reporting an error
|
||||
* if there is a conflict.
|
||||
*/
|
||||
#ifdef CONFIG_COMEDI_AMPLC_PC263_ISA
|
||||
static int pc263_request_region(unsigned minor, unsigned long from,
|
||||
unsigned long extent)
|
||||
{
|
||||
|
@ -384,6 +392,7 @@ static int pc263_request_region(unsigned minor, unsigned long from,
|
|||
}
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* DIO devices are slightly special. Although it is possible to
|
||||
* implement the insn_read/insn_write interface, it is much more
|
||||
|
@ -429,12 +438,12 @@ static int pc263_dio_insn_config(struct comedi_device *dev,
|
|||
* A convenient macro that defines init_module() and cleanup_module(),
|
||||
* as necessary.
|
||||
*/
|
||||
#ifdef CONFIG_COMEDI_PCI
|
||||
#ifdef CONFIG_COMEDI_AMPLC_PC263_PCI
|
||||
static int __devinit driver_amplc_pc263_pci_probe(struct pci_dev *dev,
|
||||
const struct pci_device_id
|
||||
*ent)
|
||||
{
|
||||
return comedi_pci_auto_config(dev, driver_amplc_pc263.driver_name);
|
||||
return comedi_pci_auto_config(dev, &driver_amplc_pc263);
|
||||
}
|
||||
|
||||
static void __devexit driver_amplc_pc263_pci_remove(struct pci_dev *dev)
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue