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 | ||
da91b269 BP |
50 | static int dt2817_attach(struct comedi_device *dev, struct comedi_devconfig *it); |
51 | static int dt2817_detach(struct comedi_device *dev); | |
139dfbdf | 52 | static struct comedi_driver driver_dt2817 = { |
68c3dbff BP |
53 | .driver_name = "dt2817", |
54 | .module = THIS_MODULE, | |
55 | .attach = dt2817_attach, | |
56 | .detach = dt2817_detach, | |
0e221af2 DS |
57 | }; |
58 | ||
59 | COMEDI_INITCLEANUP(driver_dt2817); | |
60 | ||
da91b269 BP |
61 | static int dt2817_dio_insn_config(struct comedi_device *dev, struct comedi_subdevice *s, |
62 | struct comedi_insn *insn, unsigned int *data) | |
0e221af2 DS |
63 | { |
64 | int mask; | |
65 | int chan; | |
66 | int oe = 0; | |
67 | ||
68 | if (insn->n != 1) | |
69 | return -EINVAL; | |
70 | ||
71 | chan = CR_CHAN(insn->chanspec); | |
72 | if (chan < 8) { | |
73 | mask = 0xff; | |
74 | } else if (chan < 16) { | |
75 | mask = 0xff00; | |
76 | } else if (chan < 24) { | |
77 | mask = 0xff0000; | |
78 | } else | |
79 | mask = 0xff000000; | |
80 | if (data[0]) | |
81 | s->io_bits |= mask; | |
82 | else | |
83 | s->io_bits &= ~mask; | |
84 | ||
85 | if (s->io_bits & 0x000000ff) | |
86 | oe |= 0x1; | |
87 | if (s->io_bits & 0x0000ff00) | |
88 | oe |= 0x2; | |
89 | if (s->io_bits & 0x00ff0000) | |
90 | oe |= 0x4; | |
91 | if (s->io_bits & 0xff000000) | |
92 | oe |= 0x8; | |
93 | ||
94 | outb(oe, dev->iobase + DT2817_CR); | |
95 | ||
96 | return 1; | |
97 | } | |
98 | ||
da91b269 BP |
99 | static int dt2817_dio_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s, |
100 | struct comedi_insn *insn, unsigned int *data) | |
0e221af2 DS |
101 | { |
102 | unsigned int changed; | |
103 | ||
104 | /* It's questionable whether it is more important in | |
105 | * a driver like this to be deterministic or fast. | |
106 | * We choose fast. */ | |
107 | ||
108 | if (data[0]) { | |
109 | changed = s->state; | |
110 | s->state &= ~data[0]; | |
111 | s->state |= (data[0] & data[1]); | |
112 | changed ^= s->state; | |
113 | changed &= s->io_bits; | |
114 | if (changed & 0x000000ff) | |
115 | outb(s->state & 0xff, dev->iobase + DT2817_DATA + 0); | |
116 | if (changed & 0x0000ff00) | |
117 | outb((s->state >> 8) & 0xff, | |
118 | dev->iobase + DT2817_DATA + 1); | |
119 | if (changed & 0x00ff0000) | |
120 | outb((s->state >> 16) & 0xff, | |
121 | dev->iobase + DT2817_DATA + 2); | |
122 | if (changed & 0xff000000) | |
123 | outb((s->state >> 24) & 0xff, | |
124 | dev->iobase + DT2817_DATA + 3); | |
125 | } | |
126 | data[1] = inb(dev->iobase + DT2817_DATA + 0); | |
127 | data[1] |= (inb(dev->iobase + DT2817_DATA + 1) << 8); | |
128 | data[1] |= (inb(dev->iobase + DT2817_DATA + 2) << 16); | |
129 | data[1] |= (inb(dev->iobase + DT2817_DATA + 3) << 24); | |
130 | ||
131 | return 2; | |
132 | } | |
133 | ||
da91b269 | 134 | static int dt2817_attach(struct comedi_device *dev, struct comedi_devconfig *it) |
0e221af2 DS |
135 | { |
136 | int ret; | |
34c43922 | 137 | struct comedi_subdevice *s; |
0e221af2 DS |
138 | unsigned long iobase; |
139 | ||
140 | iobase = it->options[0]; | |
141 | printk("comedi%d: dt2817: 0x%04lx ", dev->minor, iobase); | |
142 | if (!request_region(iobase, DT2817_SIZE, "dt2817")) { | |
143 | printk("I/O port conflict\n"); | |
144 | return -EIO; | |
145 | } | |
146 | dev->iobase = iobase; | |
147 | dev->board_name = "dt2817"; | |
148 | ||
c3744138 BP |
149 | ret = alloc_subdevices(dev, 1); |
150 | if (ret < 0) | |
0e221af2 DS |
151 | return ret; |
152 | ||
153 | s = dev->subdevices + 0; | |
154 | ||
155 | s->n_chan = 32; | |
156 | s->type = COMEDI_SUBD_DIO; | |
157 | s->subdev_flags = SDF_READABLE | SDF_WRITABLE; | |
158 | s->range_table = &range_digital; | |
159 | s->maxdata = 1; | |
160 | s->insn_bits = dt2817_dio_insn_bits; | |
161 | s->insn_config = dt2817_dio_insn_config; | |
162 | ||
163 | s->state = 0; | |
164 | outb(0, dev->iobase + DT2817_CR); | |
165 | ||
166 | printk("\n"); | |
167 | ||
168 | return 0; | |
169 | } | |
170 | ||
da91b269 | 171 | static int dt2817_detach(struct comedi_device *dev) |
0e221af2 DS |
172 | { |
173 | printk("comedi%d: dt2817: remove\n", dev->minor); | |
174 | ||
175 | if (dev->iobase) | |
176 | release_region(dev->iobase, DT2817_SIZE); | |
177 | ||
178 | return 0; | |
179 | } |