Commit d92d39d9 authored by H Hartley Sweeten's avatar H Hartley Sweeten Committed by Greg Kroah-Hartman

staging: comedi: me4000: convert driver to use the comedi_8254 module

Some of the hardware supported by this driver include an 8254 timer. For
aesthetics, convert it to use the comedi_8254 module to provide support for
the 8254 timer.

This also fixes the (*insn_read) and (*insn_write) to work like the comedi
API expects. Currently they only read or write a single value.

It also fixes the (*insn_config). Currently the driver is attempting to
handle the configuration instructions GPCT_RESET and GPCT_SET_OPERATION.
These are just arbitrary valuse and are not real comedi configuration_ids.
They actually coorespond to:

  GPCT_RESET -> INSN_CONFIG_DIO_OUTPUT
  GPCT_SET_OPERATION -> INSN_CONFIG_ANALOG_TRIG

The number of parameters for the instructions is validated by the comedi
core in check_insn_config_length(). GPCT_RESET happens to work (insn->n == 1)
but GPCT_SET_OPERATION would fail. The INSN_CONFIG_ANALOG_TRIG expects
insn->n == 5 but GPCT_SET_OPERATION in this driver expects insn->n == 2.
Signed-off-by: default avatarH Hartley Sweeten <hsweeten@visionengravers.com>
Reviewed-by: default avatarIan Abbott <abbotti@mev.co.uk>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 1e1fe085
......@@ -970,6 +970,7 @@ config COMEDI_CB_PCIMDDA
config COMEDI_ME4000
tristate "Meilhaus ME-4000 support"
select COMEDI_8254
---help---
Enable support for Meilhaus PCI data acquisition cards
ME-4650, ME-4670i, ME-4680, ME-4680i and ME-4680is
......
......@@ -48,7 +48,7 @@ broken.
#include "../comedidev.h"
#include "comedi_fc.h"
#include "8253.h"
#include "comedi_8254.h"
#include "plx9052.h"
#define ME4000_FIRMWARE "me4000_firmware.bin"
......@@ -170,7 +170,6 @@ broken.
struct me4000_info {
unsigned long plx_regbase;
unsigned long timer_regbase;
};
enum me4000_boardid {
......@@ -1259,85 +1258,6 @@ static int me4000_dio_insn_config(struct comedi_device *dev,
return insn->n;
}
/*=============================================================================
Counter section
===========================================================================*/
static int me4000_cnt_insn_config(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn,
unsigned int *data)
{
struct me4000_info *info = dev->private;
unsigned int chan = CR_CHAN(insn->chanspec);
int err;
switch (data[0]) {
case GPCT_RESET:
if (insn->n != 1)
return -EINVAL;
err = i8254_set_mode(info->timer_regbase, 0, chan,
I8254_MODE0 | I8254_BINARY);
if (err)
return err;
i8254_write(info->timer_regbase, 0, chan, 0);
break;
case GPCT_SET_OPERATION:
if (insn->n != 2)
return -EINVAL;
err = i8254_set_mode(info->timer_regbase, 0, chan,
(data[1] << 1) | I8254_BINARY);
if (err)
return err;
break;
default:
return -EINVAL;
}
return insn->n;
}
static int me4000_cnt_insn_read(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data)
{
struct me4000_info *info = dev->private;
if (insn->n == 0)
return 0;
if (insn->n > 1) {
dev_err(dev->class_dev, "Invalid instruction length %d\n",
insn->n);
return -EINVAL;
}
data[0] = i8254_read(info->timer_regbase, 0, insn->chanspec);
return 1;
}
static int me4000_cnt_insn_write(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data)
{
struct me4000_info *info = dev->private;
if (insn->n == 0) {
return 0;
} else if (insn->n > 1) {
dev_err(dev->class_dev, "Invalid instruction length %d\n",
insn->n);
return -EINVAL;
}
i8254_write(info->timer_regbase, 0, insn->chanspec, data[0]);
return 1;
}
static int me4000_auto_attach(struct comedi_device *dev,
unsigned long context)
{
......@@ -1364,8 +1284,7 @@ static int me4000_auto_attach(struct comedi_device *dev,
info->plx_regbase = pci_resource_start(pcidev, 1);
dev->iobase = pci_resource_start(pcidev, 2);
info->timer_regbase = pci_resource_start(pcidev, 3);
if (!info->plx_regbase || !dev->iobase || !info->timer_regbase)
if (!info->plx_regbase || !dev->iobase)
return -ENODEV;
result = comedi_load_firmware(dev, &pcidev->dev, ME4000_FIRMWARE,
......@@ -1462,20 +1381,19 @@ static int me4000_auto_attach(struct comedi_device *dev,
dev->iobase + ME4000_DIO_DIR_REG);
}
/*=========================================================================
Counter subdevice
========================================================================*/
/* Counter subdevice (8254) */
s = &dev->subdevices[3];
if (thisboard->has_counter) {
s->type = COMEDI_SUBD_COUNTER;
s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
s->n_chan = 3;
s->maxdata = 0xFFFF; /* 16 bit counters */
s->insn_read = me4000_cnt_insn_read;
s->insn_write = me4000_cnt_insn_write;
s->insn_config = me4000_cnt_insn_config;
unsigned long timer_base = pci_resource_start(pcidev, 3);
if (!timer_base)
return -ENODEV;
dev->pacer = comedi_8254_init(timer_base, 0, I8254_IO8, 0);
if (!dev->pacer)
return -ENOMEM;
comedi_8254_subdevice_init(s, dev->pacer);
} else {
s->type = COMEDI_SUBD_UNUSED;
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment