1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41#include <linux/interrupt.h>
42#include "../comedidev.h"
43
44#include <linux/ioport.h>
45
46#define DAS6402_SIZE 16
47
48#define N_WORDS (3000*64)
49
50#define STOP 0
51#define START 1
52
53#define SCANL 0x3f00
54#define BYTE unsigned char
55#define WORD unsigned short
56
57
58#define CLRINT 0x01
59#define CLRXTR 0x02
60#define CLRXIN 0x04
61#define EXTEND 0x10
62#define ARMED 0x20
63#define POSTMODE 0x40
64#define MHZ 0x80
65
66
67
68#define IRQ (0x04 << 4)
69#define IRQV 10
70
71#define CONVSRC 0x03
72#define BURSTEN 0x04
73#define XINTE 0x08
74#define INTE 0x80
75
76
77
78#define TGEN 0x01
79#define TGSEL 0x02
80#define TGPOL 0x04
81#define PRETRIG 0x08
82
83
84
85#define EOB 0x0c
86#define FIFOHFULL 0x08
87#define GAIN 0x01
88#define FIFONEPTY 0x04
89#define MODE 0x10
90#define SEM 0x20
91#define BIP 0x40
92
93
94#define M0 0x00
95#define M2 0x04
96
97#define C0 0x00
98#define C1 0x40
99#define C2 0x80
100#define RWLH 0x30
101
102struct das6402_private {
103 int ai_bytes_to_read;
104
105 int das6402_ignoreirq;
106};
107
108static void das6402_ai_fifo_dregs(struct comedi_device *dev,
109 struct comedi_subdevice *s)
110{
111 while (1) {
112 if (!(inb(dev->iobase + 8) & 0x01))
113 return;
114 comedi_buf_put(s->async, inw(dev->iobase));
115 }
116}
117
118static void das6402_setcounter(struct comedi_device *dev)
119{
120 BYTE p;
121 unsigned short ctrlwrd;
122
123
124 p = M0 | C0 | RWLH;
125 outb_p(p, dev->iobase + 15);
126 ctrlwrd = 2000;
127 p = (BYTE) (0xff & ctrlwrd);
128 outb_p(p, dev->iobase + 12);
129 p = (BYTE) (0xff & (ctrlwrd >> 8));
130 outb_p(p, dev->iobase + 12);
131
132
133 p = M2 | C1 | RWLH;
134 outb_p(p, dev->iobase + 15);
135 ctrlwrd = 10;
136 p = (BYTE) (0xff & ctrlwrd);
137 outb_p(p, dev->iobase + 13);
138 p = (BYTE) (0xff & (ctrlwrd >> 8));
139 outb_p(p, dev->iobase + 13);
140
141
142 p = M2 | C2 | RWLH;
143 outb_p(p, dev->iobase + 15);
144 ctrlwrd = 1000;
145 p = (BYTE) (0xff & ctrlwrd);
146 outb_p(p, dev->iobase + 14);
147 p = (BYTE) (0xff & (ctrlwrd >> 8));
148 outb_p(p, dev->iobase + 14);
149}
150
151static irqreturn_t intr_handler(int irq, void *d)
152{
153 struct comedi_device *dev = d;
154 struct das6402_private *devpriv = dev->private;
155 struct comedi_subdevice *s = &dev->subdevices[0];
156
157 if (!dev->attached || devpriv->das6402_ignoreirq) {
158 dev_warn(dev->class_dev, "BUG: spurious interrupt\n");
159 return IRQ_HANDLED;
160 }
161#ifdef DEBUG
162 printk("das6402: interrupt! das6402_irqcount=%i\n",
163 devpriv->das6402_irqcount);
164 printk("das6402: iobase+2=%i\n", inw_p(dev->iobase + 2));
165#endif
166
167 das6402_ai_fifo_dregs(dev, s);
168
169 if (s->async->buf_write_count >= devpriv->ai_bytes_to_read) {
170 outw_p(SCANL, dev->iobase + 2);
171 outb(0x07, dev->iobase + 8);
172#ifdef DEBUG
173 printk("das6402: Got %i samples\n\n",
174 devpriv->das6402_wordsread - diff);
175#endif
176 s->async->events |= COMEDI_CB_EOA;
177 comedi_event(dev, s);
178 }
179
180 outb(0x01, dev->iobase + 8);
181
182 comedi_event(dev, s);
183 return IRQ_HANDLED;
184}
185
186#if 0
187static void das6402_ai_fifo_read(struct comedi_device *dev, short *data, int n)
188{
189 int i;
190
191 for (i = 0; i < n; i++)
192 data[i] = inw(dev->iobase);
193}
194#endif
195
196static int das6402_ai_cancel(struct comedi_device *dev,
197 struct comedi_subdevice *s)
198{
199 struct das6402_private *devpriv = dev->private;
200
201
202
203
204
205
206 devpriv->das6402_ignoreirq = 1;
207 dev_dbg(dev->class_dev, "Stopping acquisition\n");
208 devpriv->das6402_ignoreirq = 1;
209 outb_p(0x02, dev->iobase + 10);
210 outw_p(SCANL, dev->iobase + 2);
211 outb_p(0, dev->iobase + 9);
212
213 outw_p(SCANL, dev->iobase + 2);
214
215 return 0;
216}
217
218#ifdef unused
219static int das6402_ai_mode2(struct comedi_device *dev,
220 struct comedi_subdevice *s, comedi_trig * it)
221{
222 struct das6402_private *devpriv = dev->private;
223
224 devpriv->das6402_ignoreirq = 1;
225 dev_dbg(dev->class_dev, "Starting acquisition\n");
226 outb_p(0x03, dev->iobase + 10);
227 outw_p(SCANL, dev->iobase + 2);
228 outb_p(IRQ | CONVSRC | BURSTEN | INTE, dev->iobase + 9);
229
230 devpriv->ai_bytes_to_read = it->n * sizeof(short);
231
232
233 devpriv->das6402_ignoreirq = 0;
234
235 outw_p(SCANL, dev->iobase + 2);
236
237 return 0;
238}
239#endif
240
241static int board_init(struct comedi_device *dev)
242{
243 struct das6402_private *devpriv = dev->private;
244 BYTE b;
245
246 devpriv->das6402_ignoreirq = 1;
247
248 outb(0x07, dev->iobase + 8);
249
250
251 outb_p(MODE, dev->iobase + 11);
252 b = BIP | SEM | MODE | GAIN | FIFOHFULL;
253 outb_p(b, dev->iobase + 11);
254
255
256 outb_p(EXTEND, dev->iobase + 8);
257 b = EXTEND | MHZ;
258 outb_p(b, dev->iobase + 8);
259 b = MHZ | CLRINT | CLRXTR | CLRXIN;
260 outb_p(b, dev->iobase + 8);
261
262
263 b = IRQ | CONVSRC | BURSTEN | INTE;
264 outb_p(b, dev->iobase + 9);
265
266
267 b = TGSEL | TGEN;
268 outb_p(b, dev->iobase + 10);
269
270 b = 0x07;
271 outb_p(b, dev->iobase + 8);
272
273 das6402_setcounter(dev);
274
275 outw_p(SCANL, dev->iobase + 2);
276
277 devpriv->das6402_ignoreirq = 0;
278
279 return 0;
280}
281
282static int das6402_attach(struct comedi_device *dev,
283 struct comedi_devconfig *it)
284{
285 struct das6402_private *devpriv;
286 unsigned int irq;
287 int ret;
288 struct comedi_subdevice *s;
289
290 ret = comedi_request_region(dev, it->options[0], DAS6402_SIZE);
291 if (ret)
292 return ret;
293
294 irq = it->options[0];
295 dev_dbg(dev->class_dev, "( irq = %u )\n", irq);
296 ret = request_irq(irq, intr_handler, 0, "das6402", dev);
297 if (ret < 0)
298 return ret;
299
300 dev->irq = irq;
301
302 devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
303 if (!devpriv)
304 return -ENOMEM;
305 dev->private = devpriv;
306
307 ret = comedi_alloc_subdevices(dev, 1);
308 if (ret)
309 return ret;
310
311
312 s = &dev->subdevices[0];
313 s->type = COMEDI_SUBD_AI;
314 s->subdev_flags = SDF_READABLE | SDF_GROUND;
315 s->n_chan = 8;
316
317 s->cancel = das6402_ai_cancel;
318 s->maxdata = (1 << 12) - 1;
319 s->len_chanlist = 16;
320 s->range_table = &range_unknown;
321
322 board_init(dev);
323
324 return 0;
325}
326
327static struct comedi_driver das6402_driver = {
328 .driver_name = "das6402",
329 .module = THIS_MODULE,
330 .attach = das6402_attach,
331 .detach = comedi_legacy_detach,
332};
333module_comedi_driver(das6402_driver)
334
335MODULE_AUTHOR("Comedi http://www.comedi.org");
336MODULE_DESCRIPTION("Comedi low-level driver");
337MODULE_LICENSE("GPL");
338