From 03dd4cb26d967f9588437b0fc9cc0e8353322bb7 Mon Sep 17 00:00:00 2001 From: André Fabian Silva Delgado Date: Fri, 25 Mar 2016 03:53:42 -0300 Subject: Linux-libre 4.5-gnu --- drivers/staging/comedi/Kconfig | 24 +- drivers/staging/comedi/comedi.h | 307 ++++--- drivers/staging/comedi/comedi_fops.c | 124 ++- drivers/staging/comedi/comedilib.h | 32 +- drivers/staging/comedi/drivers/Makefile | 2 + drivers/staging/comedi/drivers/adl_pci9118.c | 3 +- drivers/staging/comedi/drivers/adv_pci1710.c | 542 +++++------ drivers/staging/comedi/drivers/adv_pci1720.c | 195 ++++ drivers/staging/comedi/drivers/adv_pci1760.c | 432 +++++++++ drivers/staging/comedi/drivers/adv_pci_dio.c | 1125 ++++++----------------- drivers/staging/comedi/drivers/amplc_pci224.c | 11 +- drivers/staging/comedi/drivers/cb_pcidda.c | 6 +- drivers/staging/comedi/drivers/comedi_parport.c | 4 +- drivers/staging/comedi/drivers/das16.c | 3 +- drivers/staging/comedi/drivers/ni_6527.c | 24 +- drivers/staging/comedi/drivers/ni_65xx.c | 54 +- drivers/staging/comedi/drivers/ni_670x.c | 5 +- drivers/staging/comedi/drivers/ni_mio_common.c | 100 +- drivers/staging/comedi/drivers/plx9080.h | 126 ++- drivers/staging/comedi/drivers/s526.c | 197 ++-- 20 files changed, 1702 insertions(+), 1614 deletions(-) create mode 100644 drivers/staging/comedi/drivers/adv_pci1720.c create mode 100644 drivers/staging/comedi/drivers/adv_pci1760.c (limited to 'drivers/staging/comedi') diff --git a/drivers/staging/comedi/Kconfig b/drivers/staging/comedi/Kconfig index ac0f01007..e7255f811 100644 --- a/drivers/staging/comedi/Kconfig +++ b/drivers/staging/comedi/Kconfig @@ -737,15 +737,23 @@ config COMEDI_ADL_PCI9118 called adl_pci9118. config COMEDI_ADV_PCI1710 - tristate "Advantech PCI-171x, PCI-1720 and PCI-1731 support" + tristate "Advantech PCI-171x and PCI-1731 support" select COMEDI_8254 ---help--- Enable support for Advantech PCI-1710, PCI-1710HG, PCI-1711, - PCI-1713, PCI-1720 and PCI-1731 + PCI-1713 and PCI-1731 To compile this driver as a module, choose M here: the module will be called adv_pci1710. +config COMEDI_ADV_PCI1720 + tristate "Advantech PCI-1720 support" + ---help--- + Enable support for Advantech PCI-1720 Analog Output board. + + To compile this driver as a module, choose M here: the module will be + called adv_pci1720. + config COMEDI_ADV_PCI1723 tristate "Advantech PCI-1723 support" ---help--- @@ -764,6 +772,14 @@ config COMEDI_ADV_PCI1724 To compile this driver as a module, choose M here: the module will be called adv_pci1724. +config COMEDI_ADV_PCI1760 + tristate "Advantech PCI-1760 support" + ---help--- + Enable support for Advantech PCI-1760 board. + + To compile this driver as a module, choose M here: the module will be + called adv_pci1760. + config COMEDI_ADV_PCI_DIO tristate "Advantech PCI DIO card support" select COMEDI_8254 @@ -771,8 +787,8 @@ config COMEDI_ADV_PCI_DIO ---help--- Enable support for Advantech PCI DIO cards PCI-1730, PCI-1733, PCI-1734, PCI-1735U, PCI-1736UP, PCI-1739U, - PCI-1750, PCI-1751, PCI-1752, PCI-1753/E, PCI-1754, PCI-1756, - PCI-1760 and PCI-1762 + PCI-1750, PCI-1751, PCI-1752, PCI-1753/E, PCI-1754, PCI-1756 and + PCI-1762 To compile this driver as a module, choose M here: the module will be called adv_pci_dio. diff --git a/drivers/staging/comedi/comedi.h b/drivers/staging/comedi/comedi.h index 66edda190..83bd309d0 100644 --- a/drivers/staging/comedi/comedi.h +++ b/drivers/staging/comedi/comedi.h @@ -1,20 +1,20 @@ /* - include/comedi.h (installed as /usr/include/comedi.h) - header file for comedi - - COMEDI - Linux Control and Measurement Device Interface - Copyright (C) 1998-2001 David A. Schleef - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. -*/ + * include/comedi.h (installed as /usr/include/comedi.h) + * header file for comedi + * + * COMEDI - Linux Control and Measurement Device Interface + * Copyright (C) 1998-2001 David A. Schleef + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ #ifndef _COMEDI_H #define _COMEDI_H @@ -28,9 +28,9 @@ #define COMEDI_MAJOR 98 /* - maximum number of minor devices. This can be increased, although - kernel structures are currently statically allocated, thus you - don't want this to be much more than you actually use. + * maximum number of minor devices. This can be increased, although + * kernel structures are currently statically allocated, thus you + * don't want this to be much more than you actually use. */ #define COMEDI_NDEVICES 16 @@ -63,21 +63,21 @@ /* packs and unpacks a channel/range number */ #define CR_PACK(chan, rng, aref) \ - ((((aref)&0x3)<<24) | (((rng)&0xff)<<16) | (chan)) + ((((aref) & 0x3) << 24) | (((rng) & 0xff) << 16) | (chan)) #define CR_PACK_FLAGS(chan, range, aref, flags) \ (CR_PACK(chan, range, aref) | ((flags) & CR_FLAGS_MASK)) -#define CR_CHAN(a) ((a)&0xffff) -#define CR_RANGE(a) (((a)>>16)&0xff) -#define CR_AREF(a) (((a)>>24)&0x03) +#define CR_CHAN(a) ((a) & 0xffff) +#define CR_RANGE(a) (((a) >> 16) & 0xff) +#define CR_AREF(a) (((a) >> 24) & 0x03) #define CR_FLAGS_MASK 0xfc000000 -#define CR_ALT_FILTER (1<<26) +#define CR_ALT_FILTER (1 << 26) #define CR_DITHER CR_ALT_FILTER #define CR_DEGLITCH CR_ALT_FILTER -#define CR_ALT_SOURCE (1<<27) -#define CR_EDGE (1<<30) -#define CR_INVERT (1<<31) +#define CR_ALT_SOURCE (1 << 27) +#define CR_EDGE (1 << 30) +#define CR_INVERT (1 << 31) #define AREF_GROUND 0x00 /* analog ref = analog ground */ #define AREF_COMMON 0x01 /* analog ref = analog common */ @@ -114,11 +114,11 @@ #define INSN_READ (0 | INSN_MASK_READ) #define INSN_WRITE (1 | INSN_MASK_WRITE) -#define INSN_BITS (2 | INSN_MASK_READ|INSN_MASK_WRITE) -#define INSN_CONFIG (3 | INSN_MASK_READ|INSN_MASK_WRITE) -#define INSN_GTOD (4 | INSN_MASK_READ|INSN_MASK_SPECIAL) -#define INSN_WAIT (5 | INSN_MASK_WRITE|INSN_MASK_SPECIAL) -#define INSN_INTTRIG (6 | INSN_MASK_WRITE|INSN_MASK_SPECIAL) +#define INSN_BITS (2 | INSN_MASK_READ | INSN_MASK_WRITE) +#define INSN_CONFIG (3 | INSN_MASK_READ | INSN_MASK_WRITE) +#define INSN_GTOD (4 | INSN_MASK_READ | INSN_MASK_SPECIAL) +#define INSN_WAIT (5 | INSN_MASK_WRITE | INSN_MASK_SPECIAL) +#define INSN_INTTRIG (6 | INSN_MASK_WRITE | INSN_MASK_SPECIAL) /* trigger flags */ /* These flags are used in comedi_trig structures */ @@ -279,7 +279,8 @@ enum configuration_ids { INSN_CONFIG_SET_OTHER_SRC = 2005, /* Set other source */ /* INSN_CONFIG_GET_OTHER_SRC = 2006,*//* Get other source */ /* Get size in bytes of subdevice's on-board fifos used during - * streaming input/output */ + * streaming input/output + */ INSN_CONFIG_GET_HARDWARE_BUFFER_SIZE = 2006, INSN_CONFIG_SET_COUNTER_MODE = 4097, /* INSN_CONFIG_8254_SET_MODE is deprecated */ @@ -292,7 +293,8 @@ enum configuration_ids { INSN_CONFIG_PWM_GET_PERIOD = 5001, /* gets frequency */ INSN_CONFIG_GET_PWM_STATUS = 5002, /* is it running? */ /* sets H bridge: duty cycle and sign bit for a relay at the - * same time */ + * same time + */ INSN_CONFIG_PWM_SET_H_BRIDGE = 5003, /* gets H bridge data: duty cycle and the sign bit */ INSN_CONFIG_PWM_GET_H_BRIDGE = 5004 @@ -502,13 +504,13 @@ struct comedi_bufinfo { /* range stuff */ -#define __RANGE(a, b) ((((a)&0xffff)<<16)|((b)&0xffff)) +#define __RANGE(a, b) ((((a) & 0xffff) << 16) | ((b) & 0xffff)) -#define RANGE_OFFSET(a) (((a)>>16)&0xffff) -#define RANGE_LENGTH(b) ((b)&0xffff) +#define RANGE_OFFSET(a) (((a) >> 16) & 0xffff) +#define RANGE_LENGTH(b) ((b) & 0xffff) -#define RF_UNIT(flags) ((flags)&0xff) -#define RF_EXTERNAL (1<<8) +#define RF_UNIT(flags) ((flags) & 0xff) +#define RF_EXTERNAL (1 << 8) #define UNIT_volt 0 #define UNIT_mA 1 @@ -521,23 +523,22 @@ struct comedi_bufinfo { /**********************************************************/ /* - 8254 specific configuration. - - It supports two config commands: - - 0 ID: INSN_CONFIG_SET_COUNTER_MODE - 1 8254 Mode - I8254_MODE0, I8254_MODE1, ..., I8254_MODE5 - OR'ed with: - I8254_BCD, I8254_BINARY - - 0 ID: INSN_CONFIG_8254_READ_STATUS - 1 <-- Status byte returned here. - B7 = Output - B6 = NULL Count - B5 - B0 Current mode. - -*/ + * 8254 specific configuration. + * + * It supports two config commands: + * + * 0 ID: INSN_CONFIG_SET_COUNTER_MODE + * 1 8254 Mode + * I8254_MODE0, I8254_MODE1, ..., I8254_MODE5 + * OR'ed with: + * I8254_BCD, I8254_BINARY + * + * 0 ID: INSN_CONFIG_8254_READ_STATUS + * 1 <-- Status byte returned here. + * B7 = Output + * B6 = NULL Count + * B5 - B0 Current mode. + */ enum i8254_mode { I8254_MODE0 = (0 << 1), /* Interrupt on terminal count */ @@ -545,18 +546,20 @@ enum i8254_mode { I8254_MODE2 = (2 << 1), /* Rate generator */ I8254_MODE3 = (3 << 1), /* Square wave mode */ I8254_MODE4 = (4 << 1), /* Software triggered strobe */ - I8254_MODE5 = (5 << 1), /* Hardware triggered strobe - * (retriggerable) */ - I8254_BCD = 1, /* use binary-coded decimal instead of binary - * (pretty useless) */ + /* Hardware triggered strobe (retriggerable) */ + I8254_MODE5 = (5 << 1), + /* Use binary-coded decimal instead of binary (pretty useless) */ + I8254_BCD = 1, I8254_BINARY = 0 }; #define NI_USUAL_PFI_SELECT(x) (((x) < 10) ? (0x1 + (x)) : (0xb + (x))) #define NI_USUAL_RTSI_SELECT(x) (((x) < 7) ? (0xb + (x)) : 0x1b) -/* mode bits for NI general-purpose counters, set with - * INSN_CONFIG_SET_COUNTER_MODE */ +/* + * mode bits for NI general-purpose counters, set with + * INSN_CONFIG_SET_COUNTER_MODE + */ #define NI_GPCT_COUNTING_MODE_SHIFT 16 #define NI_GPCT_INDEX_PHASE_BITSHIFT 20 #define NI_GPCT_COUNTING_DIRECTION_SHIFT 24 @@ -624,8 +627,10 @@ enum ni_gpct_mode_bits { NI_GPCT_INVERT_OUTPUT_BIT = 0x20000000 }; -/* Bits for setting a clock source with - * INSN_CONFIG_SET_CLOCK_SRC when using NI general-purpose counters. */ +/* + * Bits for setting a clock source with + * INSN_CONFIG_SET_CLOCK_SRC when using NI general-purpose counters. + */ enum ni_gpct_clock_source_bits { NI_GPCT_CLOCK_SRC_SELECT_MASK = 0x3f, NI_GPCT_TIMEBASE_1_CLOCK_SRC_BITS = 0x0, @@ -656,9 +661,11 @@ enum ni_gpct_clock_source_bits { /* no pfi on NI 660x */ #define NI_GPCT_PFI_CLOCK_SRC_BITS(x) (0x20 + (x)) -/* Possibilities for setting a gate source with -INSN_CONFIG_SET_GATE_SRC when using NI general-purpose counters. -May be bitwise-or'd with CR_EDGE or CR_INVERT. */ +/* + * Possibilities for setting a gate source with + * INSN_CONFIG_SET_GATE_SRC when using NI general-purpose counters. + * May be bitwise-or'd with CR_EDGE or CR_INVERT. + */ enum ni_gpct_gate_select { /* m-series gates */ NI_GPCT_TIMESTAMP_MUX_GATE_SELECT = 0x0, @@ -675,9 +682,11 @@ enum ni_gpct_gate_select { /* more gates for 660x "second gate" */ NI_GPCT_UP_DOWN_PIN_i_GATE_SELECT = 0x201, NI_GPCT_SELECTED_GATE_GATE_SELECT = 0x21e, - /* m-series "second gate" sources are unknown, + /* + * m-series "second gate" sources are unknown, * we should add them here with an offset of 0x300 when - * known. */ + * known. + */ NI_GPCT_DISABLED_GATE_SELECT = 0x8000, }; @@ -686,8 +695,10 @@ enum ni_gpct_gate_select { #define NI_GPCT_PFI_GATE_SELECT(x) NI_USUAL_PFI_SELECT(x) #define NI_GPCT_UP_DOWN_PIN_GATE_SELECT(x) (0x202 + (x)) -/* Possibilities for setting a source with -INSN_CONFIG_SET_OTHER_SRC when using NI general-purpose counters. */ +/* + * Possibilities for setting a source with + * INSN_CONFIG_SET_OTHER_SRC when using NI general-purpose counters. + */ enum ni_gpct_other_index { NI_GPCT_SOURCE_ENCODER_A, NI_GPCT_SOURCE_ENCODER_B, @@ -702,18 +713,24 @@ enum ni_gpct_other_select { #define NI_GPCT_PFI_OTHER_SELECT(x) NI_USUAL_PFI_SELECT(x) -/* start sources for ni general-purpose counters for use with -INSN_CONFIG_ARM */ +/* + * start sources for ni general-purpose counters for use with + * INSN_CONFIG_ARM + */ enum ni_gpct_arm_source { NI_GPCT_ARM_IMMEDIATE = 0x0, - NI_GPCT_ARM_PAIRED_IMMEDIATE = 0x1, /* Start both the counter - * and the adjacent paired - * counter simultaneously */ - /* NI doesn't document bits for selecting hardware arm triggers. + /* + * Start both the counter and the adjacent pared + * counter simultaneously + */ + NI_GPCT_ARM_PAIRED_IMMEDIATE = 0x1, + /* + * NI doesn't document bits for selecting hardware arm triggers. * If the NI_GPCT_ARM_UNKNOWN bit is set, we will pass the least * significant bits (3 bits for 660x or 5 bits for m-series) * through to the hardware. This will at least allow someone to - * figure out what the bits do later. */ + * figure out what the bits do later. + */ NI_GPCT_ARM_UNKNOWN = 0x1000, }; @@ -728,8 +745,10 @@ enum ni_gpct_filter_select { NI_GPCT_FILTER_2x_TIMEBASE_3 = 0x6 }; -/* PFI digital filtering options for ni m-series for use with - * INSN_CONFIG_FILTER. */ +/* + * PFI digital filtering options for ni m-series for use with + * INSN_CONFIG_FILTER. + */ enum ni_pfi_filter_select { NI_PFI_FILTER_OFF = 0x0, NI_PFI_FILTER_125ns = 0x1, @@ -740,9 +759,11 @@ enum ni_pfi_filter_select { /* master clock sources for ni mio boards and INSN_CONFIG_SET_CLOCK_SRC */ enum ni_mio_clock_source { NI_MIO_INTERNAL_CLOCK = 0, - NI_MIO_RTSI_CLOCK = 1, /* doesn't work for m-series, use - NI_MIO_PLL_RTSI_CLOCK() */ - /* the NI_MIO_PLL_* sources are m-series only */ + /* + * Doesn't work for m-series, use NI_MIO_PLL_RTSI_CLOCK() + * the NI_MIO_PLL_* sources are m-series only + */ + NI_MIO_RTSI_CLOCK = 1, NI_MIO_PLL_PXI_STAR_TRIGGER_CLOCK = 2, NI_MIO_PLL_PXI10_CLOCK = 3, NI_MIO_PLL_RTSI0_CLOCK = 4 @@ -750,9 +771,11 @@ enum ni_mio_clock_source { #define NI_MIO_PLL_RTSI_CLOCK(x) (NI_MIO_PLL_RTSI0_CLOCK + (x)) -/* Signals which can be routed to an NI RTSI pin with INSN_CONFIG_SET_ROUTING. - The numbers assigned are not arbitrary, they correspond to the bits required - to program the board. */ +/* + * Signals which can be routed to an NI RTSI pin with INSN_CONFIG_SET_ROUTING. + * The numbers assigned are not arbitrary, they correspond to the bits required + * to program the board. + */ enum ni_rtsi_routing { NI_RTSI_OUTPUT_ADR_START1 = 0, NI_RTSI_OUTPUT_ADR_START2 = 1, @@ -763,17 +786,19 @@ enum ni_rtsi_routing { NI_RTSI_OUTPUT_G_GATE0 = 6, NI_RTSI_OUTPUT_RGOUT0 = 7, NI_RTSI_OUTPUT_RTSI_BRD_0 = 8, - NI_RTSI_OUTPUT_RTSI_OSC = 12 /* pre-m-series always have RTSI - * clock on line 7 */ + /* Pre-m-series always have RTSI clock on line 7 */ + NI_RTSI_OUTPUT_RTSI_OSC = 12 }; #define NI_RTSI_OUTPUT_RTSI_BRD(x) (NI_RTSI_OUTPUT_RTSI_BRD_0 + (x)) -/* Signals which can be routed to an NI PFI pin on an m-series board with +/* + * Signals which can be routed to an NI PFI pin on an m-series board with * INSN_CONFIG_SET_ROUTING. These numbers are also returned by * INSN_CONFIG_GET_ROUTING on pre-m-series boards, even though their routing * cannot be changed. The numbers assigned are not arbitrary, they correspond - * to the bits required to program the board. */ + * to the bits required to program the board. + */ enum ni_pfi_routing { NI_PFI_OUTPUT_PFI_DEFAULT = 0, NI_PFI_OUTPUT_AI_START1 = 1, @@ -803,20 +828,24 @@ enum ni_pfi_routing { #define NI_PFI_OUTPUT_RTSI(x) (NI_PFI_OUTPUT_RTSI0 + (x)) -/* Signals which can be routed to output on a NI PFI pin on a 660x board - with INSN_CONFIG_SET_ROUTING. The numbers assigned are - not arbitrary, they correspond to the bits required - to program the board. Lines 0 to 7 can only be set to - NI_660X_PFI_OUTPUT_DIO. Lines 32 to 39 can only be set to - NI_660X_PFI_OUTPUT_COUNTER. */ +/* + * Signals which can be routed to output on a NI PFI pin on a 660x board + * with INSN_CONFIG_SET_ROUTING. The numbers assigned are + * not arbitrary, they correspond to the bits required + * to program the board. Lines 0 to 7 can only be set to + * NI_660X_PFI_OUTPUT_DIO. Lines 32 to 39 can only be set to + * NI_660X_PFI_OUTPUT_COUNTER. + */ enum ni_660x_pfi_routing { NI_660X_PFI_OUTPUT_COUNTER = 1, /* counter */ NI_660X_PFI_OUTPUT_DIO = 2, /* static digital output */ }; -/* NI External Trigger lines. These values are not arbitrary, but are related +/* + * NI External Trigger lines. These values are not arbitrary, but are related * to the bits required to program the board (offset by 1 for historical - * reasons). */ + * reasons). + */ #define NI_EXT_PFI(x) (NI_USUAL_PFI_SELECT(x) - 1) #define NI_EXT_RTSI(x) (NI_USUAL_RTSI_SELECT(x) - 1) @@ -827,9 +856,11 @@ enum comedi_counter_status_flags { COMEDI_COUNTER_TERMINAL_COUNT = 0x4, }; -/* Clock sources for CDIO subdevice on NI m-series boards. Used as the +/* + * Clock sources for CDIO subdevice on NI m-series boards. Used as the * scan_begin_arg for a comedi_command. These sources may also be bitwise-or'd - * with CR_INVERT to change polarity. */ + * with CR_INVERT to change polarity. + */ enum ni_m_series_cdio_scan_begin_src { NI_CDIO_SCAN_BEGIN_SRC_GROUND = 0, NI_CDIO_SCAN_BEGIN_SRC_AI_START = 18, @@ -846,38 +877,50 @@ enum ni_m_series_cdio_scan_begin_src { #define NI_CDIO_SCAN_BEGIN_SRC_PFI(x) NI_USUAL_PFI_SELECT(x) #define NI_CDIO_SCAN_BEGIN_SRC_RTSI(x) NI_USUAL_RTSI_SELECT(x) -/* scan_begin_src for scan_begin_arg==TRIG_EXT with analog output command on NI +/* + * scan_begin_src for scan_begin_arg==TRIG_EXT with analog output command on NI * boards. These scan begin sources can also be bitwise-or'd with CR_INVERT to - * change polarity. */ + * change polarity. + */ #define NI_AO_SCAN_BEGIN_SRC_PFI(x) NI_USUAL_PFI_SELECT(x) #define NI_AO_SCAN_BEGIN_SRC_RTSI(x) NI_USUAL_RTSI_SELECT(x) -/* Bits for setting a clock source with - * INSN_CONFIG_SET_CLOCK_SRC when using NI frequency output subdevice. */ +/* + * Bits for setting a clock source with + * INSN_CONFIG_SET_CLOCK_SRC when using NI frequency output subdevice. + */ enum ni_freq_out_clock_source_bits { NI_FREQ_OUT_TIMEBASE_1_DIV_2_CLOCK_SRC, /* 10 MHz */ NI_FREQ_OUT_TIMEBASE_2_CLOCK_SRC /* 100 KHz */ }; -/* Values for setting a clock source with INSN_CONFIG_SET_CLOCK_SRC for - * 8254 counter subdevices on Amplicon DIO boards (amplc_dio200 driver). */ +/* + * Values for setting a clock source with INSN_CONFIG_SET_CLOCK_SRC for + * 8254 counter subdevices on Amplicon DIO boards (amplc_dio200 driver). + */ enum amplc_dio_clock_source { - AMPLC_DIO_CLK_CLKN, /* per channel external clock - input/output pin (pin is only an - input when clock source set to this - value, otherwise it is an output) */ + /* + * Per channel external clock + * input/output pin (pin is only an + * input when clock source set to this value, + * otherwise it is an output) + */ + AMPLC_DIO_CLK_CLKN, AMPLC_DIO_CLK_10MHZ, /* 10 MHz internal clock */ AMPLC_DIO_CLK_1MHZ, /* 1 MHz internal clock */ AMPLC_DIO_CLK_100KHZ, /* 100 kHz internal clock */ AMPLC_DIO_CLK_10KHZ, /* 10 kHz internal clock */ AMPLC_DIO_CLK_1KHZ, /* 1 kHz internal clock */ - AMPLC_DIO_CLK_OUTNM1, /* output of preceding counter channel - (for channel 0, preceding counter - channel is channel 2 on preceding - counter subdevice, for first counter - subdevice, preceding counter - subdevice is the last counter - subdevice) */ + /* + * Output of preceding counter channel + * (for channel 0, preceding counter + * channel is channel 2 on preceding + * counter subdevice, for first counter + * subdevice, preceding counter + * subdevice is the last counter + * subdevice) + */ + AMPLC_DIO_CLK_OUTNM1, AMPLC_DIO_CLK_EXT, /* per chip external input pin */ /* the following are "enhanced" clock sources for PCIe models */ AMPLC_DIO_CLK_VCC, /* clock input HIGH */ @@ -886,35 +929,39 @@ enum amplc_dio_clock_source { AMPLC_DIO_CLK_20MHZ /* 20 MHz internal clock */ }; -/* Values for setting a clock source with INSN_CONFIG_SET_CLOCK_SRC for - * timer subdevice on some Amplicon DIO PCIe boards (amplc_dio200 driver). */ +/* + * Values for setting a clock source with INSN_CONFIG_SET_CLOCK_SRC for + * timer subdevice on some Amplicon DIO PCIe boards (amplc_dio200 driver). + */ enum amplc_dio_ts_clock_src { AMPLC_DIO_TS_CLK_1GHZ, /* 1 ns period with 20 ns granularity */ AMPLC_DIO_TS_CLK_1MHZ, /* 1 us period */ AMPLC_DIO_TS_CLK_1KHZ /* 1 ms period */ }; -/* Values for setting a gate source with INSN_CONFIG_SET_GATE_SRC for - * 8254 counter subdevices on Amplicon DIO boards (amplc_dio200 driver). */ +/* + * Values for setting a gate source with INSN_CONFIG_SET_GATE_SRC for + * 8254 counter subdevices on Amplicon DIO boards (amplc_dio200 driver). + */ enum amplc_dio_gate_source { AMPLC_DIO_GAT_VCC, /* internal high logic level */ AMPLC_DIO_GAT_GND, /* internal low logic level */ AMPLC_DIO_GAT_GATN, /* per channel external gate input */ - AMPLC_DIO_GAT_NOUTNM2, /* negated output of counter channel - minus 2 (for channels 0 or 1, - channel minus 2 is channel 1 or 2 on - the preceding counter subdevice, for - the first counter subdevice the - preceding counter subdevice is the - last counter subdevice) */ + /* + * negated output of counter channel minus 2 + * (for channels 0 or 1, channel minus 2 is channel 1 or 2 on + * the preceding counter subdevice, for the first counter subdevice + * the preceding counter subdevice is the last counter subdevice) + */ + AMPLC_DIO_GAT_NOUTNM2, AMPLC_DIO_GAT_RESERVED4, AMPLC_DIO_GAT_RESERVED5, AMPLC_DIO_GAT_RESERVED6, AMPLC_DIO_GAT_RESERVED7, /* the following are "enhanced" gate sources for PCIe models */ AMPLC_DIO_GAT_NGATN = 6, /* negated per channel gate input */ - AMPLC_DIO_GAT_OUTNM2, /* non-negated output of counter - channel minus 2 */ + /* non-negated output of counter channel minus 2 */ + AMPLC_DIO_GAT_OUTNM2, AMPLC_DIO_GAT_PAT_PRESENT, /* "pattern present" signal */ AMPLC_DIO_GAT_PAT_OCCURRED, /* "pattern occurred" latched */ AMPLC_DIO_GAT_PAT_GONE, /* "pattern gone away" latched */ diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c index 7b4af519e..d57fadef4 100644 --- a/drivers/staging/comedi/comedi_fops.c +++ b/drivers/staging/comedi/comedi_fops.c @@ -2303,11 +2303,13 @@ static ssize_t comedi_write(struct file *file, const char __user *buf, { struct comedi_subdevice *s; struct comedi_async *async; - int n, m, count = 0, retval = 0; + unsigned int n, m; + ssize_t count = 0; + int retval = 0; DECLARE_WAITQUEUE(wait, current); struct comedi_file *cfp = file->private_data; struct comedi_device *dev = cfp->dev; - bool on_wait_queue = false; + bool become_nonbusy = false; bool attach_locked; unsigned int old_detach_count; @@ -2329,74 +2331,33 @@ static ssize_t comedi_write(struct file *file, const char __user *buf, } async = s->async; - - if (!s->busy || !nbytes) - goto out; - if (s->busy != file) { - retval = -EACCES; - goto out; - } - if (!(async->cmd.flags & CMDF_WRITE)) { + if (s->busy != file || !(async->cmd.flags & CMDF_WRITE)) { retval = -EINVAL; goto out; } add_wait_queue(&async->wait_head, &wait); - on_wait_queue = true; - while (nbytes > 0 && !retval) { + while (count == 0 && !retval) { unsigned runflags; + unsigned int wp, n1, n2; set_current_state(TASK_INTERRUPTIBLE); runflags = comedi_get_subdevice_runflags(s); if (!comedi_is_runflags_running(runflags)) { - if (count == 0) { - struct comedi_subdevice *new_s; - - if (comedi_is_runflags_in_error(runflags)) - retval = -EPIPE; - else - retval = 0; - /* - * To avoid deadlock, cannot acquire dev->mutex - * while dev->attach_lock is held. Need to - * remove task from the async wait queue before - * releasing dev->attach_lock, as it might not - * be valid afterwards. - */ - remove_wait_queue(&async->wait_head, &wait); - on_wait_queue = false; - up_read(&dev->attach_lock); - attach_locked = false; - mutex_lock(&dev->mutex); - /* - * Become non-busy unless things have changed - * behind our back. Checking dev->detach_count - * is unchanged ought to be sufficient (unless - * there have been 2**32 detaches in the - * meantime!), but check the subdevice pointer - * as well just in case. - */ - new_s = comedi_file_write_subdevice(file); - if (dev->attached && - old_detach_count == dev->detach_count && - s == new_s && new_s->async == async) - do_become_nonbusy(dev, s); - mutex_unlock(&dev->mutex); - } + if (comedi_is_runflags_in_error(runflags)) + retval = -EPIPE; + if (retval || nbytes) + become_nonbusy = true; break; } + if (nbytes == 0) + break; - n = nbytes; - - m = n; - if (async->buf_write_ptr + m > async->prealloc_bufsz) - m = async->prealloc_bufsz - async->buf_write_ptr; + /* Allocate all free buffer space. */ comedi_buf_write_alloc(s, async->prealloc_bufsz); - if (m > comedi_buf_write_n_allocated(s)) - m = comedi_buf_write_n_allocated(s); - if (m < n) - n = m; + m = comedi_buf_write_n_allocated(s); + n = min_t(size_t, m, nbytes); if (n == 0) { if (file->f_flags & O_NONBLOCK) { @@ -2408,21 +2369,22 @@ static ssize_t comedi_write(struct file *file, const char __user *buf, retval = -ERESTARTSYS; break; } - if (!s->busy) - break; - if (s->busy != file) { - retval = -EACCES; - break; - } - if (!(async->cmd.flags & CMDF_WRITE)) { + if (s->busy != file || + !(async->cmd.flags & CMDF_WRITE)) { retval = -EINVAL; break; } continue; } - m = copy_from_user(async->prealloc_buf + async->buf_write_ptr, - buf, n); + wp = async->buf_write_ptr; + n1 = min(n, async->prealloc_bufsz - wp); + n2 = n - n1; + m = copy_from_user(async->prealloc_buf + wp, buf, n1); + if (m) + m += n2; + else if (n2) + m = copy_from_user(async->prealloc_buf, buf + n1, n2); if (m) { n -= m; retval = -EFAULT; @@ -2433,12 +2395,38 @@ static ssize_t comedi_write(struct file *file, const char __user *buf, nbytes -= n; buf += n; - break; /* makes device work like a pipe */ } -out: - if (on_wait_queue) - remove_wait_queue(&async->wait_head, &wait); + remove_wait_queue(&async->wait_head, &wait); set_current_state(TASK_RUNNING); + if (become_nonbusy && count == 0) { + struct comedi_subdevice *new_s; + + /* + * To avoid deadlock, cannot acquire dev->mutex + * while dev->attach_lock is held. + */ + up_read(&dev->attach_lock); + attach_locked = false; + mutex_lock(&dev->mutex); + /* + * Check device hasn't become detached behind our back. + * Checking dev->detach_count is unchanged ought to be + * sufficient (unless there have been 2**32 detaches in the + * meantime!), but check the subdevice pointer as well just in + * case. + * + * Also check the subdevice is still in a suitable state to + * become non-busy in case it changed behind our back. + */ + new_s = comedi_file_write_subdevice(file); + if (dev->attached && old_detach_count == dev->detach_count && + s == new_s && new_s->async == async && s->busy == file && + (async->cmd.flags & CMDF_WRITE) && + !comedi_is_subdevice_running(s)) + do_become_nonbusy(dev, s); + mutex_unlock(&dev->mutex); + } +out: if (attach_locked) up_read(&dev->attach_lock); diff --git a/drivers/staging/comedi/comedilib.h b/drivers/staging/comedi/comedilib.h index 56baf852e..f9b56396e 100644 --- a/drivers/staging/comedi/comedilib.h +++ b/drivers/staging/comedi/comedilib.h @@ -1,20 +1,20 @@ /* - linux/include/comedilib.h - header file for kcomedilib - - COMEDI - Linux Control and Measurement Device Interface - Copyright (C) 1998-2001 David A. Schleef - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. -*/ + * comedilib.h + * Header file for kcomedilib + * + * COMEDI - Linux Control and Measurement Device Interface + * Copyright (C) 1998-2001 David A. Schleef + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ #ifndef _LINUX_COMEDILIB_H #define _LINUX_COMEDILIB_H diff --git a/drivers/staging/comedi/drivers/Makefile b/drivers/staging/comedi/drivers/Makefile index c3b8f2d76..0c8cfa738 100644 --- a/drivers/staging/comedi/drivers/Makefile +++ b/drivers/staging/comedi/drivers/Makefile @@ -78,8 +78,10 @@ obj-$(CONFIG_COMEDI_ADL_PCI8164) += adl_pci8164.o obj-$(CONFIG_COMEDI_ADL_PCI9111) += adl_pci9111.o obj-$(CONFIG_COMEDI_ADL_PCI9118) += adl_pci9118.o obj-$(CONFIG_COMEDI_ADV_PCI1710) += adv_pci1710.o +obj-$(CONFIG_COMEDI_ADV_PCI1720) += adv_pci1720.o obj-$(CONFIG_COMEDI_ADV_PCI1723) += adv_pci1723.o obj-$(CONFIG_COMEDI_ADV_PCI1724) += adv_pci1724.o +obj-$(CONFIG_COMEDI_ADV_PCI1760) += adv_pci1760.o obj-$(CONFIG_COMEDI_ADV_PCI_DIO) += adv_pci_dio.o obj-$(CONFIG_COMEDI_AMPLC_DIO200_PCI) += amplc_dio200_pci.o obj-$(CONFIG_COMEDI_AMPLC_PC236_PCI) += amplc_pci236.o diff --git a/drivers/staging/comedi/drivers/adl_pci9118.c b/drivers/staging/comedi/drivers/adl_pci9118.c index 0dff1dbb5..4437ea3ab 100644 --- a/drivers/staging/comedi/drivers/adl_pci9118.c +++ b/drivers/staging/comedi/drivers/adl_pci9118.c @@ -603,10 +603,11 @@ static void pci9118_ai_munge(struct comedi_device *dev, unsigned short *array = data; unsigned int num_samples = comedi_bytes_to_samples(s, num_bytes); unsigned int i; + __be16 *barray = data; for (i = 0; i < num_samples; i++) { if (devpriv->usedma) - array[i] = be16_to_cpu(array[i]); + array[i] = be16_to_cpu(barray[i]); if (s->maxdata == 0xffff) array[i] ^= 0x8000; else diff --git a/drivers/staging/comedi/drivers/adv_pci1710.c b/drivers/staging/comedi/drivers/adv_pci1710.c index 399c511cf..2c1b6de30 100644 --- a/drivers/staging/comedi/drivers/adv_pci1710.c +++ b/drivers/staging/comedi/drivers/adv_pci1710.c @@ -11,8 +11,9 @@ * Driver: adv_pci1710 * Description: Comedi driver for Advantech PCI-1710 series boards * Devices: [Advantech] PCI-1710 (adv_pci1710), PCI-1710HG, PCI-1711, - * PCI-1713, PCI-1720, PCI-1731 + * PCI-1713, PCI-1731 * Author: Michal Dobes + * Updated: Fri, 29 Oct 2015 17:19:35 -0700 * Status: works * * Configuration options: not applicable, uses PCI auto config @@ -40,7 +41,13 @@ #define PCI171X_AD_DATA_REG 0x00 /* R: A/D data */ #define PCI171X_SOFTTRG_REG 0x00 /* W: soft trigger for A/D */ #define PCI171X_RANGE_REG 0x02 /* W: A/D gain/range register */ +#define PCI171X_RANGE_DIFF BIT(5) +#define PCI171X_RANGE_UNI BIT(4) +#define PCI171X_RANGE_GAIN(x) (((x) & 0x7) << 0) #define PCI171X_MUX_REG 0x04 /* W: A/D multiplexor control */ +#define PCI171X_MUX_CHANH(x) (((x) & 0xf) << 8) +#define PCI171X_MUX_CHANL(x) (((x) & 0xf) << 0) +#define PCI171X_MUX_CHAN(x) (PCI171X_MUX_CHANH(x) | PCI171X_MUX_CHANL(x)) #define PCI171X_STATUS_REG 0x06 /* R: status register */ #define PCI171X_STATUS_IRQ BIT(11) /* 1=IRQ occurred */ #define PCI171X_STATUS_FF BIT(10) /* 1=FIFO is full, fatal error */ @@ -58,83 +65,58 @@ #define PCI171X_CLRFIFO_REG 0x09 /* W: clear FIFO */ #define PCI171X_DA_REG(x) (0x0a + ((x) * 2)) /* W: D/A register */ #define PCI171X_DAREF_REG 0x0e /* W: D/A reference control */ +#define PCI171X_DAREF(c, r) (((r) & 0x3) << ((c) * 2)) +#define PCI171X_DAREF_MASK(c) PCI171X_DAREF((c), 0x3) #define PCI171X_DI_REG 0x10 /* R: digital inputs */ #define PCI171X_DO_REG 0x10 /* W: digital outputs */ #define PCI171X_TIMER_BASE 0x18 /* R/W: 8254 timer */ -/* - * PCI-1720 only has analog outputs and has a different - * register map (dev->iobase) - */ -#define PCI1720_DA_REG(x) (0x00 + ((x) * 2)) /* W: D/A registers */ -#define PCI1720_RANGE_REG 0x08 /* R/W: D/A range register */ -#define PCI1720_SYNC_REG 0x09 /* W: D/A synchronized output */ -#define PCI1720_SYNC_CTRL_REG 0x0f /* R/W: D/A synchronized control */ -#define PCI1720_SYNC_CTRL_SC0 BIT(0) /* set synchronous output mode */ - -static const struct comedi_lrange range_pci1710_3 = { +static const struct comedi_lrange pci1710_ai_range = { 9, { - BIP_RANGE(5), - BIP_RANGE(2.5), - BIP_RANGE(1.25), - BIP_RANGE(0.625), - BIP_RANGE(10), - UNI_RANGE(10), - UNI_RANGE(5), - UNI_RANGE(2.5), - UNI_RANGE(1.25) + BIP_RANGE(5), /* gain 1 (0x00) */ + BIP_RANGE(2.5), /* gain 2 (0x01) */ + BIP_RANGE(1.25), /* gain 4 (0x02) */ + BIP_RANGE(0.625), /* gain 8 (0x03) */ + BIP_RANGE(10), /* gain 0.5 (0x04) */ + UNI_RANGE(10), /* gain 1 (0x00 | UNI) */ + UNI_RANGE(5), /* gain 2 (0x01 | UNI) */ + UNI_RANGE(2.5), /* gain 4 (0x02 | UNI) */ + UNI_RANGE(1.25) /* gain 8 (0x03 | UNI) */ } }; -static const char range_codes_pci1710_3[] = { 0x00, 0x01, 0x02, 0x03, 0x04, - 0x10, 0x11, 0x12, 0x13 }; - -static const struct comedi_lrange range_pci1710hg = { +static const struct comedi_lrange pci1710hg_ai_range = { 12, { - BIP_RANGE(5), - BIP_RANGE(0.5), - BIP_RANGE(0.05), - BIP_RANGE(0.005), - BIP_RANGE(10), - BIP_RANGE(1), - BIP_RANGE(0.1), - BIP_RANGE(0.01), - UNI_RANGE(10), - UNI_RANGE(1), - UNI_RANGE(0.1), - UNI_RANGE(0.01) + BIP_RANGE(5), /* gain 1 (0x00) */ + BIP_RANGE(0.5), /* gain 10 (0x01) */ + BIP_RANGE(0.05), /* gain 100 (0x02) */ + BIP_RANGE(0.005), /* gain 1000 (0x03) */ + BIP_RANGE(10), /* gain 0.5 (0x04) */ + BIP_RANGE(1), /* gain 5 (0x05) */ + BIP_RANGE(0.1), /* gain 50 (0x06) */ + BIP_RANGE(0.01), /* gain 500 (0x07) */ + UNI_RANGE(10), /* gain 1 (0x00 | UNI) */ + UNI_RANGE(1), /* gain 10 (0x01 | UNI) */ + UNI_RANGE(0.1), /* gain 100 (0x02 | UNI) */ + UNI_RANGE(0.01) /* gain 1000 (0x03 | UNI) */ } }; -static const char range_codes_pci1710hg[] = { 0x00, 0x01, 0x02, 0x03, 0x04, - 0x05, 0x06, 0x07, 0x10, 0x11, - 0x12, 0x13 }; - -static const struct comedi_lrange range_pci17x1 = { +static const struct comedi_lrange pci1711_ai_range = { 5, { - BIP_RANGE(10), - BIP_RANGE(5), - BIP_RANGE(2.5), - BIP_RANGE(1.25), - BIP_RANGE(0.625) - } -}; - -static const char range_codes_pci17x1[] = { 0x00, 0x01, 0x02, 0x03, 0x04 }; - -static const struct comedi_lrange pci1720_ao_range = { - 4, { - UNI_RANGE(5), - UNI_RANGE(10), - BIP_RANGE(5), - BIP_RANGE(10) + BIP_RANGE(10), /* gain 1 (0x00) */ + BIP_RANGE(5), /* gain 2 (0x01) */ + BIP_RANGE(2.5), /* gain 4 (0x02) */ + BIP_RANGE(1.25), /* gain 8 (0x03) */ + BIP_RANGE(0.625) /* gain 16 (0x04) */ } }; static const struct comedi_lrange pci171x_ao_range = { - 2, { - UNI_RANGE(5), - UNI_RANGE(10) + 3, { + UNI_RANGE(5), /* internal -5V ref */ + UNI_RANGE(10), /* internal -10V ref */ + RANGE_ext(0, 1) /* external -Vref (+/-10V max) */ } }; @@ -143,82 +125,43 @@ enum pci1710_boardid { BOARD_PCI1710HG, BOARD_PCI1711, BOARD_PCI1713, - BOARD_PCI1720, BOARD_PCI1731, }; struct boardtype { - const char *name; /* board name */ - int n_aichan; /* num of A/D chans */ - const struct comedi_lrange *rangelist_ai; /* rangelist for A/D */ - const char *rangecode_ai; /* range codes for programming */ + const char *name; + const struct comedi_lrange *ai_range; + unsigned int is_pci1711:1; unsigned int is_pci1713:1; - unsigned int is_pci1720:1; - unsigned int has_irq:1; - unsigned int has_large_fifo:1; /* 4K or 1K FIFO */ - unsigned int has_diff_ai:1; unsigned int has_ao:1; - unsigned int has_di_do:1; - unsigned int has_counter:1; }; static const struct boardtype boardtypes[] = { [BOARD_PCI1710] = { .name = "pci1710", - .n_aichan = 16, - .rangelist_ai = &range_pci1710_3, - .rangecode_ai = range_codes_pci1710_3, - .has_irq = 1, - .has_large_fifo = 1, - .has_diff_ai = 1, + .ai_range = &pci1710_ai_range, .has_ao = 1, - .has_di_do = 1, - .has_counter = 1, }, [BOARD_PCI1710HG] = { .name = "pci1710hg", - .n_aichan = 16, - .rangelist_ai = &range_pci1710hg, - .rangecode_ai = range_codes_pci1710hg, - .has_irq = 1, - .has_large_fifo = 1, - .has_diff_ai = 1, + .ai_range = &pci1710hg_ai_range, .has_ao = 1, - .has_di_do = 1, - .has_counter = 1, }, [BOARD_PCI1711] = { .name = "pci1711", - .n_aichan = 16, - .rangelist_ai = &range_pci17x1, - .rangecode_ai = range_codes_pci17x1, - .has_irq = 1, + .ai_range = &pci1711_ai_range, + .is_pci1711 = 1, .has_ao = 1, - .has_di_do = 1, - .has_counter = 1, }, [BOARD_PCI1713] = { .name = "pci1713", - .n_aichan = 32, - .rangelist_ai = &range_pci1710_3, - .rangecode_ai = range_codes_pci1710_3, + .ai_range = &pci1710_ai_range, .is_pci1713 = 1, - .has_irq = 1, - .has_large_fifo = 1, - .has_diff_ai = 1, - }, - [BOARD_PCI1720] = { - .name = "pci1720", - .is_pci1720 = 1, - .has_ao = 1, }, [BOARD_PCI1731] = { .name = "pci1731", - .n_aichan = 16, - .rangelist_ai = &range_pci17x1, - .rangecode_ai = range_codes_pci17x1, - .has_irq = 1, - .has_di_do = 1, + .ai_range = &pci1711_ai_range, + .is_pci1711 = 1, }, }; @@ -226,14 +169,15 @@ struct pci1710_private { unsigned int max_samples; unsigned int ctrl; /* control register value */ unsigned int ctrl_ext; /* used to switch from TRIG_EXT to TRIG_xxx */ - unsigned int mux_ext; /* used to set the channel interval to scan */ + unsigned int mux_scan; /* used to set the channel interval to scan */ unsigned char ai_et; unsigned int act_chanlist[32]; /* list of scanned channel */ unsigned char saved_seglen; /* len of the non-repeating chanlist */ unsigned char da_ranges; /* copy of D/A outpit range register */ + unsigned char unipolar_gain; /* adjust for unipolar gain codes */ }; -static int pci171x_ai_check_chanlist(struct comedi_device *dev, +static int pci1710_ai_check_chanlist(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_cmd *cmd) { @@ -299,13 +243,12 @@ static int pci171x_ai_check_chanlist(struct comedi_device *dev, return 0; } -static void pci171x_ai_setup_chanlist(struct comedi_device *dev, +static void pci1710_ai_setup_chanlist(struct comedi_device *dev, struct comedi_subdevice *s, unsigned int *chanlist, unsigned int n_chan, unsigned int seglen) { - const struct boardtype *board = dev->board_ptr; struct pci1710_private *devpriv = dev->private; unsigned int first_chan = CR_CHAN(chanlist[0]); unsigned int last_chan = CR_CHAN(chanlist[seglen - 1]); @@ -315,14 +258,18 @@ static void pci171x_ai_setup_chanlist(struct comedi_device *dev, unsigned int chan = CR_CHAN(chanlist[i]); unsigned int range = CR_RANGE(chanlist[i]); unsigned int aref = CR_AREF(chanlist[i]); - unsigned int rangeval; + unsigned int rangeval = 0; - rangeval = board->rangecode_ai[range]; if (aref == AREF_DIFF) - rangeval |= 0x0020; + rangeval |= PCI171X_RANGE_DIFF; + if (comedi_range_is_unipolar(s, range)) { + rangeval |= PCI171X_RANGE_UNI; + range -= devpriv->unipolar_gain; + } + rangeval |= PCI171X_RANGE_GAIN(range); /* select channel and set range */ - outw(chan | (chan << 8), dev->iobase + PCI171X_MUX_REG); + outw(PCI171X_MUX_CHAN(chan), dev->iobase + PCI171X_MUX_REG); outw(rangeval, dev->iobase + PCI171X_RANGE_REG); devpriv->act_chanlist[i] = chan; @@ -331,11 +278,12 @@ static void pci171x_ai_setup_chanlist(struct comedi_device *dev, devpriv->act_chanlist[i] = CR_CHAN(chanlist[i]); /* select channel interval to scan */ - devpriv->mux_ext = first_chan | (last_chan << 8); - outw(devpriv->mux_ext, dev->iobase + PCI171X_MUX_REG); + devpriv->mux_scan = PCI171X_MUX_CHANL(first_chan) | + PCI171X_MUX_CHANH(last_chan); + outw(devpriv->mux_scan, dev->iobase + PCI171X_MUX_REG); } -static int pci171x_ai_eoc(struct comedi_device *dev, +static int pci1710_ai_eoc(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned long context) @@ -348,7 +296,7 @@ static int pci171x_ai_eoc(struct comedi_device *dev, return -EBUSY; } -static int pci171x_ai_read_sample(struct comedi_device *dev, +static int pci1710_ai_read_sample(struct comedi_device *dev, struct comedi_subdevice *s, unsigned int cur_chan, unsigned int *val) @@ -377,7 +325,7 @@ static int pci171x_ai_read_sample(struct comedi_device *dev, return 0; } -static int pci171x_ai_insn_read(struct comedi_device *dev, +static int pci1710_ai_insn_read(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) @@ -386,13 +334,14 @@ static int pci171x_ai_insn_read(struct comedi_device *dev, int ret = 0; int i; - devpriv->ctrl &= PCI171X_CTRL_CNT0; - devpriv->ctrl |= PCI171X_CTRL_SW; /* set software trigger */ + /* enable software trigger */ + devpriv->ctrl |= PCI171X_CTRL_SW; outw(devpriv->ctrl, dev->iobase + PCI171X_CTRL_REG); + outb(0, dev->iobase + PCI171X_CLRFIFO_REG); outb(0, dev->iobase + PCI171X_CLRINT_REG); - pci171x_ai_setup_chanlist(dev, s, &insn->chanspec, 1, 1); + pci1710_ai_setup_chanlist(dev, s, &insn->chanspec, 1, 1); for (i = 0; i < insn->n; i++) { unsigned int val; @@ -400,111 +349,40 @@ static int pci171x_ai_insn_read(struct comedi_device *dev, /* start conversion */ outw(0, dev->iobase + PCI171X_SOFTTRG_REG); - ret = comedi_timeout(dev, s, insn, pci171x_ai_eoc, 0); + ret = comedi_timeout(dev, s, insn, pci1710_ai_eoc, 0); if (ret) break; - ret = pci171x_ai_read_sample(dev, s, 0, &val); + ret = pci1710_ai_read_sample(dev, s, 0, &val); if (ret) break; data[i] = val; } + /* disable software trigger */ + devpriv->ctrl &= ~PCI171X_CTRL_SW; + outw(devpriv->ctrl, dev->iobase + PCI171X_CTRL_REG); + outb(0, dev->iobase + PCI171X_CLRFIFO_REG); outb(0, dev->iobase + PCI171X_CLRINT_REG); return ret ? ret : insn->n; } -static int pci171x_ao_insn_write(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, - unsigned int *data) -{ - struct pci1710_private *devpriv = dev->private; - unsigned int chan = CR_CHAN(insn->chanspec); - unsigned int range = CR_RANGE(insn->chanspec); - unsigned int val = s->readback[chan]; - int i; - - devpriv->da_ranges &= ~(1 << (chan << 1)); - devpriv->da_ranges |= (range << (chan << 1)); - outw(devpriv->da_ranges, dev->iobase + PCI171X_DAREF_REG); - - for (i = 0; i < insn->n; i++) { - val = data[i]; - outw(val, dev->iobase + PCI171X_DA_REG(chan)); - } - - s->readback[chan] = val; - - return insn->n; -} - -static int pci171x_di_insn_bits(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, - unsigned int *data) -{ - data[1] = inw(dev->iobase + PCI171X_DI_REG); - - return insn->n; -} - -static int pci171x_do_insn_bits(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, - unsigned int *data) -{ - if (comedi_dio_update_state(s, data)) - outw(s->state, dev->iobase + PCI171X_DO_REG); - - data[1] = s->state; - - return insn->n; -} - -static int pci1720_ao_insn_write(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, - unsigned int *data) -{ - struct pci1710_private *devpriv = dev->private; - unsigned int chan = CR_CHAN(insn->chanspec); - unsigned int range = CR_RANGE(insn->chanspec); - unsigned int val; - int i; - - val = devpriv->da_ranges & (~(0x03 << (chan << 1))); - val |= (range << (chan << 1)); - if (val != devpriv->da_ranges) { - outb(val, dev->iobase + PCI1720_RANGE_REG); - devpriv->da_ranges = val; - } - - val = s->readback[chan]; - for (i = 0; i < insn->n; i++) { - val = data[i]; - outw(val, dev->iobase + PCI1720_DA_REG(chan)); - outb(0, dev->iobase + PCI1720_SYNC_REG); /* update outputs */ - } - - s->readback[chan] = val; - - return insn->n; -} - -static int pci171x_ai_cancel(struct comedi_device *dev, +static int pci1710_ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s) { struct pci1710_private *devpriv = dev->private; - devpriv->ctrl &= PCI171X_CTRL_CNT0; - devpriv->ctrl |= PCI171X_CTRL_SW; - /* reset any operations */ + /* disable A/D triggers and interrupt sources */ + devpriv->ctrl &= PCI171X_CTRL_CNT0; /* preserve counter 0 clk src */ outw(devpriv->ctrl, dev->iobase + PCI171X_CTRL_REG); + + /* disable pacer */ comedi_8254_pacer_enable(dev->pacer, 1, 2, false); + + /* clear A/D FIFO and any pending interrutps */ outb(0, dev->iobase + PCI171X_CLRFIFO_REG); outb(0, dev->iobase + PCI171X_CLRINT_REG); @@ -535,7 +413,7 @@ static void pci1710_handle_every_sample(struct comedi_device *dev, outb(0, dev->iobase + PCI171X_CLRINT_REG); for (; !(inw(dev->iobase + PCI171X_STATUS_REG) & PCI171X_STATUS_FE);) { - ret = pci171x_ai_read_sample(dev, s, s->async->cur_chan, &val); + ret = pci1710_ai_read_sample(dev, s, s->async->cur_chan, &val); if (ret) { s->async->events |= COMEDI_CB_ERROR; break; @@ -579,7 +457,7 @@ static void pci1710_handle_fifo(struct comedi_device *dev, unsigned int val; int ret; - ret = pci171x_ai_read_sample(dev, s, s->async->cur_chan, &val); + ret = pci1710_ai_read_sample(dev, s, s->async->cur_chan, &val); if (ret) { s->async->events |= COMEDI_CB_ERROR; break; @@ -598,7 +476,7 @@ static void pci1710_handle_fifo(struct comedi_device *dev, outb(0, dev->iobase + PCI171X_CLRINT_REG); } -static irqreturn_t interrupt_service_pci1710(int irq, void *d) +static irqreturn_t pci1710_irq_handler(int irq, void *d) { struct comedi_device *dev = d; struct pci1710_private *devpriv = dev->private; @@ -624,7 +502,7 @@ static irqreturn_t interrupt_service_pci1710(int irq, void *d) outb(0, dev->iobase + PCI171X_CLRFIFO_REG); outb(0, dev->iobase + PCI171X_CLRINT_REG); /* no sample on this interrupt; reset the channel interval */ - outw(devpriv->mux_ext, dev->iobase + PCI171X_MUX_REG); + outw(devpriv->mux_scan, dev->iobase + PCI171X_MUX_REG); outw(devpriv->ctrl, dev->iobase + PCI171X_CTRL_REG); comedi_8254_pacer_enable(dev->pacer, 1, 2, true); return IRQ_HANDLED; @@ -640,12 +518,12 @@ static irqreturn_t interrupt_service_pci1710(int irq, void *d) return IRQ_HANDLED; } -static int pci171x_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) +static int pci1710_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) { struct pci1710_private *devpriv = dev->private; struct comedi_cmd *cmd = &s->async->cmd; - pci171x_ai_setup_chanlist(dev, s, cmd->chanlist, cmd->chanlist_len, + pci1710_ai_setup_chanlist(dev, s, cmd->chanlist, cmd->chanlist_len, devpriv->saved_seglen); outb(0, dev->iobase + PCI171X_CLRFIFO_REG); @@ -681,7 +559,7 @@ static int pci171x_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) return 0; } -static int pci171x_ai_cmdtest(struct comedi_device *dev, +static int pci1710_ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_cmd *cmd) { @@ -745,7 +623,7 @@ static int pci171x_ai_cmdtest(struct comedi_device *dev, /* Step 5: check channel list */ - err |= pci171x_ai_check_chanlist(dev, s, cmd); + err |= pci1710_ai_check_chanlist(dev, s, cmd); if (err) return 5; @@ -753,7 +631,55 @@ static int pci171x_ai_cmdtest(struct comedi_device *dev, return 0; } -static int pci171x_insn_counter_config(struct comedi_device *dev, +static int pci1710_ao_insn_write(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data) +{ + struct pci1710_private *devpriv = dev->private; + unsigned int chan = CR_CHAN(insn->chanspec); + unsigned int range = CR_RANGE(insn->chanspec); + unsigned int val = s->readback[chan]; + int i; + + devpriv->da_ranges &= ~PCI171X_DAREF_MASK(chan); + devpriv->da_ranges |= PCI171X_DAREF(chan, range); + outw(devpriv->da_ranges, dev->iobase + PCI171X_DAREF_REG); + + for (i = 0; i < insn->n; i++) { + val = data[i]; + outw(val, dev->iobase + PCI171X_DA_REG(chan)); + } + + s->readback[chan] = val; + + return insn->n; +} + +static int pci1710_di_insn_bits(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data) +{ + data[1] = inw(dev->iobase + PCI171X_DI_REG); + + return insn->n; +} + +static int pci1710_do_insn_bits(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data) +{ + if (comedi_dio_update_state(s, data)) + outw(s->state, dev->iobase + PCI171X_DO_REG); + + data[1] = s->state; + + return insn->n; +} + +static int pci1710_counter_insn_config(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) @@ -780,7 +706,7 @@ static int pci171x_insn_counter_config(struct comedi_device *dev, data[2] = 0; } else { data[1] = 0; - data[2] = I8254_OSC_BASE_10MHZ; + data[2] = I8254_OSC_BASE_1MHZ; } break; default: @@ -790,56 +716,29 @@ static int pci171x_insn_counter_config(struct comedi_device *dev, return insn->n; } -static int pci171x_reset(struct comedi_device *dev) +static void pci1710_reset(struct comedi_device *dev) { const struct boardtype *board = dev->board_ptr; - struct pci1710_private *devpriv = dev->private; - /* Software trigger, CNT0=external */ - devpriv->ctrl = PCI171X_CTRL_SW | PCI171X_CTRL_CNT0; - /* reset any operations */ - outw(devpriv->ctrl, dev->iobase + PCI171X_CTRL_REG); + /* + * Disable A/D triggers and interrupt sources, set counter 0 + * to use internal 1 MHz clock. + */ + outw(0, dev->iobase + PCI171X_CTRL_REG); + + /* clear A/D FIFO and any pending interrutps */ outb(0, dev->iobase + PCI171X_CLRFIFO_REG); outb(0, dev->iobase + PCI171X_CLRINT_REG); - devpriv->da_ranges = 0; + if (board->has_ao) { /* set DACs to 0..5V and outputs to 0V */ - outb(devpriv->da_ranges, dev->iobase + PCI171X_DAREF_REG); + outb(0, dev->iobase + PCI171X_DAREF_REG); outw(0, dev->iobase + PCI171X_DA_REG(0)); outw(0, dev->iobase + PCI171X_DA_REG(1)); } - outw(0, dev->iobase + PCI171X_DO_REG); /* digital outputs to 0 */ - outb(0, dev->iobase + PCI171X_CLRFIFO_REG); - outb(0, dev->iobase + PCI171X_CLRINT_REG); - return 0; -} - -static int pci1720_reset(struct comedi_device *dev) -{ - struct pci1710_private *devpriv = dev->private; - /* set synchronous output mode */ - outb(PCI1720_SYNC_CTRL_SC0, dev->iobase + PCI1720_SYNC_CTRL_REG); - devpriv->da_ranges = 0xAA; - /* set all ranges to +/-5V and outputs to 0V */ - outb(devpriv->da_ranges, dev->iobase + PCI1720_RANGE_REG); - outw(0x0800, dev->iobase + PCI1720_DA_REG(0)); - outw(0x0800, dev->iobase + PCI1720_DA_REG(1)); - outw(0x0800, dev->iobase + PCI1720_DA_REG(2)); - outw(0x0800, dev->iobase + PCI1720_DA_REG(3)); - outb(0, dev->iobase + PCI1720_SYNC_REG); /* update outputs */ - - return 0; -} - -static int pci1710_reset(struct comedi_device *dev) -{ - const struct boardtype *board = dev->board_ptr; - - if (board->is_pci1720) - return pci1720_reset(dev); - - return pci171x_reset(dev); + /* set digital outputs to 0 */ + outw(0, dev->iobase + PCI171X_DO_REG); } static int pci1710_auto_attach(struct comedi_device *dev, @@ -850,6 +749,7 @@ static int pci1710_auto_attach(struct comedi_device *dev, struct pci1710_private *devpriv; struct comedi_subdevice *s; int ret, subdev, n_subdevices; + int i; if (context < ARRAY_SIZE(boardtypes)) board = &boardtypes[context]; @@ -872,15 +772,16 @@ static int pci1710_auto_attach(struct comedi_device *dev, if (!dev->pacer) return -ENOMEM; - n_subdevices = 0; - if (board->n_aichan) - n_subdevices++; + n_subdevices = 1; /* all boards have analog inputs */ if (board->has_ao) n_subdevices++; - if (board->has_di_do) - n_subdevices += 2; - if (board->has_counter) - n_subdevices++; + if (!board->is_pci1713) { + /* + * All other boards have digital inputs and outputs as + * well as a user counter. + */ + n_subdevices += 3; + } ret = comedi_alloc_subdevices(dev, n_subdevices); if (ret) @@ -888,8 +789,8 @@ static int pci1710_auto_attach(struct comedi_device *dev, pci1710_reset(dev); - if (board->has_irq && pcidev->irq) { - ret = request_irq(pcidev->irq, interrupt_service_pci1710, + if (pcidev->irq) { + ret = request_irq(pcidev->irq, pci1710_irq_handler, IRQF_SHARED, dev->board_name, dev); if (ret == 0) dev->irq = pcidev->irq; @@ -897,109 +798,89 @@ static int pci1710_auto_attach(struct comedi_device *dev, subdev = 0; - if (board->n_aichan) { - s = &dev->subdevices[subdev]; - s->type = COMEDI_SUBD_AI; - s->subdev_flags = SDF_READABLE | SDF_COMMON | SDF_GROUND; - if (board->has_diff_ai) - s->subdev_flags |= SDF_DIFF; - s->n_chan = board->n_aichan; - s->maxdata = 0x0fff; - s->range_table = board->rangelist_ai; - s->insn_read = pci171x_ai_insn_read; - if (dev->irq) { - dev->read_subdev = s; - s->subdev_flags |= SDF_CMD_READ; - s->len_chanlist = s->n_chan; - s->do_cmdtest = pci171x_ai_cmdtest; - s->do_cmd = pci171x_ai_cmd; - s->cancel = pci171x_ai_cancel; + /* Analog Input subdevice */ + s = &dev->subdevices[subdev++]; + s->type = COMEDI_SUBD_AI; + s->subdev_flags = SDF_READABLE | SDF_GROUND; + if (!board->is_pci1711) + s->subdev_flags |= SDF_DIFF; + s->n_chan = board->is_pci1713 ? 32 : 16; + s->maxdata = 0x0fff; + s->range_table = board->ai_range; + s->insn_read = pci1710_ai_insn_read; + if (dev->irq) { + dev->read_subdev = s; + s->subdev_flags |= SDF_CMD_READ; + s->len_chanlist = s->n_chan; + s->do_cmdtest = pci1710_ai_cmdtest; + s->do_cmd = pci1710_ai_cmd; + s->cancel = pci1710_ai_cancel; + } + + /* find the value needed to adjust for unipolar gain codes */ + for (i = 0; i < s->range_table->length; i++) { + if (comedi_range_is_unipolar(s, i)) { + devpriv->unipolar_gain = i; + break; } - subdev++; } if (board->has_ao) { - s = &dev->subdevices[subdev]; + /* Analog Output subdevice */ + s = &dev->subdevices[subdev++]; s->type = COMEDI_SUBD_AO; - s->subdev_flags = SDF_WRITABLE | SDF_GROUND | SDF_COMMON; + s->subdev_flags = SDF_WRITABLE | SDF_GROUND; + s->n_chan = 2; s->maxdata = 0x0fff; - if (board->is_pci1720) { - s->n_chan = 4; - s->range_table = &pci1720_ao_range; - s->insn_write = pci1720_ao_insn_write; - } else { - s->n_chan = 2; - s->range_table = &pci171x_ao_range; - s->insn_write = pci171x_ao_insn_write; - } + s->range_table = &pci171x_ao_range; + s->insn_write = pci1710_ao_insn_write; ret = comedi_alloc_subdev_readback(s); if (ret) return ret; - - /* initialize the readback values to match the board reset */ - if (board->is_pci1720) { - int i; - - for (i = 0; i < s->n_chan; i++) - s->readback[i] = 0x0800; - } - - subdev++; } - if (board->has_di_do) { - s = &dev->subdevices[subdev]; + if (!board->is_pci1713) { + /* Digital Input subdevice */ + s = &dev->subdevices[subdev++]; s->type = COMEDI_SUBD_DI; s->subdev_flags = SDF_READABLE; s->n_chan = 16; s->maxdata = 1; s->range_table = &range_digital; - s->insn_bits = pci171x_di_insn_bits; - subdev++; + s->insn_bits = pci1710_di_insn_bits; - s = &dev->subdevices[subdev]; + /* Digital Output subdevice */ + s = &dev->subdevices[subdev++]; s->type = COMEDI_SUBD_DO; s->subdev_flags = SDF_WRITABLE; s->n_chan = 16; s->maxdata = 1; s->range_table = &range_digital; - s->insn_bits = pci171x_do_insn_bits; - subdev++; - } + s->insn_bits = pci1710_do_insn_bits; - /* Counter subdevice (8254) */ - if (board->has_counter) { - s = &dev->subdevices[subdev]; + /* Counter subdevice (8254) */ + s = &dev->subdevices[subdev++]; comedi_8254_subdevice_init(s, dev->pacer); - dev->pacer->insn_config = pci171x_insn_counter_config; + dev->pacer->insn_config = pci1710_counter_insn_config; /* counters 1 and 2 are used internally for the pacer */ comedi_8254_set_busy(dev->pacer, 1, true); comedi_8254_set_busy(dev->pacer, 2, true); - - subdev++; } /* max_samples is half the FIFO size (2 bytes/sample) */ - devpriv->max_samples = (board->has_large_fifo) ? 2048 : 512; + devpriv->max_samples = (board->is_pci1711) ? 512 : 2048; return 0; } -static void pci1710_detach(struct comedi_device *dev) -{ - if (dev->iobase) - pci1710_reset(dev); - comedi_pci_detach(dev); -} - static struct comedi_driver adv_pci1710_driver = { .driver_name = "adv_pci1710", .module = THIS_MODULE, .auto_attach = pci1710_auto_attach, - .detach = pci1710_detach, + .detach = comedi_pci_detach, }; static int adv_pci1710_pci_probe(struct pci_dev *dev, @@ -1063,7 +944,6 @@ static const struct pci_device_id adv_pci1710_pci_table[] = { }, { PCI_VDEVICE(ADVANTECH, 0x1711), BOARD_PCI1711 }, { PCI_VDEVICE(ADVANTECH, 0x1713), BOARD_PCI1713 }, - { PCI_VDEVICE(ADVANTECH, 0x1720), BOARD_PCI1720 }, { PCI_VDEVICE(ADVANTECH, 0x1731), BOARD_PCI1731 }, { 0 } }; diff --git a/drivers/staging/comedi/drivers/adv_pci1720.c b/drivers/staging/comedi/drivers/adv_pci1720.c new file mode 100644 index 000000000..4830a1c93 --- /dev/null +++ b/drivers/staging/comedi/drivers/adv_pci1720.c @@ -0,0 +1,195 @@ +/* + * COMEDI driver for Advantech PCI-1720U + * Copyright (c) 2015 H Hartley Sweeten + * + * Separated from the adv_pci1710 driver written by: + * Michal Dobes + * + * COMEDI - Linux Control and Measurement Device Interface + * Copyright (C) 2000 David A. Schleef + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +/* + * Driver: adv_pci1720 + * Description: 4-channel Isolated D/A Output board + * Devices: [Advantech] PCI-7120U (adv_pci1720) + * Author: H Hartley Sweeten + * Updated: Fri, 29 Oct 2015 17:19:35 -0700 + * Status: untested + * + * Configuration options: not applicable, uses PCI auto config + * + * The PCI-1720 has 4 isolated 12-bit analog output channels with multiple + * output ranges. It also has a BoardID switch to allow differentiating + * multiple boards in the system. + * + * The analog outputs can operate in two modes, immediate and synchronized. + * This driver currently does not support the synchronized output mode. + * + * Jumpers JP1 to JP4 are used to set the current sink ranges for each + * analog output channel. In order to use the current sink ranges, the + * unipolar 5V range must be used. The voltage output and sink output for + * each channel is available on the connector as separate pins. + * + * Jumper JP5 controls the "hot" reset state of the analog outputs. + * Depending on its setting, the analog outputs will either keep the + * last settings and output values or reset to the default state after + * a "hot" reset. The default state for all channels is uniploar 5V range + * and all the output values are 0V. To allow this feature to work, the + * analog outputs are not "reset" when the driver attaches. + */ + +#include +#include + +#include "../comedi_pci.h" + +/* + * PCI BAR2 Register map (dev->iobase) + */ +#define PCI1720_AO_LSB_REG(x) (0x00 + ((x) * 2)) +#define PCI1720_AO_MSB_REG(x) (0x01 + ((x) * 2)) +#define PCI1720_AO_RANGE_REG 0x08 +#define PCI1720_AO_RANGE(c, r) (((r) & 0x3) << ((c) * 2)) +#define PCI1720_AO_RANGE_MASK(c) PCI1720_AO_RANGE((c), 0x3) +#define PCI1720_SYNC_REG 0x09 +#define PCI1720_SYNC_CTRL_REG 0x0f +#define PCI1720_SYNC_CTRL_SC0 BIT(0) +#define PCI1720_BOARDID_REG 0x14 + +static const struct comedi_lrange pci1720_ao_range = { + 4, { + UNI_RANGE(5), + UNI_RANGE(10), + BIP_RANGE(5), + BIP_RANGE(10) + } +}; + +static int pci1720_ao_insn_write(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data) +{ + unsigned int chan = CR_CHAN(insn->chanspec); + unsigned int range = CR_RANGE(insn->chanspec); + unsigned int val; + int i; + + /* set the channel range and polarity */ + val = inb(dev->iobase + PCI1720_AO_RANGE_REG); + val &= ~PCI1720_AO_RANGE_MASK(chan); + val |= PCI1720_AO_RANGE(chan, range); + outb(val, dev->iobase + PCI1720_AO_RANGE_REG); + + val = s->readback[chan]; + for (i = 0; i < insn->n; i++) { + val = data[i]; + + outb(val & 0xff, dev->iobase + PCI1720_AO_LSB_REG(chan)); + outb((val >> 8) & 0xff, dev->iobase + PCI1720_AO_MSB_REG(chan)); + + /* conversion time is 2us (500 kHz throughput) */ + usleep_range(2, 100); + } + + s->readback[chan] = val; + + return insn->n; +} + +static int pci1720_di_insn_bits(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data) +{ + data[1] = inb(dev->iobase + PCI1720_BOARDID_REG); + + return insn->n; +} + +static int pci1720_auto_attach(struct comedi_device *dev, + unsigned long context) +{ + struct pci_dev *pcidev = comedi_to_pci_dev(dev); + struct comedi_subdevice *s; + int ret; + + ret = comedi_pci_enable(dev); + if (ret) + return ret; + dev->iobase = pci_resource_start(pcidev, 2); + + ret = comedi_alloc_subdevices(dev, 2); + if (ret) + return ret; + + /* Analog Output subdevice */ + s = &dev->subdevices[0]; + s->type = COMEDI_SUBD_AO; + s->subdev_flags = SDF_WRITABLE; + s->n_chan = 4; + s->maxdata = 0x0fff; + s->range_table = &pci1720_ao_range; + s->insn_write = pci1720_ao_insn_write; + + ret = comedi_alloc_subdev_readback(s); + if (ret) + return ret; + + /* Digital Input subdevice (BoardID SW1) */ + s = &dev->subdevices[1]; + 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 = pci1720_di_insn_bits; + + /* disable synchronized output, channels update when written */ + outb(0, dev->iobase + PCI1720_SYNC_CTRL_REG); + + return 0; +} + +static struct comedi_driver adv_pci1720_driver = { + .driver_name = "adv_pci1720", + .module = THIS_MODULE, + .auto_attach = pci1720_auto_attach, + .detach = comedi_pci_detach, +}; + +static int adv_pci1720_pci_probe(struct pci_dev *dev, + const struct pci_device_id *id) +{ + return comedi_pci_auto_config(dev, &adv_pci1720_driver, + id->driver_data); +} + +static const struct pci_device_id adv_pci1720_pci_table[] = { + { PCI_DEVICE(PCI_VENDOR_ID_ADVANTECH, 0x1720) }, + { 0 } +}; +MODULE_DEVICE_TABLE(pci, adv_pci1720_pci_table); + +static struct pci_driver adv_pci1720_pci_driver = { + .name = "adv_pci1720", + .id_table = adv_pci1720_pci_table, + .probe = adv_pci1720_pci_probe, + .remove = comedi_pci_auto_unconfig, +}; +module_comedi_pci_driver(adv_pci1720_driver, adv_pci1720_pci_driver); + +MODULE_AUTHOR("H Hartley Sweeten "); +MODULE_DESCRIPTION("Comedi driver for Advantech PCI-1720 Analog Output board"); +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/adv_pci1760.c b/drivers/staging/comedi/drivers/adv_pci1760.c new file mode 100644 index 000000000..d7dd1e55e --- /dev/null +++ b/drivers/staging/comedi/drivers/adv_pci1760.c @@ -0,0 +1,432 @@ +/* + * COMEDI driver for the Advantech PCI-1760 + * Copyright (C) 2015 H Hartley Sweeten + * + * Based on the pci1760 support in the adv_pci_dio driver written by: + * Michal Dobes + * + * COMEDI - Linux Control and Measurement Device Interface + * Copyright (C) 2000 David A. Schleef + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +/* + * Driver: adv_pci1760 + * Description: Advantech PCI-1760 Relay & Isolated Digital Input Card + * Devices: [Advantech] PCI-1760 (adv_pci1760) + * Author: H Hartley Sweeten + * Updated: Fri, 13 Nov 2015 12:34:00 -0700 + * Status: untested + * + * Configuration Options: not applicable, uses PCI auto config + */ + +#include + +#include "../comedi_pci.h" + +/* + * PCI-1760 Register Map + * + * Outgoing Mailbox Bytes + * OMB3: Not used (must be 0) + * OMB2: The command code to the PCI-1760 + * OMB1: The hi byte of the parameter for the command in OMB2 + * OMB0: The lo byte of the parameter for the command in OMB2 + * + * Incoming Mailbox Bytes + * IMB3: The Isolated Digital Input status (updated every 100us) + * IMB2: The current command (matches OMB2 when command is successful) + * IMB1: The hi byte of the feedback data for the command in OMB2 + * IMB0: The lo byte of the feedback data for the command in OMB2 + * + * Interrupt Control/Status + * INTCSR3: Not used (must be 0) + * INTCSR2: The interrupt status (read only) + * INTCSR1: Interrupt enable/disable + * INTCSR0: Not used (must be 0) + */ +#define PCI1760_OMB_REG(x) (0x0c + (x)) +#define PCI1760_IMB_REG(x) (0x1c + (x)) +#define PCI1760_INTCSR_REG(x) (0x38 + (x)) +#define PCI1760_INTCSR1_IRQ_ENA BIT(5) +#define PCI1760_INTCSR2_OMB_IRQ BIT(0) +#define PCI1760_INTCSR2_IMB_IRQ BIT(1) +#define PCI1760_INTCSR2_IRQ_STATUS BIT(6) +#define PCI1760_INTCSR2_IRQ_ASSERTED BIT(7) + +/* PCI-1760 command codes */ +#define PCI1760_CMD_CLR_IMB2 0x00 /* Clears IMB2 */ +#define PCI1760_CMD_SET_DO 0x01 /* Set output state */ +#define PCI1760_CMD_GET_DO 0x02 /* Read output status */ +#define PCI1760_CMD_GET_STATUS 0x03 /* Read current status */ +#define PCI1760_CMD_GET_FW_VER 0x0e /* Read firware version */ +#define PCI1760_CMD_GET_HW_VER 0x0f /* Read hardware version */ +#define PCI1760_CMD_SET_PWM_HI(x) (0x10 + (x) * 2) /* Set "hi" period */ +#define PCI1760_CMD_SET_PWM_LO(x) (0x11 + (x) * 2) /* Set "lo" period */ +#define PCI1760_CMD_SET_PWM_CNT(x) (0x14 + (x)) /* Set burst count */ +#define PCI1760_CMD_ENA_PWM 0x1f /* Enable PWM outputs */ +#define PCI1760_CMD_ENA_FILT 0x20 /* Enable input filter */ +#define PCI1760_CMD_ENA_PAT_MATCH 0x21 /* Enable input pattern match */ +#define PCI1760_CMD_SET_PAT_MATCH 0x22 /* Set input pattern match */ +#define PCI1760_CMD_ENA_RISE_EDGE 0x23 /* Enable input rising edge */ +#define PCI1760_CMD_ENA_FALL_EDGE 0x24 /* Enable input falling edge */ +#define PCI1760_CMD_ENA_CNT 0x28 /* Enable counter */ +#define PCI1760_CMD_RST_CNT 0x29 /* Reset counter */ +#define PCI1760_CMD_ENA_CNT_OFLOW 0x2a /* Enable counter overflow */ +#define PCI1760_CMD_ENA_CNT_MATCH 0x2b /* Enable counter match */ +#define PCI1760_CMD_SET_CNT_EDGE 0x2c /* Set counter edge */ +#define PCI1760_CMD_GET_CNT 0x2f /* Reads counter value */ +#define PCI1760_CMD_SET_HI_SAMP(x) (0x30 + (x)) /* Set "hi" sample time */ +#define PCI1760_CMD_SET_LO_SAMP(x) (0x38 + (x)) /* Set "lo" sample time */ +#define PCI1760_CMD_SET_CNT(x) (0x40 + (x)) /* Set counter reset val */ +#define PCI1760_CMD_SET_CNT_MATCH(x) (0x48 + (x)) /* Set counter match val */ +#define PCI1760_CMD_GET_INT_FLAGS 0x60 /* Read interrupt flags */ +#define PCI1760_CMD_GET_INT_FLAGS_MATCH BIT(0) +#define PCI1760_CMD_GET_INT_FLAGS_COS BIT(1) +#define PCI1760_CMD_GET_INT_FLAGS_OFLOW BIT(2) +#define PCI1760_CMD_GET_OS 0x61 /* Read edge change flags */ +#define PCI1760_CMD_GET_CNT_STATUS 0x62 /* Read counter oflow/match */ + +#define PCI1760_CMD_TIMEOUT 250 /* 250 usec timeout */ +#define PCI1760_CMD_RETRIES 3 /* limit number of retries */ + +#define PCI1760_PWM_TIMEBASE 100000 /* 1 unit = 100 usec */ + +static int pci1760_send_cmd(struct comedi_device *dev, + unsigned char cmd, unsigned short val) +{ + unsigned long timeout; + + /* send the command and parameter */ + outb(val & 0xff, dev->iobase + PCI1760_OMB_REG(0)); + outb((val >> 8) & 0xff, dev->iobase + PCI1760_OMB_REG(1)); + outb(cmd, dev->iobase + PCI1760_OMB_REG(2)); + outb(0, dev->iobase + PCI1760_OMB_REG(3)); + + /* datasheet says to allow up to 250 usec for the command to complete */ + timeout = jiffies + usecs_to_jiffies(PCI1760_CMD_TIMEOUT); + do { + if (inb(dev->iobase + PCI1760_IMB_REG(2)) == cmd) { + /* command success; return the feedback data */ + return inb(dev->iobase + PCI1760_IMB_REG(0)) | + (inb(dev->iobase + PCI1760_IMB_REG(1)) << 8); + } + cpu_relax(); + } while (time_before(jiffies, timeout)); + + return -EBUSY; +} + +static int pci1760_cmd(struct comedi_device *dev, + unsigned char cmd, unsigned short val) +{ + int repeats; + int ret; + + /* send PCI1760_CMD_CLR_IMB2 between identical commands */ + if (inb(dev->iobase + PCI1760_IMB_REG(2)) == cmd) { + ret = pci1760_send_cmd(dev, PCI1760_CMD_CLR_IMB2, 0); + if (ret < 0) { + /* timeout? try it once more */ + ret = pci1760_send_cmd(dev, PCI1760_CMD_CLR_IMB2, 0); + if (ret < 0) + return -ETIMEDOUT; + } + } + + /* datasheet says to keep retrying the command */ + for (repeats = 0; repeats < PCI1760_CMD_RETRIES; repeats++) { + ret = pci1760_send_cmd(dev, cmd, val); + if (ret >= 0) + return ret; + } + + /* command failed! */ + return -ETIMEDOUT; +} + +static int pci1760_di_insn_bits(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data) +{ + data[1] = inb(dev->iobase + PCI1760_IMB_REG(3)); + + return insn->n; +} + +static int pci1760_do_insn_bits(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data) +{ + int ret; + + if (comedi_dio_update_state(s, data)) { + ret = pci1760_cmd(dev, PCI1760_CMD_SET_DO, s->state); + if (ret < 0) + return ret; + } + + data[1] = s->state; + + return insn->n; +} + +static int pci1760_pwm_ns_to_div(unsigned int flags, unsigned int ns) +{ + unsigned int divisor; + + switch (flags) { + case CMDF_ROUND_NEAREST: + divisor = DIV_ROUND_CLOSEST(ns, PCI1760_PWM_TIMEBASE); + break; + case CMDF_ROUND_UP: + divisor = DIV_ROUND_UP(ns, PCI1760_PWM_TIMEBASE); + break; + case CMDF_ROUND_DOWN: + divisor = ns / PCI1760_PWM_TIMEBASE; + default: + return -EINVAL; + } + + if (divisor < 1) + divisor = 1; + if (divisor > 0xffff) + divisor = 0xffff; + + return divisor; +} + +static int pci1760_pwm_enable(struct comedi_device *dev, + unsigned int chan, bool enable) +{ + int ret; + + ret = pci1760_cmd(dev, PCI1760_CMD_GET_STATUS, PCI1760_CMD_ENA_PWM); + if (ret < 0) + return ret; + + if (enable) + ret |= BIT(chan); + else + ret &= ~BIT(chan); + + return pci1760_cmd(dev, PCI1760_CMD_ENA_PWM, ret); +} + +static int pci1760_pwm_insn_config(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data) +{ + unsigned int chan = CR_CHAN(insn->chanspec); + int hi_div; + int lo_div; + int ret; + + switch (data[0]) { + case INSN_CONFIG_ARM: + ret = pci1760_pwm_enable(dev, chan, false); + if (ret < 0) + return ret; + + if (data[1] > 0xffff) + return -EINVAL; + ret = pci1760_cmd(dev, PCI1760_CMD_SET_PWM_CNT(chan), data[1]); + if (ret < 0) + return ret; + + ret = pci1760_pwm_enable(dev, chan, true); + if (ret < 0) + return ret; + break; + case INSN_CONFIG_DISARM: + ret = pci1760_pwm_enable(dev, chan, false); + if (ret < 0) + return ret; + break; + case INSN_CONFIG_PWM_OUTPUT: + ret = pci1760_pwm_enable(dev, chan, false); + if (ret < 0) + return ret; + + hi_div = pci1760_pwm_ns_to_div(data[1], data[2]); + lo_div = pci1760_pwm_ns_to_div(data[3], data[4]); + if (hi_div < 0 || lo_div < 0) + return -EINVAL; + if ((hi_div * PCI1760_PWM_TIMEBASE) != data[2] || + (lo_div * PCI1760_PWM_TIMEBASE) != data[4]) { + data[2] = hi_div * PCI1760_PWM_TIMEBASE; + data[4] = lo_div * PCI1760_PWM_TIMEBASE; + return -EAGAIN; + } + ret = pci1760_cmd(dev, PCI1760_CMD_SET_PWM_HI(chan), hi_div); + if (ret < 0) + return ret; + ret = pci1760_cmd(dev, PCI1760_CMD_SET_PWM_LO(chan), lo_div); + if (ret < 0) + return ret; + break; + case INSN_CONFIG_GET_PWM_OUTPUT: + hi_div = pci1760_cmd(dev, PCI1760_CMD_GET_STATUS, + PCI1760_CMD_SET_PWM_HI(chan)); + lo_div = pci1760_cmd(dev, PCI1760_CMD_GET_STATUS, + PCI1760_CMD_SET_PWM_LO(chan)); + if (hi_div < 0 || lo_div < 0) + return -ETIMEDOUT; + + data[1] = hi_div * PCI1760_PWM_TIMEBASE; + data[2] = lo_div * PCI1760_PWM_TIMEBASE; + break; + case INSN_CONFIG_GET_PWM_STATUS: + ret = pci1760_cmd(dev, PCI1760_CMD_GET_STATUS, + PCI1760_CMD_ENA_PWM); + if (ret < 0) + return ret; + + data[1] = (ret & BIT(chan)) ? 1 : 0; + break; + default: + return -EINVAL; + } + + return insn->n; +} + +static void pci1760_reset(struct comedi_device *dev) +{ + int i; + + /* disable interrupts (intcsr2 is read-only) */ + outb(0, dev->iobase + PCI1760_INTCSR_REG(0)); + outb(0, dev->iobase + PCI1760_INTCSR_REG(1)); + outb(0, dev->iobase + PCI1760_INTCSR_REG(3)); + + /* disable counters */ + pci1760_cmd(dev, PCI1760_CMD_ENA_CNT, 0); + + /* disable overflow interrupts */ + pci1760_cmd(dev, PCI1760_CMD_ENA_CNT_OFLOW, 0); + + /* disable match */ + pci1760_cmd(dev, PCI1760_CMD_ENA_CNT_MATCH, 0); + + /* set match and counter reset values */ + for (i = 0; i < 8; i++) { + pci1760_cmd(dev, PCI1760_CMD_SET_CNT_MATCH(i), 0x8000); + pci1760_cmd(dev, PCI1760_CMD_SET_CNT(i), 0x0000); + } + + /* reset counters to reset values */ + pci1760_cmd(dev, PCI1760_CMD_RST_CNT, 0xff); + + /* set counter count edges */ + pci1760_cmd(dev, PCI1760_CMD_SET_CNT_EDGE, 0); + + /* disable input filters */ + pci1760_cmd(dev, PCI1760_CMD_ENA_FILT, 0); + + /* disable pattern matching */ + pci1760_cmd(dev, PCI1760_CMD_ENA_PAT_MATCH, 0); + + /* set pattern match value */ + pci1760_cmd(dev, PCI1760_CMD_SET_PAT_MATCH, 0); +} + +static int pci1760_auto_attach(struct comedi_device *dev, + unsigned long context) +{ + struct pci_dev *pcidev = comedi_to_pci_dev(dev); + struct comedi_subdevice *s; + int ret; + + ret = comedi_pci_enable(dev); + if (ret) + return ret; + dev->iobase = pci_resource_start(pcidev, 0); + + pci1760_reset(dev); + + ret = comedi_alloc_subdevices(dev, 4); + if (ret) + return ret; + + /* Digital Input subdevice */ + s = &dev->subdevices[0]; + s->type = COMEDI_SUBD_DI; + s->subdev_flags = SDF_READABLE; + s->n_chan = 8; + s->maxdata = 1; + s->range_table = &range_digital; + s->insn_bits = pci1760_di_insn_bits; + + /* Digital Output subdevice */ + s = &dev->subdevices[1]; + s->type = COMEDI_SUBD_DO; + s->subdev_flags = SDF_WRITABLE; + s->n_chan = 8; + s->maxdata = 1; + s->range_table = &range_digital; + s->insn_bits = pci1760_do_insn_bits; + + /* get the current state of the outputs */ + ret = pci1760_cmd(dev, PCI1760_CMD_GET_DO, 0); + if (ret < 0) + return ret; + s->state = ret; + + /* PWM subdevice */ + s = &dev->subdevices[2]; + s->type = COMEDI_SUBD_PWM; + s->subdev_flags = SDF_PWM_COUNTER; + s->n_chan = 2; + s->insn_config = pci1760_pwm_insn_config; + + /* Counter subdevice */ + s = &dev->subdevices[3]; + s->type = COMEDI_SUBD_UNUSED; + + return 0; +} + +static struct comedi_driver pci1760_driver = { + .driver_name = "adv_pci1760", + .module = THIS_MODULE, + .auto_attach = pci1760_auto_attach, + .detach = comedi_pci_detach, +}; + +static int pci1760_pci_probe(struct pci_dev *dev, + const struct pci_device_id *id) +{ + return comedi_pci_auto_config(dev, &pci1760_driver, id->driver_data); +} + +static const struct pci_device_id pci1760_pci_table[] = { + { PCI_DEVICE(PCI_VENDOR_ID_ADVANTECH, 0x1760) }, + { 0 } +}; +MODULE_DEVICE_TABLE(pci, pci1760_pci_table); + +static struct pci_driver pci1760_pci_driver = { + .name = "adv_pci1760", + .id_table = pci1760_pci_table, + .probe = pci1760_pci_probe, + .remove = comedi_pci_auto_unconfig, +}; +module_comedi_pci_driver(pci1760_driver, pci1760_pci_driver); + +MODULE_AUTHOR("Comedi http://www.comedi.org"); +MODULE_DESCRIPTION("Comedi driver for Advantech PCI-1760"); +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/adv_pci_dio.c b/drivers/staging/comedi/drivers/adv_pci_dio.c index f1b3c5aa8..620cec13d 100644 --- a/drivers/staging/comedi/drivers/adv_pci_dio.c +++ b/drivers/staging/comedi/drivers/adv_pci_dio.c @@ -4,30 +4,21 @@ * Author: Michal Dobes * * Hardware driver for Advantech PCI DIO cards. -*/ -/* -Driver: adv_pci_dio -Description: Advantech PCI-1730, PCI-1733, PCI-1734, PCI-1735U, - PCI-1736UP, PCI-1739U, PCI-1750, PCI-1751, PCI-1752, - PCI-1753/E, PCI-1754, PCI-1756, PCI-1760, PCI-1762 -Author: Michal Dobes -Devices: [Advantech] PCI-1730 (adv_pci_dio), PCI-1733, - PCI-1734, PCI-1735U, PCI-1736UP, PCI-1739U, PCI-1750, - PCI-1751, PCI-1752, PCI-1753, - PCI-1753+PCI-1753E, PCI-1754, PCI-1756, - PCI-1760, PCI-1762 -Status: untested -Updated: Mon, 09 Jan 2012 12:40:46 +0000 - -This driver supports now only insn interface for DI/DO/DIO. + */ -Configuration options: - [0] - PCI bus of device (optional) - [1] - PCI slot of device (optional) - If bus/slot is not specified, the first available PCI - device will be used. - -*/ +/* + * Driver: adv_pci_dio + * Description: Advantech Digital I/O Cards + * Devices: [Advantech] PCI-1730 (adv_pci_dio), PCI-1733, + * PCI-1734, PCI-1735U, PCI-1736UP, PCI-1739U, PCI-1750, + * PCI-1751, PCI-1752, PCI-1753, PCI-1753+PCI-1753E, + * PCI-1754, PCI-1756, PCI-1762 + * Author: Michal Dobes + * Updated: Mon, 09 Jan 2012 12:40:46 +0000 + * Status: untested + * + * Configuration Options: not applicable, uses PCI auto config + */ #include #include @@ -37,403 +28,199 @@ Configuration options: #include "8255.h" #include "comedi_8254.h" -/* hardware types of the cards */ -enum hw_cards_id { - TYPE_PCI1730, TYPE_PCI1733, TYPE_PCI1734, TYPE_PCI1735, TYPE_PCI1736, - TYPE_PCI1739, - TYPE_PCI1750, - TYPE_PCI1751, - TYPE_PCI1752, - TYPE_PCI1753, TYPE_PCI1753E, - TYPE_PCI1754, TYPE_PCI1756, - TYPE_PCI1760, - TYPE_PCI1762 -}; - -/* which I/O instructions to use */ -enum hw_io_access { - IO_8b, IO_16b -}; - -#define MAX_DI_SUBDEVS 2 /* max number of DI subdevices per card */ -#define MAX_DO_SUBDEVS 2 /* max number of DO subdevices per card */ -#define MAX_DIO_SUBDEVG 2 /* max number of DIO subdevices group per - * card */ - -#define PCIDIO_MAINREG 2 /* main I/O region for all Advantech cards? */ - -/* Register offset definitions */ -/* Advantech PCI-1730/3/4 */ -#define PCI1730_IDI 0 /* R: Isolated digital input 0-15 */ -#define PCI1730_IDO 0 /* W: Isolated digital output 0-15 */ -#define PCI1730_DI 2 /* R: Digital input 0-15 */ -#define PCI1730_DO 2 /* W: Digital output 0-15 */ -#define PCI1733_IDI 0 /* R: Isolated digital input 0-31 */ -#define PCI1730_3_INT_EN 0x08 /* R/W: enable/disable interrupts */ -#define PCI1730_3_INT_RF 0x0c /* R/W: set falling/raising edge for - * interrupts */ -#define PCI1730_3_INT_CLR 0x10 /* R/W: clear interrupts */ -#define PCI1734_IDO 0 /* W: Isolated digital output 0-31 */ -#define PCI173x_BOARDID 4 /* R: Board I/D switch for 1730/3/4 */ - -/* Advantech PCI-1735U */ -#define PCI1735_DI 0 /* R: Digital input 0-31 */ -#define PCI1735_DO 0 /* W: Digital output 0-31 */ -#define PCI1735_C8254 4 /* R/W: 8254 counter */ -#define PCI1735_BOARDID 8 /* R: Board I/D switch for 1735U */ - -/* Advantech PCI-1736UP */ -#define PCI1736_IDI 0 /* R: Isolated digital input 0-15 */ -#define PCI1736_IDO 0 /* W: Isolated digital output 0-15 */ -#define PCI1736_3_INT_EN 0x08 /* R/W: enable/disable interrupts */ -#define PCI1736_3_INT_RF 0x0c /* R/W: set falling/raising edge for - * interrupts */ -#define PCI1736_3_INT_CLR 0x10 /* R/W: clear interrupts */ -#define PCI1736_BOARDID 4 /* R: Board I/D switch for 1736UP */ -#define PCI1736_MAINREG 0 /* Normal register (2) doesn't work */ +/* + * Register offset definitions + */ -/* Advantech PCI-1739U */ -#define PCI1739_DIO 0 /* R/W: begin of 8255 registers block */ -#define PCI1739_ICR 32 /* W: Interrupt control register */ -#define PCI1739_ISR 32 /* R: Interrupt status register */ -#define PCI1739_BOARDID 8 /* R: Board I/D switch for 1739U */ +/* PCI-1730, PCI-1733, PCI-1736 interrupt control registers */ +#define PCI173X_INT_EN_REG 0x08 /* R/W: enable/disable */ +#define PCI173X_INT_RF_REG 0x0c /* R/W: falling/rising edge */ +#define PCI173X_INT_CLR_REG 0x10 /* R/W: clear */ -/* Advantech PCI-1750 */ -#define PCI1750_IDI 0 /* R: Isolated digital input 0-15 */ -#define PCI1750_IDO 0 /* W: Isolated digital output 0-15 */ -#define PCI1750_ICR 32 /* W: Interrupt control register */ -#define PCI1750_ISR 32 /* R: Interrupt status register */ +/* PCI-1739U, PCI-1750, PCI1751 interrupt control registers */ +#define PCI1750_INT_REG 0x20 /* R/W: status/control */ -/* Advantech PCI-1751/3/3E */ -#define PCI1751_DIO 0 /* R/W: begin of 8255 registers block */ -#define PCI1751_CNT 24 /* R/W: begin of 8254 registers block */ -#define PCI1751_ICR 32 /* W: Interrupt control register */ -#define PCI1751_ISR 32 /* R: Interrupt status register */ -#define PCI1753_DIO 0 /* R/W: begin of 8255 registers block */ -#define PCI1753_ICR0 16 /* R/W: Interrupt control register group 0 */ -#define PCI1753_ICR1 17 /* R/W: Interrupt control register group 1 */ -#define PCI1753_ICR2 18 /* R/W: Interrupt control register group 2 */ -#define PCI1753_ICR3 19 /* R/W: Interrupt control register group 3 */ -#define PCI1753E_DIO 32 /* R/W: begin of 8255 registers block */ -#define PCI1753E_ICR0 48 /* R/W: Interrupt control register group 0 */ -#define PCI1753E_ICR1 49 /* R/W: Interrupt control register group 1 */ -#define PCI1753E_ICR2 50 /* R/W: Interrupt control register group 2 */ -#define PCI1753E_ICR3 51 /* R/W: Interrupt control register group 3 */ +/* PCI-1753, PCI-1753E interrupt control registers */ +#define PCI1753_INT_REG(x) (0x10 + (x)) /* R/W: control group 0 to 3 */ +#define PCI1753E_INT_REG(x) (0x30 + (x)) /* R/W: control group 0 to 3 */ -/* Advantech PCI-1752/4/6 */ -#define PCI1752_IDO 0 /* R/W: Digital output 0-31 */ -#define PCI1752_IDO2 4 /* R/W: Digital output 32-63 */ -#define PCI1754_IDI 0 /* R: Digital input 0-31 */ -#define PCI1754_IDI2 4 /* R: Digital input 32-64 */ -#define PCI1756_IDI 0 /* R: Digital input 0-31 */ -#define PCI1756_IDO 4 /* R/W: Digital output 0-31 */ -#define PCI1754_6_ICR0 0x08 /* R/W: Interrupt control register group 0 */ -#define PCI1754_6_ICR1 0x0a /* R/W: Interrupt control register group 1 */ -#define PCI1754_ICR2 0x0c /* R/W: Interrupt control register group 2 */ -#define PCI1754_ICR3 0x0e /* R/W: Interrupt control register group 3 */ -#define PCI1752_6_CFC 0x12 /* R/W: set/read channel freeze function */ -#define PCI175x_BOARDID 0x10 /* R: Board I/D switch for 1752/4/6 */ +/* PCI-1754, PCI-1756 interrupt control registers */ +#define PCI1754_INT_REG(x) (0x08 + (x) * 2) /* R/W: control group 0 to 3 */ -/* Advantech PCI-1762 registers */ -#define PCI1762_RO 0 /* R/W: Relays status/output */ -#define PCI1762_IDI 2 /* R: Isolated input status */ -#define PCI1762_BOARDID 4 /* R: Board I/D switch */ -#define PCI1762_ICR 6 /* W: Interrupt control register */ -#define PCI1762_ISR 6 /* R: Interrupt status register */ +/* PCI-1752, PCI-1756 special registers */ +#define PCI1752_CFC_REG 0x12 /* R/W: channel freeze function */ -/* Advantech PCI-1760 registers */ -#define OMB0 0x0c /* W: Mailbox outgoing registers */ -#define OMB1 0x0d -#define OMB2 0x0e -#define OMB3 0x0f -#define IMB0 0x1c /* R: Mailbox incoming registers */ -#define IMB1 0x1d -#define IMB2 0x1e -#define IMB3 0x1f -#define INTCSR0 0x38 /* R/W: Interrupt control registers */ -#define INTCSR1 0x39 -#define INTCSR2 0x3a -#define INTCSR3 0x3b +/* PCI-1762 interrupt control registers */ +#define PCI1762_INT_REG 0x06 /* R/W: status/control */ -/* PCI-1760 mailbox commands */ -#define CMD_ClearIMB2 0x00 /* Clear IMB2 status and return actual - * DI status in IMB3 */ -#define CMD_SetRelaysOutput 0x01 /* Set relay output from OMB0 */ -#define CMD_GetRelaysStatus 0x02 /* Get relay status to IMB0 */ -#define CMD_ReadCurrentStatus 0x07 /* Read the current status of the - * register in OMB0, result in IMB0 */ -#define CMD_ReadFirmwareVersion 0x0e /* Read the firmware ver., result in - * IMB1.IMB0 */ -#define CMD_ReadHardwareVersion 0x0f /* Read the hardware ver., result in - * IMB1.IMB0 */ -#define CMD_EnableIDIFilters 0x20 /* Enable IDI filters based on bits in - * OMB0 */ -#define CMD_EnableIDIPatternMatch 0x21 /* Enable IDI pattern match based on - * bits in OMB0 */ -#define CMD_SetIDIPatternMatch 0x22 /* Enable IDI pattern match based on - * bits in OMB0 */ -#define CMD_EnableIDICounters 0x28 /* Enable IDI counters based on bits in - * OMB0 */ -#define CMD_ResetIDICounters 0x29 /* Reset IDI counters based on bits in - * OMB0 to its reset values */ -#define CMD_OverflowIDICounters 0x2a /* Enable IDI counters overflow - * interrupts based on bits in OMB0 */ -#define CMD_MatchIntIDICounters 0x2b /* Enable IDI counters match value - * interrupts based on bits in OMB0 */ -#define CMD_EdgeIDICounters 0x2c /* Set IDI up counters count edge (bit=0 - * - rising, =1 - falling) */ -#define CMD_GetIDICntCurValue 0x2f /* Read IDI{OMB0} up counter current - * value */ -#define CMD_SetIDI0CntResetValue 0x40 /* Set IDI0 Counter Reset Value - * 256*OMB1+OMB0 */ -#define CMD_SetIDI1CntResetValue 0x41 /* Set IDI1 Counter Reset Value - * 256*OMB1+OMB0 */ -#define CMD_SetIDI2CntResetValue 0x42 /* Set IDI2 Counter Reset Value - * 256*OMB1+OMB0 */ -#define CMD_SetIDI3CntResetValue 0x43 /* Set IDI3 Counter Reset Value - * 256*OMB1+OMB0 */ -#define CMD_SetIDI4CntResetValue 0x44 /* Set IDI4 Counter Reset Value - * 256*OMB1+OMB0 */ -#define CMD_SetIDI5CntResetValue 0x45 /* Set IDI5 Counter Reset Value - * 256*OMB1+OMB0 */ -#define CMD_SetIDI6CntResetValue 0x46 /* Set IDI6 Counter Reset Value - * 256*OMB1+OMB0 */ -#define CMD_SetIDI7CntResetValue 0x47 /* Set IDI7 Counter Reset Value - * 256*OMB1+OMB0 */ -#define CMD_SetIDI0CntMatchValue 0x48 /* Set IDI0 Counter Match Value - * 256*OMB1+OMB0 */ -#define CMD_SetIDI1CntMatchValue 0x49 /* Set IDI1 Counter Match Value - * 256*OMB1+OMB0 */ -#define CMD_SetIDI2CntMatchValue 0x4a /* Set IDI2 Counter Match Value - * 256*OMB1+OMB0 */ -#define CMD_SetIDI3CntMatchValue 0x4b /* Set IDI3 Counter Match Value - * 256*OMB1+OMB0 */ -#define CMD_SetIDI4CntMatchValue 0x4c /* Set IDI4 Counter Match Value - * 256*OMB1+OMB0 */ -#define CMD_SetIDI5CntMatchValue 0x4d /* Set IDI5 Counter Match Value - * 256*OMB1+OMB0 */ -#define CMD_SetIDI6CntMatchValue 0x4e /* Set IDI6 Counter Match Value - * 256*OMB1+OMB0 */ -#define CMD_SetIDI7CntMatchValue 0x4f /* Set IDI7 Counter Match Value - * 256*OMB1+OMB0 */ +/* maximum number of subdevice descriptions in the boardinfo */ +#define PCI_DIO_MAX_DI_SUBDEVS 2 /* 2 x 8/16/32 input channels max */ +#define PCI_DIO_MAX_DO_SUBDEVS 2 /* 2 x 8/16/32 output channels max */ +#define PCI_DIO_MAX_DIO_SUBDEVG 2 /* 2 x any number of 8255 devices max */ -#define OMBCMD_RETRY 0x03 /* 3 times try request before error */ +enum pci_dio_boardid { + TYPE_PCI1730, + TYPE_PCI1733, + TYPE_PCI1734, + TYPE_PCI1735, + TYPE_PCI1736, + TYPE_PCI1739, + TYPE_PCI1750, + TYPE_PCI1751, + TYPE_PCI1752, + TYPE_PCI1753, + TYPE_PCI1753E, + TYPE_PCI1754, + TYPE_PCI1756, + TYPE_PCI1762 +}; struct diosubd_data { - int chans; /* num of chans */ - int addr; /* PCI address ofset */ - int regs; /* number of registers to read or 8255 - subdevices */ - unsigned int specflags; /* addon subdevice flags */ + int chans; /* num of chans or 8255 devices */ + unsigned long addr; /* PCI address ofset */ }; struct dio_boardtype { const char *name; /* board name */ - int main_pci_region; /* main I/O PCI region */ - enum hw_cards_id cardtype; int nsubdevs; - struct diosubd_data sdi[MAX_DI_SUBDEVS]; /* DI chans */ - struct diosubd_data sdo[MAX_DO_SUBDEVS]; /* DO chans */ - struct diosubd_data sdio[MAX_DIO_SUBDEVG]; /* DIO 8255 chans */ - struct diosubd_data boardid; /* card supports board ID switch */ + struct diosubd_data sdi[PCI_DIO_MAX_DI_SUBDEVS]; + struct diosubd_data sdo[PCI_DIO_MAX_DO_SUBDEVS]; + struct diosubd_data sdio[PCI_DIO_MAX_DIO_SUBDEVG]; + unsigned long id_reg; unsigned long timer_regbase; - enum hw_io_access io_access; + unsigned int is_16bit:1; }; static const struct dio_boardtype boardtypes[] = { [TYPE_PCI1730] = { .name = "pci1730", - .main_pci_region = PCIDIO_MAINREG, - .cardtype = TYPE_PCI1730, .nsubdevs = 5, - .sdi[0] = { 16, PCI1730_DI, 2, 0, }, - .sdi[1] = { 16, PCI1730_IDI, 2, 0, }, - .sdo[0] = { 16, PCI1730_DO, 2, 0, }, - .sdo[1] = { 16, PCI1730_IDO, 2, 0, }, - .boardid = { 4, PCI173x_BOARDID, 1, SDF_INTERNAL, }, - .io_access = IO_8b, + .sdi[0] = { 16, 0x02, }, /* DI 0-15 */ + .sdi[1] = { 16, 0x00, }, /* ISO DI 0-15 */ + .sdo[0] = { 16, 0x02, }, /* DO 0-15 */ + .sdo[1] = { 16, 0x00, }, /* ISO DO 0-15 */ + .id_reg = 0x04, }, [TYPE_PCI1733] = { .name = "pci1733", - .main_pci_region = PCIDIO_MAINREG, - .cardtype = TYPE_PCI1733, .nsubdevs = 2, - .sdi[1] = { 32, PCI1733_IDI, 4, 0, }, - .boardid = { 4, PCI173x_BOARDID, 1, SDF_INTERNAL, }, - .io_access = IO_8b, + .sdi[1] = { 32, 0x00, }, /* ISO DI 0-31 */ + .id_reg = 0x04, }, [TYPE_PCI1734] = { .name = "pci1734", - .main_pci_region = PCIDIO_MAINREG, - .cardtype = TYPE_PCI1734, .nsubdevs = 2, - .sdo[1] = { 32, PCI1734_IDO, 4, 0, }, - .boardid = { 4, PCI173x_BOARDID, 1, SDF_INTERNAL, }, - .io_access = IO_8b, + .sdo[1] = { 32, 0x00, }, /* ISO DO 0-31 */ + .id_reg = 0x04, }, [TYPE_PCI1735] = { .name = "pci1735", - .main_pci_region = PCIDIO_MAINREG, - .cardtype = TYPE_PCI1735, .nsubdevs = 4, - .sdi[0] = { 32, PCI1735_DI, 4, 0, }, - .sdo[0] = { 32, PCI1735_DO, 4, 0, }, - .boardid = { 4, PCI1735_BOARDID, 1, SDF_INTERNAL, }, - .timer_regbase = PCI1735_C8254, - .io_access = IO_8b, + .sdi[0] = { 32, 0x00, }, /* DI 0-31 */ + .sdo[0] = { 32, 0x00, }, /* DO 0-31 */ + .id_reg = 0x08, + .timer_regbase = 0x04, }, [TYPE_PCI1736] = { .name = "pci1736", - .main_pci_region = PCI1736_MAINREG, - .cardtype = TYPE_PCI1736, .nsubdevs = 3, - .sdi[1] = { 16, PCI1736_IDI, 2, 0, }, - .sdo[1] = { 16, PCI1736_IDO, 2, 0, }, - .boardid = { 4, PCI1736_BOARDID, 1, SDF_INTERNAL, }, - .io_access = IO_8b, + .sdi[1] = { 16, 0x00, }, /* ISO DI 0-15 */ + .sdo[1] = { 16, 0x00, }, /* ISO DO 0-15 */ + .id_reg = 0x04, }, [TYPE_PCI1739] = { .name = "pci1739", - .main_pci_region = PCIDIO_MAINREG, - .cardtype = TYPE_PCI1739, - .nsubdevs = 2, - .sdio[0] = { 48, PCI1739_DIO, 2, 0, }, - .io_access = IO_8b, + .nsubdevs = 3, + .sdio[0] = { 2, 0x00, }, /* 8255 DIO */ + .id_reg = 0x08, }, [TYPE_PCI1750] = { .name = "pci1750", - .main_pci_region = PCIDIO_MAINREG, - .cardtype = TYPE_PCI1750, .nsubdevs = 2, - .sdi[1] = { 16, PCI1750_IDI, 2, 0, }, - .sdo[1] = { 16, PCI1750_IDO, 2, 0, }, - .io_access = IO_8b, + .sdi[1] = { 16, 0x00, }, /* ISO DI 0-15 */ + .sdo[1] = { 16, 0x00, }, /* ISO DO 0-15 */ }, [TYPE_PCI1751] = { .name = "pci1751", - .main_pci_region = PCIDIO_MAINREG, - .cardtype = TYPE_PCI1751, .nsubdevs = 3, - .sdio[0] = { 48, PCI1751_DIO, 2, 0, }, - .timer_regbase = PCI1751_CNT, - .io_access = IO_8b, + .sdio[0] = { 2, 0x00, }, /* 8255 DIO */ + .timer_regbase = 0x18, }, [TYPE_PCI1752] = { .name = "pci1752", - .main_pci_region = PCIDIO_MAINREG, - .cardtype = TYPE_PCI1752, .nsubdevs = 3, - .sdo[0] = { 32, PCI1752_IDO, 2, 0, }, - .sdo[1] = { 32, PCI1752_IDO2, 2, 0, }, - .boardid = { 4, PCI175x_BOARDID, 1, SDF_INTERNAL, }, - .io_access = IO_16b, + .sdo[0] = { 32, 0x00, }, /* DO 0-31 */ + .sdo[1] = { 32, 0x04, }, /* DO 32-63 */ + .id_reg = 0x10, + .is_16bit = 1, }, [TYPE_PCI1753] = { .name = "pci1753", - .main_pci_region = PCIDIO_MAINREG, - .cardtype = TYPE_PCI1753, .nsubdevs = 4, - .sdio[0] = { 96, PCI1753_DIO, 4, 0, }, - .io_access = IO_8b, + .sdio[0] = { 4, 0x00, }, /* 8255 DIO */ }, [TYPE_PCI1753E] = { .name = "pci1753e", - .main_pci_region = PCIDIO_MAINREG, - .cardtype = TYPE_PCI1753E, .nsubdevs = 8, - .sdio[0] = { 96, PCI1753_DIO, 4, 0, }, - .sdio[1] = { 96, PCI1753E_DIO, 4, 0, }, - .io_access = IO_8b, + .sdio[0] = { 4, 0x00, }, /* 8255 DIO */ + .sdio[1] = { 4, 0x20, }, /* 8255 DIO */ }, [TYPE_PCI1754] = { .name = "pci1754", - .main_pci_region = PCIDIO_MAINREG, - .cardtype = TYPE_PCI1754, .nsubdevs = 3, - .sdi[0] = { 32, PCI1754_IDI, 2, 0, }, - .sdi[1] = { 32, PCI1754_IDI2, 2, 0, }, - .boardid = { 4, PCI175x_BOARDID, 1, SDF_INTERNAL, }, - .io_access = IO_16b, + .sdi[0] = { 32, 0x00, }, /* DI 0-31 */ + .sdi[1] = { 32, 0x04, }, /* DI 32-63 */ + .id_reg = 0x10, + .is_16bit = 1, }, [TYPE_PCI1756] = { .name = "pci1756", - .main_pci_region = PCIDIO_MAINREG, - .cardtype = TYPE_PCI1756, .nsubdevs = 3, - .sdi[1] = { 32, PCI1756_IDI, 2, 0, }, - .sdo[1] = { 32, PCI1756_IDO, 2, 0, }, - .boardid = { 4, PCI175x_BOARDID, 1, SDF_INTERNAL, }, - .io_access = IO_16b, - }, - [TYPE_PCI1760] = { - /* This card has its own 'attach' */ - .name = "pci1760", - .main_pci_region = 0, - .cardtype = TYPE_PCI1760, - .nsubdevs = 4, - .io_access = IO_8b, + .sdi[1] = { 32, 0x00, }, /* DI 0-31 */ + .sdo[1] = { 32, 0x04, }, /* DO 0-31 */ + .id_reg = 0x10, + .is_16bit = 1, }, [TYPE_PCI1762] = { .name = "pci1762", - .main_pci_region = PCIDIO_MAINREG, - .cardtype = TYPE_PCI1762, .nsubdevs = 3, - .sdi[1] = { 16, PCI1762_IDI, 1, 0, }, - .sdo[1] = { 16, PCI1762_RO, 1, 0, }, - .boardid = { 4, PCI1762_BOARDID, 1, SDF_INTERNAL, }, - .io_access = IO_16b, + .sdi[1] = { 16, 0x02, }, /* ISO DI 0-15 */ + .sdo[1] = { 16, 0x00, }, /* ISO DO 0-15 */ + .id_reg = 0x04, + .is_16bit = 1, }, }; -struct pci_dio_private { - char GlobalIrqEnabled; /* 1= any IRQ source is enabled */ - /* PCI-1760 specific data */ - unsigned char IDICntEnable; /* counter's counting enable status */ - unsigned char IDICntOverEnable; /* counter's overflow interrupts enable - * status */ - unsigned char IDICntMatchEnable; /* counter's match interrupts - * enable status */ - unsigned char IDICntEdge; /* counter's count edge value - * (bit=0 - rising, =1 - falling) */ - unsigned short CntResValue[8]; /* counters' reset value */ - unsigned short CntMatchValue[8]; /* counters' match interrupt value */ - unsigned char IDIFiltersEn; /* IDI's digital filters enable status */ - unsigned char IDIPatMatchEn; /* IDI's pattern match enable status */ - unsigned char IDIPatMatchValue; /* IDI's pattern match value */ - unsigned short IDIFiltrLow[8]; /* IDI's filter value low signal */ - unsigned short IDIFiltrHigh[8]; /* IDI's filter value high signal */ -}; - -/* -============================================================================== -*/ static int pci_dio_insn_bits_di_b(struct comedi_device *dev, struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) + struct comedi_insn *insn, + unsigned int *data) { - const struct diosubd_data *d = (const struct diosubd_data *)s->private; - int i; + unsigned long reg = (unsigned long)s->private; + unsigned long iobase = dev->iobase + reg; - data[1] = 0; - for (i = 0; i < d->regs; i++) - data[1] |= inb(dev->iobase + d->addr + i) << (8 * i); + data[1] = inb(iobase); + if (s->n_chan > 8) + data[1] |= (inb(iobase + 1) << 8); + if (s->n_chan > 16) + data[1] |= (inb(iobase + 2) << 16); + if (s->n_chan > 24) + data[1] |= (inb(iobase + 3) << 24); return insn->n; } -/* -============================================================================== -*/ static int pci_dio_insn_bits_di_w(struct comedi_device *dev, struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) + struct comedi_insn *insn, + unsigned int *data) { - const struct diosubd_data *d = (const struct diosubd_data *)s->private; - int i; + unsigned long reg = (unsigned long)s->private; + unsigned long iobase = dev->iobase + reg; - data[1] = 0; - for (i = 0; i < d->regs; i++) - data[1] |= inw(dev->iobase + d->addr + 2 * i) << (16 * i); + data[1] = inw(iobase); + if (s->n_chan > 16) + data[1] |= (inw(iobase + 2) << 16); return insn->n; } @@ -443,13 +230,17 @@ static int pci_dio_insn_bits_do_b(struct comedi_device *dev, struct comedi_insn *insn, unsigned int *data) { - const struct diosubd_data *d = (const struct diosubd_data *)s->private; - int i; + unsigned long reg = (unsigned long)s->private; + unsigned long iobase = dev->iobase + reg; if (comedi_dio_update_state(s, data)) { - for (i = 0; i < d->regs; i++) - outb((s->state >> (8 * i)) & 0xff, - dev->iobase + d->addr + i); + outb(s->state & 0xff, iobase); + if (s->n_chan > 8) + outb((s->state >> 8) & 0xff, iobase + 1); + if (s->n_chan > 16) + outb((s->state >> 16) & 0xff, iobase + 2); + if (s->n_chan > 24) + outb((s->state >> 24) & 0xff, iobase + 3); } data[1] = s->state; @@ -462,13 +253,13 @@ static int pci_dio_insn_bits_do_w(struct comedi_device *dev, struct comedi_insn *insn, unsigned int *data) { - const struct diosubd_data *d = (const struct diosubd_data *)s->private; - int i; + unsigned long reg = (unsigned long)s->private; + unsigned long iobase = dev->iobase + reg; if (comedi_dio_update_state(s, data)) { - for (i = 0; i < d->regs; i++) - outw((s->state >> (16 * i)) & 0xffff, - dev->iobase + d->addr + 2 * i); + outw(s->state & 0xffff, iobase); + if (s->n_chan > 16) + outw((s->state >> 16) & 0xffff, iobase + 2); } data[1] = s->state; @@ -476,510 +267,64 @@ static int pci_dio_insn_bits_do_w(struct comedi_device *dev, return insn->n; } -/* -============================================================================== -*/ -static int pci1760_unchecked_mbxrequest(struct comedi_device *dev, - unsigned char *omb, unsigned char *imb, - int repeats) -{ - int cnt, tout, ok = 0; - - for (cnt = 0; cnt < repeats; cnt++) { - outb(omb[0], dev->iobase + OMB0); - outb(omb[1], dev->iobase + OMB1); - outb(omb[2], dev->iobase + OMB2); - outb(omb[3], dev->iobase + OMB3); - for (tout = 0; tout < 251; tout++) { - imb[2] = inb(dev->iobase + IMB2); - if (imb[2] == omb[2]) { - imb[0] = inb(dev->iobase + IMB0); - imb[1] = inb(dev->iobase + IMB1); - imb[3] = inb(dev->iobase + IMB3); - ok = 1; - break; - } - udelay(1); - } - if (ok) - return 0; - } - - dev_err(dev->class_dev, "PCI-1760 mailbox request timeout!\n"); - return -ETIME; -} - -static int pci1760_clear_imb2(struct comedi_device *dev) -{ - unsigned char omb[4] = { 0x0, 0x0, CMD_ClearIMB2, 0x0 }; - unsigned char imb[4]; - /* check if imb2 is already clear */ - if (inb(dev->iobase + IMB2) == CMD_ClearIMB2) - return 0; - return pci1760_unchecked_mbxrequest(dev, omb, imb, OMBCMD_RETRY); -} - -static int pci1760_mbxrequest(struct comedi_device *dev, - unsigned char *omb, unsigned char *imb) -{ - if (omb[2] == CMD_ClearIMB2) { - dev_err(dev->class_dev, - "bug! this function should not be used for CMD_ClearIMB2 command\n"); - return -EINVAL; - } - if (inb(dev->iobase + IMB2) == omb[2]) { - int retval; - - retval = pci1760_clear_imb2(dev); - if (retval < 0) - return retval; - } - return pci1760_unchecked_mbxrequest(dev, omb, imb, OMBCMD_RETRY); -} - -/* -============================================================================== -*/ -static int pci1760_insn_bits_di(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) +static int pci_dio_reset(struct comedi_device *dev, unsigned long cardtype) { - data[1] = inb(dev->iobase + IMB3); + /* disable channel freeze function on the PCI-1752/1756 boards */ + if (cardtype == TYPE_PCI1752 || cardtype == TYPE_PCI1756) + outw(0, dev->iobase + PCI1752_CFC_REG); - return insn->n; -} - -static int pci1760_insn_bits_do(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, - unsigned int *data) -{ - int ret; - unsigned char omb[4] = { - 0x00, - 0x00, - CMD_SetRelaysOutput, - 0x00 - }; - unsigned char imb[4]; - - if (comedi_dio_update_state(s, data)) { - omb[0] = s->state; - ret = pci1760_mbxrequest(dev, omb, imb); - if (!ret) - return ret; - } - - data[1] = s->state; - - return insn->n; -} - -/* -============================================================================== -*/ -static int pci1760_insn_cnt_read(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) -{ - int ret, n; - unsigned char omb[4] = { - CR_CHAN(insn->chanspec) & 0x07, - 0x00, - CMD_GetIDICntCurValue, - 0x00 - }; - unsigned char imb[4]; - - for (n = 0; n < insn->n; n++) { - ret = pci1760_mbxrequest(dev, omb, imb); - if (!ret) - return ret; - data[n] = (imb[1] << 8) + imb[0]; - } - - return n; -} - -/* -============================================================================== -*/ -static int pci1760_insn_cnt_write(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) -{ - struct pci_dio_private *devpriv = dev->private; - int ret; - unsigned char chan = CR_CHAN(insn->chanspec) & 0x07; - unsigned char bitmask = 1 << chan; - unsigned char omb[4] = { - data[0] & 0xff, - (data[0] >> 8) & 0xff, - CMD_SetIDI0CntResetValue + chan, - 0x00 - }; - unsigned char imb[4]; - - /* Set reset value if different */ - if (devpriv->CntResValue[chan] != (data[0] & 0xffff)) { - ret = pci1760_mbxrequest(dev, omb, imb); - if (!ret) - return ret; - devpriv->CntResValue[chan] = data[0] & 0xffff; - } - - omb[0] = bitmask; /* reset counter to it reset value */ - omb[2] = CMD_ResetIDICounters; - ret = pci1760_mbxrequest(dev, omb, imb); - if (!ret) - return ret; - - /* start counter if it don't run */ - if (!(bitmask & devpriv->IDICntEnable)) { - omb[0] = bitmask; - omb[2] = CMD_EnableIDICounters; - ret = pci1760_mbxrequest(dev, omb, imb); - if (!ret) - return ret; - devpriv->IDICntEnable |= bitmask; - } - return 1; -} - -/* -============================================================================== -*/ -static int pci1760_reset(struct comedi_device *dev) -{ - struct pci_dio_private *devpriv = dev->private; - int i; - unsigned char omb[4] = { 0x00, 0x00, 0x00, 0x00 }; - unsigned char imb[4]; - - outb(0, dev->iobase + INTCSR0); /* disable IRQ */ - outb(0, dev->iobase + INTCSR1); - outb(0, dev->iobase + INTCSR2); - outb(0, dev->iobase + INTCSR3); - devpriv->GlobalIrqEnabled = 0; - - omb[0] = 0x00; - omb[2] = CMD_SetRelaysOutput; /* reset relay outputs */ - pci1760_mbxrequest(dev, omb, imb); - - omb[0] = 0x00; - omb[2] = CMD_EnableIDICounters; /* disable IDI up counters */ - pci1760_mbxrequest(dev, omb, imb); - devpriv->IDICntEnable = 0; - - omb[0] = 0x00; - omb[2] = CMD_OverflowIDICounters; /* disable counters overflow - * interrupts */ - pci1760_mbxrequest(dev, omb, imb); - devpriv->IDICntOverEnable = 0; - - omb[0] = 0x00; - omb[2] = CMD_MatchIntIDICounters; /* disable counters match value - * interrupts */ - pci1760_mbxrequest(dev, omb, imb); - devpriv->IDICntMatchEnable = 0; - - omb[0] = 0x00; - omb[1] = 0x80; - for (i = 0; i < 8; i++) { /* set IDI up counters match value */ - omb[2] = CMD_SetIDI0CntMatchValue + i; - pci1760_mbxrequest(dev, omb, imb); - devpriv->CntMatchValue[i] = 0x8000; - } - - omb[0] = 0x00; - omb[1] = 0x00; - for (i = 0; i < 8; i++) { /* set IDI up counters reset value */ - omb[2] = CMD_SetIDI0CntResetValue + i; - pci1760_mbxrequest(dev, omb, imb); - devpriv->CntResValue[i] = 0x0000; - } - - omb[0] = 0xff; - omb[2] = CMD_ResetIDICounters; /* reset IDI up counters to reset - * values */ - pci1760_mbxrequest(dev, omb, imb); - - omb[0] = 0x00; - omb[2] = CMD_EdgeIDICounters; /* set IDI up counters count edge */ - pci1760_mbxrequest(dev, omb, imb); - devpriv->IDICntEdge = 0x00; - - omb[0] = 0x00; - omb[2] = CMD_EnableIDIFilters; /* disable all digital in filters */ - pci1760_mbxrequest(dev, omb, imb); - devpriv->IDIFiltersEn = 0x00; - - omb[0] = 0x00; - omb[2] = CMD_EnableIDIPatternMatch; /* disable pattern matching */ - pci1760_mbxrequest(dev, omb, imb); - devpriv->IDIPatMatchEn = 0x00; - - omb[0] = 0x00; - omb[2] = CMD_SetIDIPatternMatch; /* set pattern match value */ - pci1760_mbxrequest(dev, omb, imb); - devpriv->IDIPatMatchValue = 0x00; - - return 0; -} - -/* -============================================================================== -*/ -static int pci_dio_reset(struct comedi_device *dev) -{ - const struct dio_boardtype *board = dev->board_ptr; - - switch (board->cardtype) { + /* disable and clear interrupts */ + switch (cardtype) { case TYPE_PCI1730: - outb(0, dev->iobase + PCI1730_DO); /* clear outputs */ - outb(0, dev->iobase + PCI1730_DO + 1); - outb(0, dev->iobase + PCI1730_IDO); - outb(0, dev->iobase + PCI1730_IDO + 1); - /* fallthrough */ case TYPE_PCI1733: - /* disable interrupts */ - outb(0, dev->iobase + PCI1730_3_INT_EN); - /* clear interrupts */ - outb(0x0f, dev->iobase + PCI1730_3_INT_CLR); - /* set rising edge trigger */ - outb(0, dev->iobase + PCI1730_3_INT_RF); - break; - case TYPE_PCI1734: - outb(0, dev->iobase + PCI1734_IDO); /* clear outputs */ - outb(0, dev->iobase + PCI1734_IDO + 1); - outb(0, dev->iobase + PCI1734_IDO + 2); - outb(0, dev->iobase + PCI1734_IDO + 3); - break; - case TYPE_PCI1735: - outb(0, dev->iobase + PCI1735_DO); /* clear outputs */ - outb(0, dev->iobase + PCI1735_DO + 1); - outb(0, dev->iobase + PCI1735_DO + 2); - outb(0, dev->iobase + PCI1735_DO + 3); - break; - case TYPE_PCI1736: - outb(0, dev->iobase + PCI1736_IDO); - outb(0, dev->iobase + PCI1736_IDO + 1); - /* disable interrupts */ - outb(0, dev->iobase + PCI1736_3_INT_EN); - /* clear interrupts */ - outb(0x0f, dev->iobase + PCI1736_3_INT_CLR); - /* set rising edge trigger */ - outb(0, dev->iobase + PCI1736_3_INT_RF); + outb(0, dev->iobase + PCI173X_INT_EN_REG); + outb(0x0f, dev->iobase + PCI173X_INT_CLR_REG); + outb(0, dev->iobase + PCI173X_INT_RF_REG); break; - case TYPE_PCI1739: - /* disable & clear interrupts */ - outb(0x88, dev->iobase + PCI1739_ICR); - break; - case TYPE_PCI1750: case TYPE_PCI1751: - /* disable & clear interrupts */ - outb(0x88, dev->iobase + PCI1750_ICR); - break; - case TYPE_PCI1752: - outw(0, dev->iobase + PCI1752_6_CFC); /* disable channel freeze - * function */ - outw(0, dev->iobase + PCI1752_IDO); /* clear outputs */ - outw(0, dev->iobase + PCI1752_IDO + 2); - outw(0, dev->iobase + PCI1752_IDO2); - outw(0, dev->iobase + PCI1752_IDO2 + 2); + outb(0x88, dev->iobase + PCI1750_INT_REG); break; - case TYPE_PCI1753E: - outb(0x88, dev->iobase + PCI1753E_ICR0); /* disable & clear - * interrupts */ - outb(0x80, dev->iobase + PCI1753E_ICR1); - outb(0x80, dev->iobase + PCI1753E_ICR2); - outb(0x80, dev->iobase + PCI1753E_ICR3); - /* fallthrough */ case TYPE_PCI1753: - outb(0x88, dev->iobase + PCI1753_ICR0); /* disable & clear - * interrupts */ - outb(0x80, dev->iobase + PCI1753_ICR1); - outb(0x80, dev->iobase + PCI1753_ICR2); - outb(0x80, dev->iobase + PCI1753_ICR3); + case TYPE_PCI1753E: + outb(0x88, dev->iobase + PCI1753_INT_REG(0)); + outb(0x80, dev->iobase + PCI1753_INT_REG(1)); + outb(0x80, dev->iobase + PCI1753_INT_REG(2)); + outb(0x80, dev->iobase + PCI1753_INT_REG(3)); + if (cardtype == TYPE_PCI1753E) { + outb(0x88, dev->iobase + PCI1753E_INT_REG(0)); + outb(0x80, dev->iobase + PCI1753E_INT_REG(1)); + outb(0x80, dev->iobase + PCI1753E_INT_REG(2)); + outb(0x80, dev->iobase + PCI1753E_INT_REG(3)); + } break; case TYPE_PCI1754: - outw(0x08, dev->iobase + PCI1754_6_ICR0); /* disable and clear - * interrupts */ - outw(0x08, dev->iobase + PCI1754_6_ICR1); - outw(0x08, dev->iobase + PCI1754_ICR2); - outw(0x08, dev->iobase + PCI1754_ICR3); - break; case TYPE_PCI1756: - outw(0, dev->iobase + PCI1752_6_CFC); /* disable channel freeze - * function */ - outw(0x08, dev->iobase + PCI1754_6_ICR0); /* disable and clear - * interrupts */ - outw(0x08, dev->iobase + PCI1754_6_ICR1); - outw(0, dev->iobase + PCI1756_IDO); /* clear outputs */ - outw(0, dev->iobase + PCI1756_IDO + 2); - break; - case TYPE_PCI1760: - pci1760_reset(dev); + outw(0x08, dev->iobase + PCI1754_INT_REG(0)); + outw(0x08, dev->iobase + PCI1754_INT_REG(1)); + if (cardtype == TYPE_PCI1754) { + outw(0x08, dev->iobase + PCI1754_INT_REG(2)); + outw(0x08, dev->iobase + PCI1754_INT_REG(3)); + } break; case TYPE_PCI1762: - outw(0x0101, dev->iobase + PCI1762_ICR); /* disable & clear - * interrupts */ - break; - } - - return 0; -} - -/* -============================================================================== -*/ -static int pci1760_attach(struct comedi_device *dev) -{ - struct comedi_subdevice *s; - - s = &dev->subdevices[0]; - s->type = COMEDI_SUBD_DI; - s->subdev_flags = SDF_READABLE; - s->n_chan = 8; - s->maxdata = 1; - s->len_chanlist = 8; - s->range_table = &range_digital; - s->insn_bits = pci1760_insn_bits_di; - - s = &dev->subdevices[1]; - s->type = COMEDI_SUBD_DO; - s->subdev_flags = SDF_WRITABLE; - s->n_chan = 8; - s->maxdata = 1; - s->len_chanlist = 8; - s->range_table = &range_digital; - s->state = 0; - s->insn_bits = pci1760_insn_bits_do; - - s = &dev->subdevices[2]; - s->type = COMEDI_SUBD_TIMER; - s->subdev_flags = SDF_WRITABLE | SDF_LSAMPL; - s->n_chan = 2; - s->maxdata = 0xffffffff; - s->len_chanlist = 2; -/* s->insn_config=pci1760_insn_pwm_cfg; */ - - s = &dev->subdevices[3]; - s->type = COMEDI_SUBD_COUNTER; - s->subdev_flags = SDF_READABLE | SDF_WRITABLE; - s->n_chan = 8; - s->maxdata = 0xffff; - s->len_chanlist = 8; - s->insn_read = pci1760_insn_cnt_read; - s->insn_write = pci1760_insn_cnt_write; -/* s->insn_config=pci1760_insn_cnt_cfg; */ - - return 0; -} - -/* -============================================================================== -*/ -static int pci_dio_add_di(struct comedi_device *dev, - struct comedi_subdevice *s, - const struct diosubd_data *d) -{ - const struct dio_boardtype *board = dev->board_ptr; - - s->type = COMEDI_SUBD_DI; - s->subdev_flags = SDF_READABLE | d->specflags; - if (d->chans > 16) - s->subdev_flags |= SDF_LSAMPL; - s->n_chan = d->chans; - s->maxdata = 1; - s->len_chanlist = d->chans; - s->range_table = &range_digital; - switch (board->io_access) { - case IO_8b: - s->insn_bits = pci_dio_insn_bits_di_b; - break; - case IO_16b: - s->insn_bits = pci_dio_insn_bits_di_w; - break; - } - s->private = (void *)d; - - return 0; -} - -/* -============================================================================== -*/ -static int pci_dio_add_do(struct comedi_device *dev, - struct comedi_subdevice *s, - const struct diosubd_data *d) -{ - const struct dio_boardtype *board = dev->board_ptr; - - s->type = COMEDI_SUBD_DO; - s->subdev_flags = SDF_WRITABLE; - if (d->chans > 16) - s->subdev_flags |= SDF_LSAMPL; - s->n_chan = d->chans; - s->maxdata = 1; - s->len_chanlist = d->chans; - s->range_table = &range_digital; - s->state = 0; - switch (board->io_access) { - case IO_8b: - s->insn_bits = pci_dio_insn_bits_do_b; + outw(0x0101, dev->iobase + PCI1762_INT_REG); break; - case IO_16b: - s->insn_bits = pci_dio_insn_bits_do_w; + default: break; } - s->private = (void *)d; return 0; } -static unsigned long pci_dio_override_cardtype(struct pci_dev *pcidev, - unsigned long cardtype) -{ - /* - * Change cardtype from TYPE_PCI1753 to TYPE_PCI1753E if expansion - * board available. Need to enable PCI device and request the main - * registers PCI BAR temporarily to perform the test. - */ - if (cardtype != TYPE_PCI1753) - return cardtype; - if (pci_enable_device(pcidev) < 0) - return cardtype; - if (pci_request_region(pcidev, PCIDIO_MAINREG, "adv_pci_dio") == 0) { - /* - * This test is based on Advantech's "advdaq" driver source - * (which declares its module licence as "GPL" although the - * driver source does not include a "COPYING" file). - */ - unsigned long reg = - pci_resource_start(pcidev, PCIDIO_MAINREG) + 53; - - outb(0x05, reg); - if ((inb(reg) & 0x07) == 0x02) { - outb(0x02, reg); - if ((inb(reg) & 0x07) == 0x05) - cardtype = TYPE_PCI1753E; - } - pci_release_region(pcidev, PCIDIO_MAINREG); - } - pci_disable_device(pcidev); - return cardtype; -} - static int pci_dio_auto_attach(struct comedi_device *dev, unsigned long context) { struct pci_dev *pcidev = comedi_to_pci_dev(dev); const struct dio_boardtype *board = NULL; - struct pci_dio_private *devpriv; + const struct diosubd_data *d; struct comedi_subdevice *s; int ret, subdev, i, j; @@ -990,54 +335,93 @@ static int pci_dio_auto_attach(struct comedi_device *dev, dev->board_ptr = board; dev->board_name = board->name; - devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); - if (!devpriv) - return -ENOMEM; - ret = comedi_pci_enable(dev); if (ret) return ret; - dev->iobase = pci_resource_start(pcidev, board->main_pci_region); + if (context == TYPE_PCI1736) + dev->iobase = pci_resource_start(pcidev, 0); + else + dev->iobase = pci_resource_start(pcidev, 2); + + pci_dio_reset(dev, context); ret = comedi_alloc_subdevices(dev, board->nsubdevs); if (ret) return ret; subdev = 0; - for (i = 0; i < MAX_DI_SUBDEVS; i++) - if (board->sdi[i].chans) { - s = &dev->subdevices[subdev]; - pci_dio_add_di(dev, s, &board->sdi[i]); - subdev++; + for (i = 0; i < PCI_DIO_MAX_DI_SUBDEVS; i++) { + d = &board->sdi[i]; + if (d->chans) { + s = &dev->subdevices[subdev++]; + s->type = COMEDI_SUBD_DI; + s->subdev_flags = SDF_READABLE; + s->n_chan = d->chans; + s->maxdata = 1; + s->range_table = &range_digital; + s->insn_bits = board->is_16bit + ? pci_dio_insn_bits_di_w + : pci_dio_insn_bits_di_b; + s->private = (void *)d->addr; } + } - for (i = 0; i < MAX_DO_SUBDEVS; i++) - if (board->sdo[i].chans) { - s = &dev->subdevices[subdev]; - pci_dio_add_do(dev, s, &board->sdo[i]); - subdev++; + for (i = 0; i < PCI_DIO_MAX_DO_SUBDEVS; i++) { + d = &board->sdo[i]; + if (d->chans) { + s = &dev->subdevices[subdev++]; + s->type = COMEDI_SUBD_DO; + s->subdev_flags = SDF_WRITABLE; + s->n_chan = d->chans; + s->maxdata = 1; + s->range_table = &range_digital; + s->insn_bits = board->is_16bit + ? pci_dio_insn_bits_do_w + : pci_dio_insn_bits_do_b; + s->private = (void *)d->addr; + + /* reset all outputs to 0 */ + if (board->is_16bit) { + outw(0, dev->iobase + d->addr); + if (s->n_chan > 16) + outw(0, dev->iobase + d->addr + 2); + } else { + outb(0, dev->iobase + d->addr); + if (s->n_chan > 8) + outb(0, dev->iobase + d->addr + 1); + if (s->n_chan > 16) + outb(0, dev->iobase + d->addr + 2); + if (s->n_chan > 24) + outb(0, dev->iobase + d->addr + 3); + } } + } - for (i = 0; i < MAX_DIO_SUBDEVG; i++) - for (j = 0; j < board->sdio[i].regs; j++) { - s = &dev->subdevices[subdev]; + for (i = 0; i < PCI_DIO_MAX_DIO_SUBDEVG; i++) { + d = &board->sdio[i]; + for (j = 0; j < d->chans; j++) { + s = &dev->subdevices[subdev++]; ret = subdev_8255_init(dev, s, NULL, - board->sdio[i].addr + - j * I8255_SIZE); + d->addr + j * I8255_SIZE); if (ret) return ret; - subdev++; } + } - if (board->boardid.chans) { - s = &dev->subdevices[subdev]; - s->type = COMEDI_SUBD_DI; - pci_dio_add_di(dev, s, &board->boardid); - subdev++; + if (board->id_reg) { + s = &dev->subdevices[subdev++]; + s->type = COMEDI_SUBD_DI; + s->subdev_flags = SDF_READABLE | SDF_INTERNAL; + s->n_chan = 4; + s->maxdata = 1; + s->range_table = &range_digital; + s->insn_bits = board->is_16bit ? pci_dio_insn_bits_di_w + : pci_dio_insn_bits_di_b; + s->private = (void *)board->id_reg; } if (board->timer_regbase) { - s = &dev->subdevices[subdev]; + s = &dev->subdevices[subdev++]; dev->pacer = comedi_8254_init(dev->iobase + board->timer_regbase, @@ -1046,32 +430,50 @@ static int pci_dio_auto_attach(struct comedi_device *dev, return -ENOMEM; comedi_8254_subdevice_init(s, dev->pacer); - - subdev++; } - if (board->cardtype == TYPE_PCI1760) - pci1760_attach(dev); - - pci_dio_reset(dev); - return 0; } -static void pci_dio_detach(struct comedi_device *dev) -{ - if (dev->iobase) - pci_dio_reset(dev); - comedi_pci_detach(dev); -} - static struct comedi_driver adv_pci_dio_driver = { .driver_name = "adv_pci_dio", .module = THIS_MODULE, .auto_attach = pci_dio_auto_attach, - .detach = pci_dio_detach, + .detach = comedi_pci_detach, }; +static unsigned long pci_dio_override_cardtype(struct pci_dev *pcidev, + unsigned long cardtype) +{ + /* + * Change cardtype from TYPE_PCI1753 to TYPE_PCI1753E if expansion + * board available. Need to enable PCI device and request the main + * registers PCI BAR temporarily to perform the test. + */ + if (cardtype != TYPE_PCI1753) + return cardtype; + if (pci_enable_device(pcidev) < 0) + return cardtype; + if (pci_request_region(pcidev, 2, "adv_pci_dio") == 0) { + /* + * This test is based on Advantech's "advdaq" driver source + * (which declares its module licence as "GPL" although the + * driver source does not include a "COPYING" file). + */ + unsigned long reg = pci_resource_start(pcidev, 2) + 53; + + outb(0x05, reg); + if ((inb(reg) & 0x07) == 0x02) { + outb(0x02, reg); + if ((inb(reg) & 0x07) == 0x05) + cardtype = TYPE_PCI1753E; + } + pci_release_region(pcidev, 2); + } + pci_disable_device(pcidev); + return cardtype; +} + static int adv_pci_dio_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) { @@ -1094,7 +496,6 @@ static const struct pci_device_id adv_pci_dio_pci_table[] = { { PCI_VDEVICE(ADVANTECH, 0x1753), TYPE_PCI1753 }, { PCI_VDEVICE(ADVANTECH, 0x1754), TYPE_PCI1754 }, { PCI_VDEVICE(ADVANTECH, 0x1756), TYPE_PCI1756 }, - { PCI_VDEVICE(ADVANTECH, 0x1760), TYPE_PCI1760 }, { PCI_VDEVICE(ADVANTECH, 0x1762), TYPE_PCI1762 }, { 0 } }; @@ -1109,5 +510,5 @@ static struct pci_driver adv_pci_dio_pci_driver = { module_comedi_pci_driver(adv_pci_dio_driver, adv_pci_dio_pci_driver); MODULE_AUTHOR("Comedi http://www.comedi.org"); -MODULE_DESCRIPTION("Comedi low-level driver"); +MODULE_DESCRIPTION("Comedi driver for Advantech Digital I/O Cards"); MODULE_LICENSE("GPL"); diff --git a/drivers/staging/comedi/drivers/amplc_pci224.c b/drivers/staging/comedi/drivers/amplc_pci224.c index b2f7679a0..cac011fdd 100644 --- a/drivers/staging/comedi/drivers/amplc_pci224.c +++ b/drivers/staging/comedi/drivers/amplc_pci224.c @@ -1022,14 +1022,17 @@ pci224_auto_attach(struct comedi_device *dev, unsigned long context_model) irq = pci_dev->irq; /* Allocate buffer to hold values for AO channel scan. */ - devpriv->ao_scan_vals = kmalloc(sizeof(devpriv->ao_scan_vals[0]) * - board->ao_chans, GFP_KERNEL); + devpriv->ao_scan_vals = kmalloc_array(board->ao_chans, + sizeof(devpriv->ao_scan_vals[0]), + GFP_KERNEL); if (!devpriv->ao_scan_vals) return -ENOMEM; /* Allocate buffer to hold AO channel scan order. */ - devpriv->ao_scan_order = kmalloc(sizeof(devpriv->ao_scan_order[0]) * - board->ao_chans, GFP_KERNEL); + devpriv->ao_scan_order = + kmalloc_array(board->ao_chans, + sizeof(devpriv->ao_scan_order[0]), + GFP_KERNEL); if (!devpriv->ao_scan_order) return -ENOMEM; diff --git a/drivers/staging/comedi/drivers/cb_pcidda.c b/drivers/staging/comedi/drivers/cb_pcidda.c index b00a36a5c..ccb37d1f0 100644 --- a/drivers/staging/comedi/drivers/cb_pcidda.c +++ b/drivers/staging/comedi/drivers/cb_pcidda.c @@ -51,13 +51,13 @@ /* DAC registers */ #define CB_DDA_DA_CTRL_REG 0x00 /* D/A Control Register */ -#define CB_DDA_DA_CTRL_SU (1 << 0) /* Simultaneous update */ -#define CB_DDA_DA_CTRL_EN (1 << 1) /* Enable specified DAC */ +#define CB_DDA_DA_CTRL_SU BIT(0) /* Simultaneous update */ +#define CB_DDA_DA_CTRL_EN BIT(1) /* Enable specified DAC */ #define CB_DDA_DA_CTRL_DAC(x) ((x) << 2) /* Specify DAC channel */ #define CB_DDA_DA_CTRL_RANGE2V5 (0 << 6) /* 2.5V range */ #define CB_DDA_DA_CTRL_RANGE5V (2 << 6) /* 5V range */ #define CB_DDA_DA_CTRL_RANGE10V (3 << 6) /* 10V range */ -#define CB_DDA_DA_CTRL_UNIP (1 << 8) /* Unipolar range */ +#define CB_DDA_DA_CTRL_UNIP BIT(8) /* Unipolar range */ #define DACALIBRATION1 4 /* D/A CALIBRATION REGISTER 1 */ /* write bits */ diff --git a/drivers/staging/comedi/drivers/comedi_parport.c b/drivers/staging/comedi/drivers/comedi_parport.c index 15a4093ef..1bf8ddc6f 100644 --- a/drivers/staging/comedi/drivers/comedi_parport.c +++ b/drivers/staging/comedi/drivers/comedi_parport.c @@ -75,8 +75,8 @@ #define PARPORT_DATA_REG 0x00 #define PARPORT_STATUS_REG 0x01 #define PARPORT_CTRL_REG 0x02 -#define PARPORT_CTRL_IRQ_ENA (1 << 4) -#define PARPORT_CTRL_BIDIR_ENA (1 << 5) +#define PARPORT_CTRL_IRQ_ENA BIT(4) +#define PARPORT_CTRL_BIDIR_ENA BIT(5) static int parport_data_reg_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s, diff --git a/drivers/staging/comedi/drivers/das16.c b/drivers/staging/comedi/drivers/das16.c index 056bca9c6..fd8e0b76f 100644 --- a/drivers/staging/comedi/drivers/das16.c +++ b/drivers/staging/comedi/drivers/das16.c @@ -801,9 +801,10 @@ static void das16_ai_munge(struct comedi_device *dev, unsigned short *data = array; unsigned int num_samples = comedi_bytes_to_samples(s, num_bytes); unsigned int i; + __le16 *buf = array; for (i = 0; i < num_samples; i++) { - data[i] = le16_to_cpu(data[i]); + data[i] = le16_to_cpu(buf[i]); if (s->maxdata == 0x0fff) data[i] >>= 4; data[i] &= s->maxdata; diff --git a/drivers/staging/comedi/drivers/ni_6527.c b/drivers/staging/comedi/drivers/ni_6527.c index 62a817e4c..84c62e256 100644 --- a/drivers/staging/comedi/drivers/ni_6527.c +++ b/drivers/staging/comedi/drivers/ni_6527.c @@ -42,24 +42,24 @@ #define NI6527_DO_REG(x) (0x03 + (x)) #define NI6527_ID_REG 0x06 #define NI6527_CLR_REG 0x07 -#define NI6527_CLR_EDGE (1 << 3) -#define NI6527_CLR_OVERFLOW (1 << 2) -#define NI6527_CLR_FILT (1 << 1) -#define NI6527_CLR_INTERVAL (1 << 0) +#define NI6527_CLR_EDGE BIT(3) +#define NI6527_CLR_OVERFLOW BIT(2) +#define NI6527_CLR_FILT BIT(1) +#define NI6527_CLR_INTERVAL BIT(0) #define NI6527_CLR_IRQS (NI6527_CLR_EDGE | NI6527_CLR_OVERFLOW) #define NI6527_CLR_RESET_FILT (NI6527_CLR_FILT | NI6527_CLR_INTERVAL) #define NI6527_FILT_INTERVAL_REG(x) (0x08 + (x)) #define NI6527_FILT_ENA_REG(x) (0x0c + (x)) #define NI6527_STATUS_REG 0x14 -#define NI6527_STATUS_IRQ (1 << 2) -#define NI6527_STATUS_OVERFLOW (1 << 1) -#define NI6527_STATUS_EDGE (1 << 0) +#define NI6527_STATUS_IRQ BIT(2) +#define NI6527_STATUS_OVERFLOW BIT(1) +#define NI6527_STATUS_EDGE BIT(0) #define NI6527_CTRL_REG 0x15 -#define NI6527_CTRL_FALLING (1 << 4) -#define NI6527_CTRL_RISING (1 << 3) -#define NI6527_CTRL_IRQ (1 << 2) -#define NI6527_CTRL_OVERFLOW (1 << 1) -#define NI6527_CTRL_EDGE (1 << 0) +#define NI6527_CTRL_FALLING BIT(4) +#define NI6527_CTRL_RISING BIT(3) +#define NI6527_CTRL_IRQ BIT(2) +#define NI6527_CTRL_OVERFLOW BIT(1) +#define NI6527_CTRL_EDGE BIT(0) #define NI6527_CTRL_DISABLE_IRQS 0 #define NI6527_CTRL_ENABLE_IRQS (NI6527_CTRL_FALLING | \ NI6527_CTRL_RISING | \ diff --git a/drivers/staging/comedi/drivers/ni_65xx.c b/drivers/staging/comedi/drivers/ni_65xx.c index 800d57426..251117be1 100644 --- a/drivers/staging/comedi/drivers/ni_65xx.c +++ b/drivers/staging/comedi/drivers/ni_65xx.c @@ -68,25 +68,25 @@ /* Non-recurring Registers (8-bit except where noted) */ #define NI_65XX_ID_REG 0x00 #define NI_65XX_CLR_REG 0x01 -#define NI_65XX_CLR_WDOG_INT (1 << 6) -#define NI_65XX_CLR_WDOG_PING (1 << 5) -#define NI_65XX_CLR_WDOG_EXP (1 << 4) -#define NI_65XX_CLR_EDGE_INT (1 << 3) -#define NI_65XX_CLR_OVERFLOW_INT (1 << 2) +#define NI_65XX_CLR_WDOG_INT BIT(6) +#define NI_65XX_CLR_WDOG_PING BIT(5) +#define NI_65XX_CLR_WDOG_EXP BIT(4) +#define NI_65XX_CLR_EDGE_INT BIT(3) +#define NI_65XX_CLR_OVERFLOW_INT BIT(2) #define NI_65XX_STATUS_REG 0x02 -#define NI_65XX_STATUS_WDOG_INT (1 << 5) -#define NI_65XX_STATUS_FALL_EDGE (1 << 4) -#define NI_65XX_STATUS_RISE_EDGE (1 << 3) -#define NI_65XX_STATUS_INT (1 << 2) -#define NI_65XX_STATUS_OVERFLOW_INT (1 << 1) -#define NI_65XX_STATUS_EDGE_INT (1 << 0) +#define NI_65XX_STATUS_WDOG_INT BIT(5) +#define NI_65XX_STATUS_FALL_EDGE BIT(4) +#define NI_65XX_STATUS_RISE_EDGE BIT(3) +#define NI_65XX_STATUS_INT BIT(2) +#define NI_65XX_STATUS_OVERFLOW_INT BIT(1) +#define NI_65XX_STATUS_EDGE_INT BIT(0) #define NI_65XX_CTRL_REG 0x03 -#define NI_65XX_CTRL_WDOG_ENA (1 << 5) -#define NI_65XX_CTRL_FALL_EDGE_ENA (1 << 4) -#define NI_65XX_CTRL_RISE_EDGE_ENA (1 << 3) -#define NI_65XX_CTRL_INT_ENA (1 << 2) -#define NI_65XX_CTRL_OVERFLOW_ENA (1 << 1) -#define NI_65XX_CTRL_EDGE_ENA (1 << 0) +#define NI_65XX_CTRL_WDOG_ENA BIT(5) +#define NI_65XX_CTRL_FALL_EDGE_ENA BIT(4) +#define NI_65XX_CTRL_RISE_EDGE_ENA BIT(3) +#define NI_65XX_CTRL_INT_ENA BIT(2) +#define NI_65XX_CTRL_OVERFLOW_ENA BIT(1) +#define NI_65XX_CTRL_EDGE_ENA BIT(0) #define NI_65XX_REV_REG 0x04 /* 32-bit */ #define NI_65XX_FILTER_REG 0x08 /* 32-bit */ #define NI_65XX_RTSI_ROUTE_REG 0x0c /* 16-bit */ @@ -94,24 +94,24 @@ #define NI_65XX_RTSI_WDOG_REG 0x10 /* 16-bit */ #define NI_65XX_RTSI_TRIG_REG 0x12 /* 16-bit */ #define NI_65XX_AUTO_CLK_SEL_REG 0x14 /* PXI-6528 only */ -#define NI_65XX_AUTO_CLK_SEL_STATUS (1 << 1) -#define NI_65XX_AUTO_CLK_SEL_DISABLE (1 << 0) +#define NI_65XX_AUTO_CLK_SEL_STATUS BIT(1) +#define NI_65XX_AUTO_CLK_SEL_DISABLE BIT(0) #define NI_65XX_WDOG_CTRL_REG 0x15 -#define NI_65XX_WDOG_CTRL_ENA (1 << 0) +#define NI_65XX_WDOG_CTRL_ENA BIT(0) #define NI_65XX_RTSI_CFG_REG 0x16 -#define NI_65XX_RTSI_CFG_RISE_SENSE (1 << 2) -#define NI_65XX_RTSI_CFG_FALL_SENSE (1 << 1) -#define NI_65XX_RTSI_CFG_SYNC_DETECT (1 << 0) +#define NI_65XX_RTSI_CFG_RISE_SENSE BIT(2) +#define NI_65XX_RTSI_CFG_FALL_SENSE BIT(1) +#define NI_65XX_RTSI_CFG_SYNC_DETECT BIT(0) #define NI_65XX_WDOG_STATUS_REG 0x17 -#define NI_65XX_WDOG_STATUS_EXP (1 << 0) +#define NI_65XX_WDOG_STATUS_EXP BIT(0) #define NI_65XX_WDOG_INTERVAL_REG 0x18 /* 32-bit */ /* Recurring port registers (8-bit) */ #define NI_65XX_PORT(x) ((x) * 0x10) #define NI_65XX_IO_DATA_REG(x) (0x40 + NI_65XX_PORT(x)) #define NI_65XX_IO_SEL_REG(x) (0x41 + NI_65XX_PORT(x)) -#define NI_65XX_IO_SEL_OUTPUT (0 << 0) -#define NI_65XX_IO_SEL_INPUT (1 << 0) +#define NI_65XX_IO_SEL_OUTPUT 0 +#define NI_65XX_IO_SEL_INPUT BIT(0) #define NI_65XX_RISE_EDGE_ENA_REG(x) (0x42 + NI_65XX_PORT(x)) #define NI_65XX_FALL_EDGE_ENA_REG(x) (0x43 + NI_65XX_PORT(x)) #define NI_65XX_FILTER_ENA(x) (0x44 + NI_65XX_PORT(x)) @@ -613,7 +613,7 @@ static int ni_65xx_intr_insn_config(struct comedi_device *dev, /* ripped from mite.h and mite_setup2() to avoid mite dependency */ #define MITE_IODWBSR 0xc0 /* IO Device Window Base Size Register */ -#define WENAB (1 << 7) /* window enable */ +#define WENAB BIT(7) /* window enable */ static int ni_65xx_mite_init(struct pci_dev *pcidev) { diff --git a/drivers/staging/comedi/drivers/ni_670x.c b/drivers/staging/comedi/drivers/ni_670x.c index f4c580f65..3e7271880 100644 --- a/drivers/staging/comedi/drivers/ni_670x.c +++ b/drivers/staging/comedi/drivers/ni_670x.c @@ -214,8 +214,9 @@ static int ni_670x_auto_attach(struct comedi_device *dev, if (s->n_chan == 32) { const struct comedi_lrange **range_table_list; - range_table_list = kmalloc(sizeof(struct comedi_lrange *) * 32, - GFP_KERNEL); + range_table_list = kmalloc_array(32, + sizeof(struct comedi_lrange *), + GFP_KERNEL); if (!range_table_list) return -ENOMEM; s->range_table_list = range_table_list; diff --git a/drivers/staging/comedi/drivers/ni_mio_common.c b/drivers/staging/comedi/drivers/ni_mio_common.c index 6cc304a4c..5e8130a7d 100644 --- a/drivers/staging/comedi/drivers/ni_mio_common.c +++ b/drivers/staging/comedi/drivers/ni_mio_common.c @@ -579,48 +579,54 @@ static inline unsigned ni_stc_dma_channel_select_bitfield(unsigned channel) return 0; } -/* negative channel means no channel */ -static inline void ni_set_ai_dma_channel(struct comedi_device *dev, int channel) +static inline void ni_set_ai_dma_channel(struct comedi_device *dev, + unsigned channel) { - unsigned bits = 0; - - if (channel >= 0) - bits = ni_stc_dma_channel_select_bitfield(channel); + unsigned bits = ni_stc_dma_channel_select_bitfield(channel); ni_set_bitfield(dev, NI_E_DMA_AI_AO_SEL_REG, NI_E_DMA_AI_SEL_MASK, NI_E_DMA_AI_SEL(bits)); } -/* negative channel means no channel */ -static inline void ni_set_ao_dma_channel(struct comedi_device *dev, int channel) +static inline void ni_set_ai_dma_no_channel(struct comedi_device *dev) { - unsigned bits = 0; + ni_set_bitfield(dev, NI_E_DMA_AI_AO_SEL_REG, NI_E_DMA_AI_SEL_MASK, 0); +} - if (channel >= 0) - bits = ni_stc_dma_channel_select_bitfield(channel); +static inline void ni_set_ao_dma_channel(struct comedi_device *dev, + unsigned channel) +{ + unsigned bits = ni_stc_dma_channel_select_bitfield(channel); ni_set_bitfield(dev, NI_E_DMA_AI_AO_SEL_REG, NI_E_DMA_AO_SEL_MASK, NI_E_DMA_AO_SEL(bits)); } -/* negative channel means no channel */ +static inline void ni_set_ao_dma_no_channel(struct comedi_device *dev) +{ + ni_set_bitfield(dev, NI_E_DMA_AI_AO_SEL_REG, NI_E_DMA_AO_SEL_MASK, 0); +} + static inline void ni_set_gpct_dma_channel(struct comedi_device *dev, unsigned gpct_index, - int channel) + unsigned channel) { - unsigned bits = 0; - - if (channel >= 0) - bits = ni_stc_dma_channel_select_bitfield(channel); + unsigned bits = ni_stc_dma_channel_select_bitfield(channel); ni_set_bitfield(dev, NI_E_DMA_G0_G1_SEL_REG, NI_E_DMA_G0_G1_SEL_MASK(gpct_index), NI_E_DMA_G0_G1_SEL(gpct_index, bits)); } -/* negative mite_channel means no channel */ +static inline void ni_set_gpct_dma_no_channel(struct comedi_device *dev, + unsigned gpct_index) +{ + ni_set_bitfield(dev, NI_E_DMA_G0_G1_SEL_REG, + NI_E_DMA_G0_G1_SEL_MASK(gpct_index), 0); +} + static inline void ni_set_cdo_dma_channel(struct comedi_device *dev, - int mite_channel) + unsigned mite_channel) { struct ni_private *devpriv = dev->private; unsigned long flags; @@ -628,16 +634,26 @@ static inline void ni_set_cdo_dma_channel(struct comedi_device *dev, spin_lock_irqsave(&devpriv->soft_reg_copy_lock, flags); devpriv->cdio_dma_select_reg &= ~NI_M_CDIO_DMA_SEL_CDO_MASK; - if (mite_channel >= 0) { - /* - * XXX just guessing ni_stc_dma_channel_select_bitfield() - * returns the right bits, under the assumption the cdio dma - * selection works just like ai/ao/gpct. - * Definitely works for dma channels 0 and 1. - */ - bits = ni_stc_dma_channel_select_bitfield(mite_channel); - devpriv->cdio_dma_select_reg |= NI_M_CDIO_DMA_SEL_CDO(bits); - } + /* + * XXX just guessing ni_stc_dma_channel_select_bitfield() + * returns the right bits, under the assumption the cdio dma + * selection works just like ai/ao/gpct. + * Definitely works for dma channels 0 and 1. + */ + bits = ni_stc_dma_channel_select_bitfield(mite_channel); + devpriv->cdio_dma_select_reg |= NI_M_CDIO_DMA_SEL_CDO(bits); + ni_writeb(dev, devpriv->cdio_dma_select_reg, NI_M_CDIO_DMA_SEL_REG); + mmiowb(); + spin_unlock_irqrestore(&devpriv->soft_reg_copy_lock, flags); +} + +static inline void ni_set_cdo_dma_no_channel(struct comedi_device *dev) +{ + struct ni_private *devpriv = dev->private; + unsigned long flags; + + spin_lock_irqsave(&devpriv->soft_reg_copy_lock, flags); + devpriv->cdio_dma_select_reg &= ~NI_M_CDIO_DMA_SEL_CDO_MASK; ni_writeb(dev, devpriv->cdio_dma_select_reg, NI_M_CDIO_DMA_SEL_REG); mmiowb(); spin_unlock_irqrestore(&devpriv->soft_reg_copy_lock, flags); @@ -745,7 +761,7 @@ static void ni_release_ai_mite_channel(struct comedi_device *dev) spin_lock_irqsave(&devpriv->mite_channel_lock, flags); if (devpriv->ai_mite_chan) { - ni_set_ai_dma_channel(dev, -1); + ni_set_ai_dma_no_channel(dev); mite_release_channel(devpriv->ai_mite_chan); devpriv->ai_mite_chan = NULL; } @@ -761,7 +777,7 @@ static void ni_release_ao_mite_channel(struct comedi_device *dev) spin_lock_irqsave(&devpriv->mite_channel_lock, flags); if (devpriv->ao_mite_chan) { - ni_set_ao_dma_channel(dev, -1); + ni_set_ao_dma_no_channel(dev); mite_release_channel(devpriv->ao_mite_chan); devpriv->ao_mite_chan = NULL; } @@ -781,7 +797,7 @@ static void ni_release_gpct_mite_channel(struct comedi_device *dev, struct mite_channel *mite_chan = devpriv->counter_dev->counters[gpct_index].mite_chan; - ni_set_gpct_dma_channel(dev, gpct_index, -1); + ni_set_gpct_dma_no_channel(dev, gpct_index); ni_tio_set_mite_channel(&devpriv-> counter_dev->counters[gpct_index], NULL); @@ -799,7 +815,7 @@ static void ni_release_cdo_mite_channel(struct comedi_device *dev) spin_lock_irqsave(&devpriv->mite_channel_lock, flags); if (devpriv->cdo_mite_chan) { - ni_set_cdo_dma_channel(dev, -1); + ni_set_cdo_dma_no_channel(dev); mite_release_channel(devpriv->cdo_mite_chan); devpriv->cdo_mite_chan = NULL; } @@ -1516,13 +1532,17 @@ static void ni_ai_munge(struct comedi_device *dev, struct comedi_subdevice *s, unsigned short *array = data; unsigned int *larray = data; unsigned int i; +#ifdef PCIDMA + __le16 *barray = data; + __le32 *blarray = data; +#endif for (i = 0; i < nsamples; i++) { #ifdef PCIDMA if (s->subdev_flags & SDF_LSAMPL) - larray[i] = le32_to_cpu(larray[i]); + larray[i] = le32_to_cpu(blarray[i]); else - array[i] = le16_to_cpu(array[i]); + array[i] = le16_to_cpu(barray[i]); #endif if (s->subdev_flags & SDF_LSAMPL) larray[i] += devpriv->ai_offset[chan_index]; @@ -2574,6 +2594,9 @@ static void ni_ao_munge(struct comedi_device *dev, struct comedi_subdevice *s, unsigned int nsamples = comedi_bytes_to_samples(s, num_bytes); unsigned short *array = data; unsigned int i; +#ifdef PCIDMA + __le16 buf, *barray = data; +#endif for (i = 0; i < nsamples; i++) { unsigned int range = CR_RANGE(cmd->chanlist[chan_index]); @@ -2586,10 +2609,11 @@ static void ni_ao_munge(struct comedi_device *dev, struct comedi_subdevice *s, if (comedi_range_is_bipolar(s, range)) val = comedi_offset_munge(s, val); #ifdef PCIDMA - val = cpu_to_le16(val); -#endif + buf = cpu_to_le16(val); + barray[i] = buf; +#else array[i] = val; - +#endif chan_index++; chan_index %= cmd->chanlist_len; } diff --git a/drivers/staging/comedi/drivers/plx9080.h b/drivers/staging/comedi/drivers/plx9080.h index 25706531b..f5cd6d500 100644 --- a/drivers/staging/comedi/drivers/plx9080.h +++ b/drivers/staging/comedi/drivers/plx9080.h @@ -1,4 +1,5 @@ -/* plx9080.h +/* + * plx9080.h * * Copyright (C) 2002,2003 Frank Mori Hess * @@ -33,8 +34,10 @@ struct plx_dma_desc { __le32 local_start_addr; /* transfer_size is in bytes, only first 23 bits of register are used */ __le32 transfer_size; - /* address of next descriptor (quad word aligned), plus some - * additional bits (see PLX_DMA0_DESCRIPTOR_REG) */ + /* + * address of next descriptor (quad word aligned), plus some + * additional bits (see PLX_DMA0_DESCRIPTOR_REG) + */ __le32 next; }; @@ -46,23 +49,31 @@ struct plx_dma_desc { ** **********************************************************************/ -#define PLX_LAS0RNG_REG 0x0000 /* L, Local Addr Space 0 Range Register */ -#define PLX_LAS1RNG_REG 0x00f0 /* L, Local Addr Space 1 Range Register */ +/* L, Local Addr Space 0 Range Register */ +#define PLX_LAS0RNG_REG 0x0000 +/* L, Local Addr Space 1 Range Register */ +#define PLX_LAS1RNG_REG 0x00f0 #define LRNG_IO 0x00000001 /* Map to: 1=I/O, 0=Mem */ #define LRNG_ANY32 0x00000000 /* Locate anywhere in 32 bit */ #define LRNG_LT1MB 0x00000002 /* Locate in 1st meg */ #define LRNG_ANY64 0x00000004 /* Locate anywhere in 64 bit */ -#define LRNG_MEM_MASK 0xfffffff0 /* bits that specify range for memory io */ -#define LRNG_IO_MASK 0xfffffffa /* bits that specify range for normal io */ - -#define PLX_LAS0MAP_REG 0x0004 /* L, Local Addr Space 0 Remap Register */ -#define PLX_LAS1MAP_REG 0x00f4 /* L, Local Addr Space 1 Remap Register */ +/* bits that specify range for memory io */ +#define LRNG_MEM_MASK 0xfffffff0 +/* bits that specify range for normal io */ +#define LRNG_IO_MASK 0xfffffffa +/* L, Local Addr Space 0 Remap Register */ +#define PLX_LAS0MAP_REG 0x0004 +/* L, Local Addr Space 1 Remap Register */ +#define PLX_LAS1MAP_REG 0x00f4 #define LMAP_EN 0x00000001 /* Enable slave decode */ -#define LMAP_MEM_MASK 0xfffffff0 /* bits that specify decode for memory io */ -#define LMAP_IO_MASK 0xfffffffa /* bits that specify decode bits for normal io */ +/* bits that specify decode for memory io */ +#define LMAP_MEM_MASK 0xfffffff0 +/* bits that specify decode bits for normal io */ +#define LMAP_IO_MASK 0xfffffffa -/* Mode/Arbitration Register. -*/ +/* + * Mode/Arbitration Register. + */ #define PLX_MARB_REG 0x8 /* L, Local Arbitration Register */ #define PLX_DMAARB_REG 0xac enum marb_bits { @@ -72,35 +83,45 @@ enum marb_bits { MARB_LPEN = 0x00020000, /* Pause Timer Enable */ MARB_BREQ = 0x00040000, /* Local Bus BREQ Enable */ MARB_DMA_PRIORITY_MASK = 0x00180000, - MARB_LBDS_GIVE_UP_BUS_MODE = 0x00200000, /* local bus direct slave give up bus mode */ - MARB_DS_LLOCK_ENABLE = 0x00400000, /* direct slave LLOCKo# enable */ + /* local bus direct slave give up bus mode */ + MARB_LBDS_GIVE_UP_BUS_MODE = 0x00200000, + /* direct slave LLOCKo# enable */ + MARB_DS_LLOCK_ENABLE = 0x00400000, MARB_PCI_REQUEST_MODE = 0x00800000, MARB_PCIv21_MODE = 0x01000000, /* pci specification v2.1 mode */ MARB_PCI_READ_NO_WRITE_MODE = 0x02000000, MARB_PCI_READ_WITH_WRITE_FLUSH_MODE = 0x04000000, - MARB_GATE_TIMER_WITH_BREQ = 0x08000000, /* gate local bus latency timer with BREQ */ + /* gate local bus latency timer with BREQ */ + MARB_GATE_TIMER_WITH_BREQ = 0x08000000, MARB_PCI_READ_NO_FLUSH_MODE = 0x10000000, MARB_USE_SUBSYSTEM_IDS = 0x20000000, }; #define PLX_BIGEND_REG 0xc enum bigend_bits { - BIGEND_CONFIG = 0x1, /* use big endian ordering for configuration register accesses */ + /* use big endian ordering for configuration register accesses */ + BIGEND_CONFIG = 0x1, BIGEND_DIRECT_MASTER = 0x2, BIGEND_DIRECT_SLAVE_LOCAL0 = 0x4, BIGEND_ROM = 0x8, - BIGEND_BYTE_LANE = 0x10, /* use byte lane consisting of most significant bits instead of least significant */ + /* + * use byte lane consisting of most significant bits instead of + * least significant + */ + BIGEND_BYTE_LANE = 0x10, BIGEND_DIRECT_SLAVE_LOCAL1 = 0x20, BIGEND_DMA1 = 0x40, BIGEND_DMA0 = 0x80, }; -/* Note: The Expansion ROM stuff is only relevant to the PC environment. +/* +** Note: The Expansion ROM stuff is only relevant to the PC environment. ** This expansion ROM code is executed by the host CPU at boot time. ** For this reason no bit definitions are provided here. -*/ + */ #define PLX_ROMRNG_REG 0x0010 /* L, Expn ROM Space Range Register */ -#define PLX_ROMMAP_REG 0x0014 /* L, Local Addr Space Range Register */ +/* L, Local Addr Space Range Register */ +#define PLX_ROMMAP_REG 0x0014 #define PLX_REGION0_REG 0x0018 /* L, Local Bus Region 0 Descriptor */ #define RGN_WIDTH 0x00000002 /* Local bus width bits */ @@ -190,7 +211,8 @@ enum bigend_bits { #define ICS_TA_DMA0 0x02000000 /* Target Abort - DMA #0 */ #define ICS_TA_DMA1 0x04000000 /* Target Abort - DMA #1 */ #define ICS_TA_RA 0x08000000 /* Target Abort - Retry Timeout */ -#define ICS_MBIA(x) (0x10000000 << ((x) & 0x3)) /* mailbox x is active */ +/* mailbox x is active */ +#define ICS_MBIA(x) (0x10000000 << ((x) & 0x3)) #define PLX_CONTROL_REG 0x006C /* L, EEPROM Cntl & PCI Cmd Codes */ #define CTL_RDMA 0x0000000E /* DMA Read Command */ @@ -221,28 +243,38 @@ enum bigend_bits { #define PLX_EN_BTERM_BIT 0x80 /* enable BTERM# input */ #define PLX_DMA_LOCAL_BURST_EN_BIT 0x100 /* enable local burst mode */ #define PLX_EN_CHAIN_BIT 0x200 /* enables chaining */ -#define PLX_EN_DMA_DONE_INTR_BIT 0x400 /* enables interrupt on dma done */ -#define PLX_LOCAL_ADDR_CONST_BIT 0x800 /* hold local address constant (don't increment) */ -#define PLX_DEMAND_MODE_BIT 0x1000 /* enables demand-mode for dma transfer */ +/* enables interrupt on dma done */ +#define PLX_EN_DMA_DONE_INTR_BIT 0x400 +/* hold local address constant (don't increment) */ +#define PLX_LOCAL_ADDR_CONST_BIT 0x800 +/* enables demand-mode for dma transfer */ +#define PLX_DEMAND_MODE_BIT 0x1000 #define PLX_EOT_ENABLE_BIT 0x4000 #define PLX_STOP_MODE_BIT 0x8000 -#define PLX_DMA_INTR_PCI_BIT 0x20000 /* routes dma interrupt to pci bus (instead of local bus) */ +/* routes dma interrupt to pci bus (instead of local bus) */ +#define PLX_DMA_INTR_PCI_BIT 0x20000 -#define PLX_DMA0_PCI_ADDRESS_REG 0x84 /* pci address that dma transfers start at */ +/* pci address that dma transfers start at */ +#define PLX_DMA0_PCI_ADDRESS_REG 0x84 #define PLX_DMA1_PCI_ADDRESS_REG 0x98 -#define PLX_DMA0_LOCAL_ADDRESS_REG 0x88 /* local address that dma transfers start at */ +/* local address that dma transfers start at */ +#define PLX_DMA0_LOCAL_ADDRESS_REG 0x88 #define PLX_DMA1_LOCAL_ADDRESS_REG 0x9c -#define PLX_DMA0_TRANSFER_SIZE_REG 0x8c /* number of bytes to transfer (first 23 bits) */ +/* number of bytes to transfer (first 23 bits) */ +#define PLX_DMA0_TRANSFER_SIZE_REG 0x8c #define PLX_DMA1_TRANSFER_SIZE_REG 0xa0 #define PLX_DMA0_DESCRIPTOR_REG 0x90 /* descriptor pointer register */ #define PLX_DMA1_DESCRIPTOR_REG 0xa4 -#define PLX_DESC_IN_PCI_BIT 0x1 /* descriptor is located in pci space (not local space) */ +/* descriptor is located in pci space (not local space) */ +#define PLX_DESC_IN_PCI_BIT 0x1 #define PLX_END_OF_CHAIN_BIT 0x2 /* end of chain bit */ -#define PLX_INTR_TERM_COUNT 0x4 /* interrupt when this descriptor's transfer is finished */ -#define PLX_XFER_LOCAL_TO_PCI 0x8 /* transfer from local to pci bus (not pci to local) */ +/* interrupt when this descriptor's transfer is finished */ +#define PLX_INTR_TERM_COUNT 0x4 +/* transfer from local to pci bus (not pci to local) */ +#define PLX_XFER_LOCAL_TO_PCI 0x8 #define PLX_DMA0_CS_REG 0xa8 /* command status register */ #define PLX_DMA1_CS_REG 0xa9 @@ -288,10 +320,11 @@ enum bigend_bits { #define MBX_STS_PCIRESET 0x00000100 /* Host issued PCI reset request */ #define MBX_STS_BUSY 0x00000080 /* PUTS is in progress */ #define MBX_STS_ERROR 0x00000040 /* PUTS has failed */ -#define MBX_STS_RESERVED 0x000000c0 /* Undefined -> status in transition. - We are in process of changing - bits; we SET Error bit before - RESET of Busy bit */ +/* + * Undefined -> status in transition. We are in process of changing bits; + * we SET Error bit before RESET of Busy bit + */ +#define MBX_STS_RESERVED 0x000000c0 #define MBX_RESERVED_5 0x00000020 /* FYI: reserved/unused bit */ #define MBX_RESERVED_4 0x00000010 /* FYI: reserved/unused bit */ @@ -320,12 +353,12 @@ enum bigend_bits { #define MBX_CMD_BSWAP_0 0x8c000000 /* use scheme 0 */ #define MBX_CMD_BSWAP_1 0x8c000001 /* use scheme 1 */ -#define MBX_CMD_SETHMS 0x8d000000 /* setup host memory access window - size */ -#define MBX_CMD_SETHBA 0x8e000000 /* setup host memory access base - address */ -#define MBX_CMD_MGO 0x8f000000 /* perform memory setup and continue - (IE. Done) */ +/* setup host memory access window size */ +#define MBX_CMD_SETHMS 0x8d000000 +/* setup host memory access base address */ +#define MBX_CMD_SETHBA 0x8e000000 +/* perform memory setup and continue (IE. Done) */ +#define MBX_CMD_MGO 0x8f000000 #define MBX_CMD_NOOP 0xFF000000 /* dummy, illegal command */ /*****************************************/ @@ -348,7 +381,8 @@ enum bigend_bits { /***************************************/ #define MBX_BTYPE_MASK 0x0000ffff /* PUTS Board Type Register */ -#define MBX_BTYPE_FAMILY_MASK 0x0000ff00 /* PUTS Board Family Register */ +/* PUTS Board Family Register */ +#define MBX_BTYPE_FAMILY_MASK 0x0000ff00 #define MBX_BTYPE_SUBTYPE_MASK 0x000000ff /* PUTS Board Subtype */ #define MBX_BTYPE_PLX9060 0x00000100 /* PLX family type */ @@ -378,12 +412,12 @@ enum bigend_bits { /* system allocates this many bytes for address mapping mailbox space */ #define MBX_ADDR_SPACE_360 0x80 /* wanXL100s/200/400 */ -#define MBX_ADDR_MASK_360 (MBX_ADDR_SPACE_360-1) +#define MBX_ADDR_MASK_360 (MBX_ADDR_SPACE_360 - 1) static inline int plx9080_abort_dma(void __iomem *iobase, unsigned int channel) { void __iomem *dma_cs_addr; - uint8_t dma_status; + u8 dma_status; const int timeout = 10000; unsigned int i; diff --git a/drivers/staging/comedi/drivers/s526.c b/drivers/staging/comedi/drivers/s526.c index d70c97947..c80527db9 100644 --- a/drivers/staging/comedi/drivers/s526.c +++ b/drivers/staging/comedi/drivers/s526.c @@ -37,7 +37,6 @@ #include #include "../comedidev.h" -#include /* * Register I/O map @@ -84,7 +83,92 @@ #define S526_GPCT_LSB_REG(x) (0x12 + ((x) * 8)) #define S526_GPCT_MSB_REG(x) (0x14 + ((x) * 8)) #define S526_GPCT_MODE_REG(x) (0x16 + ((x) * 8)) +#define S526_GPCT_MODE_COUT_SRC(x) ((x) << 0) +#define S526_GPCT_MODE_COUT_SRC_MASK S526_GPCT_MODE_COUT_SRC(0x1) +#define S526_GPCT_MODE_COUT_SRC_RCAP S526_GPCT_MODE_COUT_SRC(0) +#define S526_GPCT_MODE_COUT_SRC_RTGL S526_GPCT_MODE_COUT_SRC(1) +#define S526_GPCT_MODE_COUT_POL(x) ((x) << 1) +#define S526_GPCT_MODE_COUT_POL_MASK S526_GPCT_MODE_COUT_POL(0x1) +#define S526_GPCT_MODE_COUT_POL_NORM S526_GPCT_MODE_COUT_POL(0) +#define S526_GPCT_MODE_COUT_POL_INV S526_GPCT_MODE_COUT_POL(1) +#define S526_GPCT_MODE_AUTOLOAD(x) ((x) << 2) +#define S526_GPCT_MODE_AUTOLOAD_MASK S526_GPCT_MODE_AUTOLOAD(0x7) +#define S526_GPCT_MODE_AUTOLOAD_NONE S526_GPCT_MODE_AUTOLOAD(0) +/* these 3 bits can be OR'ed */ +#define S526_GPCT_MODE_AUTOLOAD_RO S526_GPCT_MODE_AUTOLOAD(0x1) +#define S526_GPCT_MODE_AUTOLOAD_IXFALL S526_GPCT_MODE_AUTOLOAD(0x2) +#define S526_GPCT_MODE_AUTOLOAD_IXRISE S526_GPCT_MODE_AUTOLOAD(0x4) +#define S526_GPCT_MODE_HWCTEN_SRC(x) ((x) << 5) +#define S526_GPCT_MODE_HWCTEN_SRC_MASK S526_GPCT_MODE_HWCTEN_SRC(0x3) +#define S526_GPCT_MODE_HWCTEN_SRC_CEN S526_GPCT_MODE_HWCTEN_SRC(0) +#define S526_GPCT_MODE_HWCTEN_SRC_IX S526_GPCT_MODE_HWCTEN_SRC(1) +#define S526_GPCT_MODE_HWCTEN_SRC_IXRF S526_GPCT_MODE_HWCTEN_SRC(2) +#define S526_GPCT_MODE_HWCTEN_SRC_NRCAP S526_GPCT_MODE_HWCTEN_SRC(3) +#define S526_GPCT_MODE_CTEN_CTRL(x) ((x) << 7) +#define S526_GPCT_MODE_CTEN_CTRL_MASK S526_GPCT_MODE_CTEN_CTRL(0x3) +#define S526_GPCT_MODE_CTEN_CTRL_DIS S526_GPCT_MODE_CTEN_CTRL(0) +#define S526_GPCT_MODE_CTEN_CTRL_ENA S526_GPCT_MODE_CTEN_CTRL(1) +#define S526_GPCT_MODE_CTEN_CTRL_HW S526_GPCT_MODE_CTEN_CTRL(2) +#define S526_GPCT_MODE_CTEN_CTRL_INVHW S526_GPCT_MODE_CTEN_CTRL(3) +#define S526_GPCT_MODE_CLK_SRC(x) ((x) << 9) +#define S526_GPCT_MODE_CLK_SRC_MASK S526_GPCT_MODE_CLK_SRC(0x3) +/* if count direction control set to quadrature */ +#define S526_GPCT_MODE_CLK_SRC_QUADX1 S526_GPCT_MODE_CLK_SRC(0) +#define S526_GPCT_MODE_CLK_SRC_QUADX2 S526_GPCT_MODE_CLK_SRC(1) +#define S526_GPCT_MODE_CLK_SRC_QUADX4 S526_GPCT_MODE_CLK_SRC(2) +#define S526_GPCT_MODE_CLK_SRC_QUADX4_ S526_GPCT_MODE_CLK_SRC(3) +/* if count direction control set to software control */ +#define S526_GPCT_MODE_CLK_SRC_ARISE S526_GPCT_MODE_CLK_SRC(0) +#define S526_GPCT_MODE_CLK_SRC_AFALL S526_GPCT_MODE_CLK_SRC(1) +#define S526_GPCT_MODE_CLK_SRC_INT S526_GPCT_MODE_CLK_SRC(2) +#define S526_GPCT_MODE_CLK_SRC_INTHALF S526_GPCT_MODE_CLK_SRC(3) +#define S526_GPCT_MODE_CT_DIR(x) ((x) << 11) +#define S526_GPCT_MODE_CT_DIR_MASK S526_GPCT_MODE_CT_DIR(0x1) +/* if count direction control set to software control */ +#define S526_GPCT_MODE_CT_DIR_UP S526_GPCT_MODE_CT_DIR(0) +#define S526_GPCT_MODE_CT_DIR_DOWN S526_GPCT_MODE_CT_DIR(1) +#define S526_GPCT_MODE_CTDIR_CTRL(x) ((x) << 12) +#define S526_GPCT_MODE_CTDIR_CTRL_MASK S526_GPCT_MODE_CTDIR_CTRL(0x1) +#define S526_GPCT_MODE_CTDIR_CTRL_QUAD S526_GPCT_MODE_CTDIR_CTRL(0) +#define S526_GPCT_MODE_CTDIR_CTRL_SOFT S526_GPCT_MODE_CTDIR_CTRL(1) +#define S526_GPCT_MODE_LATCH_CTRL(x) ((x) << 13) +#define S526_GPCT_MODE_LATCH_CTRL_MASK S526_GPCT_MODE_LATCH_CTRL(0x1) +#define S526_GPCT_MODE_LATCH_CTRL_READ S526_GPCT_MODE_LATCH_CTRL(0) +#define S526_GPCT_MODE_LATCH_CTRL_EVENT S526_GPCT_MODE_LATCH_CTRL(1) +#define S526_GPCT_MODE_PR_SELECT(x) ((x) << 14) +#define S526_GPCT_MODE_PR_SELECT_MASK S526_GPCT_MODE_PR_SELECT(0x1) +#define S526_GPCT_MODE_PR_SELECT_PR0 S526_GPCT_MODE_PR_SELECT(0) +#define S526_GPCT_MODE_PR_SELECT_PR1 S526_GPCT_MODE_PR_SELECT(1) +/* Control/Status - R = readable, W = writeable, C = write 1 to clear */ #define S526_GPCT_CTRL_REG(x) (0x18 + ((x) * 8)) +#define S526_GPCT_CTRL_EV_STATUS(x) ((x) << 0) /* RC */ +#define S526_GPCT_CTRL_EV_STATUS_MASK S526_GPCT_EV_STATUS(0xf) +#define S526_GPCT_CTRL_EV_STATUS_NONE S526_GPCT_EV_STATUS(0) +/* these 4 bits can be OR'ed */ +#define S526_GPCT_CTRL_EV_STATUS_ECAP S526_GPCT_EV_STATUS(0x1) +#define S526_GPCT_CTRL_EV_STATUS_ICAPN S526_GPCT_EV_STATUS(0x2) +#define S526_GPCT_CTRL_EV_STATUS_ICAPP S526_GPCT_EV_STATUS(0x4) +#define S526_GPCT_CTRL_EV_STATUS_RCAP S526_GPCT_EV_STATUS(0x8) +#define S526_GPCT_CTRL_COUT_STATUS BIT(4) /* R */ +#define S526_GPCT_CTRL_INDEX_STATUS BIT(5) /* R */ +#define S525_GPCT_CTRL_INTEN(x) ((x) << 6) /* W */ +#define S525_GPCT_CTRL_INTEN_MASK S526_GPCT_CTRL_INTEN(0xf) +#define S525_GPCT_CTRL_INTEN_NONE S526_GPCT_CTRL_INTEN(0) +/* these 4 bits can be OR'ed */ +#define S525_GPCT_CTRL_INTEN_ERROR S526_GPCT_CTRL_INTEN(0x1) +#define S525_GPCT_CTRL_INTEN_IXFALL S526_GPCT_CTRL_INTEN(0x2) +#define S525_GPCT_CTRL_INTEN_IXRISE S526_GPCT_CTRL_INTEN(0x4) +#define S525_GPCT_CTRL_INTEN_RO S526_GPCT_CTRL_INTEN(0x8) +#define S525_GPCT_CTRL_LATCH_SEL(x) ((x) << 10) /* W */ +#define S525_GPCT_CTRL_LATCH_SEL_MASK S526_GPCT_CTRL_LATCH_SEL(0x7) +#define S525_GPCT_CTRL_LATCH_SEL_NONE S526_GPCT_CTRL_LATCH_SEL(0) +/* these 3 bits can be OR'ed */ +#define S525_GPCT_CTRL_LATCH_SEL_IXFALL S526_GPCT_CTRL_LATCH_SEL(0x1) +#define S525_GPCT_CTRL_LATCH_SEL_IXRISE S526_GPCT_CTRL_LATCH_SEL(0x2) +#define S525_GPCT_CTRL_LATCH_SEL_ITIMER S526_GPCT_CTRL_LATCH_SEL(0x4) +#define S525_GPCT_CTRL_CT_ARM BIT(13) /* W */ +#define S525_GPCT_CTRL_CT_LOAD BIT(14) /* W */ +#define S526_GPCT_CTRL_CT_RESET BIT(15) /* W */ #define S526_EEPROM_DATA_REG 0x32 #define S526_EEPROM_CTRL_REG 0x34 #define S526_EEPROM_CTRL_ADDR(x) (((x) & 0x3f) << 3) @@ -92,41 +176,6 @@ #define S526_EEPROM_CTRL_READ S526_EEPROM_CTRL(2) #define S526_EEPROM_CTRL_START BIT(0) -struct counter_mode_register_t { -#if defined(__LITTLE_ENDIAN_BITFIELD) - unsigned short coutSource:1; - unsigned short coutPolarity:1; - unsigned short autoLoadResetRcap:3; - unsigned short hwCtEnableSource:2; - unsigned short ctEnableCtrl:2; - unsigned short clockSource:2; - unsigned short countDir:1; - unsigned short countDirCtrl:1; - unsigned short outputRegLatchCtrl:1; - unsigned short preloadRegSel:1; - unsigned short reserved:1; - #elif defined(__BIG_ENDIAN_BITFIELD) - unsigned short reserved:1; - unsigned short preloadRegSel:1; - unsigned short outputRegLatchCtrl:1; - unsigned short countDirCtrl:1; - unsigned short countDir:1; - unsigned short clockSource:2; - unsigned short ctEnableCtrl:2; - unsigned short hwCtEnableSource:2; - unsigned short autoLoadResetRcap:3; - unsigned short coutPolarity:1; - unsigned short coutSource:1; -#else -#error Unknown bit field order -#endif -}; - -union cmReg { - struct counter_mode_register_t reg; - unsigned short value; -}; - struct s526_private { unsigned int gpct_config[4]; unsigned short ai_ctrl; @@ -174,7 +223,6 @@ static int s526_gpct_insn_config(struct comedi_device *dev, struct s526_private *devpriv = dev->private; unsigned int chan = CR_CHAN(insn->chanspec); unsigned int val; - union cmReg cmReg; /* * Check what type of Counter the user requested @@ -192,28 +240,31 @@ static int s526_gpct_insn_config(struct comedi_device *dev, #if 1 /* Set Counter Mode Register */ - cmReg.value = data[1] & 0xffff; - outw(cmReg.value, dev->iobase + S526_GPCT_MODE_REG(chan)); + val = data[1] & 0xffff; + outw(val, dev->iobase + S526_GPCT_MODE_REG(chan)); /* Reset the counter if it is software preload */ - if (cmReg.reg.autoLoadResetRcap == 0) { + if ((val & S526_GPCT_MODE_AUTOLOAD_MASK) == + S526_GPCT_MODE_AUTOLOAD_NONE) { /* Reset the counter */ - outw(0x8000, dev->iobase + S526_GPCT_CTRL_REG(chan)); - /* Load the counter from PR0 - * outw(0x4000, dev->iobase + S526_GPCT_CTRL_REG(chan)); + outw(S526_GPCT_CTRL_CT_RESET, + dev->iobase + S526_GPCT_CTRL_REG(chan)); + /* + * Load the counter from PR0 + * outw(S526_GPCT_CTRL_CT_LOAD, + * dev->iobase + S526_GPCT_CTRL_REG(chan)); */ } #else - /* 0 quadrature, 1 software control */ - cmReg.reg.countDirCtrl = 0; + val = S526_GPCT_MODE_CTDIR_CTRL_QUAD; /* data[1] contains GPCT_X1, GPCT_X2 or GPCT_X4 */ if (data[1] == GPCT_X2) - cmReg.reg.clockSource = 1; + val |= S526_GPCT_MODE_CLK_SRC_QUADX2; else if (data[1] == GPCT_X4) - cmReg.reg.clockSource = 2; + val |= S526_GPCT_MODE_CLK_SRC_QUADX4; else - cmReg.reg.clockSource = 0; + val |= S526_GPCT_MODE_CLK_SRC_QUADX1; /* When to take into account the indexpulse: */ /* @@ -224,13 +275,14 @@ static int s526_gpct_insn_config(struct comedi_device *dev, * } */ /* Take into account the index pulse? */ - if (data[3] == GPCT_RESET_COUNTER_ON_INDEX) + if (data[3] == GPCT_RESET_COUNTER_ON_INDEX) { /* Auto load with INDEX^ */ - cmReg.reg.autoLoadResetRcap = 4; + val |= S526_GPCT_MODE_AUTOLOAD_IXRISE; + } /* Set Counter Mode Register */ - cmReg.value = data[1] & 0xffff; - outw(cmReg.value, dev->iobase + S526_GPCT_MODE_REG(chan)); + val = data[1] & 0xffff; + outw(val, dev->iobase + S526_GPCT_MODE_REG(chan)); /* Load the pre-load register */ s526_gpct_write(dev, chan, data[2]); @@ -241,11 +293,14 @@ static int s526_gpct_insn_config(struct comedi_device *dev, dev->iobase + S526_GPCT_CTRL_REG(chan)); /* Reset the counter if it is software preload */ - if (cmReg.reg.autoLoadResetRcap == 0) { + if ((val & S526_GPCT_MODE_AUTOLOAD_MASK) == + S526_GPCT_MODE_AUTOLOAD_NONE) { /* Reset the counter */ - outw(0x8000, dev->iobase + S526_GPCT_CTRL_REG(chan)); + outw(S526_GPCT_CTRL_CT_RESET, + dev->iobase + S526_GPCT_CTRL_REG(chan)); /* Load the counter from PR0 */ - outw(0x4000, dev->iobase + S526_GPCT_CTRL_REG(chan)); + outw(S526_GPCT_CTRL_CT_LOAD, + dev->iobase + S526_GPCT_CTRL_REG(chan)); } #endif break; @@ -261,17 +316,21 @@ static int s526_gpct_insn_config(struct comedi_device *dev, devpriv->gpct_config[chan] = data[0]; /* Set Counter Mode Register */ - cmReg.value = data[1] & 0xffff; - cmReg.reg.preloadRegSel = 0; /* PR0 */ - outw(cmReg.value, dev->iobase + S526_GPCT_MODE_REG(chan)); + val = data[1] & 0xffff; + /* Select PR0 */ + val &= ~S526_GPCT_MODE_PR_SELECT_MASK; + val |= S526_GPCT_MODE_PR_SELECT_PR0; + outw(val, dev->iobase + S526_GPCT_MODE_REG(chan)); /* Load the pre-load register 0 */ s526_gpct_write(dev, chan, data[2]); /* Set Counter Mode Register */ - cmReg.value = data[1] & 0xffff; - cmReg.reg.preloadRegSel = 1; /* PR1 */ - outw(cmReg.value, dev->iobase + S526_GPCT_MODE_REG(chan)); + val = data[1] & 0xffff; + /* Select PR1 */ + val &= ~S526_GPCT_MODE_PR_SELECT_MASK; + val |= S526_GPCT_MODE_PR_SELECT_PR1; + outw(val, dev->iobase + S526_GPCT_MODE_REG(chan)); /* Load the pre-load register 1 */ s526_gpct_write(dev, chan, data[3]); @@ -294,17 +353,21 @@ static int s526_gpct_insn_config(struct comedi_device *dev, devpriv->gpct_config[chan] = data[0]; /* Set Counter Mode Register */ - cmReg.value = data[1] & 0xffff; - cmReg.reg.preloadRegSel = 0; /* PR0 */ - outw(cmReg.value, dev->iobase + S526_GPCT_MODE_REG(chan)); + val = data[1] & 0xffff; + /* Select PR0 */ + val &= ~S526_GPCT_MODE_PR_SELECT_MASK; + val |= S526_GPCT_MODE_PR_SELECT_PR0; + outw(val, dev->iobase + S526_GPCT_MODE_REG(chan)); /* Load the pre-load register 0 */ s526_gpct_write(dev, chan, data[2]); /* Set Counter Mode Register */ - cmReg.value = data[1] & 0xffff; - cmReg.reg.preloadRegSel = 1; /* PR1 */ - outw(cmReg.value, dev->iobase + S526_GPCT_MODE_REG(chan)); + val = data[1] & 0xffff; + /* Select PR1 */ + val &= ~S526_GPCT_MODE_PR_SELECT_MASK; + val |= S526_GPCT_MODE_PR_SELECT_PR1; + outw(val, dev->iobase + S526_GPCT_MODE_REG(chan)); /* Load the pre-load register 1 */ s526_gpct_write(dev, chan, data[3]); -- cgit v1.2.3-54-g00ecf