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>

authored by Ian Abbott and committed by Greg Kroah-Hartman 10f27014 aa65d22a

+20 -15
+20 -15
drivers/staging/comedi/drivers/s526.c
··· 375 if (thisboard->have_dio) { 376 s->type = COMEDI_SUBD_DIO; 377 s->subdev_flags = SDF_READABLE | SDF_WRITABLE; 378 - s->n_chan = 2; 379 s->maxdata = 1; 380 s->range_table = &range_digital; 381 s->insn_bits = s526_dio_insn_bits; ··· 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 951 * it was a purely digital output subdevice */ 952 - /* data[1]=s->state; */ 953 954 return 2; 955 } ··· 959 struct comedi_insn *insn, unsigned int *data) 960 { 961 int chan = CR_CHAN(insn->chanspec); 962 - short value; 963 964 printk("S526 DIO insn_config\n"); 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 972 * configured by a special insn_config instruction. chanspec 973 * contains the channel to be changed, and data[0] contains the 974 * value COMEDI_INPUT or COMEDI_OUTPUT. */ 975 976 - if (data[0] == COMEDI_OUTPUT) { 977 - value |= 1 << (chan + 10); /* bit 10/11 set the group 1/2's mode */ 978 - s->io_bits |= (0xF << chan); 979 - } else { 980 - value &= ~(1 << (chan + 10)); /* 1 is output, 0 is input. */ 981 - s->io_bits &= ~(0xF << chan); 982 } 983 - outw(value, ADDR_REG(REG_DIO)); 984 985 return 1; 986 }
··· 375 if (thisboard->have_dio) { 376 s->type = COMEDI_SUBD_DIO; 377 s->subdev_flags = SDF_READABLE | SDF_WRITABLE; 378 + s->n_chan = 8; 379 s->maxdata = 1; 380 s->range_table = &range_digital; 381 s->insn_bits = s526_dio_insn_bits; ··· 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 951 * it was a purely digital output subdevice */ 952 + /* data[1]=s->state & 0xFF; */ 953 954 return 2; 955 } ··· 959 struct comedi_insn *insn, unsigned int *data) 960 { 961 int chan = CR_CHAN(insn->chanspec); 962 + int group, mask; 963 964 printk("S526 DIO insn_config\n"); 965 966 /* The input or output configuration of each digital line is 967 * configured by a special insn_config instruction. chanspec 968 * contains the channel to be changed, and data[0] contains the 969 * value COMEDI_INPUT or COMEDI_OUTPUT. */ 970 971 + group = chan >> 2; 972 + mask = 0xF << (group << 2); 973 + switch (data[0]) { 974 + case INSN_CONFIG_DIO_OUTPUT: 975 + s->state |= 1 << (group + 10); // bit 10/11 set the group 1/2's mode 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; 987 } 988 + outw(s->state, ADDR_REG(REG_DIO)); 989 990 return 1; 991 }