#define INIT_A1_BITS 0x70
#define COUNTER_B_BASE_REG 0x18
+enum scan_mode {
+ MODE_SINGLE_CHAN,
+ MODE_SINGLE_CHAN_INTERVAL,
+ MODE_MULT_CHAN_UP,
+ MODE_MULT_CHAN_DOWN,
+};
+
static int labpc_cancel(struct comedi_device *dev, struct comedi_subdevice *s);
static irqreturn_t labpc_interrupt(int irq, void *d);
static int labpc_drain_fifo(struct comedi_device *dev);
struct comedi_subdevice *s,
struct comedi_insn *insn,
unsigned int *data);
-static void labpc_adc_timing(struct comedi_device *dev, struct comedi_cmd *cmd);
+static void labpc_adc_timing(struct comedi_device *dev, struct comedi_cmd *cmd,
+ enum scan_mode scan_mode);
#ifdef CONFIG_ISA_DMA_API
-static unsigned int labpc_suggest_transfer_size(struct comedi_cmd cmd);
+static unsigned int labpc_suggest_transfer_size(const struct comedi_cmd *cmd);
#endif
static int labpc_dio_mem_callback(int dir, int port, int data,
unsigned long arg);
static void write_caldac(struct comedi_device *dev, unsigned int channel,
unsigned int value);
-enum scan_mode {
- MODE_SINGLE_CHAN,
- MODE_SINGLE_CHAN_INTERVAL,
- MODE_MULT_CHAN_UP,
- MODE_MULT_CHAN_DOWN,
-};
-
/* analog input ranges */
#define NUM_LABPC_PLUS_AI_RANGES 16
/* indicates unipolar ranges */
static inline unsigned int labpc_readb(unsigned long address)
{
- return readb((void *)address);
+ return readb((void __iomem *)address);
}
static inline void labpc_writeb(unsigned int byte, unsigned long address)
{
- writeb(byte, (void *)address);
+ writeb(byte, (void __iomem *)address);
}
static const struct labpc_board_struct labpc_boards[] = {
unsigned int count, unsigned int mode)
{
if (thisboard->memory_mapped_io)
- return i8254_mm_load((void *)base_address, 0, counter_number,
- count, mode);
+ return i8254_mm_load((void __iomem *)base_address, 0,
+ counter_number, count, mode);
else
return i8254_load(base_address, 0, counter_number, count, mode);
}
return NULL;
}
-/* FIXME: remove this when dynamic MITE allocation implemented. */
-static struct mite_struct *labpc_pci_find_mite(struct pci_dev *pcidev)
-{
- struct mite_struct *mite;
-
- for (mite = mite_devices; mite; mite = mite->next) {
- if (mite->used)
- continue;
- if (mite->pcidev == pcidev)
- return mite;
- }
- return NULL;
-}
-
static int __devinit labpc_attach_pci(struct comedi_device *dev,
struct pci_dev *pcidev)
{
dev->board_ptr = labpc_pci_find_boardinfo(pcidev);
if (!dev->board_ptr)
return -ENODEV;
- devpriv->mite = labpc_pci_find_mite(pcidev);
+ devpriv->mite = mite_alloc(pcidev);
if (!devpriv->mite)
- return -ENODEV;
+ return -ENOMEM;
ret = mite_setup(devpriv->mite);
if (ret < 0)
return ret;
if (thisboard->bustype == isa_bustype && dev->iobase)
release_region(dev->iobase, LABPC_SIZE);
#ifdef CONFIG_COMEDI_PCI_DRIVERS
- if (devpriv->mite)
+ if (devpriv->mite) {
mite_unsetup(devpriv->mite);
+ mite_free(devpriv->mite);
+ }
#endif
};
EXPORT_SYMBOL_GPL(labpc_common_detach);
}
static int labpc_ai_chanlist_invalid(const struct comedi_device *dev,
- const struct comedi_cmd *cmd)
+ const struct comedi_cmd *cmd,
+ enum scan_mode mode)
{
- int mode, channel, range, aref, i;
+ int channel, range, aref, i;
if (cmd->chanlist == NULL)
return 0;
- mode = labpc_ai_scan_mode(cmd);
-
if (mode == MODE_SINGLE_CHAN)
return 0;
return 0;
}
-static int labpc_use_continuous_mode(const struct comedi_cmd *cmd)
+static int labpc_use_continuous_mode(const struct comedi_cmd *cmd,
+ enum scan_mode mode)
{
- if (labpc_ai_scan_mode(cmd) == MODE_SINGLE_CHAN)
+ if (mode == MODE_SINGLE_CHAN)
return 1;
if (cmd->scan_begin_src == TRIG_FOLLOW)
return 0;
}
-static unsigned int labpc_ai_convert_period(const struct comedi_cmd *cmd)
+static unsigned int labpc_ai_convert_period(const struct comedi_cmd *cmd,
+ enum scan_mode mode)
{
if (cmd->convert_src != TRIG_TIMER)
return 0;
- if (labpc_ai_scan_mode(cmd) == MODE_SINGLE_CHAN &&
- cmd->scan_begin_src == TRIG_TIMER)
+ if (mode == MODE_SINGLE_CHAN && cmd->scan_begin_src == TRIG_TIMER)
return cmd->scan_begin_arg;
return cmd->convert_arg;
}
-static void labpc_set_ai_convert_period(struct comedi_cmd *cmd, unsigned int ns)
+static void labpc_set_ai_convert_period(struct comedi_cmd *cmd,
+ enum scan_mode mode, unsigned int ns)
{
if (cmd->convert_src != TRIG_TIMER)
return;
- if (labpc_ai_scan_mode(cmd) == MODE_SINGLE_CHAN &&
+ if (mode == MODE_SINGLE_CHAN &&
cmd->scan_begin_src == TRIG_TIMER) {
cmd->scan_begin_arg = ns;
if (cmd->convert_arg > cmd->scan_begin_arg)
cmd->convert_arg = ns;
}
-static unsigned int labpc_ai_scan_period(const struct comedi_cmd *cmd)
+static unsigned int labpc_ai_scan_period(const struct comedi_cmd *cmd,
+ enum scan_mode mode)
{
if (cmd->scan_begin_src != TRIG_TIMER)
return 0;
- if (labpc_ai_scan_mode(cmd) == MODE_SINGLE_CHAN &&
- cmd->convert_src == TRIG_TIMER)
+ if (mode == MODE_SINGLE_CHAN && cmd->convert_src == TRIG_TIMER)
return 0;
return cmd->scan_begin_arg;
}
-static void labpc_set_ai_scan_period(struct comedi_cmd *cmd, unsigned int ns)
+static void labpc_set_ai_scan_period(struct comedi_cmd *cmd,
+ enum scan_mode mode, unsigned int ns)
{
if (cmd->scan_begin_src != TRIG_TIMER)
return;
- if (labpc_ai_scan_mode(cmd) == MODE_SINGLE_CHAN &&
- cmd->convert_src == TRIG_TIMER)
+ if (mode == MODE_SINGLE_CHAN && cmd->convert_src == TRIG_TIMER)
return;
cmd->scan_begin_arg = ns;
{
int err = 0;
int tmp, tmp2;
- int stop_mask;
+ unsigned int stop_mask;
+ enum scan_mode mode;
- /* step 1: make sure trigger sources are trivially valid */
+ /* Step 1 : check if triggers are trivially valid */
- tmp = cmd->start_src;
- cmd->start_src &= TRIG_NOW | TRIG_EXT;
- if (!cmd->start_src || tmp != cmd->start_src)
- err++;
-
- tmp = cmd->scan_begin_src;
- cmd->scan_begin_src &= TRIG_TIMER | TRIG_FOLLOW | TRIG_EXT;
- if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
- err++;
+ err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_EXT);
+ err |= cfc_check_trigger_src(&cmd->scan_begin_src,
+ TRIG_TIMER | TRIG_FOLLOW | TRIG_EXT);
+ err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_TIMER | TRIG_EXT);
+ err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
- tmp = cmd->convert_src;
- cmd->convert_src &= TRIG_TIMER | TRIG_EXT;
- if (!cmd->convert_src || tmp != cmd->convert_src)
- err++;
-
- tmp = cmd->scan_end_src;
- cmd->scan_end_src &= TRIG_COUNT;
- if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
- err++;
-
- tmp = cmd->stop_src;
stop_mask = TRIG_COUNT | TRIG_NONE;
if (thisboard->register_layout == labpc_1200_layout)
stop_mask |= TRIG_EXT;
- cmd->stop_src &= stop_mask;
- if (!cmd->stop_src || tmp != cmd->stop_src)
- err++;
+ err |= cfc_check_trigger_src(&cmd->stop_src, stop_mask);
if (err)
return 1;
- /* step 2: make sure trigger sources are unique and mutually compatible */
+ /* Step 2a : make sure trigger sources are unique */
- if (cmd->start_src != TRIG_NOW && cmd->start_src != TRIG_EXT)
- err++;
- if (cmd->scan_begin_src != TRIG_TIMER &&
- cmd->scan_begin_src != TRIG_FOLLOW &&
- cmd->scan_begin_src != TRIG_EXT)
- err++;
- if (cmd->convert_src != TRIG_TIMER && cmd->convert_src != TRIG_EXT)
- err++;
- if (cmd->stop_src != TRIG_COUNT &&
- cmd->stop_src != TRIG_EXT && cmd->stop_src != TRIG_NONE)
- err++;
+ err |= cfc_check_trigger_is_unique(cmd->start_src);
+ err |= cfc_check_trigger_is_unique(cmd->scan_begin_src);
+ err |= cfc_check_trigger_is_unique(cmd->convert_src);
+ err |= cfc_check_trigger_is_unique(cmd->stop_src);
+
+ /* Step 2b : and mutually compatible */
/* can't have external stop and start triggers at once */
if (cmd->start_src == TRIG_EXT && cmd->stop_src == TRIG_EXT)
tmp = cmd->convert_arg;
tmp2 = cmd->scan_begin_arg;
- labpc_adc_timing(dev, cmd);
+ mode = labpc_ai_scan_mode(cmd);
+ labpc_adc_timing(dev, cmd, mode);
if (tmp != cmd->convert_arg || tmp2 != cmd->scan_begin_arg)
err++;
if (err)
return 4;
- if (labpc_ai_chanlist_invalid(dev, cmd))
+ if (labpc_ai_chanlist_invalid(dev, cmd, mode))
return 5;
return 0;
struct comedi_async *async = s->async;
struct comedi_cmd *cmd = &async->cmd;
enum transfer_type xfer;
+ enum scan_mode mode;
unsigned long flags;
if (!dev->irq) {
} else
xfer = fifo_not_empty_transfer;
devpriv->current_transfer = xfer;
+ mode = labpc_ai_scan_mode(cmd);
/* setup command6 register for 1200 boards */
if (thisboard->register_layout == labpc_1200_layout) {
else
devpriv->command6_bits &= ~A1_INTR_EN_BIT;
/* are we scanning up or down through channels? */
- if (labpc_ai_scan_mode(cmd) == MODE_MULT_CHAN_UP)
+ if (mode == MODE_MULT_CHAN_UP)
devpriv->command6_bits |= ADC_SCAN_UP_BIT;
else
devpriv->command6_bits &= ~ADC_SCAN_UP_BIT;
/* setup channel list, etc (command1 register) */
devpriv->command1_bits = 0;
- if (labpc_ai_scan_mode(cmd) == MODE_MULT_CHAN_UP)
+ if (mode == MODE_MULT_CHAN_UP)
channel = CR_CHAN(cmd->chanlist[cmd->chanlist_len - 1]);
else
channel = CR_CHAN(cmd->chanlist[0]);
/* munge channel bits for differential / scan disabled mode */
- if (labpc_ai_scan_mode(cmd) != MODE_SINGLE_CHAN && aref == AREF_DIFF)
+ if (mode != MODE_SINGLE_CHAN && aref == AREF_DIFF)
channel *= 2;
devpriv->command1_bits |= ADC_CHAN_BITS(channel);
devpriv->command1_bits |= thisboard->ai_range_code[range];
devpriv->write_byte(devpriv->command1_bits, dev->iobase + COMMAND1_REG);
/* manual says to set scan enable bit on second pass */
- if (labpc_ai_scan_mode(cmd) == MODE_MULT_CHAN_UP ||
- labpc_ai_scan_mode(cmd) == MODE_MULT_CHAN_DOWN) {
+ if (mode == MODE_MULT_CHAN_UP || mode == MODE_MULT_CHAN_DOWN) {
devpriv->command1_bits |= ADC_SCAN_EN_BIT;
/* need a brief delay before enabling scan, or scan
* list will get screwed when you switch
devpriv->command4_bits |= EXT_CONVERT_DISABLE_BIT;
/* XXX should discard first scan when using interval scanning
* since manual says it is not synced with scan clock */
- if (labpc_use_continuous_mode(cmd) == 0) {
+ if (labpc_use_continuous_mode(cmd, mode) == 0) {
devpriv->command4_bits |= INTERVAL_SCAN_EN_BIT;
if (cmd->scan_begin_src == TRIG_EXT)
devpriv->command4_bits |= EXT_SCAN_EN_BIT;
if (cmd->convert_src == TRIG_TIMER || cmd->scan_begin_src == TRIG_TIMER) {
/* set up pacing */
- labpc_adc_timing(dev, cmd);
+ labpc_adc_timing(dev, cmd, mode);
/* load counter b0 in mode 3 */
ret = labpc_counter_load(dev, dev->iobase + COUNTER_B_BASE_REG,
0, devpriv->divisor_b0, 3);
}
}
/* set up conversion pacing */
- if (labpc_ai_convert_period(cmd)) {
+ if (labpc_ai_convert_period(cmd, mode)) {
/* load counter a0 in mode 2 */
ret = labpc_counter_load(dev, dev->iobase + COUNTER_A_BASE_REG,
0, devpriv->divisor_a0, 2);
dev->iobase + COUNTER_A_CONTROL_REG);
/* set up scan pacing */
- if (labpc_ai_scan_period(cmd)) {
+ if (labpc_ai_scan_period(cmd, mode)) {
/* load counter b1 in mode 2 */
ret = labpc_counter_load(dev, dev->iobase + COUNTER_B_BASE_REG,
1, devpriv->divisor_b1, 2);
set_dma_addr(devpriv->dma_chan,
virt_to_bus(devpriv->dma_buffer));
/* set appropriate size of transfer */
- devpriv->dma_transfer_size = labpc_suggest_transfer_size(*cmd);
+ devpriv->dma_transfer_size = labpc_suggest_transfer_size(cmd);
if (cmd->stop_src == TRIG_COUNT &&
devpriv->count * sample_size < devpriv->dma_transfer_size) {
devpriv->dma_transfer_size =
#ifdef CONFIG_ISA_DMA_API
/* utility function that suggests a dma transfer size in bytes */
-static unsigned int labpc_suggest_transfer_size(struct comedi_cmd cmd)
+static unsigned int labpc_suggest_transfer_size(const struct comedi_cmd *cmd)
{
unsigned int size;
unsigned int freq;
- if (cmd.convert_src == TRIG_TIMER)
- freq = 1000000000 / cmd.convert_arg;
+ if (cmd->convert_src == TRIG_TIMER)
+ freq = 1000000000 / cmd->convert_arg;
/* return some default value */
else
freq = 0xffffffff;
#endif
/* figures out what counter values to use based on command */
-static void labpc_adc_timing(struct comedi_device *dev, struct comedi_cmd *cmd)
+static void labpc_adc_timing(struct comedi_device *dev, struct comedi_cmd *cmd,
+ enum scan_mode mode)
{
/* max value for 16 bit counter in mode 2 */
const int max_counter_value = 0x10000;
/* min value for 16 bit counter in mode 2 */
const int min_counter_value = 2;
unsigned int base_period;
+ unsigned int scan_period;
+ unsigned int convert_period;
/*
* if both convert and scan triggers are TRIG_TIMER, then they
* both rely on counter b0
*/
- if (labpc_ai_convert_period(cmd) && labpc_ai_scan_period(cmd)) {
+ convert_period = labpc_ai_convert_period(cmd, mode);
+ scan_period = labpc_ai_scan_period(cmd, mode);
+ if (convert_period && scan_period) {
/*
* pick the lowest b0 divisor value we can (for maximum input
* clock speed on convert and scan counters)
*/
- devpriv->divisor_b0 = (labpc_ai_scan_period(cmd) - 1) /
+ devpriv->divisor_b0 = (scan_period - 1) /
(LABPC_TIMER_BASE * max_counter_value) + 1;
if (devpriv->divisor_b0 < min_counter_value)
devpriv->divisor_b0 = min_counter_value;
default:
case TRIG_ROUND_NEAREST:
devpriv->divisor_a0 =
- (labpc_ai_convert_period(cmd) +
- (base_period / 2)) / base_period;
+ (convert_period + (base_period / 2)) / base_period;
devpriv->divisor_b1 =
- (labpc_ai_scan_period(cmd) +
- (base_period / 2)) / base_period;
+ (scan_period + (base_period / 2)) / base_period;
break;
case TRIG_ROUND_UP:
devpriv->divisor_a0 =
- (labpc_ai_convert_period(cmd) + (base_period -
- 1)) / base_period;
+ (convert_period + (base_period - 1)) / base_period;
devpriv->divisor_b1 =
- (labpc_ai_scan_period(cmd) + (base_period -
- 1)) / base_period;
+ (scan_period + (base_period - 1)) / base_period;
break;
case TRIG_ROUND_DOWN:
- devpriv->divisor_a0 =
- labpc_ai_convert_period(cmd) / base_period;
- devpriv->divisor_b1 =
- labpc_ai_scan_period(cmd) / base_period;
+ devpriv->divisor_a0 = convert_period / base_period;
+ devpriv->divisor_b1 = scan_period / base_period;
break;
}
/* make sure a0 and b1 values are acceptable */
if (devpriv->divisor_b1 > max_counter_value)
devpriv->divisor_b1 = max_counter_value;
/* write corrected timings to command */
- labpc_set_ai_convert_period(cmd,
+ labpc_set_ai_convert_period(cmd, mode,
base_period * devpriv->divisor_a0);
- labpc_set_ai_scan_period(cmd,
+ labpc_set_ai_scan_period(cmd, mode,
base_period * devpriv->divisor_b1);
/*
* if only one TRIG_TIMER is used, we can employ the generic
* cascaded timing functions
*/
- } else if (labpc_ai_scan_period(cmd)) {
- unsigned int scan_period;
-
- scan_period = labpc_ai_scan_period(cmd);
+ } else if (scan_period) {
/*
* calculate cascaded counter values
* that give desired scan timing
&(devpriv->divisor_b0),
&scan_period,
cmd->flags & TRIG_ROUND_MASK);
- labpc_set_ai_scan_period(cmd, scan_period);
- } else if (labpc_ai_convert_period(cmd)) {
- unsigned int convert_period;
-
- convert_period = labpc_ai_convert_period(cmd);
+ labpc_set_ai_scan_period(cmd, mode, scan_period);
+ } else if (convert_period) {
/*
* calculate cascaded counter values
* that give desired conversion timing
&(devpriv->divisor_b0),
&convert_period,
cmd->flags & TRIG_ROUND_MASK);
- labpc_set_ai_convert_period(cmd, convert_period);
+ labpc_set_ai_convert_period(cmd, mode, convert_period);
}
}
unsigned long iobase)
{
if (dir) {
- writeb(data, (void *)(iobase + port));
+ writeb(data, (void __iomem *)(iobase + port));
return 0;
} else {
- return readb((void *)(iobase + port));
+ return readb((void __iomem *)(iobase + port));
}
}