Add the rt linux 4.1.3-rt3 as base
[kvmfornfv.git] / kernel / drivers / staging / comedi / drivers / pcl724.c
diff --git a/kernel/drivers/staging/comedi/drivers/pcl724.c b/kernel/drivers/staging/comedi/drivers/pcl724.c
new file mode 100644 (file)
index 0000000..74b07e1
--- /dev/null
@@ -0,0 +1,152 @@
+/*
+ * pcl724.c
+ * Comedi driver for 8255 based ISA and PC/104 DIO boards
+ *
+ * Michal Dobes <dobes@tesnet.cz>
+ */
+
+/*
+ * Driver: pcl724
+ * Description: Comedi driver for 8255 based ISA DIO boards
+ * Devices: [Advantech] PCL-724 (pcl724), PCL-722 (pcl722), PCL-731 (pcl731),
+ *  [ADLink] ACL-7122 (acl7122), ACL-7124 (acl7124), PET-48DIO (pet48dio),
+ *  [WinSystems] PCM-IO48 (pcmio48),
+ *  [Diamond Systems] ONYX-MM-DIO (onyx-mm-dio)
+ * Author: Michal Dobes <dobes@tesnet.cz>
+ * Status: untested
+ *
+ * Configuration options:
+ *   [0] - IO Base
+ *   [1] - IRQ (not supported)
+ *   [2] - number of DIO (pcl722 and acl7122 boards)
+ *        0, 144: 144 DIO configuration
+ *        1,  96:  96 DIO configuration
+ */
+
+#include <linux/module.h>
+#include "../comedidev.h"
+
+#include "8255.h"
+
+struct pcl724_board {
+       const char *name;
+       unsigned int io_range;
+       unsigned int can_have96:1;
+       unsigned int is_pet48:1;
+       int numofports;
+};
+
+static const struct pcl724_board boardtypes[] = {
+       {
+               .name           = "pcl724",
+               .io_range       = 0x04,
+               .numofports     = 1,    /* 24 DIO channels */
+       }, {
+               .name           = "pcl722",
+               .io_range       = 0x20,
+               .can_have96     = 1,
+               .numofports     = 6,    /* 144 (or 96) DIO channels */
+       }, {
+               .name           = "pcl731",
+               .io_range       = 0x08,
+               .numofports     = 2,    /* 48 DIO channels */
+       }, {
+               .name           = "acl7122",
+               .io_range       = 0x20,
+               .can_have96     = 1,
+               .numofports     = 6,    /* 144 (or 96) DIO channels */
+       }, {
+               .name           = "acl7124",
+               .io_range       = 0x04,
+               .numofports     = 1,    /* 24 DIO channels */
+       }, {
+               .name           = "pet48dio",
+               .io_range       = 0x02,
+               .is_pet48       = 1,
+               .numofports     = 2,    /* 48 DIO channels */
+       }, {
+               .name           = "pcmio48",
+               .io_range       = 0x08,
+               .numofports     = 2,    /* 48 DIO channels */
+       }, {
+               .name           = "onyx-mm-dio",
+               .io_range       = 0x10,
+               .numofports     = 2,    /* 48 DIO channels */
+       },
+};
+
+static int pcl724_8255mapped_io(struct comedi_device *dev,
+                               int dir, int port, int data,
+                               unsigned long iobase)
+{
+       int movport = I8255_SIZE * (iobase >> 12);
+
+       iobase &= 0x0fff;
+
+       outb(port + movport, iobase);
+       if (dir) {
+               outb(data, iobase + 1);
+               return 0;
+       }
+       return inb(iobase + 1);
+}
+
+static int pcl724_attach(struct comedi_device *dev,
+                        struct comedi_devconfig *it)
+{
+       const struct pcl724_board *board = dev->board_ptr;
+       struct comedi_subdevice *s;
+       unsigned long iobase;
+       unsigned int iorange;
+       int n_subdevices;
+       int ret;
+       int i;
+
+       iorange = board->io_range;
+       n_subdevices = board->numofports;
+
+       /* Handle PCL-724 in 96 DIO configuration */
+       if (board->can_have96 &&
+           (it->options[2] == 1 || it->options[2] == 96)) {
+               iorange = 0x10;
+               n_subdevices = 4;
+       }
+
+       ret = comedi_request_region(dev, it->options[0], iorange);
+       if (ret)
+               return ret;
+
+       ret = comedi_alloc_subdevices(dev, n_subdevices);
+       if (ret)
+               return ret;
+
+       for (i = 0; i < dev->n_subdevices; i++) {
+               s = &dev->subdevices[i];
+               if (board->is_pet48) {
+                       iobase = dev->iobase + (i * 0x1000);
+                       ret = subdev_8255_init(dev, s, pcl724_8255mapped_io,
+                                              iobase);
+               } else {
+                       ret = subdev_8255_init(dev, s, NULL, i * I8255_SIZE);
+               }
+               if (ret)
+                       return ret;
+       }
+
+       return 0;
+}
+
+static struct comedi_driver pcl724_driver = {
+       .driver_name    = "pcl724",
+       .module         = THIS_MODULE,
+       .attach         = pcl724_attach,
+       .detach         = comedi_legacy_detach,
+       .board_name     = &boardtypes[0].name,
+       .num_names      = ARRAY_SIZE(boardtypes),
+       .offset         = sizeof(struct pcl724_board),
+};
+module_comedi_driver(pcl724_driver);
+
+MODULE_AUTHOR("Comedi http://www.comedi.org");
+MODULE_DESCRIPTION("Comedi driver for 8255 based ISA and PC/104 DIO boards");
+MODULE_LICENSE("GPL");