This driver currently duplicates the functionality of the 8255 module. The only difference is in how the i/o access is handled. Provide a private (*io) callback for the 8255 module to handle the differences. We can then use that module and initialize the subdevice with subdev_8255_init(). Update the Kconfig to select the COMEDI_8255 module. Signed-off-by: H Hartley Sweeten <hsweeten@xxxxxxxxxxxxxxxxxxx> Cc: Ian Abbott <abbotti@xxxxxxxxx> Cc: Greg Kroah-Hartman <gregkh@xxxxxxxxxxxxxxxxxxx> --- drivers/staging/comedi/Kconfig | 1 + .../staging/comedi/drivers/amplc_dio200_common.c | 120 +++------------------ 2 files changed, 14 insertions(+), 107 deletions(-) diff --git a/drivers/staging/comedi/Kconfig b/drivers/staging/comedi/Kconfig index 36f2c71..d5509d1 100644 --- a/drivers/staging/comedi/Kconfig +++ b/drivers/staging/comedi/Kconfig @@ -1266,6 +1266,7 @@ config COMEDI_FC config COMEDI_AMPLC_DIO200 tristate + select COMEDI_8255 config COMEDI_AMPLC_PC236 tristate diff --git a/drivers/staging/comedi/drivers/amplc_dio200_common.c b/drivers/staging/comedi/drivers/amplc_dio200_common.c index 6cadf7e..4eb883c 100644 --- a/drivers/staging/comedi/drivers/amplc_dio200_common.c +++ b/drivers/staging/comedi/drivers/amplc_dio200_common.c @@ -27,7 +27,7 @@ #include "amplc_dio200.h" #include "comedi_fc.h" #include "8253.h" -#include "8255.h" /* only for register defines */ +#include "8255.h" /* 200 series registers */ #define DIO200_IO_SIZE 0x20 @@ -111,10 +111,6 @@ struct dio200_subdev_8254 { spinlock_t spinlock; }; -struct dio200_subdev_8255 { - unsigned int ofs; /* DIO base offset */ -}; - struct dio200_subdev_intr { spinlock_t spinlock; unsigned int ofs; @@ -178,6 +174,16 @@ static void dio200_write32(struct comedi_device *dev, outl(val, dev->iobase + offset); } +static int dio200_8255_io(struct comedi_device *dev, + int dir, int port, int data, unsigned long regbase) +{ + if (dir) { + dio200_write8(dev, regbase + port, data); + return 0; + } + return dio200_read8(dev, regbase + port); +} + static int dio200_subdev_intr_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, @@ -801,106 +807,6 @@ static int dio200_subdev_8254_init(struct comedi_device *dev, return 0; } -static void dio200_subdev_8255_set_dir(struct comedi_device *dev, - struct comedi_subdevice *s) -{ - struct dio200_subdev_8255 *subpriv = s->private; - int config; - - config = I8255_CTRL_CW; - /* 1 in io_bits indicates output, 1 in config indicates input */ - if (!(s->io_bits & 0x0000ff)) - config |= I8255_CTRL_A_IO; - if (!(s->io_bits & 0x00ff00)) - config |= I8255_CTRL_B_IO; - if (!(s->io_bits & 0x0f0000)) - config |= I8255_CTRL_C_LO_IO; - if (!(s->io_bits & 0xf00000)) - config |= I8255_CTRL_C_HI_IO; - dio200_write8(dev, subpriv->ofs + I8255_CTRL_REG, config); -} - -static int dio200_subdev_8255_bits(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, - unsigned int *data) -{ - struct dio200_subdev_8255 *subpriv = s->private; - unsigned int mask; - unsigned int val; - - mask = comedi_dio_update_state(s, data); - if (mask) { - if (mask & 0xff) - dio200_write8(dev, subpriv->ofs + I8255_DATA_A_REG, - s->state & 0xff); - if (mask & 0xff00) - dio200_write8(dev, subpriv->ofs + I8255_DATA_B_REG, - (s->state >> 8) & 0xff); - if (mask & 0xff0000) - dio200_write8(dev, subpriv->ofs + I8255_DATA_C_REG, - (s->state >> 16) & 0xff); - } - - val = dio200_read8(dev, subpriv->ofs + I8255_DATA_A_REG); - val |= dio200_read8(dev, subpriv->ofs + I8255_DATA_B_REG) << 8; - val |= dio200_read8(dev, subpriv->ofs + I8255_DATA_C_REG) << 16; - - data[1] = val; - - return insn->n; -} - -static int dio200_subdev_8255_config(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, - unsigned int *data) -{ - unsigned int chan = CR_CHAN(insn->chanspec); - unsigned int mask; - int ret; - - if (chan < 8) - mask = 0x0000ff; - else if (chan < 16) - mask = 0x00ff00; - else if (chan < 20) - mask = 0x0f0000; - else - mask = 0xf00000; - - ret = comedi_dio_insn_config(dev, s, insn, data, mask); - if (ret) - return ret; - - dio200_subdev_8255_set_dir(dev, s); - - return insn->n; -} - -static int dio200_subdev_8255_init(struct comedi_device *dev, - struct comedi_subdevice *s, - unsigned int offset) -{ - struct dio200_subdev_8255 *subpriv; - - subpriv = comedi_alloc_spriv(s, sizeof(*subpriv)); - if (!subpriv) - return -ENOMEM; - - subpriv->ofs = offset; - - s->type = COMEDI_SUBD_DIO; - s->subdev_flags = SDF_READABLE | SDF_WRITABLE; - s->n_chan = 24; - s->range_table = &range_digital; - s->maxdata = 1; - s->insn_bits = dio200_subdev_8255_bits; - s->insn_config = dio200_subdev_8255_config; - dio200_subdev_8255_set_dir(dev, s); - return 0; -} - static int dio200_subdev_timer_read(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, @@ -1002,8 +908,8 @@ int amplc_dio200_common_attach(struct comedi_device *dev, unsigned int irq, break; case sd_8255: /* digital i/o subdevice (8255) */ - ret = dio200_subdev_8255_init(dev, s, - board->sdinfo[n]); + ret = subdev_8255_init(dev, s, dio200_8255_io, + board->sdinfo[n]); if (ret < 0) return ret; break; -- 2.0.3 _______________________________________________ devel mailing list devel@xxxxxxxxxxxxxxxxxxxxxx http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel