diff options
| -rw-r--r-- | drivers/staging/comedi/drivers/s526.c | 35 |
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 | } |
