X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=drivers%2Fstaging%2Fcomedi%2Fdrivers%2Fcb_pcidas64.c;h=d33b8fe872a723d2b16987c118bab6ccaa67629f;hb=HEAD;hp=c3e5495b4f06aa43b45ec8932ec0d88bee99865a;hpb=91e14b294f3fe4d8b28516b21ceef187ea9b1bdf;p=firefly-linux-kernel-4.4.55.git diff --git a/drivers/staging/comedi/drivers/cb_pcidas64.c b/drivers/staging/comedi/drivers/cb_pcidas64.c index c3e5495b4f06..d33b8fe872a7 100644 --- a/drivers/staging/comedi/drivers/cb_pcidas64.c +++ b/drivers/staging/comedi/drivers/cb_pcidas64.c @@ -28,12 +28,7 @@ but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -************************************************************************/ +*/ /* * Driver: cb_pcidas64 @@ -85,27 +80,14 @@ TODO: make ao fifo size adjustable like ai fifo */ -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include +#include #include #include -#include "../comedidev.h" +#include "../comedi_pci.h" -#include "8253.h" #include "8255.h" #include "plx9080.h" -#include "comedi_fc.h" - -#undef PCIDAS64_DEBUG /* disable debugging code */ -/* #define PCIDAS64_DEBUG enable debugging code */ - -#ifdef PCIDAS64_DEBUG -#define DEBUG_PRINT(format, args...) pr_debug(format, ## args) -#else -#define DEBUG_PRINT(format, args...) no_printk(format, ## args) -#endif #define TIMER_BASE 25 /* 40MHz master clock */ /* 100kHz 'prescaled' clock for slow acquisition, @@ -173,8 +155,10 @@ static inline unsigned int dac_msb_4020_reg(unsigned int channel) } enum read_only_registers { - /* hardware status register, - * reading this apparently clears pending interrupts as well */ + /* + * hardware status register, + * reading this apparently clears pending interrupts as well + */ HW_STATUS_REG = 0x0, PIPE1_READ_REG = 0x4, ADC_READ_PNTR_REG = 0x8, @@ -192,7 +176,7 @@ enum read_write_registers { DAC_FIFO_REG = 0x300, }; -/* devpriv->dio_counter_iobase registers */ +/* dev->mmio registers */ enum dio_counter_registers { DIO_8255_OFFSET = 0x0, DO_REG = 0x20, @@ -261,7 +245,8 @@ enum adc_control0_contents { ADC_SOFT_GATE_BITS = 0x1, /* software gate */ ADC_EXT_GATE_BITS = 0x2, /* external digital gate */ ADC_ANALOG_GATE_BITS = 0x3, /* analog level gate */ - ADC_GATE_LEVEL_BIT = 0x4, /* level-sensitive gate (for digital) */ + /* level-sensitive gate (for digital) */ + ADC_GATE_LEVEL_BIT = 0x4, ADC_GATE_POLARITY_BIT = 0x8, /* gate active low */ ADC_START_TRIG_SOFT_BITS = 0x10, ADC_START_TRIG_EXT_BITS = 0x20, @@ -318,7 +303,8 @@ enum calibration_contents { CAL_GAIN_BIT = 0x800, }; -/* calibration sources for 6025 are: +/* + * calibration sources for 6025 are: * 0 : ground * 1 : 10V * 2 : 5V @@ -442,91 +428,122 @@ static inline uint8_t attenuate_bit(unsigned int channel) /* analog input ranges for 64xx boards */ static const struct comedi_lrange ai_ranges_64xx = { - 8, - { - BIP_RANGE(10), - BIP_RANGE(5), - BIP_RANGE(2.5), - BIP_RANGE(1.25), - UNI_RANGE(10), - UNI_RANGE(5), - UNI_RANGE(2.5), - UNI_RANGE(1.25) - } + 8, { + BIP_RANGE(10), + BIP_RANGE(5), + BIP_RANGE(2.5), + BIP_RANGE(1.25), + UNI_RANGE(10), + UNI_RANGE(5), + UNI_RANGE(2.5), + UNI_RANGE(1.25) + } +}; + +static const uint8_t ai_range_code_64xx[8] = { + 0x0, 0x1, 0x2, 0x3, /* bipolar 10, 5, 2,5, 1.25 */ + 0x8, 0x9, 0xa, 0xb /* unipolar 10, 5, 2.5, 1.25 */ +}; + +/* analog input ranges for 64-Mx boards */ +static const struct comedi_lrange ai_ranges_64_mx = { + 7, { + BIP_RANGE(5), + BIP_RANGE(2.5), + BIP_RANGE(1.25), + BIP_RANGE(0.625), + UNI_RANGE(5), + UNI_RANGE(2.5), + UNI_RANGE(1.25) + } +}; + +static const uint8_t ai_range_code_64_mx[7] = { + 0x0, 0x1, 0x2, 0x3, /* bipolar 5, 2.5, 1.25, 0.625 */ + 0x9, 0xa, 0xb /* unipolar 5, 2.5, 1.25 */ }; /* analog input ranges for 60xx boards */ static const struct comedi_lrange ai_ranges_60xx = { - 4, - { - BIP_RANGE(10), - BIP_RANGE(5), - BIP_RANGE(0.5), - BIP_RANGE(0.05), - } + 4, { + BIP_RANGE(10), + BIP_RANGE(5), + BIP_RANGE(0.5), + BIP_RANGE(0.05) + } +}; + +static const uint8_t ai_range_code_60xx[4] = { + 0x0, 0x1, 0x4, 0x7 /* bipolar 10, 5, 0.5, 0.05 */ }; /* analog input ranges for 6030, etc boards */ static const struct comedi_lrange ai_ranges_6030 = { - 14, - { - BIP_RANGE(10), - BIP_RANGE(5), - BIP_RANGE(2), - BIP_RANGE(1), - BIP_RANGE(0.5), - BIP_RANGE(0.2), - BIP_RANGE(0.1), - UNI_RANGE(10), - UNI_RANGE(5), - UNI_RANGE(2), - UNI_RANGE(1), - UNI_RANGE(0.5), - UNI_RANGE(0.2), - UNI_RANGE(0.1), - } + 14, { + BIP_RANGE(10), + BIP_RANGE(5), + BIP_RANGE(2), + BIP_RANGE(1), + BIP_RANGE(0.5), + BIP_RANGE(0.2), + BIP_RANGE(0.1), + UNI_RANGE(10), + UNI_RANGE(5), + UNI_RANGE(2), + UNI_RANGE(1), + UNI_RANGE(0.5), + UNI_RANGE(0.2), + UNI_RANGE(0.1) + } +}; + +static const uint8_t ai_range_code_6030[14] = { + 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, /* bip 10, 5, 2, 1, 0.5, 0.2, 0.1 */ + 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf /* uni 10, 5, 2, 1, 0.5, 0.2, 0.1 */ }; /* analog input ranges for 6052, etc boards */ static const struct comedi_lrange ai_ranges_6052 = { - 15, - { - BIP_RANGE(10), - BIP_RANGE(5), - BIP_RANGE(2.5), - BIP_RANGE(1), - BIP_RANGE(0.5), - BIP_RANGE(0.25), - BIP_RANGE(0.1), - BIP_RANGE(0.05), - UNI_RANGE(10), - UNI_RANGE(5), - UNI_RANGE(2), - UNI_RANGE(1), - UNI_RANGE(0.5), - UNI_RANGE(0.2), - UNI_RANGE(0.1), - } + 15, { + BIP_RANGE(10), + BIP_RANGE(5), + BIP_RANGE(2.5), + BIP_RANGE(1), + BIP_RANGE(0.5), + BIP_RANGE(0.25), + BIP_RANGE(0.1), + BIP_RANGE(0.05), + UNI_RANGE(10), + UNI_RANGE(5), + UNI_RANGE(2), + UNI_RANGE(1), + UNI_RANGE(0.5), + UNI_RANGE(0.2), + UNI_RANGE(0.1) + } +}; + +static const uint8_t ai_range_code_6052[15] = { + 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, /* bipolar 10 ... 0.05 */ + 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf /* unipolar 10 ... 0.1 */ }; /* analog input ranges for 4020 board */ static const struct comedi_lrange ai_ranges_4020 = { - 2, - { - BIP_RANGE(5), - BIP_RANGE(1), - } + 2, { + BIP_RANGE(5), + BIP_RANGE(1) + } }; /* analog output ranges */ static const struct comedi_lrange ao_ranges_64xx = { - 4, - { - BIP_RANGE(5), - BIP_RANGE(10), - UNI_RANGE(5), - UNI_RANGE(10), - } + 4, { + BIP_RANGE(5), + BIP_RANGE(10), + UNI_RANGE(5), + UNI_RANGE(10) + } }; static const int ao_range_code_64xx[] = { @@ -541,11 +558,10 @@ static const int ao_range_code_60xx[] = { }; static const struct comedi_lrange ao_ranges_6030 = { - 2, - { - BIP_RANGE(10), - UNI_RANGE(10), - } + 2, { + BIP_RANGE(10), + UNI_RANGE(10) + } }; static const int ao_range_code_6030[] = { @@ -554,11 +570,10 @@ static const int ao_range_code_6030[] = { }; static const struct comedi_lrange ao_ranges_4020 = { - 2, - { - BIP_RANGE(5), - BIP_RANGE(10), - } + 2, { + BIP_RANGE(5), + BIP_RANGE(10) + } }; static const int ao_range_code_4020[] = { @@ -616,6 +631,7 @@ struct pcidas64_board { int ai_bits; /* analog input resolution */ int ai_speed; /* fastest conversion period in ns */ const struct comedi_lrange *ai_range_table; + const uint8_t *ai_range_code; int ao_nchan; /* number of analog out channels */ int ao_bits; /* analog output resolution */ int ao_scan_speed; /* analog output scan speed */ @@ -648,8 +664,10 @@ static const struct hw_fifo_info ai_fifo_60xx = { .fifo_size_reg_mask = 0x7f, }; -/* maximum number of dma transfers we will chain together into a ring - * (and the maximum number of dma buffers we maintain) */ +/* + * maximum number of dma transfers we will chain together into a ring + * (and the maximum number of dma buffers we maintain) + */ #define MAX_AI_DMA_RING_COUNT (0x80000 / DMA_BUFFER_SIZE) #define MIN_AI_DMA_RING_COUNT (0x10000 / DMA_BUFFER_SIZE) #define AO_DMA_RING_COUNT (0x10000 / DMA_BUFFER_SIZE) @@ -657,8 +675,8 @@ static inline unsigned int ai_dma_ring_count(const struct pcidas64_board *board) { if (board->layout == LAYOUT_4020) return MAX_AI_DMA_RING_COUNT; - else - return MIN_AI_DMA_RING_COUNT; + + return MIN_AI_DMA_RING_COUNT; } static const int bytes_in_sample = 2; @@ -674,6 +692,7 @@ static const struct pcidas64_board pcidas64_boards[] = { .ao_scan_speed = 10000, .layout = LAYOUT_64XX, .ai_range_table = &ai_ranges_64xx, + .ai_range_code = ai_range_code_64xx, .ao_range_table = &ao_ranges_64xx, .ao_range_code = ao_range_code_64xx, .ai_fifo = &ai_fifo_64xx, @@ -689,6 +708,7 @@ static const struct pcidas64_board pcidas64_boards[] = { .ao_scan_speed = 10000, .layout = LAYOUT_64XX, .ai_range_table = &ai_ranges_64xx, + .ai_range_code = ai_range_code_64xx, .ao_range_table = &ao_ranges_64xx, .ao_range_code = ao_range_code_64xx, .ai_fifo = &ai_fifo_64xx, @@ -703,7 +723,8 @@ static const struct pcidas64_board pcidas64_boards[] = { .ao_bits = 16, .ao_scan_speed = 10000, .layout = LAYOUT_64XX, - .ai_range_table = &ai_ranges_64xx, + .ai_range_table = &ai_ranges_64_mx, + .ai_range_code = ai_range_code_64_mx, .ao_range_table = &ao_ranges_64xx, .ao_range_code = ao_range_code_64xx, .ai_fifo = &ai_fifo_64xx, @@ -718,7 +739,8 @@ static const struct pcidas64_board pcidas64_boards[] = { .ao_bits = 16, .ao_scan_speed = 10000, .layout = LAYOUT_64XX, - .ai_range_table = &ai_ranges_64xx, + .ai_range_table = &ai_ranges_64_mx, + .ai_range_code = ai_range_code_64_mx, .ao_range_table = &ao_ranges_64xx, .ao_range_code = ao_range_code_64xx, .ai_fifo = &ai_fifo_64xx, @@ -733,7 +755,8 @@ static const struct pcidas64_board pcidas64_boards[] = { .ao_bits = 16, .ao_scan_speed = 10000, .layout = LAYOUT_64XX, - .ai_range_table = &ai_ranges_64xx, + .ai_range_table = &ai_ranges_64_mx, + .ai_range_code = ai_range_code_64_mx, .ao_range_table = &ao_ranges_64xx, .ao_range_code = ao_range_code_64xx, .ai_fifo = &ai_fifo_64xx, @@ -748,6 +771,7 @@ static const struct pcidas64_board pcidas64_boards[] = { .ao_bits = 16, .layout = LAYOUT_60XX, .ai_range_table = &ai_ranges_60xx, + .ai_range_code = ai_range_code_60xx, .ao_range_table = &range_bipolar10, .ao_range_code = ao_range_code_60xx, .ai_fifo = &ai_fifo_60xx, @@ -763,6 +787,7 @@ static const struct pcidas64_board pcidas64_boards[] = { .ao_scan_speed = 100000, .layout = LAYOUT_60XX, .ai_range_table = &ai_ranges_60xx, + .ai_range_code = ai_range_code_60xx, .ao_range_table = &range_bipolar10, .ao_range_code = ao_range_code_60xx, .ai_fifo = &ai_fifo_60xx, @@ -777,6 +802,7 @@ static const struct pcidas64_board pcidas64_boards[] = { .ao_scan_speed = 100000, .layout = LAYOUT_60XX, .ai_range_table = &ai_ranges_60xx, + .ai_range_code = ai_range_code_60xx, .ao_range_table = &range_bipolar10, .ao_range_code = ao_range_code_60xx, .ai_fifo = &ai_fifo_60xx, @@ -792,6 +818,7 @@ static const struct pcidas64_board pcidas64_boards[] = { .ao_scan_speed = 100000, .layout = LAYOUT_60XX, .ai_range_table = &ai_ranges_60xx, + .ai_range_code = ai_range_code_60xx, .ao_range_table = &range_bipolar10, .ao_range_code = ao_range_code_60xx, .ai_fifo = &ai_fifo_60xx, @@ -807,6 +834,7 @@ static const struct pcidas64_board pcidas64_boards[] = { .ao_scan_speed = 10000, .layout = LAYOUT_60XX, .ai_range_table = &ai_ranges_6030, + .ai_range_code = ai_range_code_6030, .ao_range_table = &ao_ranges_6030, .ao_range_code = ao_range_code_6030, .ai_fifo = &ai_fifo_60xx, @@ -822,6 +850,7 @@ static const struct pcidas64_board pcidas64_boards[] = { .ao_scan_speed = 10000, .layout = LAYOUT_60XX, .ai_range_table = &ai_ranges_6030, + .ai_range_code = ai_range_code_6030, .ao_range_table = &ao_ranges_6030, .ao_range_code = ao_range_code_6030, .ai_fifo = &ai_fifo_60xx, @@ -835,6 +864,7 @@ static const struct pcidas64_board pcidas64_boards[] = { .ao_nchan = 0, .layout = LAYOUT_60XX, .ai_range_table = &ai_ranges_6030, + .ai_range_code = ai_range_code_6030, .ai_fifo = &ai_fifo_60xx, .has_8255 = 0, }, @@ -846,6 +876,7 @@ static const struct pcidas64_board pcidas64_boards[] = { .ao_nchan = 0, .layout = LAYOUT_60XX, .ai_range_table = &ai_ranges_6030, + .ai_range_code = ai_range_code_6030, .ai_fifo = &ai_fifo_60xx, .has_8255 = 0, }, @@ -858,6 +889,7 @@ static const struct pcidas64_board pcidas64_boards[] = { .ao_scan_speed = 0, .layout = LAYOUT_60XX, .ai_range_table = &ai_ranges_60xx, + .ai_range_code = ai_range_code_60xx, .ai_fifo = &ai_fifo_60xx, .has_8255 = 0, }, @@ -871,6 +903,7 @@ static const struct pcidas64_board pcidas64_boards[] = { .ao_scan_speed = 100000, .layout = LAYOUT_60XX, .ai_range_table = &ai_ranges_60xx, + .ai_range_code = ai_range_code_60xx, .ao_range_table = &range_bipolar10, .ao_range_code = ao_range_code_60xx, .ai_fifo = &ai_fifo_60xx, @@ -886,6 +919,7 @@ static const struct pcidas64_board pcidas64_boards[] = { .ao_scan_speed = 100000, .layout = LAYOUT_60XX, .ai_range_table = &ai_ranges_60xx, + .ai_range_code = ai_range_code_60xx, .ao_range_table = &range_bipolar10, .ao_range_code = ao_range_code_60xx, .ai_fifo = &ai_fifo_60xx, @@ -901,6 +935,7 @@ static const struct pcidas64_board pcidas64_boards[] = { .ao_scan_speed = 1000, .layout = LAYOUT_60XX, .ai_range_table = &ai_ranges_6052, + .ai_range_code = ai_range_code_6052, .ao_range_table = &ao_ranges_6030, .ao_range_code = ao_range_code_6030, .ai_fifo = &ai_fifo_60xx, @@ -916,6 +951,7 @@ static const struct pcidas64_board pcidas64_boards[] = { .ao_scan_speed = 3333, .layout = LAYOUT_60XX, .ai_range_table = &ai_ranges_6052, + .ai_range_code = ai_range_code_6052, .ao_range_table = &ao_ranges_6030, .ao_range_code = ao_range_code_6030, .ai_fifo = &ai_fifo_60xx, @@ -931,6 +967,7 @@ static const struct pcidas64_board pcidas64_boards[] = { .ao_scan_speed = 1000, .layout = LAYOUT_60XX, .ai_range_table = &ai_ranges_6052, + .ai_range_code = ai_range_code_6052, .ao_range_table = &ao_ranges_6030, .ao_range_code = ao_range_code_6030, .ai_fifo = &ai_fifo_60xx, @@ -946,6 +983,7 @@ static const struct pcidas64_board pcidas64_boards[] = { .ao_scan_speed = 1000, .layout = LAYOUT_60XX, .ai_range_table = &ai_ranges_6052, + .ai_range_code = ai_range_code_6052, .ao_range_table = &ao_ranges_6030, .ao_range_code = ao_range_code_6030, .ai_fifo = &ai_fifo_60xx, @@ -980,6 +1018,7 @@ static const struct pcidas64_board pcidas64_boards[] = { .ao_scan_speed = 10000, .layout = LAYOUT_64XX, .ai_range_table = &ai_ranges_64xx, + .ai_range_code = ai_range_code_64xx, .ai_fifo = ai_fifo_64xx, .has_8255 = 1, }, @@ -991,7 +1030,8 @@ static const struct pcidas64_board pcidas64_boards[] = { .ao_nchan = 0, .ao_scan_speed = 10000, .layout = LAYOUT_64XX, - .ai_range_table = &ai_ranges_64xx, + .ai_range_table = &ai_ranges_64_mx, + .ai_range_code = ai_range_code_64_mx, .ai_fifo = ai_fifo_64xx, .has_8255 = 1, }, @@ -1003,7 +1043,8 @@ static const struct pcidas64_board pcidas64_boards[] = { .ao_nchan = 0, .ao_scan_speed = 10000, .layout = LAYOUT_64XX, - .ai_range_table = &ai_ranges_64xx, + .ai_range_table = &ai_ranges_64_mx, + .ai_range_code = ai_range_code_64_mx, .ai_fifo = ai_fifo_64xx, .has_8255 = 1, }, @@ -1015,7 +1056,8 @@ static const struct pcidas64_board pcidas64_boards[] = { .ao_nchan = 0, .ao_scan_speed = 10000, .layout = LAYOUT_64XX, - .ai_range_table = &ai_ranges_64xx, + .ai_range_table = &ai_ranges_64_mx, + .ai_range_code = ai_range_code_64_mx, .ai_fifo = ai_fifo_64xx, .has_8255 = 1, }, @@ -1027,7 +1069,8 @@ static const struct pcidas64_board pcidas64_boards[] = { .ao_nchan = 2, .ao_scan_speed = 10000, .layout = LAYOUT_64XX, - .ai_range_table = &ai_ranges_64xx, + .ai_range_table = &ai_ranges_64_mx, + .ai_range_code = ai_range_code_64_mx, .ai_fifo = ai_fifo_64xx, .has_8255 = 1, }, @@ -1039,7 +1082,8 @@ static const struct pcidas64_board pcidas64_boards[] = { .ao_nchan = 2, .ao_scan_speed = 10000, .layout = LAYOUT_64XX, - .ai_range_table = &ai_ranges_64xx, + .ai_range_table = &ai_ranges_64_mx, + .ai_range_code = ai_range_code_64_mx, .ai_fifo = ai_fifo_64xx, .has_8255 = 1, }, @@ -1051,7 +1095,8 @@ static const struct pcidas64_board pcidas64_boards[] = { .ao_nchan = 2, .ao_scan_speed = 10000, .layout = LAYOUT_64XX, - .ai_range_table = &ai_ranges_64xx, + .ai_range_table = &ai_ranges_64_mx, + .ai_range_code = ai_range_code_64_mx, .ai_fifo = ai_fifo_64xx, .has_8255 = 1, }, @@ -1061,14 +1106,14 @@ static const struct pcidas64_board pcidas64_boards[] = { static inline unsigned short se_diff_bit_6xxx(struct comedi_device *dev, int use_differential) { - const struct pcidas64_board *thisboard = comedi_board(dev); + const struct pcidas64_board *board = dev->board_ptr; - if ((thisboard->layout == LAYOUT_64XX && !use_differential) || - (thisboard->layout == LAYOUT_60XX && use_differential)) + if ((board->layout == LAYOUT_64XX && !use_differential) || + (board->layout == LAYOUT_60XX && use_differential)) return ADC_SE_DIFF_BIT; - else - return 0; -}; + + return 0; +} struct ext_clock_info { /* master clock divisor to use for scans with external master clock */ @@ -1085,12 +1130,9 @@ struct pcidas64_private { /* base addresses (ioremapped) */ void __iomem *plx9080_iobase; void __iomem *main_iobase; - void __iomem *dio_counter_iobase; /* local address (used by dma controller) */ uint32_t local0_iobase; uint32_t local1_iobase; - /* number of analog input samples remaining */ - volatile unsigned int ai_count; /* dma buffers for analog input */ uint16_t *ai_buffer[MAX_AI_DMA_RING_COUNT]; /* physical addresses of ai dma buffers */ @@ -1102,7 +1144,7 @@ struct pcidas64_private { dma_addr_t ai_dma_desc_bus_addr; /* index of the ai dma descriptor/buffer * that is currently being used */ - volatile unsigned int ai_dma_index; + unsigned int ai_dma_index; /* dma buffers for analog output */ uint16_t *ao_buffer[AO_DMA_RING_COUNT]; /* physical addresses of ao dma buffers */ @@ -1110,107 +1152,63 @@ struct pcidas64_private { struct plx_dma_desc *ao_dma_desc; dma_addr_t ao_dma_desc_bus_addr; /* keeps track of buffer where the next ao sample should go */ - volatile unsigned int ao_dma_index; - /* number of analog output samples remaining */ - volatile unsigned long ao_count; - /* remember what the analog outputs are set to, to allow readback */ - volatile unsigned int ao_value[2]; + unsigned int ao_dma_index; unsigned int hw_revision; /* stc chip hardware revision number */ /* last bits sent to INTR_ENABLE_REG register */ - volatile unsigned int intr_enable_bits; + unsigned int intr_enable_bits; /* last bits sent to ADC_CONTROL1_REG register */ - volatile uint16_t adc_control1_bits; + uint16_t adc_control1_bits; /* last bits sent to FIFO_SIZE_REG register */ - volatile uint16_t fifo_size_bits; + uint16_t fifo_size_bits; /* last bits sent to HW_CONFIG_REG register */ - volatile uint16_t hw_config_bits; - volatile uint16_t dac_control1_bits; + uint16_t hw_config_bits; + uint16_t dac_control1_bits; /* last bits written to plx9080 control register */ - volatile uint32_t plx_control_bits; + uint32_t plx_control_bits; /* last bits written to plx interrupt control and status register */ - volatile uint32_t plx_intcsr_bits; + uint32_t plx_intcsr_bits; /* index of calibration source readable through ai ch0 */ - volatile int calibration_source; + int calibration_source; /* bits written to i2c calibration/range register */ - volatile uint8_t i2c_cal_range_bits; + uint8_t i2c_cal_range_bits; /* configure digital triggers to trigger on falling edge */ - volatile unsigned int ext_trig_falling; - /* states of various devices stored to enable read-back */ - unsigned int ad8402_state[2]; - unsigned int caldac_state[8]; - volatile short ai_cmd_running; + unsigned int ext_trig_falling; + short ai_cmd_running; unsigned int ai_fifo_segment_length; struct ext_clock_info ext_clock; - short ao_bounce_buffer[DAC_FIFO_SIZE]; + unsigned short ao_bounce_buffer[DAC_FIFO_SIZE]; }; static unsigned int ai_range_bits_6xxx(const struct comedi_device *dev, unsigned int range_index) { - const struct pcidas64_board *thisboard = comedi_board(dev); - const struct comedi_krange *range = - &thisboard->ai_range_table->range[range_index]; - unsigned int bits = 0; - - switch (range->max) { - case 10000000: - bits = 0x000; - break; - case 5000000: - bits = 0x100; - break; - case 2000000: - case 2500000: - bits = 0x200; - break; - case 1000000: - case 1250000: - bits = 0x300; - break; - case 500000: - bits = 0x400; - break; - case 200000: - case 250000: - bits = 0x500; - break; - case 100000: - bits = 0x600; - break; - case 50000: - bits = 0x700; - break; - default: - comedi_error(dev, "bug! in ai_range_bits_6xxx"); - break; - } - if (range->min == 0) - bits += 0x900; - return bits; + const struct pcidas64_board *board = dev->board_ptr; + + return board->ai_range_code[range_index] << 8; } static unsigned int hw_revision(const struct comedi_device *dev, uint16_t hw_status_bits) { - const struct pcidas64_board *thisboard = comedi_board(dev); + const struct pcidas64_board *board = dev->board_ptr; - if (thisboard->layout == LAYOUT_4020) + if (board->layout == LAYOUT_4020) return (hw_status_bits >> 13) & 0x7; return (hw_status_bits >> 12) & 0xf; } static void set_dac_range_bits(struct comedi_device *dev, - volatile uint16_t *bits, unsigned int channel, + uint16_t *bits, unsigned int channel, unsigned int range) { - const struct pcidas64_board *thisboard = comedi_board(dev); - unsigned int code = thisboard->ao_range_code[range]; + const struct pcidas64_board *board = dev->board_ptr; + unsigned int code = board->ao_range_code[range]; if (channel > 1) - comedi_error(dev, "bug! bad channel?"); + dev_err(dev->class_dev, "bug! bad channel?\n"); if (code & ~0x3) - comedi_error(dev, "bug! bad range code?"); + dev_err(dev->class_dev, "bug! bad range code?\n"); *bits &= ~(0x3 << (2 * channel)); *bits |= code << (2 * channel); @@ -1256,39 +1254,38 @@ static void disable_ai_interrupts(struct comedi_device *dev) writew(devpriv->intr_enable_bits, devpriv->main_iobase + INTR_ENABLE_REG); spin_unlock_irqrestore(&dev->spinlock, flags); - - DEBUG_PRINT("intr enable bits 0x%x\n", devpriv->intr_enable_bits); } static void enable_ai_interrupts(struct comedi_device *dev, const struct comedi_cmd *cmd) { - const struct pcidas64_board *thisboard = comedi_board(dev); + const struct pcidas64_board *board = dev->board_ptr; struct pcidas64_private *devpriv = dev->private; uint32_t bits; unsigned long flags; bits = EN_ADC_OVERRUN_BIT | EN_ADC_DONE_INTR_BIT | EN_ADC_ACTIVE_INTR_BIT | EN_ADC_STOP_INTR_BIT; - /* Use pio transfer and interrupt on end of conversion - * if TRIG_WAKE_EOS flag is set. */ - if (cmd->flags & TRIG_WAKE_EOS) { + /* + * Use pio transfer and interrupt on end of conversion + * if CMDF_WAKE_EOS flag is set. + */ + if (cmd->flags & CMDF_WAKE_EOS) { /* 4020 doesn't support pio transfers except for fifo dregs */ - if (thisboard->layout != LAYOUT_4020) + if (board->layout != LAYOUT_4020) bits |= ADC_INTR_EOSCAN_BITS | EN_ADC_INTR_SRC_BIT; } spin_lock_irqsave(&dev->spinlock, flags); devpriv->intr_enable_bits |= bits; writew(devpriv->intr_enable_bits, devpriv->main_iobase + INTR_ENABLE_REG); - DEBUG_PRINT("intr enable bits 0x%x\n", devpriv->intr_enable_bits); spin_unlock_irqrestore(&dev->spinlock, flags); } /* initialize plx9080 chip */ static void init_plx9080(struct comedi_device *dev) { - const struct pcidas64_board *thisboard = comedi_board(dev); + const struct pcidas64_board *board = dev->board_ptr; struct pcidas64_private *devpriv = dev->private; uint32_t bits; void __iomem *plx_iobase = devpriv->plx9080_iobase; @@ -1296,38 +1293,6 @@ static void init_plx9080(struct comedi_device *dev) devpriv->plx_control_bits = readl(devpriv->plx9080_iobase + PLX_CONTROL_REG); - /* plx9080 dump */ - DEBUG_PRINT(" plx interrupt status 0x%x\n", - readl(plx_iobase + PLX_INTRCS_REG)); - DEBUG_PRINT(" plx id bits 0x%x\n", readl(plx_iobase + PLX_ID_REG)); - DEBUG_PRINT(" plx control reg 0x%x\n", devpriv->plx_control_bits); - DEBUG_PRINT(" plx mode/arbitration reg 0x%x\n", - readl(plx_iobase + PLX_MARB_REG)); - DEBUG_PRINT(" plx region0 reg 0x%x\n", - readl(plx_iobase + PLX_REGION0_REG)); - DEBUG_PRINT(" plx region1 reg 0x%x\n", - readl(plx_iobase + PLX_REGION1_REG)); - - DEBUG_PRINT(" plx revision 0x%x\n", - readl(plx_iobase + PLX_REVISION_REG)); - DEBUG_PRINT(" plx dma channel 0 mode 0x%x\n", - readl(plx_iobase + PLX_DMA0_MODE_REG)); - DEBUG_PRINT(" plx dma channel 1 mode 0x%x\n", - readl(plx_iobase + PLX_DMA1_MODE_REG)); - DEBUG_PRINT(" plx dma channel 0 pci address 0x%x\n", - readl(plx_iobase + PLX_DMA0_PCI_ADDRESS_REG)); - DEBUG_PRINT(" plx dma channel 0 local address 0x%x\n", - readl(plx_iobase + PLX_DMA0_LOCAL_ADDRESS_REG)); - DEBUG_PRINT(" plx dma channel 0 transfer size 0x%x\n", - readl(plx_iobase + PLX_DMA0_TRANSFER_SIZE_REG)); - DEBUG_PRINT(" plx dma channel 0 descriptor 0x%x\n", - readl(plx_iobase + PLX_DMA0_DESCRIPTOR_REG)); - DEBUG_PRINT(" plx dma channel 0 command status 0x%x\n", - readb(plx_iobase + PLX_DMA0_CS_REG)); - DEBUG_PRINT(" plx dma channel 0 threshold 0x%x\n", - readl(plx_iobase + PLX_DMA0_THRESHOLD_REG)); - DEBUG_PRINT(" plx bigend 0x%x\n", readl(plx_iobase + PLX_BIGEND_REG)); - #ifdef __BIG_ENDIAN bits = BIGEND_DMA0 | BIGEND_DMA1; #else @@ -1361,12 +1326,12 @@ static void init_plx9080(struct comedi_device *dev) /* enable local burst mode */ bits |= PLX_DMA_LOCAL_BURST_EN_BIT; /* 4020 uses 32 bit dma */ - if (thisboard->layout == LAYOUT_4020) + if (board->layout == LAYOUT_4020) bits |= PLX_LOCAL_BUS_32_WIDE_BITS; else /* localspace0 bus is 16 bits wide */ bits |= PLX_LOCAL_BUS_16_WIDE_BITS; writel(bits, plx_iobase + PLX_DMA1_MODE_REG); - if (ao_cmd_is_supported(thisboard)) + if (ao_cmd_is_supported(board)) writel(bits, plx_iobase + PLX_DMA0_MODE_REG); /* enable interrupts on plx 9080 */ @@ -1398,10 +1363,10 @@ static void disable_ai_pacing(struct comedi_device *dev) static int set_ai_fifo_segment_length(struct comedi_device *dev, unsigned int num_entries) { - const struct pcidas64_board *thisboard = comedi_board(dev); + const struct pcidas64_board *board = dev->board_ptr; struct pcidas64_private *devpriv = dev->private; static const int increment_size = 0x100; - const struct hw_fifo_info *const fifo = thisboard->ai_fifo; + const struct hw_fifo_info *const fifo = board->ai_fifo; unsigned int num_increments; uint16_t bits; @@ -1421,19 +1386,18 @@ static int set_ai_fifo_segment_length(struct comedi_device *dev, devpriv->ai_fifo_segment_length = num_increments * increment_size; - DEBUG_PRINT("set hardware fifo segment length to %i\n", - devpriv->ai_fifo_segment_length); - return devpriv->ai_fifo_segment_length; } -/* adjusts the size of hardware fifo (which determines block size for dma xfers) */ +/* + * adjusts the size of hardware fifo (which determines block size for dma xfers) + */ static int set_ai_fifo_size(struct comedi_device *dev, unsigned int num_samples) { - const struct pcidas64_board *thisboard = comedi_board(dev); + const struct pcidas64_board *board = dev->board_ptr; unsigned int num_fifo_entries; int retval; - const struct hw_fifo_info *const fifo = thisboard->ai_fifo; + const struct hw_fifo_info *const fifo = board->ai_fifo; num_fifo_entries = num_samples / fifo->sample_packing_ratio; @@ -1445,33 +1409,33 @@ static int set_ai_fifo_size(struct comedi_device *dev, unsigned int num_samples) num_samples = retval * fifo->num_segments * fifo->sample_packing_ratio; - DEBUG_PRINT("set hardware fifo size to %i\n", num_samples); - return num_samples; } /* query length of fifo */ static unsigned int ai_fifo_size(struct comedi_device *dev) { - const struct pcidas64_board *thisboard = comedi_board(dev); + const struct pcidas64_board *board = dev->board_ptr; struct pcidas64_private *devpriv = dev->private; return devpriv->ai_fifo_segment_length * - thisboard->ai_fifo->num_segments * - thisboard->ai_fifo->sample_packing_ratio; + board->ai_fifo->num_segments * + board->ai_fifo->sample_packing_ratio; } static void init_stc_registers(struct comedi_device *dev) { - const struct pcidas64_board *thisboard = comedi_board(dev); + const struct pcidas64_board *board = dev->board_ptr; struct pcidas64_private *devpriv = dev->private; uint16_t bits; unsigned long flags; spin_lock_irqsave(&dev->spinlock, flags); - /* bit should be set for 6025, - * although docs say boards with <= 16 chans should be cleared XXX */ + /* + * bit should be set for 6025, + * although docs say boards with <= 16 chans should be cleared XXX + */ if (1) devpriv->adc_control1_bits |= ADC_QUEUE_CONFIG_BIT; writew(devpriv->adc_control1_bits, @@ -1481,7 +1445,7 @@ static void init_stc_registers(struct comedi_device *dev) writew(0xff, devpriv->main_iobase + ADC_SAMPLE_INTERVAL_UPPER_REG); bits = SLOW_DAC_BIT | DMA_CH_SELECT_BIT; - if (thisboard->layout == LAYOUT_4020) + if (board->layout == LAYOUT_4020) bits |= INTERNAL_CLOCK_4020_BITS; devpriv->hw_config_bits |= bits; writew(devpriv->hw_config_bits, @@ -1494,8 +1458,7 @@ static void init_stc_registers(struct comedi_device *dev) /* set fifos to maximum size */ devpriv->fifo_size_bits |= DAC_FIFO_BITS; - set_ai_fifo_segment_length(dev, - thisboard->ai_fifo->max_segment_length); + set_ai_fifo_segment_length(dev, board->ai_fifo->max_segment_length); devpriv->dac_control1_bits = DAC_OUTPUT_ENABLE_BIT; devpriv->intr_enable_bits = @@ -1509,58 +1472,51 @@ static void init_stc_registers(struct comedi_device *dev) static int alloc_and_init_dma_members(struct comedi_device *dev) { - const struct pcidas64_board *thisboard = comedi_board(dev); + const struct pcidas64_board *board = dev->board_ptr; struct pci_dev *pcidev = comedi_to_pci_dev(dev); struct pcidas64_private *devpriv = dev->private; int i; /* allocate pci dma buffers */ - for (i = 0; i < ai_dma_ring_count(thisboard); i++) { + for (i = 0; i < ai_dma_ring_count(board); i++) { devpriv->ai_buffer[i] = pci_alloc_consistent(pcidev, DMA_BUFFER_SIZE, &devpriv->ai_buffer_bus_addr[i]); - if (devpriv->ai_buffer[i] == NULL) + if (!devpriv->ai_buffer[i]) return -ENOMEM; - } for (i = 0; i < AO_DMA_RING_COUNT; i++) { - if (ao_cmd_is_supported(thisboard)) { + if (ao_cmd_is_supported(board)) { devpriv->ao_buffer[i] = pci_alloc_consistent(pcidev, DMA_BUFFER_SIZE, &devpriv-> ao_buffer_bus_addr[i]); - if (devpriv->ao_buffer[i] == NULL) + if (!devpriv->ao_buffer[i]) return -ENOMEM; - } } /* allocate dma descriptors */ devpriv->ai_dma_desc = pci_alloc_consistent(pcidev, sizeof(struct plx_dma_desc) * - ai_dma_ring_count(thisboard), + ai_dma_ring_count(board), &devpriv->ai_dma_desc_bus_addr); - if (devpriv->ai_dma_desc == NULL) + if (!devpriv->ai_dma_desc) return -ENOMEM; - DEBUG_PRINT("ai dma descriptors start at bus addr 0x%llx\n", - (unsigned long long)devpriv->ai_dma_desc_bus_addr); - if (ao_cmd_is_supported(thisboard)) { + if (ao_cmd_is_supported(board)) { devpriv->ao_dma_desc = pci_alloc_consistent(pcidev, sizeof(struct plx_dma_desc) * AO_DMA_RING_COUNT, &devpriv->ao_dma_desc_bus_addr); - if (devpriv->ao_dma_desc == NULL) + if (!devpriv->ao_dma_desc) return -ENOMEM; - - DEBUG_PRINT("ao dma descriptors start at bus addr 0x%llx\n", - (unsigned long long)devpriv->ao_dma_desc_bus_addr); } /* initialize dma descriptors */ - for (i = 0; i < ai_dma_ring_count(thisboard); i++) { + for (i = 0; i < ai_dma_ring_count(board); i++) { devpriv->ai_dma_desc[i].pci_start_addr = cpu_to_le32(devpriv->ai_buffer_bus_addr[i]); - if (thisboard->layout == LAYOUT_4020) + if (board->layout == LAYOUT_4020) devpriv->ai_dma_desc[i].local_start_addr = cpu_to_le32(devpriv->local1_iobase + ADC_FIFO_REG); @@ -1571,12 +1527,12 @@ static int alloc_and_init_dma_members(struct comedi_device *dev) devpriv->ai_dma_desc[i].transfer_size = cpu_to_le32(0); devpriv->ai_dma_desc[i].next = cpu_to_le32((devpriv->ai_dma_desc_bus_addr + - ((i + 1) % ai_dma_ring_count(thisboard)) * + ((i + 1) % ai_dma_ring_count(board)) * sizeof(devpriv->ai_dma_desc[0])) | PLX_DESC_IN_PCI_BIT | PLX_INTR_TERM_COUNT | PLX_XFER_LOCAL_TO_PCI); } - if (ao_cmd_is_supported(thisboard)) { + if (ao_cmd_is_supported(board)) { for (i = 0; i < AO_DMA_RING_COUNT; i++) { devpriv->ao_dma_desc[i].pci_start_addr = cpu_to_le32(devpriv->ao_buffer_bus_addr[i]); @@ -1595,15 +1551,57 @@ static int alloc_and_init_dma_members(struct comedi_device *dev) return 0; } +static void cb_pcidas64_free_dma(struct comedi_device *dev) +{ + const struct pcidas64_board *board = dev->board_ptr; + struct pci_dev *pcidev = comedi_to_pci_dev(dev); + struct pcidas64_private *devpriv = dev->private; + int i; + + if (!devpriv) + return; + + /* free pci dma buffers */ + for (i = 0; i < ai_dma_ring_count(board); i++) { + if (devpriv->ai_buffer[i]) + pci_free_consistent(pcidev, + DMA_BUFFER_SIZE, + devpriv->ai_buffer[i], + devpriv->ai_buffer_bus_addr[i]); + } + for (i = 0; i < AO_DMA_RING_COUNT; i++) { + if (devpriv->ao_buffer[i]) + pci_free_consistent(pcidev, + DMA_BUFFER_SIZE, + devpriv->ao_buffer[i], + devpriv->ao_buffer_bus_addr[i]); + } + /* free dma descriptors */ + if (devpriv->ai_dma_desc) + pci_free_consistent(pcidev, + sizeof(struct plx_dma_desc) * + ai_dma_ring_count(board), + devpriv->ai_dma_desc, + devpriv->ai_dma_desc_bus_addr); + if (devpriv->ao_dma_desc) + pci_free_consistent(pcidev, + sizeof(struct plx_dma_desc) * + AO_DMA_RING_COUNT, + devpriv->ao_dma_desc, + devpriv->ao_dma_desc_bus_addr); +} + static inline void warn_external_queue(struct comedi_device *dev) { - comedi_error(dev, - "AO command and AI external channel queue cannot be used simultaneously."); - comedi_error(dev, - "Use internal AI channel queue (channels must be consecutive and use same range/aref)"); + dev_err(dev->class_dev, + "AO command and AI external channel queue cannot be used simultaneously\n"); + dev_err(dev->class_dev, + "Use internal AI channel queue (channels must be consecutive and use same range/aref)\n"); } -/* Their i2c requires a huge delay on setting clock or data high for some reason */ +/* + * their i2c requires a huge delay on setting clock or data high for some reason + */ static const int i2c_high_udelay = 1000; static const int i2c_low_udelay = 10; @@ -1654,8 +1652,6 @@ static void i2c_write_byte(struct comedi_device *dev, uint8_t byte) uint8_t bit; unsigned int num_bits = 8; - DEBUG_PRINT("writing to i2c byte 0x%x\n", byte); - for (bit = 1 << (num_bits - 1); bit; bit >>= 1) { i2c_set_scl(dev, 0); if ((byte & bit)) @@ -1701,8 +1697,10 @@ static void i2c_write(struct comedi_device *dev, unsigned int address, uint8_t bitstream; static const int read_bit = 0x1; - /* XXX need mutex to prevent simultaneous attempts to access - * eeprom and i2c bus */ + /* + * XXX need mutex to prevent simultaneous attempts to access + * eeprom and i2c bus + */ /* make sure we dont send anything to eeprom */ devpriv->plx_control_bits &= ~CTL_EE_CS; @@ -1716,7 +1714,7 @@ static void i2c_write(struct comedi_device *dev, unsigned int address, /* get acknowledge */ if (i2c_read_ack(dev) != 0) { - comedi_error(dev, "i2c write failed: no acknowledge"); + dev_err(dev->class_dev, "failed: no acknowledge\n"); i2c_stop(dev); return; } @@ -1724,7 +1722,7 @@ static void i2c_write(struct comedi_device *dev, unsigned int address, for (i = 0; i < length; i++) { i2c_write_byte(dev, data[i]); if (i2c_read_ack(dev) != 0) { - comedi_error(dev, "i2c write failed: no acknowledge"); + dev_err(dev->class_dev, "failed: no acknowledge\n"); i2c_stop(dev); return; } @@ -1732,17 +1730,37 @@ static void i2c_write(struct comedi_device *dev, unsigned int address, i2c_stop(dev); } +static int cb_pcidas64_ai_eoc(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned long context) +{ + const struct pcidas64_board *board = dev->board_ptr; + struct pcidas64_private *devpriv = dev->private; + unsigned int status; + + status = readw(devpriv->main_iobase + HW_STATUS_REG); + if (board->layout == LAYOUT_4020) { + status = readw(devpriv->main_iobase + ADC_WRITE_PNTR_REG); + if (status) + return 0; + } else { + if (pipe_full_bits(status)) + return 0; + } + return -EBUSY; +} + static int ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { - const struct pcidas64_board *thisboard = comedi_board(dev); + const struct pcidas64_board *board = dev->board_ptr; struct pcidas64_private *devpriv = dev->private; - unsigned int bits = 0, n, i; + unsigned int bits = 0, n; unsigned int channel, range, aref; unsigned long flags; - static const int timeout = 100; + int ret; - DEBUG_PRINT("chanspec 0x%x\n", insn->chanspec); channel = CR_CHAN(insn->chanspec); range = CR_RANGE(insn->chanspec); aref = CR_AREF(insn->chanspec); @@ -1760,7 +1778,7 @@ static int ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, devpriv->main_iobase + ADC_CONTROL1_REG); spin_unlock_irqrestore(&dev->spinlock, flags); - if (thisboard->layout != LAYOUT_4020) { + if (board->layout != LAYOUT_4020) { /* use internal queue */ devpriv->hw_config_bits &= ~EXT_QUEUE_BIT; writew(devpriv->hw_config_bits, @@ -1770,19 +1788,22 @@ static int ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, if (insn->chanspec & CR_ALT_SOURCE) { unsigned int cal_en_bit; - DEBUG_PRINT("reading calibration source\n"); - if (thisboard->layout == LAYOUT_60XX) + if (board->layout == LAYOUT_60XX) cal_en_bit = CAL_EN_60XX_BIT; else cal_en_bit = CAL_EN_64XX_BIT; - /* select internal reference source to connect - * to channel 0 */ + /* + * select internal reference source to connect + * to channel 0 + */ writew(cal_en_bit | adc_src_bits(devpriv->calibration_source), devpriv->main_iobase + CALIBRATION_REG); } else { - /* make sure internal calibration source - * is turned off */ + /* + * make sure internal calibration source + * is turned off + */ writew(0, devpriv->main_iobase + CALIBRATION_REG); } /* load internal queue */ @@ -1804,7 +1825,6 @@ static int ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, devpriv->i2c_cal_range_bits &= ~ADC_SRC_4020_MASK; if (insn->chanspec & CR_ALT_SOURCE) { - DEBUG_PRINT("reading calibration source\n"); devpriv->i2c_cal_range_bits |= adc_src_4020_bits(devpriv->calibration_source); } else { /* select BNC inputs */ @@ -1815,24 +1835,28 @@ static int ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, devpriv->i2c_cal_range_bits |= attenuate_bit(channel); else devpriv->i2c_cal_range_bits &= ~attenuate_bit(channel); - /* update calibration/range i2c register only if necessary, - * as it is very slow */ + /* + * update calibration/range i2c register only if necessary, + * as it is very slow + */ if (old_cal_range_bits != devpriv->i2c_cal_range_bits) { uint8_t i2c_data = devpriv->i2c_cal_range_bits; + i2c_write(dev, RANGE_CAL_I2C_ADDR, &i2c_data, sizeof(i2c_data)); } - /* 4020 manual asks that sample interval register to be set + /* + * 4020 manual asks that sample interval register to be set * before writing to convert register. * Using somewhat arbitrary setting of 4 master clock ticks - * = 0.1 usec */ + * = 0.1 usec + */ writew(0, devpriv->main_iobase + ADC_SAMPLE_INTERVAL_UPPER_REG); writew(2, devpriv->main_iobase + ADC_SAMPLE_INTERVAL_LOWER_REG); } for (n = 0; n < insn->n; n++) { - /* clear adc buffer (inside loop for 4020 sake) */ writew(0, devpriv->main_iobase + ADC_BUFFER_CLEAR_REG); @@ -1841,28 +1865,12 @@ static int ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, devpriv->main_iobase + ADC_CONVERT_REG); /* wait for data */ - for (i = 0; i < timeout; i++) { - bits = readw(devpriv->main_iobase + HW_STATUS_REG); - DEBUG_PRINT(" pipe bits 0x%x\n", pipe_full_bits(bits)); - if (thisboard->layout == LAYOUT_4020) { - if (readw(devpriv->main_iobase + - ADC_WRITE_PNTR_REG)) - break; - } else { - if (pipe_full_bits(bits)) - break; - } - udelay(1); - } - DEBUG_PRINT(" looped %i times waiting for data\n", i); - if (i == timeout) { - comedi_error(dev, " analog input read insn timed out"); - dev_info(dev->class_dev, "status 0x%x\n", bits); - return -ETIME; - } - if (thisboard->layout == LAYOUT_4020) - data[n] = readl(devpriv->dio_counter_iobase + - ADC_FIFO_REG) & 0xffff; + ret = comedi_timeout(dev, s, insn, cb_pcidas64_ai_eoc, 0); + if (ret) + return ret; + + if (board->layout == LAYOUT_4020) + data[n] = readl(dev->mmio + ADC_FIFO_REG) & 0xffff; else data[n] = readw(devpriv->main_iobase + PIPE1_READ_REG); } @@ -1873,12 +1881,12 @@ static int ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, static int ai_config_calibration_source(struct comedi_device *dev, unsigned int *data) { - const struct pcidas64_board *thisboard = comedi_board(dev); + const struct pcidas64_board *board = dev->board_ptr; struct pcidas64_private *devpriv = dev->private; unsigned int source = data[1]; int num_calibration_sources; - if (thisboard->layout == LAYOUT_60XX) + if (board->layout == LAYOUT_60XX) num_calibration_sources = 16; else num_calibration_sources = 8; @@ -1888,7 +1896,6 @@ static int ai_config_calibration_source(struct comedi_device *dev, return -EINVAL; } - DEBUG_PRINT("setting calibration source to %i\n", source); devpriv->calibration_source = source; return 2; @@ -1896,9 +1903,9 @@ static int ai_config_calibration_source(struct comedi_device *dev, static int ai_config_block_size(struct comedi_device *dev, unsigned int *data) { - const struct pcidas64_board *thisboard = comedi_board(dev); + const struct pcidas64_board *board = dev->board_ptr; int fifo_size; - const struct hw_fifo_info *const fifo = thisboard->ai_fifo; + const struct hw_fifo_info *const fifo = board->ai_fifo; unsigned int block_size, requested_block_size; int retval; @@ -1911,7 +1918,6 @@ static int ai_config_block_size(struct comedi_device *dev, unsigned int *data) retval = set_ai_fifo_size(dev, fifo_size); if (retval < 0) return retval; - } block_size = ai_fifo_size(dev) / fifo->num_segments * bytes_in_sample; @@ -1940,7 +1946,6 @@ static int ai_config_master_clock_4020(struct comedi_device *dev, break; default: return -EINVAL; - break; } data[4] = divisor; @@ -1951,15 +1956,13 @@ static int ai_config_master_clock_4020(struct comedi_device *dev, /* XXX could add support for 60xx series */ static int ai_config_master_clock(struct comedi_device *dev, unsigned int *data) { - const struct pcidas64_board *thisboard = comedi_board(dev); + const struct pcidas64_board *board = dev->board_ptr; - switch (thisboard->layout) { + switch (board->layout) { case LAYOUT_4020: return ai_config_master_clock_4020(dev, data); - break; default: return -EINVAL; - break; } return -EINVAL; @@ -1973,35 +1976,33 @@ static int ai_config_insn(struct comedi_device *dev, struct comedi_subdevice *s, switch (id) { case INSN_CONFIG_ALT_SOURCE: return ai_config_calibration_source(dev, data); - break; case INSN_CONFIG_BLOCK_SIZE: return ai_config_block_size(dev, data); - break; case INSN_CONFIG_TIMER_1: return ai_config_master_clock(dev, data); - break; default: return -EINVAL; - break; } return -EINVAL; } -/* Gets nearest achievable timing given master clock speed, does not +/* + * Gets nearest achievable timing given master clock speed, does not * take into account possible minimum/maximum divisor values. Used - * by other timing checking functions. */ + * by other timing checking functions. + */ static unsigned int get_divisor(unsigned int ns, unsigned int flags) { unsigned int divisor; - switch (flags & TRIG_ROUND_MASK) { - case TRIG_ROUND_UP: + switch (flags & CMDF_ROUND_MASK) { + case CMDF_ROUND_UP: divisor = (ns + TIMER_BASE - 1) / TIMER_BASE; break; - case TRIG_ROUND_DOWN: + case CMDF_ROUND_DOWN: divisor = ns / TIMER_BASE; break; - case TRIG_ROUND_NEAREST: + case CMDF_ROUND_NEAREST: default: divisor = (ns + TIMER_BASE / 2) / TIMER_BASE; break; @@ -2009,14 +2010,17 @@ static unsigned int get_divisor(unsigned int ns, unsigned int flags) return divisor; } -/* utility function that rounds desired timing to an achievable time, and +/* + * utility function that rounds desired timing to an achievable time, and * sets cmd members appropriately. - * adc paces conversions from master clock by dividing by (x + 3) where x is 24 bit number + * adc paces conversions from master clock by dividing by (x + 3) where x is + * 24 bit number */ static void check_adc_timing(struct comedi_device *dev, struct comedi_cmd *cmd) { - const struct pcidas64_board *thisboard = comedi_board(dev); - unsigned int convert_divisor = 0, scan_divisor; + const struct pcidas64_board *board = dev->board_ptr; + unsigned long long convert_divisor = 0; + unsigned int scan_divisor; static const int min_convert_divisor = 3; static const int max_convert_divisor = max_counter_value + min_convert_divisor; @@ -2024,7 +2028,7 @@ static void check_adc_timing(struct comedi_device *dev, struct comedi_cmd *cmd) unsigned long long max_scan_divisor, min_scan_divisor; if (cmd->convert_src == TRIG_TIMER) { - if (thisboard->layout == LAYOUT_4020) { + if (board->layout == LAYOUT_4020) { cmd->convert_arg = 0; } else { convert_divisor = get_divisor(cmd->convert_arg, @@ -2042,7 +2046,6 @@ static void check_adc_timing(struct comedi_device *dev, struct comedi_cmd *cmd) if (cmd->scan_begin_src == TRIG_TIMER) { scan_divisor = get_divisor(cmd->scan_begin_arg, cmd->flags); if (cmd->convert_src == TRIG_TIMER) { - /* XXX check for integer overflows */ min_scan_divisor = convert_divisor * cmd->chanlist_len; max_scan_divisor = (convert_divisor * cmd->chanlist_len - 1) + @@ -2057,90 +2060,141 @@ static void check_adc_timing(struct comedi_device *dev, struct comedi_cmd *cmd) scan_divisor = min_scan_divisor; cmd->scan_begin_arg = scan_divisor * TIMER_BASE; } +} + +static int cb_pcidas64_ai_check_chanlist(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_cmd *cmd) +{ + const struct pcidas64_board *board = dev->board_ptr; + unsigned int aref0 = CR_AREF(cmd->chanlist[0]); + int i; - return; + for (i = 1; i < cmd->chanlist_len; i++) { + unsigned int aref = CR_AREF(cmd->chanlist[i]); + + if (aref != aref0) { + dev_dbg(dev->class_dev, + "all elements in chanlist must use the same analog reference\n"); + return -EINVAL; + } + } + + if (board->layout == LAYOUT_4020) { + unsigned int chan0 = CR_CHAN(cmd->chanlist[0]); + + for (i = 1; i < cmd->chanlist_len; i++) { + unsigned int chan = CR_CHAN(cmd->chanlist[i]); + + if (chan != (chan0 + i)) { + dev_dbg(dev->class_dev, + "chanlist must use consecutive channels\n"); + return -EINVAL; + } + } + if (cmd->chanlist_len == 3) { + dev_dbg(dev->class_dev, + "chanlist cannot be 3 channels long, use 1, 2, or 4 channels\n"); + return -EINVAL; + } + } + + return 0; } static int ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_cmd *cmd) { - const struct pcidas64_board *thisboard = comedi_board(dev); + const struct pcidas64_board *board = dev->board_ptr; int err = 0; unsigned int tmp_arg, tmp_arg2; - int i; - int aref; unsigned int triggers; /* Step 1 : check if triggers are trivially valid */ - err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_EXT); + err |= comedi_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_EXT); triggers = TRIG_TIMER; - if (thisboard->layout == LAYOUT_4020) + if (board->layout == LAYOUT_4020) triggers |= TRIG_OTHER; else triggers |= TRIG_FOLLOW; - err |= cfc_check_trigger_src(&cmd->scan_begin_src, triggers); + err |= comedi_check_trigger_src(&cmd->scan_begin_src, triggers); triggers = TRIG_TIMER; - if (thisboard->layout == LAYOUT_4020) + if (board->layout == LAYOUT_4020) triggers |= TRIG_NOW; else triggers |= TRIG_EXT; - err |= cfc_check_trigger_src(&cmd->convert_src, triggers); - err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT); - err |= cfc_check_trigger_src(&cmd->stop_src, - TRIG_COUNT | TRIG_EXT | TRIG_NONE); + err |= comedi_check_trigger_src(&cmd->convert_src, triggers); + err |= comedi_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT); + err |= comedi_check_trigger_src(&cmd->stop_src, + TRIG_COUNT | TRIG_EXT | TRIG_NONE); if (err) return 1; /* Step 2a : make sure trigger sources are unique */ - err |= cfc_check_trigger_is_unique(cmd->start_src); - err |= cfc_check_trigger_is_unique(cmd->scan_begin_src); - err |= cfc_check_trigger_is_unique(cmd->convert_src); - err |= cfc_check_trigger_is_unique(cmd->stop_src); + err |= comedi_check_trigger_is_unique(cmd->start_src); + err |= comedi_check_trigger_is_unique(cmd->scan_begin_src); + err |= comedi_check_trigger_is_unique(cmd->convert_src); + err |= comedi_check_trigger_is_unique(cmd->stop_src); /* Step 2b : and mutually compatible */ if (cmd->convert_src == TRIG_EXT && cmd->scan_begin_src == TRIG_TIMER) err |= -EINVAL; - if (cmd->stop_src != TRIG_COUNT && - cmd->stop_src != TRIG_NONE && cmd->stop_src != TRIG_EXT) - err |= -EINVAL; if (err) return 2; /* Step 3: check if arguments are trivially valid */ + switch (cmd->start_src) { + case TRIG_NOW: + err |= comedi_check_trigger_arg_is(&cmd->start_arg, 0); + break; + case TRIG_EXT: + /* + * start_arg is the CR_CHAN | CR_INVERT of the + * external trigger. + */ + break; + } + if (cmd->convert_src == TRIG_TIMER) { - if (thisboard->layout == LAYOUT_4020) { - err |= cfc_check_trigger_arg_is(&cmd->convert_arg, 0); + if (board->layout == LAYOUT_4020) { + err |= comedi_check_trigger_arg_is(&cmd->convert_arg, + 0); } else { - err |= cfc_check_trigger_arg_min(&cmd->convert_arg, - thisboard->ai_speed); - /* if scans are timed faster than conversion rate allows */ - if (cmd->scan_begin_src == TRIG_TIMER) - err |= cfc_check_trigger_arg_min( + err |= comedi_check_trigger_arg_min(&cmd->convert_arg, + board->ai_speed); + /* + * if scans are timed faster than conversion rate + * allows + */ + if (cmd->scan_begin_src == TRIG_TIMER) { + err |= comedi_check_trigger_arg_min( &cmd->scan_begin_arg, cmd->convert_arg * cmd->chanlist_len); + } } } - err |= cfc_check_trigger_arg_min(&cmd->chanlist_len, 1); - err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len); + err |= comedi_check_trigger_arg_min(&cmd->chanlist_len, 1); + err |= comedi_check_trigger_arg_is(&cmd->scan_end_arg, + cmd->chanlist_len); switch (cmd->stop_src) { case TRIG_EXT: break; case TRIG_COUNT: - err |= cfc_check_trigger_arg_min(&cmd->stop_arg, 1); + err |= comedi_check_trigger_arg_min(&cmd->stop_arg, 1); break; case TRIG_NONE: - err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0); + err |= comedi_check_trigger_arg_is(&cmd->stop_arg, 0); break; default: break; @@ -2164,36 +2218,9 @@ static int ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, if (err) return 4; - /* make sure user is doesn't change analog reference mid chanlist */ - if (cmd->chanlist) { - aref = CR_AREF(cmd->chanlist[0]); - for (i = 1; i < cmd->chanlist_len; i++) { - if (aref != CR_AREF(cmd->chanlist[i])) { - comedi_error(dev, - "all elements in chanlist must use the same analog reference"); - err++; - break; - } - } - /* check 4020 chanlist */ - if (thisboard->layout == LAYOUT_4020) { - unsigned int first_channel = CR_CHAN(cmd->chanlist[0]); - for (i = 1; i < cmd->chanlist_len; i++) { - if (CR_CHAN(cmd->chanlist[i]) != - first_channel + i) { - comedi_error(dev, - "chanlist must use consecutive channels"); - err++; - break; - } - } - if (cmd->chanlist_len == 3) { - comedi_error(dev, - "chanlist cannot be 3 channels long, use 1, 2, or 4 channels"); - err++; - } - } - } + /* Step 5: check channel list if it exists */ + if (cmd->chanlist && cmd->chanlist_len > 0) + err |= cb_pcidas64_ai_check_chanlist(dev, s, cmd); if (err) return 5; @@ -2208,8 +2235,8 @@ static int use_hw_sample_counter(struct comedi_cmd *cmd) if (cmd->stop_src == TRIG_COUNT && cmd->stop_arg <= max_counter_value) return 1; - else - return 0; + + return 0; } static void setup_sample_counters(struct comedi_device *dev, @@ -2217,10 +2244,6 @@ static void setup_sample_counters(struct comedi_device *dev, { struct pcidas64_private *devpriv = dev->private; - if (cmd->stop_src == TRIG_COUNT) { - /* set software count */ - devpriv->ai_count = cmd->stop_arg * cmd->chanlist_len; - } /* load hardware conversion counter */ if (use_hw_sample_counter(cmd)) { writew(cmd->stop_arg & 0xffff, @@ -2234,12 +2257,12 @@ static void setup_sample_counters(struct comedi_device *dev, static inline unsigned int dma_transfer_size(struct comedi_device *dev) { - const struct pcidas64_board *thisboard = comedi_board(dev); + const struct pcidas64_board *board = dev->board_ptr; struct pcidas64_private *devpriv = dev->private; unsigned int num_samples; num_samples = devpriv->ai_fifo_segment_length * - thisboard->ai_fifo->sample_packing_ratio; + board->ai_fifo->sample_packing_ratio; if (num_samples > DMA_BUFFER_SIZE / sizeof(uint16_t)) num_samples = DMA_BUFFER_SIZE / sizeof(uint16_t); @@ -2270,7 +2293,6 @@ static uint32_t ai_scan_counter_6xxx(struct comedi_device *dev, break; default: return 0; - break; } return count - 3; } @@ -2289,7 +2311,7 @@ static uint32_t ai_convert_counter_4020(struct comedi_device *dev, divisor = devpriv->ext_clock.divisor; break; default: /* should never happen */ - comedi_error(dev, "bug! failed to set ai pacing!"); + dev_err(dev->class_dev, "bug! failed to set ai pacing!\n"); divisor = 1000; break; } @@ -2322,9 +2344,9 @@ static void select_master_clock_4020(struct comedi_device *dev, static void select_master_clock(struct comedi_device *dev, const struct comedi_cmd *cmd) { - const struct pcidas64_board *thisboard = comedi_board(dev); + const struct pcidas64_board *board = dev->board_ptr; - switch (thisboard->layout) { + switch (board->layout) { case LAYOUT_4020: select_master_clock_4020(dev, cmd); break; @@ -2354,7 +2376,7 @@ static inline void dma_start_sync(struct comedi_device *dev, static void set_ai_pacing(struct comedi_device *dev, struct comedi_cmd *cmd) { - const struct pcidas64_board *thisboard = comedi_board(dev); + const struct pcidas64_board *board = dev->board_ptr; struct pcidas64_private *devpriv = dev->private; uint32_t convert_counter = 0, scan_counter = 0; @@ -2362,7 +2384,7 @@ static void set_ai_pacing(struct comedi_device *dev, struct comedi_cmd *cmd) select_master_clock(dev, cmd); - if (thisboard->layout == LAYOUT_4020) { + if (board->layout == LAYOUT_4020) { convert_counter = ai_convert_counter_4020(dev, cmd); } else { convert_counter = ai_convert_counter_6xxx(dev, cmd); @@ -2372,7 +2394,6 @@ static void set_ai_pacing(struct comedi_device *dev, struct comedi_cmd *cmd) /* load lower 16 bits of convert interval */ writew(convert_counter & 0xffff, devpriv->main_iobase + ADC_SAMPLE_INTERVAL_LOWER_REG); - DEBUG_PRINT("convert counter 0x%x\n", convert_counter); /* load upper 8 bits of convert interval */ writew((convert_counter >> 16) & 0xff, devpriv->main_iobase + ADC_SAMPLE_INTERVAL_UPPER_REG); @@ -2382,7 +2403,6 @@ static void set_ai_pacing(struct comedi_device *dev, struct comedi_cmd *cmd) /* load upper 8 bits of scan delay */ writew((scan_counter >> 16) & 0xff, devpriv->main_iobase + ADC_DELAY_INTERVAL_UPPER_REG); - DEBUG_PRINT("scan counter 0x%x\n", scan_counter); } static int use_internal_queue_6xxx(const struct comedi_cmd *cmd) @@ -2405,12 +2425,12 @@ static int use_internal_queue_6xxx(const struct comedi_cmd *cmd) static int setup_channel_queue(struct comedi_device *dev, const struct comedi_cmd *cmd) { - const struct pcidas64_board *thisboard = comedi_board(dev); + const struct pcidas64_board *board = dev->board_ptr; struct pcidas64_private *devpriv = dev->private; unsigned short bits; int i; - if (thisboard->layout != LAYOUT_4020) { + if (board->layout != LAYOUT_4020) { if (use_internal_queue_6xxx(cmd)) { devpriv->hw_config_bits &= ~EXT_QUEUE_BIT; writew(devpriv->hw_config_bits, @@ -2473,12 +2493,11 @@ static int setup_channel_queue(struct comedi_device *dev, writew(bits, devpriv->main_iobase + ADC_QUEUE_FIFO_REG); - DEBUG_PRINT( - "wrote 0x%x to external channel queue\n", - bits); } - /* doing a queue clear is not specified in board docs, - * but required for reliable operation */ + /* + * doing a queue clear is not specified in board docs, + * but required for reliable operation + */ writew(0, devpriv->main_iobase + ADC_QUEUE_CLEAR_REG); /* prime queue holding register */ writew(0, devpriv->main_iobase + ADC_QUEUE_LOAD_REG); @@ -2501,10 +2520,13 @@ static int setup_channel_queue(struct comedi_device *dev, devpriv->i2c_cal_range_bits &= ~attenuate_bit(channel); } - /* update calibration/range i2c register only if necessary, - * as it is very slow */ + /* + * update calibration/range i2c register only if necessary, + * as it is very slow + */ if (old_cal_range_bits != devpriv->i2c_cal_range_bits) { uint8_t i2c_data = devpriv->i2c_cal_range_bits; + i2c_write(dev, RANGE_CAL_I2C_ADDR, &i2c_data, sizeof(i2c_data)); } @@ -2518,11 +2540,13 @@ static inline void load_first_dma_descriptor(struct comedi_device *dev, { struct pcidas64_private *devpriv = dev->private; - /* The transfer size, pci address, and local address registers + /* + * The transfer size, pci address, and local address registers * are supposedly unused during chained dma, * but I have found that left over values from last operation * occasionally cause problems with transfer of first dma - * block. Initializing them to zero seems to fix the problem. */ + * block. Initializing them to zero seems to fix the problem. + */ if (dma_channel) { writel(0, devpriv->plx9080_iobase + PLX_DMA1_TRANSFER_SIZE_REG); @@ -2544,7 +2568,7 @@ static inline void load_first_dma_descriptor(struct comedi_device *dev, static int ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) { - const struct pcidas64_board *thisboard = comedi_board(dev); + const struct pcidas64_board *board = dev->board_ptr; struct pcidas64_private *devpriv = dev->private; struct comedi_async *async = s->async; struct comedi_cmd *cmd = &async->cmd; @@ -2573,7 +2597,7 @@ static int ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) /* set mode, allow conversions through software gate */ devpriv->adc_control1_bits |= ADC_SW_GATE_BIT; devpriv->adc_control1_bits &= ~ADC_DITHER_BIT; - if (thisboard->layout != LAYOUT_4020) { + if (board->layout != LAYOUT_4020) { devpriv->adc_control1_bits &= ~ADC_MODE_MASK; if (cmd->convert_src == TRIG_EXT) /* good old mode 13 */ @@ -2597,18 +2621,17 @@ static int ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) } writew(devpriv->adc_control1_bits, devpriv->main_iobase + ADC_CONTROL1_REG); - DEBUG_PRINT("control1 bits 0x%x\n", devpriv->adc_control1_bits); spin_unlock_irqrestore(&dev->spinlock, flags); /* clear adc buffer */ writew(0, devpriv->main_iobase + ADC_BUFFER_CLEAR_REG); - if ((cmd->flags & TRIG_WAKE_EOS) == 0 || - thisboard->layout == LAYOUT_4020) { + if ((cmd->flags & CMDF_WAKE_EOS) == 0 || + board->layout == LAYOUT_4020) { devpriv->ai_dma_index = 0; /* set dma transfer size */ - for (i = 0; i < ai_dma_ring_count(thisboard); i++) + for (i = 0; i < ai_dma_ring_count(board); i++) devpriv->ai_dma_desc[i].transfer_size = cpu_to_le32(dma_transfer_size(dev) * sizeof(uint16_t)); @@ -2623,7 +2646,7 @@ static int ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) dma_start_sync(dev, 1); } - if (thisboard->layout == LAYOUT_4020) { + if (board->layout == LAYOUT_4020) { /* set source for external triggers */ bits = 0; if (cmd->start_src == TRIG_EXT && CR_CHAN(cmd->start_arg)) @@ -2637,29 +2660,27 @@ static int ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) /* enable pacing, triggering, etc */ bits = ADC_ENABLE_BIT | ADC_SOFT_GATE_BITS | ADC_GATE_LEVEL_BIT; - if (cmd->flags & TRIG_WAKE_EOS) + if (cmd->flags & CMDF_WAKE_EOS) bits |= ADC_DMA_DISABLE_BIT; /* set start trigger */ if (cmd->start_src == TRIG_EXT) { bits |= ADC_START_TRIG_EXT_BITS; if (cmd->start_arg & CR_INVERT) bits |= ADC_START_TRIG_FALLING_BIT; - } else if (cmd->start_src == TRIG_NOW) + } else if (cmd->start_src == TRIG_NOW) { bits |= ADC_START_TRIG_SOFT_BITS; + } if (use_hw_sample_counter(cmd)) bits |= ADC_SAMPLE_COUNTER_EN_BIT; writew(bits, devpriv->main_iobase + ADC_CONTROL0_REG); - DEBUG_PRINT("control0 bits 0x%x\n", bits); devpriv->ai_cmd_running = 1; spin_unlock_irqrestore(&dev->spinlock, flags); /* start acquisition */ - if (cmd->start_src == TRIG_NOW) { + if (cmd->start_src == TRIG_NOW) writew(0, devpriv->main_iobase + ADC_START_REG); - DEBUG_PRINT("soft trig\n"); - } return 0; } @@ -2669,8 +2690,6 @@ static void pio_drain_ai_fifo_16(struct comedi_device *dev) { struct pcidas64_private *devpriv = dev->private; struct comedi_subdevice *s = dev->read_subdev; - struct comedi_async *async = s->async; - struct comedi_cmd *cmd = &async->cmd; unsigned int i; uint16_t prepost_bits; int read_segment, read_index, write_segment, write_index; @@ -2682,55 +2701,49 @@ static void pio_drain_ai_fifo_16(struct comedi_device *dev) 0x7fff; write_index = readw(devpriv->main_iobase + ADC_WRITE_PNTR_REG) & 0x7fff; - /* Get most significant bits (grey code). + /* + * Get most significant bits (grey code). * Different boards use different code so use a scheme * that doesn't depend on encoding. This read must * occur after reading least significant 15 bits to avoid race - * with fifo switching to next segment. */ + * with fifo switching to next segment. + */ prepost_bits = readw(devpriv->main_iobase + PREPOST_REG); - /* if read and write pointers are not on the same fifo segment, - * read to the end of the read segment */ + /* + * if read and write pointers are not on the same fifo segment, + * read to the end of the read segment + */ read_segment = adc_upper_read_ptr_code(prepost_bits); write_segment = adc_upper_write_ptr_code(prepost_bits); - DEBUG_PRINT(" rd seg %i, wrt seg %i, rd idx %i, wrt idx %i\n", - read_segment, write_segment, read_index, - write_index); - if (read_segment != write_segment) num_samples = devpriv->ai_fifo_segment_length - read_index; else num_samples = write_index - read_index; - - if (cmd->stop_src == TRIG_COUNT) { - if (devpriv->ai_count == 0) - break; - if (num_samples > devpriv->ai_count) - num_samples = devpriv->ai_count; - - devpriv->ai_count -= num_samples; - } - if (num_samples < 0) { dev_err(dev->class_dev, "cb_pcidas64: bug! num_samples < 0\n"); break; } - DEBUG_PRINT(" read %i samples from fifo\n", num_samples); + num_samples = comedi_nsamples_left(s, num_samples); + if (num_samples == 0) + break; for (i = 0; i < num_samples; i++) { - cfc_write_to_buffer(s, - readw(devpriv->main_iobase + - ADC_FIFO_REG)); + unsigned short val; + + val = readw(devpriv->main_iobase + ADC_FIFO_REG); + comedi_buf_write_samples(s, &val, 1); } } while (read_segment != write_segment); } -/* Read from 32 bit wide ai fifo of 4020 - deal with insane grey coding of +/* + * Read from 32 bit wide ai fifo of 4020 - deal with insane grey coding of * pointers. The pci-4020 hardware only supports dma transfers (it only * supports the use of pio for draining the last remaining points from the * fifo when a data acquisition operation has completed). @@ -2739,41 +2752,38 @@ static void pio_drain_ai_fifo_32(struct comedi_device *dev) { struct pcidas64_private *devpriv = dev->private; struct comedi_subdevice *s = dev->read_subdev; - struct comedi_async *async = s->async; - struct comedi_cmd *cmd = &async->cmd; + unsigned int nsamples; unsigned int i; - unsigned int max_transfer = 100000; uint32_t fifo_data; int write_code = readw(devpriv->main_iobase + ADC_WRITE_PNTR_REG) & 0x7fff; int read_code = readw(devpriv->main_iobase + ADC_READ_PNTR_REG) & 0x7fff; - if (cmd->stop_src == TRIG_COUNT) { - if (max_transfer > devpriv->ai_count) - max_transfer = devpriv->ai_count; + nsamples = comedi_nsamples_left(s, 100000); + for (i = 0; read_code != write_code && i < nsamples;) { + unsigned short val; - } - for (i = 0; read_code != write_code && i < max_transfer;) { - fifo_data = readl(devpriv->dio_counter_iobase + ADC_FIFO_REG); - cfc_write_to_buffer(s, fifo_data & 0xffff); + fifo_data = readl(dev->mmio + ADC_FIFO_REG); + val = fifo_data & 0xffff; + comedi_buf_write_samples(s, &val, 1); i++; - if (i < max_transfer) { - cfc_write_to_buffer(s, (fifo_data >> 16) & 0xffff); + if (i < nsamples) { + val = (fifo_data >> 16) & 0xffff; + comedi_buf_write_samples(s, &val, 1); i++; } read_code = readw(devpriv->main_iobase + ADC_READ_PNTR_REG) & 0x7fff; } - devpriv->ai_count -= i; } /* empty fifo */ static void pio_drain_ai_fifo(struct comedi_device *dev) { - const struct pcidas64_board *thisboard = comedi_board(dev); + const struct pcidas64_board *board = dev->board_ptr; - if (thisboard->layout == LAYOUT_4020) + if (board->layout == LAYOUT_4020) pio_drain_ai_fifo_32(dev); else pio_drain_ai_fifo_16(dev); @@ -2781,9 +2791,9 @@ static void pio_drain_ai_fifo(struct comedi_device *dev) static void drain_dma_buffers(struct comedi_device *dev, unsigned int channel) { - const struct pcidas64_board *thisboard = comedi_board(dev); + const struct pcidas64_board *board = dev->board_ptr; struct pcidas64_private *devpriv = dev->private; - struct comedi_async *async = dev->read_subdev->async; + struct comedi_subdevice *s = dev->read_subdev; uint32_t next_transfer_addr; int j; int num_samples = 0; @@ -2802,35 +2812,26 @@ static void drain_dma_buffers(struct comedi_device *dev, unsigned int channel) devpriv->ai_buffer_bus_addr[devpriv->ai_dma_index] || next_transfer_addr >= devpriv->ai_buffer_bus_addr[devpriv->ai_dma_index] + - DMA_BUFFER_SIZE) && j < ai_dma_ring_count(thisboard); j++) { + DMA_BUFFER_SIZE) && j < ai_dma_ring_count(board); j++) { /* transfer data from dma buffer to comedi buffer */ - num_samples = dma_transfer_size(dev); - if (async->cmd.stop_src == TRIG_COUNT) { - if (num_samples > devpriv->ai_count) - num_samples = devpriv->ai_count; - devpriv->ai_count -= num_samples; - } - cfc_write_array_to_buffer(dev->read_subdev, - devpriv->ai_buffer[devpriv-> - ai_dma_index], - num_samples * sizeof(uint16_t)); + num_samples = comedi_nsamples_left(s, dma_transfer_size(dev)); + comedi_buf_write_samples(s, + devpriv->ai_buffer[devpriv->ai_dma_index], + num_samples); devpriv->ai_dma_index = (devpriv->ai_dma_index + 1) % - ai_dma_ring_count(thisboard); - - DEBUG_PRINT("next buffer addr 0x%lx\n", - (unsigned long)devpriv-> - ai_buffer_bus_addr[devpriv->ai_dma_index]); - DEBUG_PRINT("pci addr reg 0x%x\n", next_transfer_addr); + ai_dma_ring_count(board); } - /* XXX check for dma ring buffer overrun - * (use end-of-chain bit to mark last unused buffer) */ + /* + * XXX check for dma ring buffer overrun + * (use end-of-chain bit to mark last unused buffer) + */ } static void handle_ai_interrupt(struct comedi_device *dev, unsigned short status, unsigned int plx_status) { - const struct pcidas64_board *thisboard = comedi_board(dev); + const struct pcidas64_board *board = dev->board_ptr; struct pcidas64_private *devpriv = dev->private; struct comedi_subdevice *s = dev->read_subdev; struct comedi_async *async = s->async; @@ -2840,8 +2841,8 @@ static void handle_ai_interrupt(struct comedi_device *dev, /* check for fifo overrun */ if (status & ADC_OVERRUN_BIT) { - comedi_error(dev, "fifo overrun"); - async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR; + dev_err(dev->class_dev, "fifo overrun\n"); + async->events |= COMEDI_CB_ERROR; } /* spin lock makes sure no one else changes plx dma control reg */ spin_lock_irqsave(&dev->spinlock, flags); @@ -2849,38 +2850,32 @@ static void handle_ai_interrupt(struct comedi_device *dev, if (plx_status & ICS_DMA1_A) { /* dma chan 1 interrupt */ writeb((dma1_status & PLX_DMA_EN_BIT) | PLX_CLEAR_DMA_INTR_BIT, devpriv->plx9080_iobase + PLX_DMA1_CS_REG); - DEBUG_PRINT("dma1 status 0x%x\n", dma1_status); if (dma1_status & PLX_DMA_EN_BIT) drain_dma_buffers(dev, 1); - - DEBUG_PRINT(" cleared dma ch1 interrupt\n"); } spin_unlock_irqrestore(&dev->spinlock, flags); - if (status & ADC_DONE_BIT) - DEBUG_PRINT("adc done interrupt\n"); - /* drain fifo with pio */ if ((status & ADC_DONE_BIT) || - ((cmd->flags & TRIG_WAKE_EOS) && + ((cmd->flags & CMDF_WAKE_EOS) && (status & ADC_INTR_PENDING_BIT) && - (thisboard->layout != LAYOUT_4020))) { - DEBUG_PRINT("pio fifo drain\n"); + (board->layout != LAYOUT_4020))) { spin_lock_irqsave(&dev->spinlock, flags); if (devpriv->ai_cmd_running) { spin_unlock_irqrestore(&dev->spinlock, flags); pio_drain_ai_fifo(dev); - } else + } else { spin_unlock_irqrestore(&dev->spinlock, flags); + } } /* if we are have all the data, then quit */ - if ((cmd->stop_src == TRIG_COUNT && (int)devpriv->ai_count <= 0) || - (cmd->stop_src == TRIG_EXT && (status & ADC_STOP_BIT))) { + if ((cmd->stop_src == TRIG_COUNT && + async->scans_done >= cmd->stop_arg) || + (cmd->stop_src == TRIG_EXT && (status & ADC_STOP_BIT))) async->events |= COMEDI_CB_EOA; - } - cfc_handle_events(dev, s); + comedi_handle_events(dev, s); } static inline unsigned int prev_ao_dma_index(struct comedi_device *dev) @@ -2915,22 +2910,6 @@ static int last_ao_dma_load_completed(struct comedi_device *dev) return 1; } -static int ao_stopped_by_error(struct comedi_device *dev, - const struct comedi_cmd *cmd) -{ - struct pcidas64_private *devpriv = dev->private; - - if (cmd->stop_src == TRIG_NONE) - return 1; - if (cmd->stop_src == TRIG_COUNT) { - if (devpriv->ao_count) - return 1; - if (last_ao_dma_load_completed(dev) == 0) - return 1; - } - return 0; -} - static inline int ao_dma_needs_restart(struct comedi_device *dev, unsigned short dma_status) { @@ -2951,58 +2930,59 @@ static void restart_ao_dma(struct comedi_device *dev) dma_desc_bits = readl(devpriv->plx9080_iobase + PLX_DMA0_DESCRIPTOR_REG); dma_desc_bits &= ~PLX_END_OF_CHAIN_BIT; - DEBUG_PRINT("restarting ao dma, descriptor reg 0x%x\n", dma_desc_bits); load_first_dma_descriptor(dev, 0, dma_desc_bits); dma_start_sync(dev, 0); } +static unsigned int cb_pcidas64_ao_fill_buffer(struct comedi_device *dev, + struct comedi_subdevice *s, + unsigned short *dest, + unsigned int max_bytes) +{ + unsigned int nsamples = comedi_bytes_to_samples(s, max_bytes); + unsigned int actual_bytes; + + nsamples = comedi_nsamples_left(s, nsamples); + actual_bytes = comedi_buf_read_samples(s, dest, nsamples); + + return comedi_bytes_to_samples(s, actual_bytes); +} + static unsigned int load_ao_dma_buffer(struct comedi_device *dev, const struct comedi_cmd *cmd) { struct pcidas64_private *devpriv = dev->private; - unsigned int num_bytes, buffer_index, prev_buffer_index; + struct comedi_subdevice *s = dev->write_subdev; + unsigned int buffer_index = devpriv->ao_dma_index; + unsigned int prev_buffer_index = prev_ao_dma_index(dev); + unsigned int nsamples; + unsigned int nbytes; unsigned int next_bits; - buffer_index = devpriv->ao_dma_index; - prev_buffer_index = prev_ao_dma_index(dev); - - DEBUG_PRINT("attempting to load ao buffer %i (0x%llx)\n", buffer_index, - (unsigned long long)devpriv->ao_buffer_bus_addr[ - buffer_index]); - - num_bytes = comedi_buf_read_n_available(dev->write_subdev->async); - if (num_bytes > DMA_BUFFER_SIZE) - num_bytes = DMA_BUFFER_SIZE; - if (cmd->stop_src == TRIG_COUNT && num_bytes > devpriv->ao_count) - num_bytes = devpriv->ao_count; - num_bytes -= num_bytes % bytes_in_sample; - - if (num_bytes == 0) + nsamples = cb_pcidas64_ao_fill_buffer(dev, s, + devpriv->ao_buffer[buffer_index], + DMA_BUFFER_SIZE); + if (nsamples == 0) return 0; - DEBUG_PRINT("loading %i bytes\n", num_bytes); - - num_bytes = cfc_read_array_from_buffer(dev->write_subdev, - devpriv-> - ao_buffer[buffer_index], - num_bytes); - devpriv->ao_dma_desc[buffer_index].transfer_size = - cpu_to_le32(num_bytes); + nbytes = comedi_samples_to_bytes(s, nsamples); + devpriv->ao_dma_desc[buffer_index].transfer_size = cpu_to_le32(nbytes); /* set end of chain bit so we catch underruns */ next_bits = le32_to_cpu(devpriv->ao_dma_desc[buffer_index].next); next_bits |= PLX_END_OF_CHAIN_BIT; devpriv->ao_dma_desc[buffer_index].next = cpu_to_le32(next_bits); - /* clear end of chain bit on previous buffer now that we have set it - * for the last buffer */ + /* + * clear end of chain bit on previous buffer now that we have set it + * for the last buffer + */ next_bits = le32_to_cpu(devpriv->ao_dma_desc[prev_buffer_index].next); next_bits &= ~PLX_END_OF_CHAIN_BIT; devpriv->ao_dma_desc[prev_buffer_index].next = cpu_to_le32(next_bits); devpriv->ao_dma_index = (buffer_index + 1) % AO_DMA_RING_COUNT; - devpriv->ao_count -= num_bytes; - return num_bytes; + return nbytes; } static void load_ao_dma(struct comedi_device *dev, const struct comedi_cmd *cmd) @@ -3039,7 +3019,7 @@ static void handle_ao_interrupt(struct comedi_device *dev, unsigned long flags; /* board might not support ao, in which case write_subdev is NULL */ - if (s == NULL) + if (!s) return; async = s->async; cmd = &async->cmd; @@ -3056,30 +3036,25 @@ static void handle_ao_interrupt(struct comedi_device *dev, writeb(PLX_CLEAR_DMA_INTR_BIT, devpriv->plx9080_iobase + PLX_DMA0_CS_REG); spin_unlock_irqrestore(&dev->spinlock, flags); - DEBUG_PRINT("dma0 status 0x%x\n", dma0_status); if (dma0_status & PLX_DMA_EN_BIT) { load_ao_dma(dev, cmd); /* try to recover from dma end-of-chain event */ if (ao_dma_needs_restart(dev, dma0_status)) restart_ao_dma(dev); } - DEBUG_PRINT(" cleared dma ch0 interrupt\n"); } else { spin_unlock_irqrestore(&dev->spinlock, flags); } if ((status & DAC_DONE_BIT)) { - async->events |= COMEDI_CB_EOA; - if (ao_stopped_by_error(dev, cmd)) + if ((cmd->stop_src == TRIG_COUNT && + async->scans_done >= cmd->stop_arg) || + last_ao_dma_load_completed(dev)) + async->events |= COMEDI_CB_EOA; + else async->events |= COMEDI_CB_ERROR; - DEBUG_PRINT("plx dma0 desc reg 0x%x\n", - readl(devpriv->plx9080_iobase + - PLX_DMA0_DESCRIPTOR_REG)); - DEBUG_PRINT("plx dma0 address reg 0x%x\n", - readl(devpriv->plx9080_iobase + - PLX_DMA0_PCI_ADDRESS_REG)); } - cfc_handle_events(dev, s); + comedi_handle_events(dev, s); } static irqreturn_t handle_interrupt(int irq, void *d) @@ -3093,15 +3068,14 @@ static irqreturn_t handle_interrupt(int irq, void *d) plx_status = readl(devpriv->plx9080_iobase + PLX_INTRCS_REG); status = readw(devpriv->main_iobase + HW_STATUS_REG); - DEBUG_PRINT("hw status 0x%x, plx status 0x%x\n", status, plx_status); - - /* an interrupt before all the postconfig stuff gets done could + /* + * an interrupt before all the postconfig stuff gets done could * cause a NULL dereference if we continue through the - * interrupt handler */ - if (!dev->attached) { - DEBUG_PRINT("premature interrupt, ignoring\n"); + * interrupt handler + */ + if (!dev->attached) return IRQ_HANDLED; - } + handle_ai_interrupt(dev, status, plx_status); handle_ao_interrupt(dev, status, plx_status); @@ -3109,11 +3083,8 @@ static irqreturn_t handle_interrupt(int irq, void *d) if (plx_status & ICS_LDIA) { /* clear local doorbell interrupt */ plx_bits = readl(devpriv->plx9080_iobase + PLX_DBR_OUT_REG); writel(plx_bits, devpriv->plx9080_iobase + PLX_DBR_OUT_REG); - DEBUG_PRINT(" cleared local doorbell bits 0x%x\n", plx_bits); } - DEBUG_PRINT("exiting handler\n"); - return IRQ_HANDLED; } @@ -3134,14 +3105,13 @@ static int ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s) abort_dma(dev, 1); - DEBUG_PRINT("ai canceled\n"); return 0; } static int ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { - const struct pcidas64_board *thisboard = comedi_board(dev); + const struct pcidas64_board *board = dev->board_ptr; struct pcidas64_private *devpriv = dev->private; int chan = CR_CHAN(insn->chanspec); int range = CR_RANGE(insn->chanspec); @@ -3155,7 +3125,7 @@ static int ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s, devpriv->main_iobase + DAC_CONTROL1_REG); /* write to channel */ - if (thisboard->layout == LAYOUT_4020) { + if (board->layout == LAYOUT_4020) { writew(data[0] & 0xff, devpriv->main_iobase + dac_lsb_4020_reg(chan)); writew((data[0] >> 8) & 0xf, @@ -3165,18 +3135,7 @@ static int ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s, } /* remember output value */ - devpriv->ao_value[chan] = data[0]; - - return 1; -} - -static int ao_readback_insn(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) -{ - struct pcidas64_private *devpriv = dev->private; - - data[0] = devpriv->ao_value[CR_CHAN(insn->chanspec)]; + s->readback[chan] = data[0]; return 1; } @@ -3232,7 +3191,8 @@ static void set_dac_select_reg(struct comedi_device *dev, first_channel = CR_CHAN(cmd->chanlist[0]); last_channel = CR_CHAN(cmd->chanlist[cmd->chanlist_len - 1]); if (last_channel < first_channel) - comedi_error(dev, "bug! last ao channel < first ao channel"); + dev_err(dev->class_dev, + "bug! last ao channel < first ao channel\n"); bits = (first_channel & 0x7) | (last_channel & 0x7) << 3; @@ -3255,7 +3215,7 @@ static void set_dac_interval_regs(struct comedi_device *dev, divisor = get_ao_divisor(cmd->scan_begin_arg, cmd->flags); if (divisor > max_counter_value) { - comedi_error(dev, "bug! ao divisor too big"); + dev_err(dev->class_dev, "bug! ao divisor too big\n"); divisor = max_counter_value; } writew(divisor & 0xffff, @@ -3267,30 +3227,35 @@ static void set_dac_interval_regs(struct comedi_device *dev, static int prep_ao_dma(struct comedi_device *dev, const struct comedi_cmd *cmd) { struct pcidas64_private *devpriv = dev->private; - unsigned int num_bytes; + struct comedi_subdevice *s = dev->write_subdev; + unsigned int nsamples; + unsigned int nbytes; int i; - /* clear queue pointer too, since external queue has - * weird interactions with ao fifo */ + /* + * clear queue pointer too, since external queue has + * weird interactions with ao fifo + */ writew(0, devpriv->main_iobase + ADC_QUEUE_CLEAR_REG); writew(0, devpriv->main_iobase + DAC_BUFFER_CLEAR_REG); - num_bytes = (DAC_FIFO_SIZE / 2) * bytes_in_sample; - if (cmd->stop_src == TRIG_COUNT && - num_bytes / bytes_in_sample > devpriv->ao_count) - num_bytes = devpriv->ao_count * bytes_in_sample; - num_bytes = cfc_read_array_from_buffer(dev->write_subdev, - devpriv->ao_bounce_buffer, - num_bytes); - for (i = 0; i < num_bytes / bytes_in_sample; i++) { + nsamples = cb_pcidas64_ao_fill_buffer(dev, s, + devpriv->ao_bounce_buffer, + DAC_FIFO_SIZE); + if (nsamples == 0) + return -1; + + for (i = 0; i < nsamples; i++) { writew(devpriv->ao_bounce_buffer[i], devpriv->main_iobase + DAC_FIFO_REG); } - devpriv->ao_count -= num_bytes / bytes_in_sample; - if (cmd->stop_src == TRIG_COUNT && devpriv->ao_count == 0) + + if (cmd->stop_src == TRIG_COUNT && + s->async->scans_done >= cmd->stop_arg) return 0; - num_bytes = load_ao_dma_buffer(dev, cmd); - if (num_bytes == 0) + + nbytes = load_ao_dma_buffer(dev, cmd); + if (nbytes == 0) return -1; load_ao_dma(dev, cmd); @@ -3299,15 +3264,17 @@ static int prep_ao_dma(struct comedi_device *dev, const struct comedi_cmd *cmd) return 0; } -static inline int external_ai_queue_in_use(struct comedi_device *dev) +static inline int external_ai_queue_in_use(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_cmd *cmd) { - const struct pcidas64_board *thisboard = comedi_board(dev); + const struct pcidas64_board *board = dev->board_ptr; - if (dev->read_subdev->busy) + if (s->busy) return 0; - if (thisboard->layout == LAYOUT_4020) + if (board->layout == LAYOUT_4020) return 0; - else if (use_internal_queue_6xxx(&dev->read_subdev->async->cmd)) + else if (use_internal_queue_6xxx(cmd)) return 0; return 1; } @@ -3319,7 +3286,7 @@ static int ao_inttrig(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_cmd *cmd = &s->async->cmd; int retval; - if (trig_num != 0) + if (trig_num != cmd->start_arg) return -EINVAL; retval = prep_ao_dma(dev, cmd); @@ -3341,7 +3308,7 @@ static int ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s) struct pcidas64_private *devpriv = dev->private; struct comedi_cmd *cmd = &s->async->cmd; - if (external_ai_queue_in_use(dev)) { + if (external_ai_queue_in_use(dev, s, cmd)) { warn_external_queue(dev); return -EBUSY; } @@ -3349,7 +3316,6 @@ static int ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s) writew(0x0, devpriv->main_iobase + DAC_CONTROL0_REG); devpriv->ao_dma_index = 0; - devpriv->ao_count = cmd->stop_arg * cmd->chanlist_len; set_dac_select_reg(dev, cmd); set_dac_interval_regs(dev, cmd); @@ -3362,30 +3328,49 @@ static int ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s) return 0; } +static int cb_pcidas64_ao_check_chanlist(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_cmd *cmd) +{ + unsigned int chan0 = CR_CHAN(cmd->chanlist[0]); + int i; + + for (i = 1; i < cmd->chanlist_len; i++) { + unsigned int chan = CR_CHAN(cmd->chanlist[i]); + + if (chan != (chan0 + i)) { + dev_dbg(dev->class_dev, + "chanlist must use consecutive channels\n"); + return -EINVAL; + } + } + + return 0; +} + static int ao_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_cmd *cmd) { - const struct pcidas64_board *thisboard = comedi_board(dev); + const struct pcidas64_board *board = dev->board_ptr; int err = 0; unsigned int tmp_arg; - int i; /* Step 1 : check if triggers are trivially valid */ - err |= cfc_check_trigger_src(&cmd->start_src, TRIG_INT | TRIG_EXT); - err |= cfc_check_trigger_src(&cmd->scan_begin_src, - TRIG_TIMER | TRIG_EXT); - err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_NOW); - err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT); - err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_NONE); + err |= comedi_check_trigger_src(&cmd->start_src, TRIG_INT | TRIG_EXT); + err |= comedi_check_trigger_src(&cmd->scan_begin_src, + TRIG_TIMER | TRIG_EXT); + err |= comedi_check_trigger_src(&cmd->convert_src, TRIG_NOW); + err |= comedi_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT); + err |= comedi_check_trigger_src(&cmd->stop_src, TRIG_NONE); if (err) return 1; /* Step 2a : make sure trigger sources are unique */ - err |= cfc_check_trigger_is_unique(cmd->start_src); - err |= cfc_check_trigger_is_unique(cmd->scan_begin_src); + err |= comedi_check_trigger_is_unique(cmd->start_src); + err |= comedi_check_trigger_is_unique(cmd->scan_begin_src); /* Step 2b : and mutually compatible */ @@ -3400,9 +3385,11 @@ static int ao_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, /* Step 3: check if arguments are trivially valid */ + err |= comedi_check_trigger_arg_is(&cmd->start_arg, 0); + if (cmd->scan_begin_src == TRIG_TIMER) { - err |= cfc_check_trigger_arg_min(&cmd->scan_begin_arg, - thisboard->ao_scan_speed); + err |= comedi_check_trigger_arg_min(&cmd->scan_begin_arg, + board->ao_scan_speed); if (get_ao_divisor(cmd->scan_begin_arg, cmd->flags) > max_counter_value) { cmd->scan_begin_arg = (max_counter_value + 2) * @@ -3411,8 +3398,9 @@ static int ao_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, } } - err |= cfc_check_trigger_arg_min(&cmd->chanlist_len, 1); - err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len); + err |= comedi_check_trigger_arg_min(&cmd->chanlist_len, 1); + err |= comedi_check_trigger_arg_is(&cmd->scan_end_arg, + cmd->chanlist_len); if (err) return 3; @@ -3430,17 +3418,9 @@ static int ao_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, if (err) return 4; - if (cmd->chanlist) { - unsigned int first_channel = CR_CHAN(cmd->chanlist[0]); - for (i = 1; i < cmd->chanlist_len; i++) { - if (CR_CHAN(cmd->chanlist[i]) != first_channel + i) { - comedi_error(dev, - "chanlist must use consecutive channels"); - err++; - break; - } - } - } + /* Step 5: check channel list if it exists */ + if (cmd->chanlist && cmd->chanlist_len > 0) + err |= cb_pcidas64_ao_check_chanlist(dev, s, cmd); if (err) return 5; @@ -3457,36 +3437,24 @@ static int ao_cancel(struct comedi_device *dev, struct comedi_subdevice *s) return 0; } -static int dio_callback(int dir, int port, int data, unsigned long arg) +static int dio_callback_4020(struct comedi_device *dev, + int dir, int port, int data, unsigned long iobase) { - void __iomem *iobase = (void __iomem *)arg; - if (dir) { - writeb(data, iobase + port); - DEBUG_PRINT("wrote 0x%x to port %i\n", data, port); - return 0; - } else { - return readb(iobase + port); - } -} + struct pcidas64_private *devpriv = dev->private; -static int dio_callback_4020(int dir, int port, int data, unsigned long arg) -{ - void __iomem *iobase = (void __iomem *)arg; if (dir) { - writew(data, iobase + 2 * port); + writew(data, devpriv->main_iobase + iobase + 2 * port); return 0; - } else { - return readw(iobase + 2 * port); } + return readw(devpriv->main_iobase + iobase + 2 * port); } static int di_rbits(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { - struct pcidas64_private *devpriv = dev->private; unsigned int bits; - bits = readb(devpriv->dio_counter_iobase + DI_REG); + bits = readb(dev->mmio + DI_REG); bits &= 0xf; data[1] = bits; data[0] = 0; @@ -3494,18 +3462,13 @@ static int di_rbits(struct comedi_device *dev, struct comedi_subdevice *s, return insn->n; } -static int do_wbits(struct comedi_device *dev, struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) +static int do_wbits(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data) { - struct pcidas64_private *devpriv = dev->private; - - data[0] &= 0xf; - /* zero bits we are going to change */ - s->state &= ~data[0]; - /* set new bits */ - s->state |= data[0] & data[1]; - - writeb(s->state, devpriv->dio_counter_iobase + DO_REG); + if (comedi_dio_update_state(s, data)) + writeb(s->state, dev->mmio + DO_REG); data[1] = s->state; @@ -3514,51 +3477,35 @@ static int do_wbits(struct comedi_device *dev, struct comedi_subdevice *s, static int dio_60xx_config_insn(struct comedi_device *dev, struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) + struct comedi_insn *insn, + unsigned int *data) { - struct pcidas64_private *devpriv = dev->private; - unsigned int mask; - - mask = 1 << CR_CHAN(insn->chanspec); + int ret; - switch (data[0]) { - case INSN_CONFIG_DIO_INPUT: - s->io_bits &= ~mask; - break; - case INSN_CONFIG_DIO_OUTPUT: - s->io_bits |= mask; - break; - case INSN_CONFIG_DIO_QUERY: - data[1] = (s->io_bits & mask) ? COMEDI_OUTPUT : COMEDI_INPUT; - return 2; - default: - return -EINVAL; - } + ret = comedi_dio_insn_config(dev, s, insn, data, 0); + if (ret) + return ret; - writeb(s->io_bits, - devpriv->dio_counter_iobase + DIO_DIRECTION_60XX_REG); + writeb(s->io_bits, dev->mmio + DIO_DIRECTION_60XX_REG); - return 1; + return insn->n; } -static int dio_60xx_wbits(struct comedi_device *dev, struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) +static int dio_60xx_wbits(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data) { - struct pcidas64_private *devpriv = dev->private; - - if (data[0]) { - s->state &= ~data[0]; - s->state |= (data[0] & data[1]); - writeb(s->state, - devpriv->dio_counter_iobase + DIO_DATA_60XX_REG); - } + if (comedi_dio_update_state(s, data)) + writeb(s->state, dev->mmio + DIO_DATA_60XX_REG); - data[1] = readb(devpriv->dio_counter_iobase + DIO_DATA_60XX_REG); + data[1] = readb(dev->mmio + DIO_DATA_60XX_REG); return insn->n; } -/* pci-6025 8800 caldac: +/* + * pci-6025 8800 caldac: * address 0 == dac channel 0 offset * address 1 == dac channel 0 gain * address 2 == dac channel 1 offset @@ -3568,7 +3515,8 @@ static int dio_60xx_wbits(struct comedi_device *dev, struct comedi_subdevice *s, * address 6 == coarse adc gain * address 7 == fine adc gain */ -/* pci-6402/16 uses all 8 channels for dac: +/* + * pci-6402/16 uses all 8 channels for dac: * address 0 == dac channel 0 fine gain * address 1 == dac channel 0 coarse gain * address 2 == dac channel 0 coarse offset @@ -3577,7 +3525,7 @@ static int dio_60xx_wbits(struct comedi_device *dev, struct comedi_subdevice *s, * address 5 == dac channel 1 coarse gain * address 6 == dac channel 0 fine offset * address 7 == dac channel 1 fine offset -*/ + */ static int caldac_8800_write(struct comedi_device *dev, unsigned int address, uint8_t value) @@ -3590,7 +3538,7 @@ static int caldac_8800_write(struct comedi_device *dev, unsigned int address, static const int caldac_8800_udelay = 1; if (address >= num_caldac_channels) { - comedi_error(dev, "illegal caldac channel"); + dev_err(dev->class_dev, "illegal caldac channel\n"); return -1; } for (bit = 1 << (bitstream_length - 1); bit; bit >>= 1) { @@ -3662,9 +3610,8 @@ static int caldac_i2c_write(struct comedi_device *dev, serial_bytes[0] = GAIN_1_3; break; default: - comedi_error(dev, "invalid caldac channel\n"); + dev_err(dev->class_dev, "invalid caldac channel\n"); return -1; - break; } serial_bytes[1] = NOT_CLEAR_REGISTERS | ((value >> 8) & 0xf); serial_bytes[2] = value & 0xff; @@ -3675,12 +3622,9 @@ static int caldac_i2c_write(struct comedi_device *dev, static void caldac_write(struct comedi_device *dev, unsigned int channel, unsigned int value) { - const struct pcidas64_board *thisboard = comedi_board(dev); - struct pcidas64_private *devpriv = dev->private; + const struct pcidas64_board *board = dev->board_ptr; - devpriv->caldac_state[channel] = value; - - switch (thisboard->layout) { + switch (board->layout) { case LAYOUT_60XX: case LAYOUT_64XX: caldac_8800_write(dev, channel, value); @@ -3693,33 +3637,27 @@ static void caldac_write(struct comedi_device *dev, unsigned int channel, } } -static int calib_write_insn(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) +static int cb_pcidas64_calib_insn_write(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data) { - struct pcidas64_private *devpriv = dev->private; - int channel = CR_CHAN(insn->chanspec); + unsigned int chan = CR_CHAN(insn->chanspec); - /* return immediately if setting hasn't changed, since - * programming these things is slow */ - if (devpriv->caldac_state[channel] == data[0]) - return 1; - - caldac_write(dev, channel, data[0]); - - return 1; -} - -static int calib_read_insn(struct comedi_device *dev, - struct comedi_subdevice *s, struct comedi_insn *insn, - unsigned int *data) -{ - struct pcidas64_private *devpriv = dev->private; - unsigned int channel = CR_CHAN(insn->chanspec); + /* + * Programming the calib device is slow. Only write the + * last data value if the value has changed. + */ + if (insn->n) { + unsigned int val = data[insn->n - 1]; - data[0] = devpriv->caldac_state[channel]; + if (s->readback[chan] != val) { + caldac_write(dev, chan, val); + s->readback[chan] = val; + } + } - return 1; + return insn->n; } static void ad8402_write(struct comedi_device *dev, unsigned int channel, @@ -3731,8 +3669,6 @@ static void ad8402_write(struct comedi_device *dev, unsigned int channel, unsigned int bitstream = ((channel & 0x3) << 8) | (value & 0xff); static const int ad8402_udelay = 1; - devpriv->ad8402_state[channel] = value; - register_bits = SELECT_8402_64XX_BIT; udelay(ad8402_udelay); writew(register_bits, devpriv->main_iobase + CALIBRATION_REG); @@ -3754,35 +3690,27 @@ static void ad8402_write(struct comedi_device *dev, unsigned int channel, } /* for pci-das6402/16, channel 0 is analog input gain and channel 1 is offset */ -static int ad8402_write_insn(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) +static int cb_pcidas64_ad8402_insn_write(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data) { - struct pcidas64_private *devpriv = dev->private; - int channel = CR_CHAN(insn->chanspec); - - /* return immediately if setting hasn't changed, since - * programming these things is slow */ - if (devpriv->ad8402_state[channel] == data[0]) - return 1; - - devpriv->ad8402_state[channel] = data[0]; - - ad8402_write(dev, channel, data[0]); - - return 1; -} + unsigned int chan = CR_CHAN(insn->chanspec); -static int ad8402_read_insn(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) -{ - struct pcidas64_private *devpriv = dev->private; - unsigned int channel = CR_CHAN(insn->chanspec); + /* + * Programming the calib device is slow. Only write the + * last data value if the value has changed. + */ + if (insn->n) { + unsigned int val = data[insn->n - 1]; - data[0] = devpriv->ad8402_state[channel]; + if (s->readback[chan] != val) { + ad8402_write(dev, chan, val); + s->readback[chan] = val; + } + } - return 1; + return insn->n; } static uint16_t read_eeprom(struct comedi_device *dev, uint8_t address) @@ -3857,14 +3785,14 @@ static int eeprom_read_insn(struct comedi_device *dev, return 1; } -/* Allocate and initialize the subdevice structures. +/* + * Allocate and initialize the subdevice structures. */ static int setup_subdevices(struct comedi_device *dev) { - const struct pcidas64_board *thisboard = comedi_board(dev); + const struct pcidas64_board *board = dev->board_ptr; struct pcidas64_private *devpriv = dev->private; struct comedi_subdevice *s; - void __iomem *dio_8255_iobase; int i; int ret; @@ -3877,24 +3805,26 @@ static int setup_subdevices(struct comedi_device *dev) dev->read_subdev = s; s->type = COMEDI_SUBD_AI; s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_DITHER | SDF_CMD_READ; - if (thisboard->layout == LAYOUT_60XX) + if (board->layout == LAYOUT_60XX) s->subdev_flags |= SDF_COMMON | SDF_DIFF; - else if (thisboard->layout == LAYOUT_64XX) + else if (board->layout == LAYOUT_64XX) s->subdev_flags |= SDF_DIFF; /* XXX Number of inputs in differential mode is ignored */ - s->n_chan = thisboard->ai_se_chans; + s->n_chan = board->ai_se_chans; s->len_chanlist = 0x2000; - s->maxdata = (1 << thisboard->ai_bits) - 1; - s->range_table = thisboard->ai_range_table; + s->maxdata = (1 << board->ai_bits) - 1; + s->range_table = board->ai_range_table; s->insn_read = ai_rinsn; s->insn_config = ai_config_insn; s->do_cmd = ai_cmd; s->do_cmdtest = ai_cmdtest; s->cancel = ai_cancel; - if (thisboard->layout == LAYOUT_4020) { + if (board->layout == LAYOUT_4020) { uint8_t data; - /* set adc to read from inputs - * (not internal calibration sources) */ + /* + * set adc to read from inputs + * (not internal calibration sources) + */ devpriv->i2c_cal_range_bits = adc_src_4020_bits(4); /* set channels to +-5 volt input ranges */ for (i = 0; i < s->n_chan; i++) @@ -3905,20 +3835,24 @@ static int setup_subdevices(struct comedi_device *dev) /* analog output subdevice */ s = &dev->subdevices[1]; - if (thisboard->ao_nchan) { + if (board->ao_nchan) { s->type = COMEDI_SUBD_AO; s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_GROUND | SDF_CMD_WRITE; - s->n_chan = thisboard->ao_nchan; - s->maxdata = (1 << thisboard->ao_bits) - 1; - s->range_table = thisboard->ao_range_table; - s->insn_read = ao_readback_insn; + s->n_chan = board->ao_nchan; + s->maxdata = (1 << board->ao_bits) - 1; + s->range_table = board->ao_range_table; s->insn_write = ao_winsn; - if (ao_cmd_is_supported(thisboard)) { + + ret = comedi_alloc_subdev_readback(s); + if (ret) + return ret; + + if (ao_cmd_is_supported(board)) { dev->write_subdev = s; s->do_cmdtest = ao_cmdtest; s->do_cmd = ao_cmd; - s->len_chanlist = thisboard->ao_nchan; + s->len_chanlist = board->ao_nchan; s->cancel = ao_cancel; } } else { @@ -3927,47 +3861,49 @@ static int setup_subdevices(struct comedi_device *dev) /* digital input */ s = &dev->subdevices[2]; - if (thisboard->layout == LAYOUT_64XX) { + if (board->layout == LAYOUT_64XX) { s->type = COMEDI_SUBD_DI; s->subdev_flags = SDF_READABLE; s->n_chan = 4; s->maxdata = 1; s->range_table = &range_digital; s->insn_bits = di_rbits; - } else + } else { s->type = COMEDI_SUBD_UNUSED; + } /* digital output */ - if (thisboard->layout == LAYOUT_64XX) { + if (board->layout == LAYOUT_64XX) { s = &dev->subdevices[3]; s->type = COMEDI_SUBD_DO; - s->subdev_flags = SDF_WRITABLE | SDF_READABLE; + s->subdev_flags = SDF_WRITABLE; s->n_chan = 4; s->maxdata = 1; s->range_table = &range_digital; s->insn_bits = do_wbits; - } else + } else { s->type = COMEDI_SUBD_UNUSED; + } /* 8255 */ s = &dev->subdevices[4]; - if (thisboard->has_8255) { - if (thisboard->layout == LAYOUT_4020) { - dio_8255_iobase = devpriv->main_iobase + I8255_4020_REG; - subdev_8255_init(dev, s, dio_callback_4020, - (unsigned long)dio_8255_iobase); + if (board->has_8255) { + if (board->layout == LAYOUT_4020) { + ret = subdev_8255_init(dev, s, dio_callback_4020, + I8255_4020_REG); } else { - dio_8255_iobase = - devpriv->dio_counter_iobase + DIO_8255_OFFSET; - subdev_8255_init(dev, s, dio_callback, - (unsigned long)dio_8255_iobase); + ret = subdev_8255_mm_init(dev, s, NULL, + DIO_8255_OFFSET); } - } else + if (ret) + return ret; + } else { s->type = COMEDI_SUBD_UNUSED; + } /* 8 channel dio for 60xx */ s = &dev->subdevices[5]; - if (thisboard->layout == LAYOUT_60XX) { + if (board->layout == LAYOUT_60XX) { s->type = COMEDI_SUBD_DIO; s->subdev_flags = SDF_WRITABLE | SDF_READABLE; s->n_chan = 8; @@ -3975,36 +3911,50 @@ static int setup_subdevices(struct comedi_device *dev) s->range_table = &range_digital; s->insn_config = dio_60xx_config_insn; s->insn_bits = dio_60xx_wbits; - } else + } else { s->type = COMEDI_SUBD_UNUSED; + } /* caldac */ s = &dev->subdevices[6]; s->type = COMEDI_SUBD_CALIB; s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_INTERNAL; s->n_chan = 8; - if (thisboard->layout == LAYOUT_4020) + if (board->layout == LAYOUT_4020) s->maxdata = 0xfff; else s->maxdata = 0xff; - s->insn_read = calib_read_insn; - s->insn_write = calib_write_insn; - for (i = 0; i < s->n_chan; i++) + s->insn_write = cb_pcidas64_calib_insn_write; + + ret = comedi_alloc_subdev_readback(s); + if (ret) + return ret; + + for (i = 0; i < s->n_chan; i++) { caldac_write(dev, i, s->maxdata / 2); + s->readback[i] = s->maxdata / 2; + } /* 2 channel ad8402 potentiometer */ s = &dev->subdevices[7]; - if (thisboard->layout == LAYOUT_64XX) { + if (board->layout == LAYOUT_64XX) { s->type = COMEDI_SUBD_CALIB; s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_INTERNAL; s->n_chan = 2; - s->insn_read = ad8402_read_insn; - s->insn_write = ad8402_write_insn; s->maxdata = 0xff; - for (i = 0; i < s->n_chan; i++) + s->insn_write = cb_pcidas64_ad8402_insn_write; + + ret = comedi_alloc_subdev_readback(s); + if (ret) + return ret; + + for (i = 0; i < s->n_chan; i++) { ad8402_write(dev, i, s->maxdata / 2); - } else + s->readback[i] = s->maxdata / 2; + } + } else { s->type = COMEDI_SUBD_UNUSED; + } /* serial EEPROM, if present */ s = &dev->subdevices[8]; @@ -4014,8 +3964,9 @@ static int setup_subdevices(struct comedi_device *dev) s->n_chan = 128; s->maxdata = 0xffff; s->insn_read = eeprom_read_insn; - } else + } else { s->type = COMEDI_SUBD_UNUSED; + } /* user counter subd XXX */ s = &dev->subdevices[9]; @@ -4028,21 +3979,20 @@ static int auto_attach(struct comedi_device *dev, unsigned long context) { struct pci_dev *pcidev = comedi_to_pci_dev(dev); - const struct pcidas64_board *thisboard = NULL; + const struct pcidas64_board *board = NULL; struct pcidas64_private *devpriv; uint32_t local_range, local_decode; int retval; if (context < ARRAY_SIZE(pcidas64_boards)) - thisboard = &pcidas64_boards[context]; - if (!thisboard) + board = &pcidas64_boards[context]; + if (!board) return -ENODEV; - dev->board_ptr = thisboard; + dev->board_ptr = board; - devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL); + devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); if (!devpriv) return -ENOMEM; - dev->private = devpriv; retval = comedi_pci_enable(dev); if (retval) @@ -4050,26 +4000,20 @@ static int auto_attach(struct comedi_device *dev, pci_set_master(pcidev); /* Initialize dev->board_name */ - dev->board_name = thisboard->name; + dev->board_name = board->name; devpriv->main_phys_iobase = pci_resource_start(pcidev, 2); devpriv->dio_counter_phys_iobase = pci_resource_start(pcidev, 3); devpriv->plx9080_iobase = pci_ioremap_bar(pcidev, 0); devpriv->main_iobase = pci_ioremap_bar(pcidev, 2); - devpriv->dio_counter_iobase = pci_ioremap_bar(pcidev, 3); + dev->mmio = pci_ioremap_bar(pcidev, 3); - if (!devpriv->plx9080_iobase || !devpriv->main_iobase - || !devpriv->dio_counter_iobase) { + if (!devpriv->plx9080_iobase || !devpriv->main_iobase || !dev->mmio) { dev_warn(dev->class_dev, "failed to remap io memory\n"); return -ENOMEM; } - DEBUG_PRINT(" plx9080 remapped to 0x%p\n", devpriv->plx9080_iobase); - DEBUG_PRINT(" main remapped to 0x%p\n", devpriv->main_iobase); - DEBUG_PRINT(" diocounter remapped to 0x%p\n", - devpriv->dio_counter_iobase); - /* figure out what local addresses are */ local_range = readl(devpriv->plx9080_iobase + PLX_LAS0RNG_REG) & LRNG_MEM_MASK; @@ -4084,9 +4028,6 @@ static int auto_attach(struct comedi_device *dev, devpriv->local1_iobase = ((uint32_t)devpriv->dio_counter_phys_iobase & ~local_range) | local_decode; - DEBUG_PRINT(" local 0 io addr 0x%x\n", devpriv->local0_iobase); - DEBUG_PRINT(" local 1 io addr 0x%x\n", devpriv->local1_iobase); - retval = alloc_and_init_dma_members(dev); if (retval < 0) return retval; @@ -4097,12 +4038,13 @@ static int auto_attach(struct comedi_device *dev, devpriv->hw_revision); init_plx9080(dev); init_stc_registers(dev); - /* get irq */ - if (request_irq(pcidev->irq, handle_interrupt, IRQF_SHARED, - "cb_pcidas64", dev)) { + + retval = request_irq(pcidev->irq, handle_interrupt, IRQF_SHARED, + dev->board_name, dev); + if (retval) { dev_dbg(dev->class_dev, "unable to allocate irq %u\n", pcidev->irq); - return -EINVAL; + return retval; } dev->irq = pcidev->irq; dev_dbg(dev->class_dev, "irq %u\n", dev->irq); @@ -4116,55 +4058,22 @@ static int auto_attach(struct comedi_device *dev, static void detach(struct comedi_device *dev) { - const struct pcidas64_board *thisboard = comedi_board(dev); - struct pci_dev *pcidev = comedi_to_pci_dev(dev); struct pcidas64_private *devpriv = dev->private; - unsigned int i; if (dev->irq) free_irq(dev->irq, dev); if (devpriv) { - if (pcidev) { - if (devpriv->plx9080_iobase) { - disable_plx_interrupts(dev); - iounmap(devpriv->plx9080_iobase); - } - if (devpriv->main_iobase) - iounmap(devpriv->main_iobase); - if (devpriv->dio_counter_iobase) - iounmap(devpriv->dio_counter_iobase); - /* free pci dma buffers */ - for (i = 0; i < ai_dma_ring_count(thisboard); i++) { - if (devpriv->ai_buffer[i]) - pci_free_consistent(pcidev, - DMA_BUFFER_SIZE, - devpriv->ai_buffer[i], - devpriv->ai_buffer_bus_addr[i]); - } - for (i = 0; i < AO_DMA_RING_COUNT; i++) { - if (devpriv->ao_buffer[i]) - pci_free_consistent(pcidev, - DMA_BUFFER_SIZE, - devpriv->ao_buffer[i], - devpriv->ao_buffer_bus_addr[i]); - } - /* free dma descriptors */ - if (devpriv->ai_dma_desc) - pci_free_consistent(pcidev, - sizeof(struct plx_dma_desc) * - ai_dma_ring_count(thisboard), - devpriv->ai_dma_desc, - devpriv->ai_dma_desc_bus_addr); - if (devpriv->ao_dma_desc) - pci_free_consistent(pcidev, - sizeof(struct plx_dma_desc) * - AO_DMA_RING_COUNT, - devpriv->ao_dma_desc, - devpriv->ao_dma_desc_bus_addr); + if (devpriv->plx9080_iobase) { + disable_plx_interrupts(dev); + iounmap(devpriv->plx9080_iobase); } + if (devpriv->main_iobase) + iounmap(devpriv->main_iobase); + if (dev->mmio) + iounmap(dev->mmio); } - comedi_spriv_free(dev, 4); comedi_pci_disable(dev); + cb_pcidas64_free_dma(dev); } static struct comedi_driver cb_pcidas64_driver = { @@ -4181,7 +4090,7 @@ static int cb_pcidas64_pci_probe(struct pci_dev *dev, id->driver_data); } -static DEFINE_PCI_DEVICE_TABLE(cb_pcidas64_pci_table) = { +static const struct pci_device_id cb_pcidas64_pci_table[] = { { PCI_VDEVICE(CB, 0x001d), BOARD_PCIDAS6402_16 }, { PCI_VDEVICE(CB, 0x001e), BOARD_PCIDAS6402_12 }, { PCI_VDEVICE(CB, 0x0035), BOARD_PCIDAS64_M1_16 },