Revert "staging: comedi: drivers: use comedi_dio_insn_config() for complex cases"
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 12 Aug 2013 22:14:18 +0000 (15:14 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 12 Aug 2013 22:14:18 +0000 (15:14 -0700)
This reverts commit f21c53945cb95f66faa9636af5f23cb00ba73019.

I applied the wrong patch :(

Cc: H Hartley Sweeten <hsweeten@visionengravers.com>
Cc: Ian Abbott <abbotti@mev.co.uk>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
15 files changed:
drivers/staging/comedi/drivers/8255.c
drivers/staging/comedi/drivers/addi_apci_16xx.c
drivers/staging/comedi/drivers/addi_apci_3xxx.c
drivers/staging/comedi/drivers/adv_pci1723.c
drivers/staging/comedi/drivers/amplc_dio200_common.c
drivers/staging/comedi/drivers/cb_das16_cs.c
drivers/staging/comedi/drivers/dt2801.c
drivers/staging/comedi/drivers/dt3000.c
drivers/staging/comedi/drivers/gsc_hpdi.c
drivers/staging/comedi/drivers/ii_pci20kc.c
drivers/staging/comedi/drivers/me4000.c
drivers/staging/comedi/drivers/me_daq.c
drivers/staging/comedi/drivers/ni_at_ao.c
drivers/staging/comedi/drivers/pcm3724.c
drivers/staging/comedi/drivers/s526.c

index 2f070fdbbb1d3b206b6e17f5f10bea0ec6e3a02a..1fa29ac4eb5df194ef44afcf41ae35c21b0e9d95 100644 (file)
@@ -184,29 +184,39 @@ static void subdev_8255_do_config(struct comedi_device *dev,
 
 static int subdev_8255_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;
-       int ret;
+       unsigned int bits;
 
-       if (chan < 8)
-               mask = 0x0000ff;
-       else if (chan < 16)
-               mask = 0x00ff00;
-       else if (chan < 20)
-               mask = 0x0f0000;
+       mask = 1 << CR_CHAN(insn->chanspec);
+       if (mask & 0x0000ff)
+               bits = 0x0000ff;
+       else if (mask & 0x00ff00)
+               bits = 0x00ff00;
+       else if (mask & 0x0f0000)
+               bits = 0x0f0000;
        else
-               mask = 0xf00000;
-
-       ret = comedi_dio_insn_config(dev, s, insn, data, mask);
-       if (ret)
-               return ret;
+               bits = 0xf00000;
+
+       switch (data[0]) {
+       case INSN_CONFIG_DIO_INPUT:
+               s->io_bits &= ~bits;
+               break;
+       case INSN_CONFIG_DIO_OUTPUT:
+               s->io_bits |= bits;
+               break;
+       case INSN_CONFIG_DIO_QUERY:
+               data[1] = (s->io_bits & bits) ? COMEDI_OUTPUT : COMEDI_INPUT;
+               return insn->n;
+               break;
+       default:
+               return -EINVAL;
+       }
 
        subdev_8255_do_config(dev, s);
 
-       return insn->n;
+       return 1;
 }
 
 static int subdev_8255_cmdtest(struct comedi_device *dev,
index 96523744b8de57cc5203d7c7667b60f67f4b647c..43296a6e7d4e664393337dbaaae4ea86bf247092 100644 (file)
@@ -60,22 +60,36 @@ static int apci16xx_insn_config(struct comedi_device *dev,
                                struct comedi_insn *insn,
                                unsigned int *data)
 {
-       unsigned int chan = CR_CHAN(insn->chanspec);
-       unsigned int mask;
-       int ret;
+       unsigned int chan_mask = 1 << CR_CHAN(insn->chanspec);
+       unsigned int bits;
 
-       if (chan < 8)
-               mask = 0x000000ff;
-       else if (chan < 16)
-               mask = 0x0000ff00;
-       else if (chan < 24)
-               mask = 0x00ff0000;
+       /*
+        * Each 8-bit "port" is configurable as either input or
+        * output. Changing the configuration of any channel in
+        * a port changes the entire port.
+        */
+       if (chan_mask & 0x000000ff)
+               bits = 0x000000ff;
+       else if (chan_mask & 0x0000ff00)
+               bits = 0x0000ff00;
+       else if (chan_mask & 0x00ff0000)
+               bits = 0x00ff0000;
        else
-               mask = 0xff000000;
-
-       ret = comedi_dio_insn_config(dev, s, insn, data, mask);
-       if (ret)
-               return ret;
+               bits = 0xff000000;
+
+       switch (data[0]) {
+       case INSN_CONFIG_DIO_INPUT:
+               s->io_bits &= ~bits;
+               break;
+       case INSN_CONFIG_DIO_OUTPUT:
+               s->io_bits |= bits;
+               break;
+       case INSN_CONFIG_DIO_QUERY:
+               data[1] = (s->io_bits & bits) ? COMEDI_INPUT : COMEDI_OUTPUT;
+               return insn->n;
+       default:
+               return -EINVAL;
+       }
 
        outl(s->io_bits, dev->iobase + APCI16XX_DIR_REG(s->index));
 
index cf5dd10eaf91daa71cb75ced4270c450d49d31de..dbc0678027ca79b879661d0c03501b14c4960987 100644 (file)
@@ -686,28 +686,38 @@ static int apci3xxx_dio_insn_config(struct comedi_device *dev,
                                    unsigned int *data)
 {
        unsigned int chan = CR_CHAN(insn->chanspec);
-       unsigned int mask;
-       int ret;
+       unsigned int mask = 1 << chan;
+       unsigned int bits;
 
        /*
         * Port 0 (channels 0-7) are always inputs
         * Port 1 (channels 8-15) are always outputs
         * Port 2 (channels 16-23) are programmable i/o
+        *
+        * Changing any channel in port 2 changes the entire port.
         */
-       if (chan < 16) {
-               if (data[0] != INSN_CONFIG_DIO_QUERY)
-                       return -EINVAL;
-       } else {
-               /* changing any channel in port 2 changes the entire port */
-               mask = 0xff0000;
+       if (mask & 0xff0000)
+               bits = 0xff0000;
+       else
+               bits = 0;
+
+       switch (data[0]) {
+       case INSN_CONFIG_DIO_INPUT:
+               s->io_bits &= ~bits;
+               break;
+       case INSN_CONFIG_DIO_OUTPUT:
+               s->io_bits |= bits;
+               break;
+       case INSN_CONFIG_DIO_QUERY:
+               data[1] = (s->io_bits & bits) ? COMEDI_OUTPUT : COMEDI_INPUT;
+               return insn->n;
+       default:
+               return -EINVAL;
        }
 
-       ret = comedi_dio_insn_config(dev, s, insn, data, mask);
-       if (ret)
-               return ret;
-
        /* update port 2 configuration */
-       outl((s->io_bits >> 24) & 0xff, dev->iobase + 224);
+       if (bits)
+               outl((s->io_bits >> 24) & 0xff, dev->iobase + 224);
 
        return insn->n;
 }
index b793d6987b843366654ac9935b0546ade9230f10..f914fb1f571be13fd248203765a00b5a788a984f 100644 (file)
@@ -180,29 +180,38 @@ static int pci1723_dio_insn_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;
-       unsigned short mode;
-       int ret;
+       unsigned int bits;
+       unsigned short dio_mode;
 
-       if (chan < 8)
-               mask = 0x00ff;
+       mask = 1 << CR_CHAN(insn->chanspec);
+       if (mask & 0x00FF)
+               bits = 0x00FF;
        else
-               mask = 0xff00;
+               bits = 0xFF00;
 
-       ret = comedi_dio_insn_config(dev, s, insn, data, mask);
-       if (ret)
-               return ret;
+       switch (data[0]) {
+       case INSN_CONFIG_DIO_INPUT:
+               s->io_bits &= ~bits;
+               break;
+       case INSN_CONFIG_DIO_OUTPUT:
+               s->io_bits |= bits;
+               break;
+       case INSN_CONFIG_DIO_QUERY:
+               data[1] = (s->io_bits & bits) ? COMEDI_OUTPUT : COMEDI_INPUT;
+               return insn->n;
+       default:
+               return -EINVAL;
+       }
 
        /* update hardware DIO mode */
-       mode = 0x0000;                  /* assume output */
-       if (!(s->io_bits & 0x00ff))
-               mode |= 0x0001;         /* low byte input */
-       if (!(s->io_bits & 0xff00))
-               mode |= 0x0002;         /* high byte input */
-       outw(mode, dev->iobase + PCI1723_DIGITAL_IO_PORT_SET);
-
-       return insn->n;
+       dio_mode = 0x0000;      /* low byte output, high byte output */
+       if ((s->io_bits & 0x00FF) == 0)
+               dio_mode |= 0x0001;     /* low byte input */
+       if ((s->io_bits & 0xFF00) == 0)
+               dio_mode |= 0x0002;     /* high byte input */
+       outw(dio_mode, dev->iobase + PCI1723_DIGITAL_IO_PORT_SET);
+       return 1;
 }
 
 /*
index c1f723e8614613826d9753e07ec6af5044f925a7..32c490b27b55505de50241662e4682b80ff9b021 100644 (file)
@@ -976,26 +976,34 @@ static int dio200_subdev_8255_config(struct comedi_device *dev,
                                     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;
+       unsigned int bits;
+
+       mask = 1 << CR_CHAN(insn->chanspec);
+       if (mask & 0x0000ff)
+               bits = 0x0000ff;
+       else if (mask & 0x00ff00)
+               bits = 0x00ff00;
+       else if (mask & 0x0f0000)
+               bits = 0x0f0000;
        else
-               mask = 0xf00000;
-
-       ret = comedi_dio_insn_config(dev, s, insn, data, mask);
-       if (ret)
-               return ret;
-
+               bits = 0xf00000;
+       switch (data[0]) {
+       case INSN_CONFIG_DIO_INPUT:
+               s->io_bits &= ~bits;
+               break;
+       case INSN_CONFIG_DIO_OUTPUT:
+               s->io_bits |= bits;
+               break;
+       case INSN_CONFIG_DIO_QUERY:
+               data[1] = (s->io_bits & bits) ? COMEDI_OUTPUT : COMEDI_INPUT;
+               return insn->n;
+               break;
+       default:
+               return -EINVAL;
+       }
        dio200_subdev_8255_set_dir(dev, s);
-
-       return insn->n;
+       return 1;
 }
 
 /*
index 0ce93da70847c566fd328ae21ae80f258fade0f1..05e01a3b5af6aed51fb2f31e15e542cf3c5d440d 100644 (file)
@@ -341,22 +341,33 @@ static int das16cs_dio_insn_bits(struct comedi_device *dev,
 
 static int das16cs_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)
 {
        struct das16cs_private *devpriv = dev->private;
-       unsigned int chan = CR_CHAN(insn->chanspec);
-       unsigned int mask;
-       int ret;
+       int chan = CR_CHAN(insn->chanspec);
+       int bits;
 
        if (chan < 4)
-               mask = 0x0f;
+               bits = 0x0f;
        else
-               mask = 0xf0;
+               bits = 0xf0;
 
-       ret = comedi_dio_insn_config(dev, s, insn, data, mask);
-       if (ret)
-               return ret;
+       switch (data[0]) {
+       case INSN_CONFIG_DIO_OUTPUT:
+               s->io_bits |= bits;
+               break;
+       case INSN_CONFIG_DIO_INPUT:
+               s->io_bits &= bits;
+               break;
+       case INSN_CONFIG_DIO_QUERY:
+               data[1] =
+                   (s->io_bits & (1 << chan)) ? COMEDI_OUTPUT : COMEDI_INPUT;
+               return insn->n;
+               break;
+       default:
+               return -EINVAL;
+               break;
+       }
 
        devpriv->status2 &= ~0x00c0;
        devpriv->status2 |= (s->io_bits & 0xf0) ? 0x0080 : 0;
index 38918a1198aa83cfbcc717f69be05c074b9bd7aa..e0e7beab7274b255c79e079fa94a5e190b2a13f6 100644 (file)
@@ -551,19 +551,32 @@ static int dt2801_dio_insn_bits(struct comedi_device *dev,
 
 static int dt2801_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)
 {
-       int ret;
+       int which = 0;
 
-       ret = comedi_dio_insn_config(dev, s, insn, data, 0xff);
-       if (ret)
-               return ret;
+       if (s == &dev->subdevices[3])
+               which = 1;
 
-       dt2801_writecmd(dev, s->io_bits ? DT_C_SET_DIGOUT : DT_C_SET_DIGIN);
-       dt2801_writedata(dev, (s == &dev->subdevices[3]) ? 1 : 0);
+       /* configure */
+       switch (data[0]) {
+       case INSN_CONFIG_DIO_OUTPUT:
+               s->io_bits = 0xff;
+               dt2801_writecmd(dev, DT_C_SET_DIGOUT);
+               break;
+       case INSN_CONFIG_DIO_INPUT:
+               s->io_bits = 0;
+               dt2801_writecmd(dev, DT_C_SET_DIGIN);
+               break;
+       case INSN_CONFIG_DIO_QUERY:
+               data[1] = s->io_bits ? COMEDI_OUTPUT : COMEDI_INPUT;
+               return insn->n;
+       default:
+               return -EINVAL;
+       }
+       dt2801_writedata(dev, which);
 
-       return insn->n;
+       return 1;
 }
 
 /*
index 64ef87598b607deffe7b9a11999c753defbce126..e4748da1993b8dc13cab8176616f4583c6491a31 100644 (file)
@@ -642,23 +642,32 @@ static void dt3k_dio_config(struct comedi_device *dev, int bits)
 
 static int dt3k_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;
-       int ret;
-
-       if (chan < 4)
-               mask = 0x0f;
-       else
-               mask = 0xf0;
-
-       ret = comedi_dio_insn_config(dev, s, insn, data, mask);
-       if (ret)
-               return ret;
-
-       dt3k_dio_config(dev, (s->io_bits & 0x01) | ((s->io_bits & 0x10) >> 3));
+       int mask;
+
+       mask = (CR_CHAN(insn->chanspec) < 4) ? 0x0f : 0xf0;
+
+       switch (data[0]) {
+       case INSN_CONFIG_DIO_OUTPUT:
+               s->io_bits |= mask;
+               break;
+       case INSN_CONFIG_DIO_INPUT:
+               s->io_bits &= ~mask;
+               break;
+       case INSN_CONFIG_DIO_QUERY:
+               data[1] =
+                   (s->
+                    io_bits & (1 << CR_CHAN(insn->chanspec))) ? COMEDI_OUTPUT :
+                   COMEDI_INPUT;
+               return insn->n;
+               break;
+       default:
+               return -EINVAL;
+               break;
+       }
+       mask = (s->io_bits & 0x01) | ((s->io_bits & 0x10) >> 3);
+       dt3k_dio_config(dev, mask);
 
        return insn->n;
 }
index 559bf5583530c2e2796ece8ad712dcec22514fa1..cdcc8f42e20935bd477b7385badf977ac7761a4f 100644 (file)
@@ -224,26 +224,37 @@ struct hpdi_private {
        volatile uint32_t bits[24];
        /* number of bytes at which to generate COMEDI_CB_BLOCK events */
        volatile unsigned int block_size;
+       unsigned dio_config_output:1;
 };
 
 static int dio_config_insn(struct comedi_device *dev,
-                          struct comedi_subdevice *s,
-                          struct comedi_insn *insn,
+                          struct comedi_subdevice *s, struct comedi_insn *insn,
                           unsigned int *data)
 {
-       int ret;
+       struct hpdi_private *devpriv = dev->private;
 
        switch (data[0]) {
+       case INSN_CONFIG_DIO_OUTPUT:
+               devpriv->dio_config_output = 1;
+               return insn->n;
+               break;
+       case INSN_CONFIG_DIO_INPUT:
+               devpriv->dio_config_output = 0;
+               return insn->n;
+               break;
+       case INSN_CONFIG_DIO_QUERY:
+               data[1] =
+                   devpriv->dio_config_output ? COMEDI_OUTPUT : COMEDI_INPUT;
+               return insn->n;
+               break;
        case INSN_CONFIG_BLOCK_SIZE:
                return dio_config_block_size(dev, data);
+               break;
        default:
-               ret = comedi_dio_insn_config(dev, s, insn, data, 0xffffffff);
-               if (ret)
-                       return ret;
                break;
        }
 
-       return insn->n;
+       return -EINVAL;
 }
 
 static void disable_plx_interrupts(struct comedi_device *dev)
@@ -662,7 +673,9 @@ static int di_cmd_test(struct comedi_device *dev, struct comedi_subdevice *s,
 static int hpdi_cmd_test(struct comedi_device *dev, struct comedi_subdevice *s,
                         struct comedi_cmd *cmd)
 {
-       if (s->io_bits)
+       struct hpdi_private *devpriv = dev->private;
+
+       if (devpriv->dio_config_output)
                return -EINVAL;
        else
                return di_cmd_test(dev, s, cmd);
@@ -733,7 +746,9 @@ static int di_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 
 static int hpdi_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 {
-       if (s->io_bits)
+       struct hpdi_private *devpriv = dev->private;
+
+       if (devpriv->dio_config_output)
                return -EINVAL;
        else
                return di_cmd(dev, s);
index 5c3a318b464012bff1f5a44c2788e20008399ed7..954c5397f33c84630b3726c8f3ab45f584ae8d76 100644 (file)
@@ -350,22 +350,31 @@ static int ii20k_dio_insn_config(struct comedi_device *dev,
                                 struct comedi_insn *insn,
                                 unsigned int *data)
 {
-       unsigned int chan = CR_CHAN(insn->chanspec);
-       unsigned int mask;
-       int ret;
-
-       if (chan < 8)
-               mask = 0x000000ff;
-       else if (chan < 16)
-               mask = 0x0000ff00;
-       else if (chan < 24)
-               mask = 0x00ff0000;
+       unsigned int mask = 1 << CR_CHAN(insn->chanspec);
+       unsigned int bits;
+
+       if (mask & 0x000000ff)
+               bits = 0x000000ff;
+       else if (mask & 0x0000ff00)
+               bits = 0x0000ff00;
+       else if (mask & 0x00ff0000)
+               bits = 0x00ff0000;
        else
-               mask = 0xff000000;
+               bits = 0xff000000;
 
-       ret = comedi_dio_insn_config(dev, s, insn, data, mask);
-       if (ret)
-               return ret;
+       switch (data[0]) {
+       case INSN_CONFIG_DIO_INPUT:
+               s->io_bits &= ~bits;
+               break;
+       case INSN_CONFIG_DIO_OUTPUT:
+               s->io_bits |= bits;
+               break;
+       case INSN_CONFIG_DIO_QUERY:
+               data[1] = (s->io_bits & bits) ? COMEDI_OUTPUT : COMEDI_INPUT;
+               return insn->n;
+       default:
+               return -EINVAL;
+       }
 
        ii20k_dio_config(dev, s);
 
index 8f4afadab76a617a526da821d3ac029562eadf3c..1eda40a9332ee04ba801e86670f310c333bdccb4 100644 (file)
@@ -1358,57 +1358,98 @@ static int me4000_dio_insn_bits(struct comedi_device *dev,
 
 static int me4000_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 tmp;
-       int ret;
+       unsigned long tmp;
+       int chan = CR_CHAN(insn->chanspec);
 
-       if (chan < 8)
-               mask = 0x000000ff;
-       else if (chan < 16)
-               mask = 0x0000ff00;
-       else if (chan < 24)
-               mask = 0x00ff0000;
-       else
-               mask = 0xff000000;
+       switch (data[0]) {
+       default:
+               return -EINVAL;
+       case INSN_CONFIG_DIO_QUERY:
+               data[1] =
+                   (s->io_bits & (1 << chan)) ? COMEDI_OUTPUT : COMEDI_INPUT;
+               return insn->n;
+       case INSN_CONFIG_DIO_INPUT:
+       case INSN_CONFIG_DIO_OUTPUT:
+               break;
+       }
 
-       ret = comedi_dio_insn_config(dev, s, insn, data, mask);
-       if (ret)
-               return ret;
+       /*
+        * The input or output configuration of each digital line is
+        * configured by a special insn_config instruction.  chanspec
+        * contains the channel to be changed, and data[0] contains the
+        * value INSN_CONFIG_DIO_INPUT or INSN_CONFIG_DIO_OUTPUT.
+        * On the ME-4000 it is only possible to switch port wise (8 bit)
+        */
 
        tmp = inl(dev->iobase + ME4000_DIO_CTRL_REG);
-       tmp &= ~(ME4000_DIO_CTRL_BIT_MODE_0 | ME4000_DIO_CTRL_BIT_MODE_1 |
-                ME4000_DIO_CTRL_BIT_MODE_2 | ME4000_DIO_CTRL_BIT_MODE_3 |
-                ME4000_DIO_CTRL_BIT_MODE_4 | ME4000_DIO_CTRL_BIT_MODE_5 |
-                ME4000_DIO_CTRL_BIT_MODE_6 | ME4000_DIO_CTRL_BIT_MODE_7);
-       if (s->io_bits & 0x000000ff)
-               tmp |= ME4000_DIO_CTRL_BIT_MODE_0;
-       if (s->io_bits & 0x0000ff00)
-               tmp |= ME4000_DIO_CTRL_BIT_MODE_2;
-       if (s->io_bits & 0x00ff0000)
-               tmp |= ME4000_DIO_CTRL_BIT_MODE_4;
-       if (s->io_bits & 0xff000000)
-               tmp |= ME4000_DIO_CTRL_BIT_MODE_6;
 
-       /*
-        * Check for optoisolated ME-4000 version.
-        * If one the first port is a fixed output
-        * port and the second is a fixed input port.
-        */
-       if (inl(dev->iobase + ME4000_DIO_DIR_REG)) {
-               s->io_bits |= 0x000000ff;
-               s->io_bits &= ~0x0000ff00;
-               tmp |= ME4000_DIO_CTRL_BIT_MODE_0;
-               tmp &= ~(ME4000_DIO_CTRL_BIT_MODE_2 |
-                        ME4000_DIO_CTRL_BIT_MODE_3);
+       if (data[0] == INSN_CONFIG_DIO_OUTPUT) {
+               if (chan < 8) {
+                       s->io_bits |= 0xFF;
+                       tmp &= ~(ME4000_DIO_CTRL_BIT_MODE_0 |
+                                ME4000_DIO_CTRL_BIT_MODE_1);
+                       tmp |= ME4000_DIO_CTRL_BIT_MODE_0;
+               } else if (chan < 16) {
+                       /*
+                        * Chech for optoisolated ME-4000 version.
+                        * If one the first port is a fixed output
+                        * port and the second is a fixed input port.
+                        */
+                       if (!inl(dev->iobase + ME4000_DIO_DIR_REG))
+                               return -ENODEV;
+
+                       s->io_bits |= 0xFF00;
+                       tmp &= ~(ME4000_DIO_CTRL_BIT_MODE_2 |
+                                ME4000_DIO_CTRL_BIT_MODE_3);
+                       tmp |= ME4000_DIO_CTRL_BIT_MODE_2;
+               } else if (chan < 24) {
+                       s->io_bits |= 0xFF0000;
+                       tmp &= ~(ME4000_DIO_CTRL_BIT_MODE_4 |
+                                ME4000_DIO_CTRL_BIT_MODE_5);
+                       tmp |= ME4000_DIO_CTRL_BIT_MODE_4;
+               } else if (chan < 32) {
+                       s->io_bits |= 0xFF000000;
+                       tmp &= ~(ME4000_DIO_CTRL_BIT_MODE_6 |
+                                ME4000_DIO_CTRL_BIT_MODE_7);
+                       tmp |= ME4000_DIO_CTRL_BIT_MODE_6;
+               } else {
+                       return -EINVAL;
+               }
+       } else {
+               if (chan < 8) {
+                       /*
+                        * Chech for optoisolated ME-4000 version.
+                        * If one the first port is a fixed output
+                        * port and the second is a fixed input port.
+                        */
+                       if (!inl(dev->iobase + ME4000_DIO_DIR_REG))
+                               return -ENODEV;
+
+                       s->io_bits &= ~0xFF;
+                       tmp &= ~(ME4000_DIO_CTRL_BIT_MODE_0 |
+                                ME4000_DIO_CTRL_BIT_MODE_1);
+               } else if (chan < 16) {
+                       s->io_bits &= ~0xFF00;
+                       tmp &= ~(ME4000_DIO_CTRL_BIT_MODE_2 |
+                                ME4000_DIO_CTRL_BIT_MODE_3);
+               } else if (chan < 24) {
+                       s->io_bits &= ~0xFF0000;
+                       tmp &= ~(ME4000_DIO_CTRL_BIT_MODE_4 |
+                                ME4000_DIO_CTRL_BIT_MODE_5);
+               } else if (chan < 32) {
+                       s->io_bits &= ~0xFF000000;
+                       tmp &= ~(ME4000_DIO_CTRL_BIT_MODE_6 |
+                                ME4000_DIO_CTRL_BIT_MODE_7);
+               } else {
+                       return -EINVAL;
+               }
        }
 
        outl(tmp, dev->iobase + ME4000_DIO_CTRL_REG);
 
-       return insn->n;
+       return 1;
 }
 
 /*=============================================================================
index a6f6d4a46587f06d1b84ba53a45df3ebcf150821..e8a743c2f9a166a160ab50f09f9b8f0870a96f60 100644 (file)
@@ -186,30 +186,38 @@ static int me_dio_insn_config(struct comedi_device *dev,
                              struct comedi_insn *insn,
                              unsigned int *data)
 {
-       struct me_private_data *devpriv = dev->private;
-       unsigned int chan = CR_CHAN(insn->chanspec);
-       unsigned int mask;
-       int ret;
-
-       if (chan < 16)
-               mask = 0x0000ffff;
-       else
-               mask = 0xffff0000;
+       struct me_private_data *dev_private = dev->private;
+       unsigned int mask = 1 << CR_CHAN(insn->chanspec);
+       unsigned int bits;
+       unsigned int port;
 
-       ret = comedi_dio_insn_config(dev, s, insn, data, mask);
-       if (ret)
-               return ret;
+       if (mask & 0x0000ffff) {
+               bits = 0x0000ffff;
+               port = ENABLE_PORT_A;
+       } else {
+               bits = 0xffff0000;
+               port = ENABLE_PORT_B;
+       }
 
-       if (s->io_bits & 0x0000ffff)
-               devpriv->control_2 |= ENABLE_PORT_A;
-       else
-               devpriv->control_2 &= ~ENABLE_PORT_A;
-       if (s->io_bits & 0xffff0000)
-               devpriv->control_2 |= ENABLE_PORT_B;
-       else
-               devpriv->control_2 &= ~ENABLE_PORT_B;
+       switch (data[0]) {
+       case INSN_CONFIG_DIO_INPUT:
+               s->io_bits &= ~bits;
+               dev_private->control_2 &= ~port;
+               break;
+       case INSN_CONFIG_DIO_OUTPUT:
+               s->io_bits |= bits;
+               dev_private->control_2 |= port;
+               break;
+       case INSN_CONFIG_DIO_QUERY:
+               data[1] = (s->io_bits & bits) ? COMEDI_OUTPUT : COMEDI_INPUT;
+               return insn->n;
+               break;
+       default:
+               return -EINVAL;
+       }
 
-       writew(devpriv->control_2, devpriv->me_regbase + ME_CONTROL_2);
+       /* Update the port configuration */
+       writew(dev_private->control_2, dev_private->me_regbase + ME_CONTROL_2);
 
        return insn->n;
 }
index b9122fd835e1e714cec811c43d2c6c1a51675e9e..0025496bc643caf04b2c74374f65c4e642de3592 100644 (file)
@@ -248,35 +248,42 @@ static int atao_dio_insn_bits(struct comedi_device *dev,
 
 static int atao_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)
 {
        struct atao_private *devpriv = dev->private;
-       unsigned int chan = CR_CHAN(insn->chanspec);
-       unsigned int mask;
-       int ret;
-
-       if (chan < 4)
-               mask = 0x0f;
-       else
-               mask = 0xf0;
-
-       ret = comedi_dio_insn_config(dev, s, insn, data, mask);
-       if (ret)
-               return ret;
-
-       if (s->io_bits & 0x0f)
-               devpriv->cfg3 |= DOUTEN1;
-       else
-               devpriv->cfg3 &= ~DOUTEN1;
-       if (s->io_bits & 0xf0)
-               devpriv->cfg3 |= DOUTEN2;
-       else
-               devpriv->cfg3 &= ~DOUTEN2;
+       int chan = CR_CHAN(insn->chanspec);
+       unsigned int mask, bit;
+
+       /* The input or output configuration of each digital line is
+        * configured by a special insn_config instruction.  chanspec
+        * contains the channel to be changed, and data[0] contains the
+        * value COMEDI_INPUT or COMEDI_OUTPUT. */
+
+       mask = (chan < 4) ? 0x0f : 0xf0;
+       bit = (chan < 4) ? DOUTEN1 : DOUTEN2;
+
+       switch (data[0]) {
+       case INSN_CONFIG_DIO_OUTPUT:
+               s->io_bits |= mask;
+               devpriv->cfg3 |= bit;
+               break;
+       case INSN_CONFIG_DIO_INPUT:
+               s->io_bits &= ~mask;
+               devpriv->cfg3 &= ~bit;
+               break;
+       case INSN_CONFIG_DIO_QUERY:
+               data[1] =
+                   (s->io_bits & (1 << chan)) ? COMEDI_OUTPUT : COMEDI_INPUT;
+               return insn->n;
+               break;
+       default:
+               return -EINVAL;
+               break;
+       }
 
        outw(devpriv->cfg3, dev->iobase + ATAO_CFG3);
 
-       return insn->n;
+       return 1;
 }
 
 /*
index cc1dc7f66e5b5868d4c717b352a9e54e8785c149..cca972ebd010edb604a07986113a48b4af02ffd7 100644 (file)
@@ -184,30 +184,39 @@ static void enable_chan(struct comedi_device *dev, struct comedi_subdevice *s,
 /* overriding the 8255 insn config */
 static int subdev_3724_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;
-       int ret;
-
-       if (chan < 8)
-               mask = 0x0000ff;
-       else if (chan < 16)
-               mask = 0x00ff00;
-       else if (chan < 20)
-               mask = 0x0f0000;
+       unsigned int bits;
+
+       mask = 1 << CR_CHAN(insn->chanspec);
+       if (mask & 0x0000ff)
+               bits = 0x0000ff;
+       else if (mask & 0x00ff00)
+               bits = 0x00ff00;
+       else if (mask & 0x0f0000)
+               bits = 0x0f0000;
        else
-               mask = 0xf00000;
-
-       ret = comedi_dio_insn_config(dev, s, insn, data, mask);
-       if (ret)
-               return ret;
+               bits = 0xf00000;
+
+       switch (data[0]) {
+       case INSN_CONFIG_DIO_INPUT:
+               s->io_bits &= ~bits;
+               break;
+       case INSN_CONFIG_DIO_OUTPUT:
+               s->io_bits |= bits;
+               break;
+       case INSN_CONFIG_DIO_QUERY:
+               data[1] = (s->io_bits & bits) ? COMEDI_OUTPUT : COMEDI_INPUT;
+               return insn->n;
+               break;
+       default:
+               return -EINVAL;
+       }
 
        do_3724_config(dev, s, insn->chanspec);
        enable_chan(dev, s, insn->chanspec);
-
-       return insn->n;
+       return 1;
 }
 
 static int pcm3724_attach(struct comedi_device *dev,
index d629463b85a2ae38ba7c97d8329633ce606b7c1c..6670b865256b3aa4ba6652fae636532d00053b63 100644 (file)
@@ -515,35 +515,32 @@ static int s526_dio_insn_bits(struct comedi_device *dev,
 
 static int s526_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;
-       int ret;
-
-       if (chan < 4)
-               mask = 0x0f;
-       else
-               mask = 0xf0;
-
-       ret = comedi_dio_insn_config(dev, s, insn, data, mask);
-       if (ret)
-               return ret;
-
-       /* bit 10/11 set the group 1/2's mode */
-       if (s->io_bits & 0x0f)
-               s->state |= (1 << 10);
-       else
-               s->state &= ~(1 << 10);
-       if (s->io_bits & 0xf0)
-               s->state |= (1 << 11);
-       else
-               s->state &= ~(1 << 11);
+       int group, mask;
 
+       group = chan >> 2;
+       mask = 0xF << (group << 2);
+       switch (data[0]) {
+       case INSN_CONFIG_DIO_OUTPUT:
+               /* bit 10/11 set the group 1/2's mode */
+               s->state |= 1 << (group + 10);
+               s->io_bits |= mask;
+               break;
+       case INSN_CONFIG_DIO_INPUT:
+               s->state &= ~(1 << (group + 10)); /* 1 is output, 0 is input. */
+               s->io_bits &= ~mask;
+               break;
+       case INSN_CONFIG_DIO_QUERY:
+               data[1] = (s->io_bits & mask) ? COMEDI_OUTPUT : COMEDI_INPUT;
+               return insn->n;
+       default:
+               return -EINVAL;
+       }
        outw(s->state, dev->iobase + REG_DIO);
 
-       return insn->n;
+       return 1;
 }
 
 static int s526_attach(struct comedi_device *dev, struct comedi_devconfig *it)