|
@@ -93,68 +93,48 @@ static int dnp_dio_insn_bits(struct comedi_device *dev,
|
|
|
|
|
|
}
|
|
|
|
|
|
-/* ------------------------------------------------------------------------- */
|
|
|
-/* Configure the direction of the bidirectional digital i/o pins. chanspec */
|
|
|
-/* contains the channel to be changed and data[0] contains either */
|
|
|
-/* COMEDI_INPUT or COMEDI_OUTPUT. */
|
|
|
-/* ------------------------------------------------------------------------- */
|
|
|
-
|
|
|
static int dnp_dio_insn_config(struct comedi_device *dev,
|
|
|
struct comedi_subdevice *s,
|
|
|
- struct comedi_insn *insn, unsigned int *data)
|
|
|
+ struct comedi_insn *insn,
|
|
|
+ unsigned int *data)
|
|
|
{
|
|
|
+ unsigned int chan = CR_CHAN(insn->chanspec);
|
|
|
+ unsigned int mask;
|
|
|
+ unsigned int val;
|
|
|
+ int ret;
|
|
|
|
|
|
- u8 register_buffer;
|
|
|
-
|
|
|
- /* reduces chanspec to lower 16 bits */
|
|
|
- int chan = CR_CHAN(insn->chanspec);
|
|
|
-
|
|
|
- switch (data[0]) {
|
|
|
- case INSN_CONFIG_DIO_OUTPUT:
|
|
|
- case INSN_CONFIG_DIO_INPUT:
|
|
|
- break;
|
|
|
- case INSN_CONFIG_DIO_QUERY:
|
|
|
- data[1] =
|
|
|
- (inb(CSCDR) & (1 << chan)) ? COMEDI_OUTPUT : COMEDI_INPUT;
|
|
|
- return insn->n;
|
|
|
- break;
|
|
|
- default:
|
|
|
- return -EINVAL;
|
|
|
- break;
|
|
|
- }
|
|
|
- /* Test: which port does the channel belong to? */
|
|
|
-
|
|
|
- /* We have to pay attention with port C: this is the meaning of PCMR: */
|
|
|
- /* Bit in PCMR: 7 6 5 4 3 2 1 0 */
|
|
|
- /* Corresponding port C pin: d 3 d 2 d 1 d 0 d= don't touch */
|
|
|
+ ret = comedi_dio_insn_config(dev, s, insn, data, 0);
|
|
|
+ if (ret)
|
|
|
+ return ret;
|
|
|
|
|
|
- if ((chan >= 0) && (chan <= 7)) {
|
|
|
- /* this is port A */
|
|
|
+ if (chan < 8) { /* Port A */
|
|
|
+ mask = 1 << chan;
|
|
|
outb(PAMR, CSCIR);
|
|
|
- } else if ((chan >= 8) && (chan <= 15)) {
|
|
|
- /* this is port B */
|
|
|
- chan -= 8;
|
|
|
+ } else if (chan < 16) { /* Port B */
|
|
|
+ mask = 1 << (chan - 8);
|
|
|
outb(PBMR, CSCIR);
|
|
|
- } else if ((chan >= 16) && (chan <= 19)) {
|
|
|
- /* this is port C; multiplication with 2 brings bits into */
|
|
|
- /* correct position for PCMR! */
|
|
|
- chan -= 16;
|
|
|
- chan *= 2;
|
|
|
+ } else { /* Port C */
|
|
|
+ /*
|
|
|
+ * We have to pay attention with port C.
|
|
|
+ * This is the meaning of PCMR:
|
|
|
+ * Bit in PCMR: 7 6 5 4 3 2 1 0
|
|
|
+ * Corresponding port C pin: d 3 d 2 d 1 d 0 d= don't touch
|
|
|
+ *
|
|
|
+ * Multiplication by 2 brings bits into correct position
|
|
|
+ * for PCMR!
|
|
|
+ */
|
|
|
+ mask = 1 << ((chan - 16) * 2);
|
|
|
outb(PCMR, CSCIR);
|
|
|
- } else {
|
|
|
- return -EINVAL;
|
|
|
}
|
|
|
|
|
|
- /* read 'old' direction of the port and set bits (out=1, in=0) */
|
|
|
- register_buffer = inb(CSCDR);
|
|
|
+ val = inb(CSCDR);
|
|
|
if (data[0] == COMEDI_OUTPUT)
|
|
|
- register_buffer |= (1 << chan);
|
|
|
+ val |= mask;
|
|
|
else
|
|
|
- register_buffer &= ~(1 << chan);
|
|
|
-
|
|
|
- outb(register_buffer, CSCDR);
|
|
|
+ val &= ~mask;
|
|
|
+ outb(val, CSCDR);
|
|
|
|
|
|
- return 1;
|
|
|
+ return insn->n;
|
|
|
|
|
|
}
|
|
|
|