aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIan Abbott <abbotti@mev.co.uk>2009-09-21 15:29:59 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2009-10-09 16:47:24 -0400
commit10f27014f42f0a4cb32bf45f214fa7ad7c261b1e (patch)
tree66ad044771f15b83058cf8bc1f1cfc506f201ee7
parentaa65d22ae6412f474e5ba23fc363137b6c53eef9 (diff)
Staging: comedi: s526: Fix number of channels on DIO subdevice
Correct operation of INSN_CONFIG_DIO_INPUT and INSN_CONFIG_DIO_OUTPUT and support INSN_CONFIG_DIO_QUERY. Thanks to Alessio Margan for some testing. Signed-off-by: Frank Mori Hess <fmhess@users.sourceforge.net> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r--drivers/staging/comedi/drivers/s526.c35
1 files changed, 20 insertions, 15 deletions
diff --git a/drivers/staging/comedi/drivers/s526.c b/drivers/staging/comedi/drivers/s526.c
index b89e1ec267c5..736441f3c815 100644
--- a/drivers/staging/comedi/drivers/s526.c
+++ b/drivers/staging/comedi/drivers/s526.c
@@ -375,7 +375,7 @@ static int s526_attach(struct comedi_device *dev, struct comedi_devconfig *it)
375 if (thisboard->have_dio) { 375 if (thisboard->have_dio) {
376 s->type = COMEDI_SUBD_DIO; 376 s->type = COMEDI_SUBD_DIO;
377 s->subdev_flags = SDF_READABLE | SDF_WRITABLE; 377 s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
378 s->n_chan = 2; 378 s->n_chan = 8;
379 s->maxdata = 1; 379 s->maxdata = 1;
380 s->range_table = &range_digital; 380 s->range_table = &range_digital;
381 s->insn_bits = s526_dio_insn_bits; 381 s->insn_bits = s526_dio_insn_bits;
@@ -949,7 +949,7 @@ static int s526_dio_insn_bits(struct comedi_device *dev,
949 data[1] = inw(ADDR_REG(REG_DIO)) & 0xFF; /* low 8 bits are the data */ 949 data[1] = inw(ADDR_REG(REG_DIO)) & 0xFF; /* low 8 bits are the data */
950 /* or we could just return the software copy of the output values if 950 /* or we could just return the software copy of the output values if
951 * it was a purely digital output subdevice */ 951 * it was a purely digital output subdevice */
952 /* data[1]=s->state; */ 952 /* data[1]=s->state & 0xFF; */
953 953
954 return 2; 954 return 2;
955} 955}
@@ -959,28 +959,33 @@ static int s526_dio_insn_config(struct comedi_device *dev,
959 struct comedi_insn *insn, unsigned int *data) 959 struct comedi_insn *insn, unsigned int *data)
960{ 960{
961 int chan = CR_CHAN(insn->chanspec); 961 int chan = CR_CHAN(insn->chanspec);
962 short value; 962 int group, mask;
963 963
964 printk("S526 DIO insn_config\n"); 964 printk("S526 DIO insn_config\n");
965 965
966 if (insn->n != 1)
967 return -EINVAL;
968
969 value = inw(ADDR_REG(REG_DIO));
970
971 /* The input or output configuration of each digital line is 966 /* The input or output configuration of each digital line is
972 * configured by a special insn_config instruction. chanspec 967 * configured by a special insn_config instruction. chanspec
973 * contains the channel to be changed, and data[0] contains the 968 * contains the channel to be changed, and data[0] contains the
974 * value COMEDI_INPUT or COMEDI_OUTPUT. */ 969 * value COMEDI_INPUT or COMEDI_OUTPUT. */
975 970
976 if (data[0] == COMEDI_OUTPUT) { 971 group = chan >> 2;
977 value |= 1 << (chan + 10); /* bit 10/11 set the group 1/2's mode */ 972 mask = 0xF << (group << 2);
978 s->io_bits |= (0xF << chan); 973 switch (data[0]) {
979 } else { 974 case INSN_CONFIG_DIO_OUTPUT:
980 value &= ~(1 << (chan + 10)); /* 1 is output, 0 is input. */ 975 s->state |= 1 << (group + 10); // bit 10/11 set the group 1/2's mode
981 s->io_bits &= ~(0xF << chan); 976 s->io_bits |= mask;
977 break;
978 case INSN_CONFIG_DIO_INPUT:
979 s->state &= ~(1 << (group + 10));// 1 is output, 0 is input.
980 s->io_bits &= ~mask;
981 break;
982 case INSN_CONFIG_DIO_QUERY:
983 data[1] = (s->io_bits & mask) ? COMEDI_OUTPUT : COMEDI_INPUT;
984 return insn->n;
985 default:
986 return -EINVAL;
982 } 987 }
983 outw(value, ADDR_REG(REG_DIO)); 988 outw(s->state, ADDR_REG(REG_DIO));
984 989
985 return 1; 990 return 1;
986} 991}