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