summaryrefslogtreecommitdiff
path: root/drivers/staging/comedi/drivers/cb_pcidas.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/staging/comedi/drivers/cb_pcidas.c')
-rw-r--r--drivers/staging/comedi/drivers/cb_pcidas.c1175
1 files changed, 550 insertions, 625 deletions
diff --git a/drivers/staging/comedi/drivers/cb_pcidas.c b/drivers/staging/comedi/drivers/cb_pcidas.c
index b43e836575fd..3cd008acb657 100644
--- a/drivers/staging/comedi/drivers/cb_pcidas.c
+++ b/drivers/staging/comedi/drivers/cb_pcidas.c
@@ -1,65 +1,64 @@
/*
- comedi/drivers/cb_pcidas.c
+ * cb_pcidas.c
+ * Developed by Ivan Martinez and Frank Mori Hess, with valuable help from
+ * David Schleef and the rest of the Comedi developers comunity.
+ *
+ * Copyright (C) 2001-2003 Ivan Martinez <imr@oersted.dtu.dk>
+ * Copyright (C) 2001,2002 Frank Mori Hess <fmhess@users.sourceforge.net>
+ *
+ * COMEDI - Linux Control and Measurement Device Interface
+ * Copyright (C) 1997-8 David A. Schleef <ds@schleef.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
- Developed by Ivan Martinez and Frank Mori Hess, with valuable help from
- David Schleef and the rest of the Comedi developers comunity.
-
- Copyright (C) 2001-2003 Ivan Martinez <imr@oersted.dtu.dk>
- Copyright (C) 2001,2002 Frank Mori Hess <fmhess@users.sourceforge.net>
-
- COMEDI - Linux Control and Measurement Device Interface
- Copyright (C) 1997-8 David A. Schleef <ds@schleef.org>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-*/
-/*
-Driver: cb_pcidas
-Description: MeasurementComputing PCI-DAS series
- with the AMCC S5933 PCI controller
-Author: Ivan Martinez <imr@oersted.dtu.dk>,
- Frank Mori Hess <fmhess@users.sourceforge.net>
-Updated: 2003-3-11
-Devices: [Measurement Computing] PCI-DAS1602/16 (cb_pcidas),
- PCI-DAS1602/16jr, PCI-DAS1602/12, PCI-DAS1200, PCI-DAS1200jr,
- PCI-DAS1000, PCI-DAS1001, PCI_DAS1002
-
-Status:
- There are many reports of the driver being used with most of the
- supported cards. Despite no detailed log is maintained, it can
- be said that the driver is quite tested and stable.
-
- The boards may be autocalibrated using the comedi_calibrate
- utility.
-
-Configuration options: not applicable, uses PCI auto config
-
-For commands, the scanned channels must be consecutive
-(i.e. 4-5-6-7, 2-3-4,...), and must all have the same
-range and aref.
-
-AI Triggering:
- For start_src == TRIG_EXT, the A/D EXTERNAL TRIGGER IN (pin 45) is used.
- For 1602 series, the start_arg is interpreted as follows:
- start_arg == 0 => gated trigger (level high)
- start_arg == CR_INVERT => gated trigger (level low)
- start_arg == CR_EDGE => Rising edge
- start_arg == CR_EDGE | CR_INVERT => Falling edge
- For the other boards the trigger will be done on rising edge
-*/
/*
+ * Driver: cb_pcidas
+ * Description: MeasurementComputing PCI-DAS series
+ * with the AMCC S5933 PCI controller
+ * Devices: [Measurement Computing] PCI-DAS1602/16 (cb_pcidas),
+ * PCI-DAS1602/16jr, PCI-DAS1602/12, PCI-DAS1200, PCI-DAS1200jr,
+ * PCI-DAS1000, PCI-DAS1001, PCI_DAS1002
+ * Author: Ivan Martinez <imr@oersted.dtu.dk>,
+ * Frank Mori Hess <fmhess@users.sourceforge.net>
+ * Updated: 2003-3-11
+ *
+ * Status:
+ * There are many reports of the driver being used with most of the
+ * supported cards. Despite no detailed log is maintained, it can
+ * be said that the driver is quite tested and stable.
+ *
+ * The boards may be autocalibrated using the comedi_calibrate
+ * utility.
+ *
+ * Configuration options: not applicable, uses PCI auto config
+ *
+ * For commands, the scanned channels must be consecutive
+ * (i.e. 4-5-6-7, 2-3-4,...), and must all have the same
+ * range and aref.
+ *
+ * AI Triggering:
+ * For start_src == TRIG_EXT, the A/D EXTERNAL TRIGGER IN (pin 45) is used.
+ * For 1602 series, the start_arg is interpreted as follows:
+ * start_arg == 0 => gated trigger (level high)
+ * start_arg == CR_INVERT => gated trigger (level low)
+ * start_arg == CR_EDGE => Rising edge
+ * start_arg == CR_EDGE | CR_INVERT => Falling edge
+ * For the other boards the trigger will be done on rising edge
+ */
-TODO:
-
-analog triggering on 1602 series
-*/
+/*
+ * TODO:
+ * analog triggering on 1602 series
+ */
#include <linux/module.h>
#include <linux/delay.h>
@@ -73,109 +72,107 @@ analog triggering on 1602 series
#define AI_BUFFER_SIZE 1024 /* max ai fifo size */
#define AO_BUFFER_SIZE 1024 /* max ao fifo size */
-#define NUM_CHANNELS_8800 8
-#define NUM_CHANNELS_7376 1
-#define NUM_CHANNELS_8402 2
-#define NUM_CHANNELS_DAC08 1
-
-/* Control/Status registers */
-#define INT_ADCFIFO 0 /* INTERRUPT / ADC FIFO register */
-#define INT_EOS 0x1 /* int end of scan */
-#define INT_FHF 0x2 /* int fifo half full */
-#define INT_FNE 0x3 /* int fifo not empty */
-#define INT_MASK 0x3 /* mask of int select bits */
-#define INTE 0x4 /* int enable */
-#define DAHFIE 0x8 /* dac half full int enable */
-#define EOAIE 0x10 /* end of acq. int enable */
-#define DAHFI 0x20 /* dac half full status / clear */
-#define EOAI 0x40 /* end of acq. int status / clear */
-#define INT 0x80 /* int status / clear */
-#define EOBI 0x200 /* end of burst int status */
-#define ADHFI 0x400 /* half-full int status */
-#define ADNEI 0x800 /* fifo not empty int status (latch) */
-#define ADNE 0x1000 /* fifo not empty status (realtime) */
-#define DAEMIE 0x1000 /* dac empty int enable */
-#define LADFUL 0x2000 /* fifo overflow / clear */
-#define DAEMI 0x4000 /* dac fifo empty int status / clear */
-
-#define ADCMUX_CONT 2 /* ADC CHANNEL MUX AND CONTROL reg */
-#define BEGIN_SCAN(x) ((x) & 0xf)
-#define END_SCAN(x) (((x) & 0xf) << 4)
-#define GAIN_BITS(x) (((x) & 0x3) << 8)
-#define UNIP 0x800 /* Analog front-end unipolar mode */
-#define SE 0x400 /* Inputs in single-ended mode */
-#define PACER_MASK 0x3000 /* pacer source bits */
-#define PACER_INT 0x1000 /* int. pacer */
-#define PACER_EXT_FALL 0x2000 /* ext. falling edge */
-#define PACER_EXT_RISE 0x3000 /* ext. rising edge */
-#define EOC 0x4000 /* adc not busy */
-
-#define TRIG_CONTSTAT 4 /* TRIGGER CONTROL/STATUS register */
-#define SW_TRIGGER 0x1 /* software start trigger */
-#define EXT_TRIGGER 0x2 /* ext. start trigger */
-#define ANALOG_TRIGGER 0x3 /* ext. analog trigger */
-#define TRIGGER_MASK 0x3 /* start trigger mask */
-#define TGPOL 0x04 /* invert trigger (1602 only) */
-#define TGSEL 0x08 /* edge/level trigerred (1602 only) */
-#define TGEN 0x10 /* enable external start trigger */
-#define BURSTE 0x20 /* burst mode enable */
-#define XTRCL 0x80 /* clear external trigger */
-
-#define CALIBRATION_REG 6 /* CALIBRATION register */
-#define SELECT_8800_BIT 0x100 /* select 8800 caldac */
-#define SELECT_TRIMPOT_BIT 0x200 /* select ad7376 trim pot */
-#define SELECT_DAC08_BIT 0x400 /* select dac08 caldac */
-#define CAL_SRC_BITS(x) (((x) & 0x7) << 11)
-#define CAL_EN_BIT 0x4000 /* calibration source enable */
-#define SERIAL_DATA_IN_BIT 0x8000 /* serial data bit going to caldac */
-
-#define DAC_CSR 0x8 /* dac control and status register */
-#define DACEN 0x02 /* dac enable */
-#define DAC_MODE_UPDATE_BOTH 0x80 /* update both dacs */
-
-static inline unsigned int DAC_RANGE(unsigned int channel, unsigned int range)
-{
- return (range & 0x3) << (8 + 2 * (channel & 0x1));
-}
-
-static inline unsigned int DAC_RANGE_MASK(unsigned int channel)
-{
- return 0x3 << (8 + 2 * (channel & 0x1));
-};
-
-/* bits for 1602 series only */
-#define DAC_EMPTY 0x1 /* fifo empty, read, write clear */
-#define DAC_START 0x4 /* start/arm fifo operations */
-#define DAC_PACER_MASK 0x18 /* bits that set pacer source */
-#define DAC_PACER_INT 0x8 /* int. pacing */
-#define DAC_PACER_EXT_FALL 0x10 /* ext. pacing, falling edge */
-#define DAC_PACER_EXT_RISE 0x18 /* ext. pacing, rising edge */
-
-static inline unsigned int DAC_CHAN_EN(unsigned int channel)
-{
- return 1 << (5 + (channel & 0x1)); /* enable channel 0 or 1 */
-};
-
-/* analog input fifo */
-#define ADCDATA 0 /* ADC DATA register */
-#define ADCFIFOCLR 2 /* ADC FIFO CLEAR */
-/* pacer, counter, dio registers */
-#define ADC8254 0
-#define DIO_8255 4
-#define DAC8254 8
+/*
+ * PCI BAR1 Register map (devpriv->pcibar1)
+ */
+#define PCIDAS_CTRL_REG 0x00 /* INTERRUPT / ADC FIFO register */
+#define PCIDAS_CTRL_INT(x) (((x) & 0x3) << 0)
+#define PCIDAS_CTRL_INT_NONE PCIDAS_CTRL_INT(0) /* no int selected */
+#define PCIDAS_CTRL_INT_EOS PCIDAS_CTRL_INT(1) /* int on end of scan */
+#define PCIDAS_CTRL_INT_FHF PCIDAS_CTRL_INT(2) /* int on fifo half full */
+#define PCIDAS_CTRL_INT_FNE PCIDAS_CTRL_INT(3) /* int on fifo not empty */
+#define PCIDAS_CTRL_INT_MASK PCIDAS_CTRL_INT(3) /* mask of int select bits */
+#define PCIDAS_CTRL_INTE BIT(2) /* int enable */
+#define PCIDAS_CTRL_DAHFIE BIT(3) /* dac half full int enable */
+#define PCIDAS_CTRL_EOAIE BIT(4) /* end of acq. int enable */
+#define PCIDAS_CTRL_DAHFI BIT(5) /* dac half full status / clear */
+#define PCIDAS_CTRL_EOAI BIT(6) /* end of acq. int status / clear */
+#define PCIDAS_CTRL_INT_CLR BIT(7) /* int status / clear */
+#define PCIDAS_CTRL_EOBI BIT(9) /* end of burst int status */
+#define PCIDAS_CTRL_ADHFI BIT(10) /* half-full int status */
+#define PCIDAS_CTRL_ADNEI BIT(11) /* fifo not empty int status (latch) */
+#define PCIDAS_CTRL_ADNE BIT(12) /* fifo not empty status (realtime) */
+#define PCIDAS_CTRL_DAEMIE BIT(12) /* dac empty int enable */
+#define PCIDAS_CTRL_LADFUL BIT(13) /* fifo overflow / clear */
+#define PCIDAS_CTRL_DAEMI BIT(14) /* dac fifo empty int status / clear */
+
+#define PCIDAS_CTRL_AI_INT (PCIDAS_CTRL_EOAI | PCIDAS_CTRL_EOBI | \
+ PCIDAS_CTRL_ADHFI | PCIDAS_CTRL_ADNEI | \
+ PCIDAS_CTRL_LADFUL)
+#define PCIDAS_CTRL_AO_INT (PCIDAS_CTRL_DAHFI | PCIDAS_CTRL_DAEMI)
+
+#define PCIDAS_AI_REG 0x02 /* ADC CHANNEL MUX AND CONTROL reg */
+#define PCIDAS_AI_FIRST(x) ((x) & 0xf)
+#define PCIDAS_AI_LAST(x) (((x) & 0xf) << 4)
+#define PCIDAS_AI_CHAN(x) (PCIDAS_AI_FIRST(x) | PCIDAS_AI_LAST(x))
+#define PCIDAS_AI_GAIN(x) (((x) & 0x3) << 8)
+#define PCIDAS_AI_SE BIT(10) /* Inputs in single-ended mode */
+#define PCIDAS_AI_UNIP BIT(11) /* Analog front-end unipolar mode */
+#define PCIDAS_AI_PACER(x) (((x) & 0x3) << 12)
+#define PCIDAS_AI_PACER_SW PCIDAS_AI_PACER(0) /* software pacer */
+#define PCIDAS_AI_PACER_INT PCIDAS_AI_PACER(1) /* int. pacer */
+#define PCIDAS_AI_PACER_EXTN PCIDAS_AI_PACER(2) /* ext. falling edge */
+#define PCIDAS_AI_PACER_EXTP PCIDAS_AI_PACER(3) /* ext. rising edge */
+#define PCIDAS_AI_PACER_MASK PCIDAS_AI_PACER(3) /* pacer source bits */
+#define PCIDAS_AI_EOC BIT(14) /* adc not busy */
+
+#define PCIDAS_TRIG_REG 0x04 /* TRIGGER CONTROL/STATUS register */
+#define PCIDAS_TRIG_SEL(x) (((x) & 0x3) << 0)
+#define PCIDAS_TRIG_SEL_NONE PCIDAS_TRIG_SEL(0) /* no start trigger */
+#define PCIDAS_TRIG_SEL_SW PCIDAS_TRIG_SEL(1) /* software start trigger */
+#define PCIDAS_TRIG_SEL_EXT PCIDAS_TRIG_SEL(2) /* ext. start trigger */
+#define PCIDAS_TRIG_SEL_ANALOG PCIDAS_TRIG_SEL(3) /* ext. analog trigger */
+#define PCIDAS_TRIG_SEL_MASK PCIDAS_TRIG_SEL(3) /* start trigger mask */
+#define PCIDAS_TRIG_POL BIT(2) /* invert trigger (1602 only) */
+#define PCIDAS_TRIG_MODE BIT(3) /* edge/level trigerred (1602 only) */
+#define PCIDAS_TRIG_EN BIT(4) /* enable external start trigger */
+#define PCIDAS_TRIG_BURSTE BIT(5) /* burst mode enable */
+#define PCIDAS_TRIG_CLR BIT(7) /* clear external trigger */
+
+#define PCIDAS_CALIB_REG 0x06 /* CALIBRATION register */
+#define PCIDAS_CALIB_8800_SEL BIT(8) /* select 8800 caldac */
+#define PCIDAS_CALIB_TRIM_SEL BIT(9) /* select ad7376 trim pot */
+#define PCIDAS_CALIB_DAC08_SEL BIT(10) /* select dac08 caldac */
+#define PCIDAS_CALIB_SRC(x) (((x) & 0x7) << 11)
+#define PCIDAS_CALIB_EN BIT(14) /* calibration source enable */
+#define PCIDAS_CALIB_DATA BIT(15) /* serial data bit going to caldac */
+
+#define PCIDAS_AO_REG 0x08 /* dac control and status register */
+#define PCIDAS_AO_EMPTY BIT(0) /* fifo empty, write clear (1602) */
+#define PCIDAS_AO_DACEN BIT(1) /* dac enable */
+#define PCIDAS_AO_START BIT(2) /* start/arm fifo (1602) */
+#define PCIDAS_AO_PACER(x) (((x) & 0x3) << 3) /* (1602) */
+#define PCIDAS_AO_PACER_SW PCIDAS_AO_PACER(0) /* software pacer */
+#define PCIDAS_AO_PACER_INT PCIDAS_AO_PACER(1) /* int. pacer */
+#define PCIDAS_AO_PACER_EXTN PCIDAS_AO_PACER(2) /* ext. falling edge */
+#define PCIDAS_AO_PACER_EXTP PCIDAS_AO_PACER(3) /* ext. rising edge */
+#define PCIDAS_AO_PACER_MASK PCIDAS_AO_PACER(3) /* pacer source bits */
+#define PCIDAS_AO_CHAN_EN(c) BIT(5 + ((c) & 0x1))
+#define PCIDAS_AO_CHAN_MASK (PCIDAS_AO_CHAN_EN(0) | PCIDAS_AO_CHAN_EN(1))
+#define PCIDAS_AO_UPDATE_BOTH BIT(7) /* update both dacs */
+#define PCIDAS_AO_RANGE(c, r) (((r) & 0x3) << (8 + 2 * ((c) & 0x1)))
+#define PCIDAS_AO_RANGE_MASK(c) PCIDAS_AO_RANGE((c), 0x3)
-/* analog output registers for 100x, 1200 series */
-static inline unsigned int DAC_DATA_REG(unsigned int channel)
-{
- return 2 * (channel & 0x1);
-}
+/*
+ * PCI BAR2 Register map (devpriv->pcibar2)
+ */
+#define PCIDAS_AI_DATA_REG 0x00
+#define PCIDAS_AI_FIFO_CLR_REG 0x02
-/* analog output registers for 1602 series*/
-#define DACDATA 0 /* DAC DATA register */
-#define DACFIFOCLR 2 /* DAC FIFO CLEAR */
+/*
+ * PCI BAR3 Register map (dev->iobase)
+ */
+#define PCIDAS_AI_8254_BASE 0x00
+#define PCIDAS_8255_BASE 0x04
+#define PCIDAS_AO_8254_BASE 0x08
-#define IS_UNIPOLAR 0x4 /* unipolar range mask */
+/*
+ * PCI BAR4 Register map (devpriv->pcibar4)
+ */
+#define PCIDAS_AO_DATA_REG(x) (0x00 + ((x) * 2))
+#define PCIDAS_AO_FIFO_REG 0x00
+#define PCIDAS_AO_FIFO_CLR_REG 0x02
/* analog input ranges for most boards */
static const struct comedi_lrange cb_pcidas_ranges = {
@@ -215,11 +212,6 @@ static const struct comedi_lrange cb_pcidas_ao_ranges = {
}
};
-enum trimpot_model {
- AD7376,
- AD8402,
-};
-
enum cb_pcidas_boardid {
BOARD_PCIDAS1602_16,
BOARD_PCIDAS1200,
@@ -233,132 +225,97 @@ enum cb_pcidas_boardid {
struct cb_pcidas_board {
const char *name;
- int ai_nchan; /* Inputs in single-ended mode */
- int ai_bits; /* analog input resolution */
int ai_speed; /* fastest conversion period in ns */
- int ao_nchan; /* number of analog out channels */
- int has_ao_fifo; /* analog output has fifo */
int ao_scan_speed; /* analog output scan speed for 1602 series */
int fifo_size; /* number of samples fifo can hold */
- const struct comedi_lrange *ranges;
- enum trimpot_model trimpot;
- unsigned has_dac08:1;
- unsigned is_1602:1;
+ unsigned int is_16bit; /* ai/ao is 1=16-bit; 0=12-bit */
+ unsigned int use_alt_range:1; /* use alternate ai range table */
+ unsigned int has_ao:1; /* has 2 analog output channels */
+ unsigned int has_ao_fifo:1; /* analog output has fifo */
+ unsigned int has_ad8402:1; /* trimpot type 1=AD8402; 0=AD7376 */
+ unsigned int has_dac08:1;
+ unsigned int is_1602:1;
};
static const struct cb_pcidas_board cb_pcidas_boards[] = {
[BOARD_PCIDAS1602_16] = {
.name = "pci-das1602/16",
- .ai_nchan = 16,
- .ai_bits = 16,
.ai_speed = 5000,
- .ao_nchan = 2,
- .has_ao_fifo = 1,
.ao_scan_speed = 10000,
.fifo_size = 512,
- .ranges = &cb_pcidas_ranges,
- .trimpot = AD8402,
+ .is_16bit = 1,
+ .has_ao = 1,
+ .has_ao_fifo = 1,
+ .has_ad8402 = 1,
.has_dac08 = 1,
.is_1602 = 1,
},
[BOARD_PCIDAS1200] = {
.name = "pci-das1200",
- .ai_nchan = 16,
- .ai_bits = 12,
.ai_speed = 3200,
- .ao_nchan = 2,
.fifo_size = 1024,
- .ranges = &cb_pcidas_ranges,
- .trimpot = AD7376,
+ .has_ao = 1,
},
[BOARD_PCIDAS1602_12] = {
.name = "pci-das1602/12",
- .ai_nchan = 16,
- .ai_bits = 12,
.ai_speed = 3200,
- .ao_nchan = 2,
- .has_ao_fifo = 1,
.ao_scan_speed = 4000,
.fifo_size = 1024,
- .ranges = &cb_pcidas_ranges,
- .trimpot = AD7376,
+ .has_ao = 1,
+ .has_ao_fifo = 1,
.is_1602 = 1,
},
[BOARD_PCIDAS1200_JR] = {
.name = "pci-das1200/jr",
- .ai_nchan = 16,
- .ai_bits = 12,
.ai_speed = 3200,
.fifo_size = 1024,
- .ranges = &cb_pcidas_ranges,
- .trimpot = AD7376,
},
[BOARD_PCIDAS1602_16_JR] = {
.name = "pci-das1602/16/jr",
- .ai_nchan = 16,
- .ai_bits = 16,
.ai_speed = 5000,
.fifo_size = 512,
- .ranges = &cb_pcidas_ranges,
- .trimpot = AD8402,
+ .is_16bit = 1,
+ .has_ad8402 = 1,
.has_dac08 = 1,
.is_1602 = 1,
},
[BOARD_PCIDAS1000] = {
.name = "pci-das1000",
- .ai_nchan = 16,
- .ai_bits = 12,
.ai_speed = 4000,
.fifo_size = 1024,
- .ranges = &cb_pcidas_ranges,
- .trimpot = AD7376,
},
[BOARD_PCIDAS1001] = {
.name = "pci-das1001",
- .ai_nchan = 16,
- .ai_bits = 12,
.ai_speed = 6800,
- .ao_nchan = 2,
.fifo_size = 1024,
- .ranges = &cb_pcidas_alt_ranges,
- .trimpot = AD7376,
+ .use_alt_range = 1,
+ .has_ao = 1,
},
[BOARD_PCIDAS1002] = {
.name = "pci-das1002",
- .ai_nchan = 16,
- .ai_bits = 12,
.ai_speed = 6800,
- .ao_nchan = 2,
.fifo_size = 1024,
- .ranges = &cb_pcidas_ranges,
- .trimpot = AD7376,
+ .has_ao = 1,
},
};
struct cb_pcidas_private {
struct comedi_8254 *ao_pacer;
/* base addresses */
- unsigned long s5933_config;
- unsigned long control_status;
- unsigned long adc_fifo;
- unsigned long ao_registers;
+ unsigned long amcc; /* pcibar0 */
+ unsigned long pcibar1;
+ unsigned long pcibar2;
+ unsigned long pcibar4;
/* bits to write to registers */
- unsigned int adc_fifo_bits;
- unsigned int s5933_intcsr_bits;
- unsigned int ao_control_bits;
+ unsigned int ctrl;
+ unsigned int amcc_intcsr;
+ unsigned int ao_ctrl;
/* fifo buffers */
unsigned short ai_buffer[AI_BUFFER_SIZE];
unsigned short ao_buffer[AO_BUFFER_SIZE];
- unsigned int calibration_source;
+ unsigned int calib_src;
};
-static inline unsigned int cal_enable_bits(struct comedi_device *dev)
-{
- struct cb_pcidas_private *devpriv = dev->private;
-
- return CAL_EN_BIT | CAL_SRC_BITS(devpriv->calibration_source);
-}
-
static int cb_pcidas_ai_eoc(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn,
@@ -367,15 +324,16 @@ static int cb_pcidas_ai_eoc(struct comedi_device *dev,
struct cb_pcidas_private *devpriv = dev->private;
unsigned int status;
- status = inw(devpriv->control_status + ADCMUX_CONT);
- if (status & EOC)
+ status = inw(devpriv->pcibar1 + PCIDAS_AI_REG);
+ if (status & PCIDAS_AI_EOC)
return 0;
return -EBUSY;
}
-static int cb_pcidas_ai_rinsn(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data)
+static int cb_pcidas_ai_insn_read(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn,
+ unsigned int *data)
{
struct cb_pcidas_private *devpriv = dev->private;
unsigned int chan = CR_CHAN(insn->chanspec);
@@ -387,30 +345,30 @@ static int cb_pcidas_ai_rinsn(struct comedi_device *dev,
/* enable calibration input if appropriate */
if (insn->chanspec & CR_ALT_SOURCE) {
- outw(cal_enable_bits(dev),
- devpriv->control_status + CALIBRATION_REG);
+ outw(PCIDAS_CALIB_EN | PCIDAS_CALIB_SRC(devpriv->calib_src),
+ devpriv->pcibar1 + PCIDAS_CALIB_REG);
chan = 0;
} else {
- outw(0, devpriv->control_status + CALIBRATION_REG);
+ outw(0, devpriv->pcibar1 + PCIDAS_CALIB_REG);
}
/* set mux limits and gain */
- bits = BEGIN_SCAN(chan) | END_SCAN(chan) | GAIN_BITS(range);
+ bits = PCIDAS_AI_CHAN(chan) | PCIDAS_AI_GAIN(range);
/* set unipolar/bipolar */
- if (range & IS_UNIPOLAR)
- bits |= UNIP;
+ if (comedi_range_is_unipolar(s, range))
+ bits |= PCIDAS_AI_UNIP;
/* set single-ended/differential */
if (aref != AREF_DIFF)
- bits |= SE;
- outw(bits, devpriv->control_status + ADCMUX_CONT);
+ bits |= PCIDAS_AI_SE;
+ outw(bits, devpriv->pcibar1 + PCIDAS_AI_REG);
/* clear fifo */
- outw(0, devpriv->adc_fifo + ADCFIFOCLR);
+ outw(0, devpriv->pcibar2 + PCIDAS_AI_FIFO_CLR_REG);
/* convert n samples */
for (n = 0; n < insn->n; n++) {
/* trigger conversion */
- outw(0, devpriv->adc_fifo + ADCDATA);
+ outw(0, devpriv->pcibar2 + PCIDAS_AI_DATA_REG);
/* wait for conversion to end */
ret = comedi_timeout(dev, s, insn, cb_pcidas_ai_eoc, 0);
@@ -418,15 +376,17 @@ static int cb_pcidas_ai_rinsn(struct comedi_device *dev,
return ret;
/* read data */
- data[n] = inw(devpriv->adc_fifo + ADCDATA);
+ data[n] = inw(devpriv->pcibar2 + PCIDAS_AI_DATA_REG);
}
/* return the number of samples read/written */
return n;
}
-static int ai_config_insn(struct comedi_device *dev, struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data)
+static int cb_pcidas_ai_insn_config(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn,
+ unsigned int *data)
{
struct cb_pcidas_private *devpriv = dev->private;
int id = data[0];
@@ -440,7 +400,7 @@ static int ai_config_insn(struct comedi_device *dev, struct comedi_subdevice *s,
source);
return -EINVAL;
}
- devpriv->calibration_source = source;
+ devpriv->calib_src = source;
break;
default:
return -EINVAL;
@@ -449,155 +409,160 @@ static int ai_config_insn(struct comedi_device *dev, struct comedi_subdevice *s,
}
/* analog output insn for pcidas-1000 and 1200 series */
-static int cb_pcidas_ao_nofifo_winsn(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn,
- unsigned int *data)
+static int cb_pcidas_ao_nofifo_insn_write(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn,
+ unsigned int *data)
{
struct cb_pcidas_private *devpriv = dev->private;
unsigned int chan = CR_CHAN(insn->chanspec);
unsigned int range = CR_RANGE(insn->chanspec);
+ unsigned int val = s->readback[chan];
unsigned long flags;
+ int i;
/* set channel and range */
spin_lock_irqsave(&dev->spinlock, flags);
- devpriv->ao_control_bits &= (~DAC_MODE_UPDATE_BOTH &
- ~DAC_RANGE_MASK(chan));
- devpriv->ao_control_bits |= (DACEN | DAC_RANGE(chan, range));
- outw(devpriv->ao_control_bits, devpriv->control_status + DAC_CSR);
+ devpriv->ao_ctrl &= ~(PCIDAS_AO_UPDATE_BOTH |
+ PCIDAS_AO_RANGE_MASK(chan));
+ devpriv->ao_ctrl |= PCIDAS_AO_DACEN | PCIDAS_AO_RANGE(chan, range);
+ outw(devpriv->ao_ctrl, devpriv->pcibar1 + PCIDAS_AO_REG);
spin_unlock_irqrestore(&dev->spinlock, flags);
- /* remember value for readback */
- s->readback[chan] = data[0];
+ for (i = 0; i < insn->n; i++) {
+ val = data[i];
+ outw(val, devpriv->pcibar4 + PCIDAS_AO_DATA_REG(chan));
+ }
- /* send data */
- outw(data[0], devpriv->ao_registers + DAC_DATA_REG(chan));
+ s->readback[chan] = val;
return insn->n;
}
/* analog output insn for pcidas-1602 series */
-static int cb_pcidas_ao_fifo_winsn(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data)
+static int cb_pcidas_ao_fifo_insn_write(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn,
+ unsigned int *data)
{
struct cb_pcidas_private *devpriv = dev->private;
unsigned int chan = CR_CHAN(insn->chanspec);
unsigned int range = CR_RANGE(insn->chanspec);
+ unsigned int val = s->readback[chan];
unsigned long flags;
+ int i;
/* clear dac fifo */
- outw(0, devpriv->ao_registers + DACFIFOCLR);
+ outw(0, devpriv->pcibar4 + PCIDAS_AO_FIFO_CLR_REG);
/* set channel and range */
spin_lock_irqsave(&dev->spinlock, flags);
- devpriv->ao_control_bits &= (~DAC_CHAN_EN(0) & ~DAC_CHAN_EN(1) &
- ~DAC_RANGE_MASK(chan) & ~DAC_PACER_MASK);
- devpriv->ao_control_bits |= (DACEN | DAC_RANGE(chan, range) |
- DAC_CHAN_EN(chan) | DAC_START);
- outw(devpriv->ao_control_bits, devpriv->control_status + DAC_CSR);
+ devpriv->ao_ctrl &= ~(PCIDAS_AO_CHAN_MASK | PCIDAS_AO_RANGE_MASK(chan) |
+ PCIDAS_AO_PACER_MASK);
+ devpriv->ao_ctrl |= PCIDAS_AO_DACEN | PCIDAS_AO_RANGE(chan, range) |
+ PCIDAS_AO_CHAN_EN(chan) | PCIDAS_AO_START;
+ outw(devpriv->ao_ctrl, devpriv->pcibar1 + PCIDAS_AO_REG);
spin_unlock_irqrestore(&dev->spinlock, flags);
- /* remember value for readback */
- s->readback[chan] = data[0];
+ for (i = 0; i < insn->n; i++) {
+ val = data[i];
+ outw(val, devpriv->pcibar4 + PCIDAS_AO_FIFO_REG);
+ }
- /* send data */
- outw(data[0], devpriv->ao_registers + DACDATA);
+ s->readback[chan] = val;
return insn->n;
}
-static int wait_for_nvram_ready(unsigned long s5933_base_addr)
+static int cb_pcidas_eeprom_ready(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn,
+ unsigned long context)
{
- static const int timeout = 1000;
- unsigned int i;
+ struct cb_pcidas_private *devpriv = dev->private;
+ unsigned int status;
- for (i = 0; i < timeout; i++) {
- if ((inb(s5933_base_addr +
- AMCC_OP_REG_MCSR_NVCMD) & MCSR_NV_BUSY)
- == 0)
- return 0;
- udelay(1);
- }
- return -1;
+ status = inb(devpriv->amcc + AMCC_OP_REG_MCSR_NVCMD);
+ if ((status & MCSR_NV_BUSY) == 0)
+ return 0;
+ return -EBUSY;
}
-static int nvram_read(struct comedi_device *dev, unsigned int address,
- uint8_t *data)
+static int cb_pcidas_eeprom_insn_read(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn,
+ unsigned int *data)
{
struct cb_pcidas_private *devpriv = dev->private;
- unsigned long iobase = devpriv->s5933_config;
-
- if (wait_for_nvram_ready(iobase) < 0)
- return -ETIMEDOUT;
-
- outb(MCSR_NV_ENABLE | MCSR_NV_LOAD_LOW_ADDR,
- iobase + AMCC_OP_REG_MCSR_NVCMD);
- outb(address & 0xff, iobase + AMCC_OP_REG_MCSR_NVDATA);
- outb(MCSR_NV_ENABLE | MCSR_NV_LOAD_HIGH_ADDR,
- iobase + AMCC_OP_REG_MCSR_NVCMD);
- outb((address >> 8) & 0xff, iobase + AMCC_OP_REG_MCSR_NVDATA);
- outb(MCSR_NV_ENABLE | MCSR_NV_READ, iobase + AMCC_OP_REG_MCSR_NVCMD);
-
- if (wait_for_nvram_ready(iobase) < 0)
- return -ETIMEDOUT;
-
- *data = inb(iobase + AMCC_OP_REG_MCSR_NVDATA);
-
- return 0;
-}
+ unsigned int chan = CR_CHAN(insn->chanspec);
+ int ret;
+ int i;
-static int eeprom_read_insn(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data)
-{
- uint8_t nvram_data;
- int retval;
+ for (i = 0; i < insn->n; i++) {
+ /* make sure eeprom is ready */
+ ret = comedi_timeout(dev, s, insn, cb_pcidas_eeprom_ready, 0);
+ if (ret)
+ return ret;
- retval = nvram_read(dev, CR_CHAN(insn->chanspec), &nvram_data);
- if (retval < 0)
- return retval;
+ /* set address (chan) and read operation */
+ outb(MCSR_NV_ENABLE | MCSR_NV_LOAD_LOW_ADDR,
+ devpriv->amcc + AMCC_OP_REG_MCSR_NVCMD);
+ outb(chan & 0xff, devpriv->amcc + AMCC_OP_REG_MCSR_NVDATA);
+ outb(MCSR_NV_ENABLE | MCSR_NV_LOAD_HIGH_ADDR,
+ devpriv->amcc + AMCC_OP_REG_MCSR_NVCMD);
+ outb((chan >> 8) & 0xff,
+ devpriv->amcc + AMCC_OP_REG_MCSR_NVDATA);
+ outb(MCSR_NV_ENABLE | MCSR_NV_READ,
+ devpriv->amcc + AMCC_OP_REG_MCSR_NVCMD);
+
+ /* wait for data to be returned */
+ ret = comedi_timeout(dev, s, insn, cb_pcidas_eeprom_ready, 0);
+ if (ret)
+ return ret;
- data[0] = nvram_data;
+ data[i] = inb(devpriv->amcc + AMCC_OP_REG_MCSR_NVDATA);
+ }
- return 1;
+ return insn->n;
}
-static void write_calibration_bitstream(struct comedi_device *dev,
- unsigned int register_bits,
- unsigned int bitstream,
- unsigned int bitstream_length)
+static void cb_pcidas_calib_write(struct comedi_device *dev,
+ unsigned int val, unsigned int len,
+ bool trimpot)
{
struct cb_pcidas_private *devpriv = dev->private;
- static const int write_delay = 1;
+ unsigned int calib_bits;
unsigned int bit;
- for (bit = 1 << (bitstream_length - 1); bit; bit >>= 1) {
- if (bitstream & bit)
- register_bits |= SERIAL_DATA_IN_BIT;
+ calib_bits = PCIDAS_CALIB_EN | PCIDAS_CALIB_SRC(devpriv->calib_src);
+ if (trimpot) {
+ /* select trimpot */
+ calib_bits |= PCIDAS_CALIB_TRIM_SEL;
+ outw(calib_bits, devpriv->pcibar1 + PCIDAS_CALIB_REG);
+ }
+
+ /* write bitstream to calibration device */
+ for (bit = 1 << (len - 1); bit; bit >>= 1) {
+ if (val & bit)
+ calib_bits |= PCIDAS_CALIB_DATA;
else
- register_bits &= ~SERIAL_DATA_IN_BIT;
- udelay(write_delay);
- outw(register_bits, devpriv->control_status + CALIBRATION_REG);
+ calib_bits &= ~PCIDAS_CALIB_DATA;
+ udelay(1);
+ outw(calib_bits, devpriv->pcibar1 + PCIDAS_CALIB_REG);
}
-}
+ udelay(1);
-static void caldac_8800_write(struct comedi_device *dev,
- unsigned int chan, uint8_t val)
-{
- struct cb_pcidas_private *devpriv = dev->private;
- static const int bitstream_length = 11;
- unsigned int bitstream = ((chan & 0x7) << 8) | val;
- static const int caldac_8800_udelay = 1;
-
- write_calibration_bitstream(dev, cal_enable_bits(dev), bitstream,
- bitstream_length);
-
- udelay(caldac_8800_udelay);
- outw(cal_enable_bits(dev) | SELECT_8800_BIT,
- devpriv->control_status + CALIBRATION_REG);
- udelay(caldac_8800_udelay);
- outw(cal_enable_bits(dev), devpriv->control_status + CALIBRATION_REG);
+ calib_bits = PCIDAS_CALIB_EN | PCIDAS_CALIB_SRC(devpriv->calib_src);
+
+ if (!trimpot) {
+ /* select caldac */
+ outw(calib_bits | PCIDAS_CALIB_8800_SEL,
+ devpriv->pcibar1 + PCIDAS_CALIB_REG);
+ udelay(1);
+ }
+
+ /* latch value to trimpot/caldac */
+ outw(calib_bits, devpriv->pcibar1 + PCIDAS_CALIB_REG);
}
static int cb_pcidas_caldac_insn_write(struct comedi_device *dev,
@@ -611,7 +576,9 @@ static int cb_pcidas_caldac_insn_write(struct comedi_device *dev,
unsigned int val = data[insn->n - 1];
if (s->readback[chan] != val) {
- caldac_8800_write(dev, chan, val);
+ /* write 11-bit channel/value to caldac */
+ cb_pcidas_calib_write(dev, (chan << 8) | val, 11,
+ false);
s->readback[chan] = val;
}
}
@@ -619,21 +586,19 @@ static int cb_pcidas_caldac_insn_write(struct comedi_device *dev,
return insn->n;
}
-/* 1602/16 pregain offset */
-static void dac08_write(struct comedi_device *dev, unsigned int value)
+static void cb_pcidas_dac08_write(struct comedi_device *dev, unsigned int val)
{
struct cb_pcidas_private *devpriv = dev->private;
- value &= 0xff;
- value |= cal_enable_bits(dev);
+ val |= PCIDAS_CALIB_EN | PCIDAS_CALIB_SRC(devpriv->calib_src);
/* latch the new value into the caldac */
- outw(value, devpriv->control_status + CALIBRATION_REG);
+ outw(val, devpriv->pcibar1 + PCIDAS_CALIB_REG);
udelay(1);
- outw(value | SELECT_DAC08_BIT,
- devpriv->control_status + CALIBRATION_REG);
+ outw(val | PCIDAS_CALIB_DAC08_SEL,
+ devpriv->pcibar1 + PCIDAS_CALIB_REG);
udelay(1);
- outw(value, devpriv->control_status + CALIBRATION_REG);
+ outw(val, devpriv->pcibar1 + PCIDAS_CALIB_REG);
udelay(1);
}
@@ -648,7 +613,7 @@ static int cb_pcidas_dac08_insn_write(struct comedi_device *dev,
unsigned int val = data[insn->n - 1];
if (s->readback[chan] != val) {
- dac08_write(dev, val);
+ cb_pcidas_dac08_write(dev, val);
s->readback[chan] = val;
}
}
@@ -656,67 +621,17 @@ static int cb_pcidas_dac08_insn_write(struct comedi_device *dev,
return insn->n;
}
-static int trimpot_7376_write(struct comedi_device *dev, uint8_t value)
-{
- struct cb_pcidas_private *devpriv = dev->private;
- static const int bitstream_length = 7;
- unsigned int bitstream = value & 0x7f;
- unsigned int register_bits;
- static const int ad7376_udelay = 1;
-
- register_bits = cal_enable_bits(dev) | SELECT_TRIMPOT_BIT;
- udelay(ad7376_udelay);
- outw(register_bits, devpriv->control_status + CALIBRATION_REG);
-
- write_calibration_bitstream(dev, register_bits, bitstream,
- bitstream_length);
-
- udelay(ad7376_udelay);
- outw(cal_enable_bits(dev), devpriv->control_status + CALIBRATION_REG);
-
- return 0;
-}
-
-/* For 1602/16 only
- * ch 0 : adc gain
- * ch 1 : adc postgain offset */
-static int trimpot_8402_write(struct comedi_device *dev, unsigned int channel,
- uint8_t value)
-{
- struct cb_pcidas_private *devpriv = dev->private;
- static const int bitstream_length = 10;
- unsigned int bitstream = ((channel & 0x3) << 8) | (value & 0xff);
- unsigned int register_bits;
- static const int ad8402_udelay = 1;
-
- register_bits = cal_enable_bits(dev) | SELECT_TRIMPOT_BIT;
- udelay(ad8402_udelay);
- outw(register_bits, devpriv->control_status + CALIBRATION_REG);
-
- write_calibration_bitstream(dev, register_bits, bitstream,
- bitstream_length);
-
- udelay(ad8402_udelay);
- outw(cal_enable_bits(dev), devpriv->control_status + CALIBRATION_REG);
-
- return 0;
-}
-
static void cb_pcidas_trimpot_write(struct comedi_device *dev,
unsigned int chan, unsigned int val)
{
const struct cb_pcidas_board *board = dev->board_ptr;
- switch (board->trimpot) {
- case AD7376:
- trimpot_7376_write(dev, val);
- break;
- case AD8402:
- trimpot_8402_write(dev, chan, val);
- break;
- default:
- dev_err(dev->class_dev, "driver bug?\n");
- break;
+ if (board->has_ad8402) {
+ /* write 10-bit channel/value to AD8402 trimpot */
+ cb_pcidas_calib_write(dev, (chan << 8) | val, 10, true);
+ } else {
+ /* write 7-bit value to AD7376 trimpot */
+ cb_pcidas_calib_write(dev, val, 7, true);
}
}
@@ -883,32 +798,33 @@ static int cb_pcidas_ai_cmd(struct comedi_device *dev,
struct cb_pcidas_private *devpriv = dev->private;
struct comedi_async *async = s->async;
struct comedi_cmd *cmd = &async->cmd;
+ unsigned int range0 = CR_RANGE(cmd->chanlist[0]);
unsigned int bits;
unsigned long flags;
- /* make sure CAL_EN_BIT is disabled */
- outw(0, devpriv->control_status + CALIBRATION_REG);
+ /* make sure PCIDAS_CALIB_EN is disabled */
+ outw(0, devpriv->pcibar1 + PCIDAS_CALIB_REG);
/* initialize before settings pacer source and count values */
- outw(0, devpriv->control_status + TRIG_CONTSTAT);
+ outw(PCIDAS_TRIG_SEL_NONE, devpriv->pcibar1 + PCIDAS_TRIG_REG);
/* clear fifo */
- outw(0, devpriv->adc_fifo + ADCFIFOCLR);
+ outw(0, devpriv->pcibar2 + PCIDAS_AI_FIFO_CLR_REG);
/* set mux limits, gain and pacer source */
- bits = BEGIN_SCAN(CR_CHAN(cmd->chanlist[0])) |
- END_SCAN(CR_CHAN(cmd->chanlist[cmd->chanlist_len - 1])) |
- GAIN_BITS(CR_RANGE(cmd->chanlist[0]));
+ bits = PCIDAS_AI_FIRST(CR_CHAN(cmd->chanlist[0])) |
+ PCIDAS_AI_LAST(CR_CHAN(cmd->chanlist[cmd->chanlist_len - 1])) |
+ PCIDAS_AI_GAIN(range0);
/* set unipolar/bipolar */
- if (CR_RANGE(cmd->chanlist[0]) & IS_UNIPOLAR)
- bits |= UNIP;
+ if (comedi_range_is_unipolar(s, range0))
+ bits |= PCIDAS_AI_UNIP;
/* set singleended/differential */
if (CR_AREF(cmd->chanlist[0]) != AREF_DIFF)
- bits |= SE;
+ bits |= PCIDAS_AI_SE;
/* set pacer source */
if (cmd->convert_src == TRIG_EXT || cmd->scan_begin_src == TRIG_EXT)
- bits |= PACER_EXT_RISE;
+ bits |= PCIDAS_AI_PACER_EXTP;
else
- bits |= PACER_INT;
- outw(bits, devpriv->control_status + ADCMUX_CONT);
+ bits |= PCIDAS_AI_PACER_INT;
+ outw(bits, devpriv->pcibar1 + PCIDAS_AI_REG);
/* load counters */
if (cmd->scan_begin_src == TRIG_TIMER ||
@@ -919,42 +835,43 @@ static int cb_pcidas_ai_cmd(struct comedi_device *dev,
/* enable interrupts */
spin_lock_irqsave(&dev->spinlock, flags);
- devpriv->adc_fifo_bits |= INTE;
- devpriv->adc_fifo_bits &= ~INT_MASK;
+ devpriv->ctrl |= PCIDAS_CTRL_INTE;
+ devpriv->ctrl &= ~PCIDAS_CTRL_INT_MASK;
if (cmd->flags & CMDF_WAKE_EOS) {
if (cmd->convert_src == TRIG_NOW && cmd->chanlist_len > 1) {
/* interrupt end of burst */
- devpriv->adc_fifo_bits |= INT_EOS;
+ devpriv->ctrl |= PCIDAS_CTRL_INT_EOS;
} else {
/* interrupt fifo not empty */
- devpriv->adc_fifo_bits |= INT_FNE;
+ devpriv->ctrl |= PCIDAS_CTRL_INT_FNE;
}
} else {
/* interrupt fifo half full */
- devpriv->adc_fifo_bits |= INT_FHF;
+ devpriv->ctrl |= PCIDAS_CTRL_INT_FHF;
}
/* enable (and clear) interrupts */
- outw(devpriv->adc_fifo_bits | EOAI | INT | LADFUL,
- devpriv->control_status + INT_ADCFIFO);
+ outw(devpriv->ctrl |
+ PCIDAS_CTRL_EOAI | PCIDAS_CTRL_INT_CLR | PCIDAS_CTRL_LADFUL,
+ devpriv->pcibar1 + PCIDAS_CTRL_REG);
spin_unlock_irqrestore(&dev->spinlock, flags);
/* set start trigger and burst mode */
bits = 0;
if (cmd->start_src == TRIG_NOW) {
- bits |= SW_TRIGGER;
+ bits |= PCIDAS_TRIG_SEL_SW;
} else { /* TRIG_EXT */
- bits |= EXT_TRIGGER | TGEN | XTRCL;
+ bits |= PCIDAS_TRIG_SEL_EXT | PCIDAS_TRIG_EN | PCIDAS_TRIG_CLR;
if (board->is_1602) {
if (cmd->start_arg & CR_INVERT)
- bits |= TGPOL;
+ bits |= PCIDAS_TRIG_POL;
if (cmd->start_arg & CR_EDGE)
- bits |= TGSEL;
+ bits |= PCIDAS_TRIG_MODE;
}
}
if (cmd->convert_src == TRIG_NOW && cmd->chanlist_len > 1)
- bits |= BURSTE;
- outw(bits, devpriv->control_status + TRIG_CONTSTAT);
+ bits |= PCIDAS_TRIG_BURSTE;
+ outw(bits, devpriv->pcibar1 + PCIDAS_TRIG_REG);
return 0;
}
@@ -1051,23 +968,21 @@ static int cb_pcidas_ao_cmdtest(struct comedi_device *dev,
return 0;
}
-/* cancel analog input command */
-static int cb_pcidas_cancel(struct comedi_device *dev,
- struct comedi_subdevice *s)
+static int cb_pcidas_ai_cancel(struct comedi_device *dev,
+ struct comedi_subdevice *s)
{
struct cb_pcidas_private *devpriv = dev->private;
unsigned long flags;
spin_lock_irqsave(&dev->spinlock, flags);
/* disable interrupts */
- devpriv->adc_fifo_bits &= ~INTE & ~EOAIE;
- outw(devpriv->adc_fifo_bits, devpriv->control_status + INT_ADCFIFO);
+ devpriv->ctrl &= ~(PCIDAS_CTRL_INTE | PCIDAS_CTRL_EOAIE);
+ outw(devpriv->ctrl, devpriv->pcibar1 + PCIDAS_CTRL_REG);
spin_unlock_irqrestore(&dev->spinlock, flags);
/* disable start trigger source and burst mode */
- outw(0, devpriv->control_status + TRIG_CONTSTAT);
- /* software pacer source */
- outw(0, devpriv->control_status + ADCMUX_CONT);
+ outw(PCIDAS_TRIG_SEL_NONE, devpriv->pcibar1 + PCIDAS_TRIG_REG);
+ outw(PCIDAS_AI_PACER_SW, devpriv->pcibar1 + PCIDAS_AI_REG);
return 0;
}
@@ -1083,7 +998,8 @@ static void cb_pcidas_ao_load_fifo(struct comedi_device *dev,
nbytes = comedi_buf_read_samples(s, devpriv->ao_buffer, nsamples);
nsamples = comedi_bytes_to_samples(s, nbytes);
- outsw(devpriv->ao_registers + DACDATA, devpriv->ao_buffer, nsamples);
+ outsw(devpriv->pcibar4 + PCIDAS_AO_FIFO_REG,
+ devpriv->ao_buffer, nsamples);
}
static int cb_pcidas_ao_inttrig(struct comedi_device *dev,
@@ -1103,15 +1019,15 @@ static int cb_pcidas_ao_inttrig(struct comedi_device *dev,
/* enable dac half-full and empty interrupts */
spin_lock_irqsave(&dev->spinlock, flags);
- devpriv->adc_fifo_bits |= DAEMIE | DAHFIE;
+ devpriv->ctrl |= PCIDAS_CTRL_DAEMIE | PCIDAS_CTRL_DAHFIE;
/* enable and clear interrupts */
- outw(devpriv->adc_fifo_bits | DAEMI | DAHFI,
- devpriv->control_status + INT_ADCFIFO);
+ outw(devpriv->ctrl | PCIDAS_CTRL_DAEMI | PCIDAS_CTRL_DAHFI,
+ devpriv->pcibar1 + PCIDAS_CTRL_REG);
/* start dac */
- devpriv->ao_control_bits |= DAC_START | DACEN | DAC_EMPTY;
- outw(devpriv->ao_control_bits, devpriv->control_status + DAC_CSR);
+ devpriv->ao_ctrl |= PCIDAS_AO_START | PCIDAS_AO_DACEN | PCIDAS_AO_EMPTY;
+ outw(devpriv->ao_ctrl, devpriv->pcibar1 + PCIDAS_AO_REG);
spin_unlock_irqrestore(&dev->spinlock, flags);
@@ -1132,21 +1048,21 @@ static int cb_pcidas_ao_cmd(struct comedi_device *dev,
/* set channel limits, gain */
spin_lock_irqsave(&dev->spinlock, flags);
for (i = 0; i < cmd->chanlist_len; i++) {
+ unsigned int chan = CR_CHAN(cmd->chanlist[i]);
+ unsigned int range = CR_RANGE(cmd->chanlist[i]);
+
/* enable channel */
- devpriv->ao_control_bits |=
- DAC_CHAN_EN(CR_CHAN(cmd->chanlist[i]));
+ devpriv->ao_ctrl |= PCIDAS_AO_CHAN_EN(chan);
/* set range */
- devpriv->ao_control_bits |= DAC_RANGE(CR_CHAN(cmd->chanlist[i]),
- CR_RANGE(cmd->
- chanlist[i]));
+ devpriv->ao_ctrl |= PCIDAS_AO_RANGE(chan, range);
}
/* disable analog out before settings pacer source and count values */
- outw(devpriv->ao_control_bits, devpriv->control_status + DAC_CSR);
+ outw(devpriv->ao_ctrl, devpriv->pcibar1 + PCIDAS_AO_REG);
spin_unlock_irqrestore(&dev->spinlock, flags);
/* clear fifo */
- outw(0, devpriv->ao_registers + DACFIFOCLR);
+ outw(0, devpriv->pcibar4 + PCIDAS_AO_FIFO_CLR_REG);
/* load counters */
if (cmd->scan_begin_src == TRIG_TIMER) {
@@ -1158,10 +1074,10 @@ static int cb_pcidas_ao_cmd(struct comedi_device *dev,
spin_lock_irqsave(&dev->spinlock, flags);
switch (cmd->scan_begin_src) {
case TRIG_TIMER:
- devpriv->ao_control_bits |= DAC_PACER_INT;
+ devpriv->ao_ctrl |= PCIDAS_AO_PACER_INT;
break;
case TRIG_EXT:
- devpriv->ao_control_bits |= DAC_PACER_EXT_RISE;
+ devpriv->ao_ctrl |= PCIDAS_AO_PACER_EXTP;
break;
default:
spin_unlock_irqrestore(&dev->spinlock, flags);
@@ -1175,7 +1091,6 @@ static int cb_pcidas_ao_cmd(struct comedi_device *dev,
return 0;
}
-/* cancel analog output command */
static int cb_pcidas_ao_cancel(struct comedi_device *dev,
struct comedi_subdevice *s)
{
@@ -1184,33 +1099,31 @@ static int cb_pcidas_ao_cancel(struct comedi_device *dev,
spin_lock_irqsave(&dev->spinlock, flags);
/* disable interrupts */
- devpriv->adc_fifo_bits &= ~DAHFIE & ~DAEMIE;
- outw(devpriv->adc_fifo_bits, devpriv->control_status + INT_ADCFIFO);
+ devpriv->ctrl &= ~(PCIDAS_CTRL_DAHFIE | PCIDAS_CTRL_DAEMIE);
+ outw(devpriv->ctrl, devpriv->pcibar1 + PCIDAS_CTRL_REG);
/* disable output */
- devpriv->ao_control_bits &= ~DACEN & ~DAC_PACER_MASK;
- outw(devpriv->ao_control_bits, devpriv->control_status + DAC_CSR);
+ devpriv->ao_ctrl &= ~(PCIDAS_AO_DACEN | PCIDAS_AO_PACER_MASK);
+ outw(devpriv->ao_ctrl, devpriv->pcibar1 + PCIDAS_AO_REG);
spin_unlock_irqrestore(&dev->spinlock, flags);
return 0;
}
-static void handle_ao_interrupt(struct comedi_device *dev, unsigned int status)
+static unsigned int cb_pcidas_ao_interrupt(struct comedi_device *dev,
+ unsigned int status)
{
const struct cb_pcidas_board *board = dev->board_ptr;
struct cb_pcidas_private *devpriv = dev->private;
struct comedi_subdevice *s = dev->write_subdev;
struct comedi_async *async = s->async;
struct comedi_cmd *cmd = &async->cmd;
- unsigned long flags;
+ unsigned int irq_clr = 0;
- if (status & DAEMI) {
- /* clear dac empty interrupt latch */
- spin_lock_irqsave(&dev->spinlock, flags);
- outw(devpriv->adc_fifo_bits | DAEMI,
- devpriv->control_status + INT_ADCFIFO);
- spin_unlock_irqrestore(&dev->spinlock, flags);
- if (inw(devpriv->ao_registers + DAC_CSR) & DAC_EMPTY) {
+ if (status & PCIDAS_CTRL_DAEMI) {
+ irq_clr |= PCIDAS_CTRL_DAEMI;
+
+ if (inw(devpriv->pcibar4 + PCIDAS_AO_REG) & PCIDAS_AO_EMPTY) {
if (cmd->stop_src == TRIG_COUNT &&
async->scans_done >= cmd->stop_arg) {
async->events |= COMEDI_CB_EOA;
@@ -1219,83 +1132,55 @@ static void handle_ao_interrupt(struct comedi_device *dev, unsigned int status)
async->events |= COMEDI_CB_ERROR;
}
}
- } else if (status & DAHFI) {
- cb_pcidas_ao_load_fifo(dev, s, board->fifo_size / 2);
+ } else if (status & PCIDAS_CTRL_DAHFI) {
+ irq_clr |= PCIDAS_CTRL_DAHFI;
- /* clear half-full interrupt latch */
- spin_lock_irqsave(&dev->spinlock, flags);
- outw(devpriv->adc_fifo_bits | DAHFI,
- devpriv->control_status + INT_ADCFIFO);
- spin_unlock_irqrestore(&dev->spinlock, flags);
+ cb_pcidas_ao_load_fifo(dev, s, board->fifo_size / 2);
}
comedi_handle_events(dev, s);
+
+ return irq_clr;
}
-static irqreturn_t cb_pcidas_interrupt(int irq, void *d)
+static unsigned int cb_pcidas_ai_interrupt(struct comedi_device *dev,
+ unsigned int status)
{
- struct comedi_device *dev = (struct comedi_device *)d;
const struct cb_pcidas_board *board = dev->board_ptr;
struct cb_pcidas_private *devpriv = dev->private;
struct comedi_subdevice *s = dev->read_subdev;
- struct comedi_async *async;
- struct comedi_cmd *cmd;
- int status, s5933_status;
- int half_fifo = board->fifo_size / 2;
- unsigned int num_samples, i;
- static const int timeout = 10000;
- unsigned long flags;
-
- if (!dev->attached)
- return IRQ_NONE;
-
- async = s->async;
- cmd = &async->cmd;
+ struct comedi_async *async = s->async;
+ struct comedi_cmd *cmd = &async->cmd;
+ unsigned int irq_clr = 0;
- s5933_status = inl(devpriv->s5933_config + AMCC_OP_REG_INTCSR);
+ if (status & PCIDAS_CTRL_ADHFI) {
+ unsigned int num_samples;
- if ((INTCSR_INTR_ASSERTED & s5933_status) == 0)
- return IRQ_NONE;
+ irq_clr |= PCIDAS_CTRL_INT_CLR;
- /* make sure mailbox 4 is empty */
- inl_p(devpriv->s5933_config + AMCC_OP_REG_IMB4);
- /* clear interrupt on amcc s5933 */
- outl(devpriv->s5933_intcsr_bits | INTCSR_INBOX_INTR_STATUS,
- devpriv->s5933_config + AMCC_OP_REG_INTCSR);
-
- status = inw(devpriv->control_status + INT_ADCFIFO);
-
- /* check for analog output interrupt */
- if (status & (DAHFI | DAEMI))
- handle_ao_interrupt(dev, status);
- /* check for analog input interrupts */
- /* if fifo half-full */
- if (status & ADHFI) {
- /* read data */
- num_samples = comedi_nsamples_left(s, half_fifo);
- insw(devpriv->adc_fifo + ADCDATA, devpriv->ai_buffer,
- num_samples);
+ /* FIFO is half-full - read data */
+ num_samples = comedi_nsamples_left(s, board->fifo_size / 2);
+ insw(devpriv->pcibar2 + PCIDAS_AI_DATA_REG,
+ devpriv->ai_buffer, num_samples);
comedi_buf_write_samples(s, devpriv->ai_buffer, num_samples);
if (cmd->stop_src == TRIG_COUNT &&
async->scans_done >= cmd->stop_arg)
async->events |= COMEDI_CB_EOA;
+ } else if (status & (PCIDAS_CTRL_ADNEI | PCIDAS_CTRL_EOBI)) {
+ unsigned int i;
- /* clear half-full interrupt latch */
- spin_lock_irqsave(&dev->spinlock, flags);
- outw(devpriv->adc_fifo_bits | INT,
- devpriv->control_status + INT_ADCFIFO);
- spin_unlock_irqrestore(&dev->spinlock, flags);
- /* else if fifo not empty */
- } else if (status & (ADNEI | EOBI)) {
- for (i = 0; i < timeout; i++) {
+ irq_clr |= PCIDAS_CTRL_INT_CLR;
+
+ /* FIFO is not empty - read data until empty or timeoout */
+ for (i = 0; i < 10000; i++) {
unsigned short val;
/* break if fifo is empty */
- if ((ADNE & inw(devpriv->control_status +
- INT_ADCFIFO)) == 0)
+ if ((inw(devpriv->pcibar1 + PCIDAS_CTRL_REG) &
+ PCIDAS_CTRL_ADNE) == 0)
break;
- val = inw(devpriv->adc_fifo);
+ val = inw(devpriv->pcibar2 + PCIDAS_AI_DATA_REG);
comedi_buf_write_samples(s, &val, 1);
if (cmd->stop_src == TRIG_COUNT &&
@@ -1304,33 +1189,67 @@ static irqreturn_t cb_pcidas_interrupt(int irq, void *d)
break;
}
}
- /* clear not-empty interrupt latch */
- spin_lock_irqsave(&dev->spinlock, flags);
- outw(devpriv->adc_fifo_bits | INT,
- devpriv->control_status + INT_ADCFIFO);
- spin_unlock_irqrestore(&dev->spinlock, flags);
- } else if (status & EOAI) {
+ } else if (status & PCIDAS_CTRL_EOAI) {
+ irq_clr |= PCIDAS_CTRL_EOAI;
+
dev_err(dev->class_dev,
"bug! encountered end of acquisition interrupt?\n");
- /* clear EOA interrupt latch */
- spin_lock_irqsave(&dev->spinlock, flags);
- outw(devpriv->adc_fifo_bits | EOAI,
- devpriv->control_status + INT_ADCFIFO);
- spin_unlock_irqrestore(&dev->spinlock, flags);
}
+
/* check for fifo overflow */
- if (status & LADFUL) {
+ if (status & PCIDAS_CTRL_LADFUL) {
+ irq_clr |= PCIDAS_CTRL_LADFUL;
+
dev_err(dev->class_dev, "fifo overflow\n");
- /* clear overflow interrupt latch */
- spin_lock_irqsave(&dev->spinlock, flags);
- outw(devpriv->adc_fifo_bits | LADFUL,
- devpriv->control_status + INT_ADCFIFO);
- spin_unlock_irqrestore(&dev->spinlock, flags);
async->events |= COMEDI_CB_ERROR;
}
comedi_handle_events(dev, s);
+ return irq_clr;
+}
+
+static irqreturn_t cb_pcidas_interrupt(int irq, void *d)
+{
+ struct comedi_device *dev = d;
+ struct cb_pcidas_private *devpriv = dev->private;
+ unsigned int irq_clr = 0;
+ unsigned int amcc_status;
+ unsigned int status;
+
+ if (!dev->attached)
+ return IRQ_NONE;
+
+ amcc_status = inl(devpriv->amcc + AMCC_OP_REG_INTCSR);
+
+ if ((INTCSR_INTR_ASSERTED & amcc_status) == 0)
+ return IRQ_NONE;
+
+ /* make sure mailbox 4 is empty */
+ inl_p(devpriv->amcc + AMCC_OP_REG_IMB4);
+ /* clear interrupt on amcc s5933 */
+ outl(devpriv->amcc_intcsr | INTCSR_INBOX_INTR_STATUS,
+ devpriv->amcc + AMCC_OP_REG_INTCSR);
+
+ status = inw(devpriv->pcibar1 + PCIDAS_CTRL_REG);
+
+ /* handle analog output interrupts */
+ if (status & PCIDAS_CTRL_AO_INT)
+ irq_clr |= cb_pcidas_ao_interrupt(dev, status);
+
+ /* handle analog input interrupts */
+ if (status & PCIDAS_CTRL_AI_INT)
+ irq_clr |= cb_pcidas_ai_interrupt(dev, status);
+
+ if (irq_clr) {
+ unsigned long flags;
+
+ spin_lock_irqsave(&dev->spinlock, flags);
+ outw(devpriv->ctrl | irq_clr,
+ devpriv->pcibar1 + PCIDAS_CTRL_REG);
+ spin_unlock_irqrestore(&dev->spinlock, flags);
+ }
+
return IRQ_HANDLED;
}
@@ -1359,16 +1278,16 @@ static int cb_pcidas_auto_attach(struct comedi_device *dev,
if (ret)
return ret;
- devpriv->s5933_config = pci_resource_start(pcidev, 0);
- devpriv->control_status = pci_resource_start(pcidev, 1);
- devpriv->adc_fifo = pci_resource_start(pcidev, 2);
+ devpriv->amcc = pci_resource_start(pcidev, 0);
+ devpriv->pcibar1 = pci_resource_start(pcidev, 1);
+ devpriv->pcibar2 = pci_resource_start(pcidev, 2);
dev->iobase = pci_resource_start(pcidev, 3);
- if (board->ao_nchan)
- devpriv->ao_registers = pci_resource_start(pcidev, 4);
+ if (board->has_ao)
+ devpriv->pcibar4 = pci_resource_start(pcidev, 4);
/* disable and clear interrupts on amcc s5933 */
outl(INTCSR_INBOX_INTR_STATUS,
- devpriv->s5933_config + AMCC_OP_REG_INTCSR);
+ devpriv->amcc + AMCC_OP_REG_INTCSR);
ret = request_irq(pcidev->irq, cb_pcidas_interrupt, IRQF_SHARED,
dev->board_name, dev);
@@ -1379,12 +1298,12 @@ static int cb_pcidas_auto_attach(struct comedi_device *dev,
}
dev->irq = pcidev->irq;
- dev->pacer = comedi_8254_init(dev->iobase + ADC8254,
+ dev->pacer = comedi_8254_init(dev->iobase + PCIDAS_AI_8254_BASE,
I8254_OSC_BASE_10MHZ, I8254_IO8, 0);
if (!dev->pacer)
return -ENOMEM;
- devpriv->ao_pacer = comedi_8254_init(dev->iobase + DAC8254,
+ devpriv->ao_pacer = comedi_8254_init(dev->iobase + PCIDAS_AO_8254_BASE,
I8254_OSC_BASE_10MHZ,
I8254_IO8, 0);
if (!devpriv->ao_pacer)
@@ -1394,97 +1313,104 @@ static int cb_pcidas_auto_attach(struct comedi_device *dev,
if (ret)
return ret;
+ /* Analog Input subdevice */
s = &dev->subdevices[0];
- /* analog input subdevice */
- dev->read_subdev = s;
- s->type = COMEDI_SUBD_AI;
- s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_DIFF | SDF_CMD_READ;
- /* WARNING: Number of inputs in differential mode is ignored */
- s->n_chan = board->ai_nchan;
- s->len_chanlist = board->ai_nchan;
- s->maxdata = (1 << board->ai_bits) - 1;
- s->range_table = board->ranges;
- s->insn_read = cb_pcidas_ai_rinsn;
- s->insn_config = ai_config_insn;
- s->do_cmd = cb_pcidas_ai_cmd;
- s->do_cmdtest = cb_pcidas_ai_cmdtest;
- s->cancel = cb_pcidas_cancel;
-
- /* analog output subdevice */
+ s->type = COMEDI_SUBD_AI;
+ s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_DIFF;
+ s->n_chan = 16;
+ s->maxdata = board->is_16bit ? 0xffff : 0x0fff;
+ s->range_table = board->use_alt_range ? &cb_pcidas_alt_ranges
+ : &cb_pcidas_ranges;
+ s->insn_read = cb_pcidas_ai_insn_read;
+ s->insn_config = cb_pcidas_ai_insn_config;
+ if (dev->irq) {
+ dev->read_subdev = s;
+ s->subdev_flags |= SDF_CMD_READ;
+ s->len_chanlist = s->n_chan;
+ s->do_cmd = cb_pcidas_ai_cmd;
+ s->do_cmdtest = cb_pcidas_ai_cmdtest;
+ s->cancel = cb_pcidas_ai_cancel;
+ }
+
+ /* Analog Output subdevice */
s = &dev->subdevices[1];
- if (board->ao_nchan) {
- s->type = COMEDI_SUBD_AO;
- s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_GROUND;
- s->n_chan = board->ao_nchan;
- /*
- * analog out resolution is the same as
- * analog input resolution, so use ai_bits
- */
- s->maxdata = (1 << board->ai_bits) - 1;
- s->range_table = &cb_pcidas_ao_ranges;
- /* default to no fifo (*insn_write) */
- s->insn_write = cb_pcidas_ao_nofifo_winsn;
+ if (board->has_ao) {
+ s->type = COMEDI_SUBD_AO;
+ s->subdev_flags = SDF_WRITABLE | SDF_GROUND;
+ s->n_chan = 2;
+ s->maxdata = board->is_16bit ? 0xffff : 0x0fff;
+ s->range_table = &cb_pcidas_ao_ranges;
+ s->insn_write = (board->has_ao_fifo)
+ ? cb_pcidas_ao_fifo_insn_write
+ : cb_pcidas_ao_nofifo_insn_write;
ret = comedi_alloc_subdev_readback(s);
if (ret)
return ret;
- if (board->has_ao_fifo) {
+ if (dev->irq && board->has_ao_fifo) {
dev->write_subdev = s;
- s->subdev_flags |= SDF_CMD_WRITE;
- /* use fifo (*insn_write) instead */
- s->insn_write = cb_pcidas_ao_fifo_winsn;
- s->do_cmdtest = cb_pcidas_ao_cmdtest;
- s->do_cmd = cb_pcidas_ao_cmd;
- s->cancel = cb_pcidas_ao_cancel;
+ s->subdev_flags |= SDF_CMD_WRITE;
+ s->do_cmdtest = cb_pcidas_ao_cmdtest;
+ s->do_cmd = cb_pcidas_ao_cmd;
+ s->cancel = cb_pcidas_ao_cancel;
}
} else {
- s->type = COMEDI_SUBD_UNUSED;
+ s->type = COMEDI_SUBD_UNUSED;
}
/* 8255 */
s = &dev->subdevices[2];
- ret = subdev_8255_init(dev, s, NULL, DIO_8255);
+ ret = subdev_8255_init(dev, s, NULL, PCIDAS_8255_BASE);
if (ret)
return ret;
- /* serial EEPROM, */
+ /* Memory subdevice - serial EEPROM */
s = &dev->subdevices[3];
- s->type = COMEDI_SUBD_MEMORY;
- s->subdev_flags = SDF_READABLE | SDF_INTERNAL;
- s->n_chan = 256;
- s->maxdata = 0xff;
- s->insn_read = eeprom_read_insn;
+ s->type = COMEDI_SUBD_MEMORY;
+ s->subdev_flags = SDF_READABLE | SDF_INTERNAL;
+ s->n_chan = 256;
+ s->maxdata = 0xff;
+ s->insn_read = cb_pcidas_eeprom_insn_read;
- /* 8800 caldac */
+ /* Calibration subdevice - 8800 caldac */
s = &dev->subdevices[4];
- s->type = COMEDI_SUBD_CALIB;
- s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_INTERNAL;
- s->n_chan = NUM_CHANNELS_8800;
- s->maxdata = 0xff;
- s->insn_write = cb_pcidas_caldac_insn_write;
+ s->type = COMEDI_SUBD_CALIB;
+ s->subdev_flags = SDF_WRITABLE | SDF_INTERNAL;
+ s->n_chan = 8;
+ s->maxdata = 0xff;
+ s->insn_write = cb_pcidas_caldac_insn_write;
ret = comedi_alloc_subdev_readback(s);
if (ret)
return ret;
for (i = 0; i < s->n_chan; i++) {
- caldac_8800_write(dev, i, s->maxdata / 2);
- s->readback[i] = s->maxdata / 2;
+ unsigned int val = s->maxdata / 2;
+
+ /* write 11-bit channel/value to caldac */
+ cb_pcidas_calib_write(dev, (i << 8) | val, 11, false);
+ s->readback[i] = val;
}
- /* trim potentiometer */
+ /* Calibration subdevice - trim potentiometer */
s = &dev->subdevices[5];
- s->type = COMEDI_SUBD_CALIB;
- s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_INTERNAL;
- if (board->trimpot == AD7376) {
- s->n_chan = NUM_CHANNELS_7376;
- s->maxdata = 0x7f;
+ s->type = COMEDI_SUBD_CALIB;
+ s->subdev_flags = SDF_WRITABLE | SDF_INTERNAL;
+ if (board->has_ad8402) {
+ /*
+ * pci-das1602/16 have an AD8402 trimpot:
+ * chan 0 : adc gain
+ * chan 1 : adc postgain offset
+ */
+ s->n_chan = 2;
+ s->maxdata = 0xff;
} else {
- s->n_chan = NUM_CHANNELS_8402;
- s->maxdata = 0xff;
+ /* all other boards have an AD7376 trimpot */
+ s->n_chan = 1;
+ s->maxdata = 0x7f;
}
- s->insn_write = cb_pcidas_trimpot_insn_write;
+ s->insn_write = cb_pcidas_trimpot_insn_write;
ret = comedi_alloc_subdev_readback(s);
if (ret)
@@ -1495,36 +1421,35 @@ static int cb_pcidas_auto_attach(struct comedi_device *dev,
s->readback[i] = s->maxdata / 2;
}
- /* dac08 caldac */
+ /* Calibration subdevice - pci-das1602/16 pregain offset (dac08) */
s = &dev->subdevices[6];
if (board->has_dac08) {
- s->type = COMEDI_SUBD_CALIB;
- s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_INTERNAL;
- s->n_chan = NUM_CHANNELS_DAC08;
- s->maxdata = 0xff;
- s->insn_write = cb_pcidas_dac08_insn_write;
+ s->type = COMEDI_SUBD_CALIB;
+ s->subdev_flags = SDF_WRITABLE | SDF_INTERNAL;
+ s->n_chan = 1;
+ s->maxdata = 0xff;
+ s->insn_write = cb_pcidas_dac08_insn_write;
ret = comedi_alloc_subdev_readback(s);
if (ret)
return ret;
for (i = 0; i < s->n_chan; i++) {
- dac08_write(dev, s->maxdata / 2);
+ cb_pcidas_dac08_write(dev, s->maxdata / 2);
s->readback[i] = s->maxdata / 2;
}
} else {
- s->type = COMEDI_SUBD_UNUSED;
+ s->type = COMEDI_SUBD_UNUSED;
}
/* make sure mailbox 4 is empty */
- inl(devpriv->s5933_config + AMCC_OP_REG_IMB4);
+ inl(devpriv->amcc + AMCC_OP_REG_IMB4);
/* Set bits to enable incoming mailbox interrupts on amcc s5933. */
- devpriv->s5933_intcsr_bits =
- INTCSR_INBOX_BYTE(3) | INTCSR_INBOX_SELECT(3) |
- INTCSR_INBOX_FULL_INT;
+ devpriv->amcc_intcsr = INTCSR_INBOX_BYTE(3) | INTCSR_INBOX_SELECT(3) |
+ INTCSR_INBOX_FULL_INT;
/* clear and enable interrupt on amcc s5933 */
- outl(devpriv->s5933_intcsr_bits | INTCSR_INBOX_INTR_STATUS,
- devpriv->s5933_config + AMCC_OP_REG_INTCSR);
+ outl(devpriv->amcc_intcsr | INTCSR_INBOX_INTR_STATUS,
+ devpriv->amcc + AMCC_OP_REG_INTCSR);
return 0;
}
@@ -1534,9 +1459,9 @@ static void cb_pcidas_detach(struct comedi_device *dev)
struct cb_pcidas_private *devpriv = dev->private;
if (devpriv) {
- if (devpriv->s5933_config)
+ if (devpriv->amcc)
outl(INTCSR_INBOX_INTR_STATUS,
- devpriv->s5933_config + AMCC_OP_REG_INTCSR);
+ devpriv->amcc + AMCC_OP_REG_INTCSR);
kfree(devpriv->ao_pacer);
}
comedi_pci_detach(dev);
@@ -1578,5 +1503,5 @@ static struct pci_driver cb_pcidas_pci_driver = {
module_comedi_pci_driver(cb_pcidas_driver, cb_pcidas_pci_driver);
MODULE_AUTHOR("Comedi http://www.comedi.org");
-MODULE_DESCRIPTION("Comedi low-level driver");
+MODULE_DESCRIPTION("Comedi driver for MeasurementComputing PCI-DAS series");
MODULE_LICENSE("GPL");