Add the rt linux 4.1.3-rt3 as base
[kvmfornfv.git] / kernel / drivers / staging / comedi / drivers / pcl724.c
1 /*
2  * pcl724.c
3  * Comedi driver for 8255 based ISA and PC/104 DIO boards
4  *
5  * Michal Dobes <dobes@tesnet.cz>
6  */
7
8 /*
9  * Driver: pcl724
10  * Description: Comedi driver for 8255 based ISA DIO boards
11  * Devices: [Advantech] PCL-724 (pcl724), PCL-722 (pcl722), PCL-731 (pcl731),
12  *  [ADLink] ACL-7122 (acl7122), ACL-7124 (acl7124), PET-48DIO (pet48dio),
13  *  [WinSystems] PCM-IO48 (pcmio48),
14  *  [Diamond Systems] ONYX-MM-DIO (onyx-mm-dio)
15  * Author: Michal Dobes <dobes@tesnet.cz>
16  * Status: untested
17  *
18  * Configuration options:
19  *   [0] - IO Base
20  *   [1] - IRQ (not supported)
21  *   [2] - number of DIO (pcl722 and acl7122 boards)
22  *         0, 144: 144 DIO configuration
23  *         1,  96:  96 DIO configuration
24  */
25
26 #include <linux/module.h>
27 #include "../comedidev.h"
28
29 #include "8255.h"
30
31 struct pcl724_board {
32         const char *name;
33         unsigned int io_range;
34         unsigned int can_have96:1;
35         unsigned int is_pet48:1;
36         int numofports;
37 };
38
39 static const struct pcl724_board boardtypes[] = {
40         {
41                 .name           = "pcl724",
42                 .io_range       = 0x04,
43                 .numofports     = 1,    /* 24 DIO channels */
44         }, {
45                 .name           = "pcl722",
46                 .io_range       = 0x20,
47                 .can_have96     = 1,
48                 .numofports     = 6,    /* 144 (or 96) DIO channels */
49         }, {
50                 .name           = "pcl731",
51                 .io_range       = 0x08,
52                 .numofports     = 2,    /* 48 DIO channels */
53         }, {
54                 .name           = "acl7122",
55                 .io_range       = 0x20,
56                 .can_have96     = 1,
57                 .numofports     = 6,    /* 144 (or 96) DIO channels */
58         }, {
59                 .name           = "acl7124",
60                 .io_range       = 0x04,
61                 .numofports     = 1,    /* 24 DIO channels */
62         }, {
63                 .name           = "pet48dio",
64                 .io_range       = 0x02,
65                 .is_pet48       = 1,
66                 .numofports     = 2,    /* 48 DIO channels */
67         }, {
68                 .name           = "pcmio48",
69                 .io_range       = 0x08,
70                 .numofports     = 2,    /* 48 DIO channels */
71         }, {
72                 .name           = "onyx-mm-dio",
73                 .io_range       = 0x10,
74                 .numofports     = 2,    /* 48 DIO channels */
75         },
76 };
77
78 static int pcl724_8255mapped_io(struct comedi_device *dev,
79                                 int dir, int port, int data,
80                                 unsigned long iobase)
81 {
82         int movport = I8255_SIZE * (iobase >> 12);
83
84         iobase &= 0x0fff;
85
86         outb(port + movport, iobase);
87         if (dir) {
88                 outb(data, iobase + 1);
89                 return 0;
90         }
91         return inb(iobase + 1);
92 }
93
94 static int pcl724_attach(struct comedi_device *dev,
95                          struct comedi_devconfig *it)
96 {
97         const struct pcl724_board *board = dev->board_ptr;
98         struct comedi_subdevice *s;
99         unsigned long iobase;
100         unsigned int iorange;
101         int n_subdevices;
102         int ret;
103         int i;
104
105         iorange = board->io_range;
106         n_subdevices = board->numofports;
107
108         /* Handle PCL-724 in 96 DIO configuration */
109         if (board->can_have96 &&
110             (it->options[2] == 1 || it->options[2] == 96)) {
111                 iorange = 0x10;
112                 n_subdevices = 4;
113         }
114
115         ret = comedi_request_region(dev, it->options[0], iorange);
116         if (ret)
117                 return ret;
118
119         ret = comedi_alloc_subdevices(dev, n_subdevices);
120         if (ret)
121                 return ret;
122
123         for (i = 0; i < dev->n_subdevices; i++) {
124                 s = &dev->subdevices[i];
125                 if (board->is_pet48) {
126                         iobase = dev->iobase + (i * 0x1000);
127                         ret = subdev_8255_init(dev, s, pcl724_8255mapped_io,
128                                                iobase);
129                 } else {
130                         ret = subdev_8255_init(dev, s, NULL, i * I8255_SIZE);
131                 }
132                 if (ret)
133                         return ret;
134         }
135
136         return 0;
137 }
138
139 static struct comedi_driver pcl724_driver = {
140         .driver_name    = "pcl724",
141         .module         = THIS_MODULE,
142         .attach         = pcl724_attach,
143         .detach         = comedi_legacy_detach,
144         .board_name     = &boardtypes[0].name,
145         .num_names      = ARRAY_SIZE(boardtypes),
146         .offset         = sizeof(struct pcl724_board),
147 };
148 module_comedi_driver(pcl724_driver);
149
150 MODULE_AUTHOR("Comedi http://www.comedi.org");
151 MODULE_DESCRIPTION("Comedi driver for 8255 based ISA and PC/104 DIO boards");
152 MODULE_LICENSE("GPL");