Commit | Line | Data |
---|---|---|
0e221af2 DS |
1 | /* |
2 | comedi/drivers/dt2817.c | |
3 | Hardware driver for Data Translation DT2817 | |
4 | ||
5 | COMEDI - Linux Control and Measurement Device Interface | |
6 | Copyright (C) 1998 David A. Schleef <ds@schleef.org> | |
7 | ||
8 | This program is free software; you can redistribute it and/or modify | |
9 | it under the terms of the GNU General Public License as published by | |
10 | the Free Software Foundation; either version 2 of the License, or | |
11 | (at your option) any later version. | |
12 | ||
13 | This program is distributed in the hope that it will be useful, | |
14 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
16 | GNU General Public License for more details. | |
17 | ||
18 | You should have received a copy of the GNU General Public License | |
19 | along with this program; if not, write to the Free Software | |
20 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |
21 | ||
22 | */ | |
23 | /* | |
24 | Driver: dt2817 | |
25 | Description: Data Translation DT2817 | |
26 | Author: ds | |
27 | Status: complete | |
28 | Devices: [Data Translation] DT2817 (dt2817) | |
29 | ||
30 | A very simple digital I/O card. Four banks of 8 lines, each bank | |
31 | is configurable for input or output. One wonders why it takes a | |
32 | 50 page manual to describe this thing. | |
33 | ||
34 | The driver (which, btw, is much less than 50 pages) has 1 subdevice | |
35 | with 32 channels, configurable in groups of 8. | |
36 | ||
37 | Configuration options: | |
38 | [0] - I/O port base base address | |
39 | */ | |
40 | ||
41 | #include "../comedidev.h" | |
42 | ||
43 | #include <linux/ioport.h> | |
44 | ||
45 | #define DT2817_SIZE 5 | |
46 | ||
47 | #define DT2817_CR 0 | |
48 | #define DT2817_DATA 1 | |
49 | ||
0a85b6f0 MT |
50 | static int dt2817_dio_insn_config(struct comedi_device *dev, |
51 | struct comedi_subdevice *s, | |
52 | struct comedi_insn *insn, unsigned int *data) | |
0e221af2 DS |
53 | { |
54 | int mask; | |
55 | int chan; | |
56 | int oe = 0; | |
57 | ||
58 | if (insn->n != 1) | |
59 | return -EINVAL; | |
60 | ||
61 | chan = CR_CHAN(insn->chanspec); | |
8cbf7a9e | 62 | if (chan < 8) |
0e221af2 | 63 | mask = 0xff; |
8cbf7a9e | 64 | else if (chan < 16) |
0e221af2 | 65 | mask = 0xff00; |
8cbf7a9e | 66 | else if (chan < 24) |
0e221af2 | 67 | mask = 0xff0000; |
8cbf7a9e | 68 | else |
0e221af2 DS |
69 | mask = 0xff000000; |
70 | if (data[0]) | |
71 | s->io_bits |= mask; | |
72 | else | |
73 | s->io_bits &= ~mask; | |
74 | ||
75 | if (s->io_bits & 0x000000ff) | |
76 | oe |= 0x1; | |
77 | if (s->io_bits & 0x0000ff00) | |
78 | oe |= 0x2; | |
79 | if (s->io_bits & 0x00ff0000) | |
80 | oe |= 0x4; | |
81 | if (s->io_bits & 0xff000000) | |
82 | oe |= 0x8; | |
83 | ||
84 | outb(oe, dev->iobase + DT2817_CR); | |
85 | ||
86 | return 1; | |
87 | } | |
88 | ||
0a85b6f0 MT |
89 | static int dt2817_dio_insn_bits(struct comedi_device *dev, |
90 | struct comedi_subdevice *s, | |
91 | struct comedi_insn *insn, unsigned int *data) | |
0e221af2 DS |
92 | { |
93 | unsigned int changed; | |
94 | ||
95 | /* It's questionable whether it is more important in | |
96 | * a driver like this to be deterministic or fast. | |
97 | * We choose fast. */ | |
98 | ||
99 | if (data[0]) { | |
100 | changed = s->state; | |
101 | s->state &= ~data[0]; | |
102 | s->state |= (data[0] & data[1]); | |
103 | changed ^= s->state; | |
104 | changed &= s->io_bits; | |
105 | if (changed & 0x000000ff) | |
106 | outb(s->state & 0xff, dev->iobase + DT2817_DATA + 0); | |
107 | if (changed & 0x0000ff00) | |
108 | outb((s->state >> 8) & 0xff, | |
0a85b6f0 | 109 | dev->iobase + DT2817_DATA + 1); |
0e221af2 DS |
110 | if (changed & 0x00ff0000) |
111 | outb((s->state >> 16) & 0xff, | |
0a85b6f0 | 112 | dev->iobase + DT2817_DATA + 2); |
0e221af2 DS |
113 | if (changed & 0xff000000) |
114 | outb((s->state >> 24) & 0xff, | |
0a85b6f0 | 115 | dev->iobase + DT2817_DATA + 3); |
0e221af2 DS |
116 | } |
117 | data[1] = inb(dev->iobase + DT2817_DATA + 0); | |
118 | data[1] |= (inb(dev->iobase + DT2817_DATA + 1) << 8); | |
119 | data[1] |= (inb(dev->iobase + DT2817_DATA + 2) << 16); | |
120 | data[1] |= (inb(dev->iobase + DT2817_DATA + 3) << 24); | |
121 | ||
a2714e3e | 122 | return insn->n; |
0e221af2 DS |
123 | } |
124 | ||
da91b269 | 125 | static int dt2817_attach(struct comedi_device *dev, struct comedi_devconfig *it) |
0e221af2 DS |
126 | { |
127 | int ret; | |
34c43922 | 128 | struct comedi_subdevice *s; |
0e221af2 DS |
129 | unsigned long iobase; |
130 | ||
131 | iobase = it->options[0]; | |
8cbf7a9e | 132 | printk(KERN_INFO "comedi%d: dt2817: 0x%04lx ", dev->minor, iobase); |
0e221af2 DS |
133 | if (!request_region(iobase, DT2817_SIZE, "dt2817")) { |
134 | printk("I/O port conflict\n"); | |
135 | return -EIO; | |
136 | } | |
137 | dev->iobase = iobase; | |
138 | dev->board_name = "dt2817"; | |
139 | ||
2f0b9d08 | 140 | ret = comedi_alloc_subdevices(dev, 1); |
8b6c5694 | 141 | if (ret) |
0e221af2 DS |
142 | return ret; |
143 | ||
d784e4c3 | 144 | s = &dev->subdevices[0]; |
0e221af2 DS |
145 | |
146 | s->n_chan = 32; | |
147 | s->type = COMEDI_SUBD_DIO; | |
148 | s->subdev_flags = SDF_READABLE | SDF_WRITABLE; | |
149 | s->range_table = &range_digital; | |
150 | s->maxdata = 1; | |
151 | s->insn_bits = dt2817_dio_insn_bits; | |
152 | s->insn_config = dt2817_dio_insn_config; | |
153 | ||
154 | s->state = 0; | |
155 | outb(0, dev->iobase + DT2817_CR); | |
156 | ||
8cbf7a9e | 157 | printk(KERN_INFO "\n"); |
0e221af2 DS |
158 | |
159 | return 0; | |
160 | } | |
161 | ||
484ecc95 | 162 | static void dt2817_detach(struct comedi_device *dev) |
0e221af2 | 163 | { |
0e221af2 DS |
164 | if (dev->iobase) |
165 | release_region(dev->iobase, DT2817_SIZE); | |
0e221af2 | 166 | } |
90f703d3 | 167 | |
294f930d | 168 | static struct comedi_driver dt2817_driver = { |
597092fc HS |
169 | .driver_name = "dt2817", |
170 | .module = THIS_MODULE, | |
171 | .attach = dt2817_attach, | |
172 | .detach = dt2817_detach, | |
173 | }; | |
294f930d | 174 | module_comedi_driver(dt2817_driver); |
597092fc | 175 | |
90f703d3 AT |
176 | MODULE_AUTHOR("Comedi http://www.comedi.org"); |
177 | MODULE_DESCRIPTION("Comedi low-level driver"); | |
178 | MODULE_LICENSE("GPL"); |