Staging: comedi: remove comedi-specific wrappers
[deliverable/linux.git] / drivers / staging / comedi / drivers / das6402.c
CommitLineData
48f16b6a
OS
1/*
2 Some comments on the code..
3
4 - it shouldn't be necessary to use outb_p().
5
6 - ignoreirq creates a race condition. It needs to be fixed.
7
8 */
9
10/*
11 comedi/drivers/das6402.c
12 An experimental driver for Computerboards' DAS6402 I/O card
13
14 Copyright (C) 1999 Oystein Svendsen <svendsen@pvv.org>
15
16 This program is free software; you can redistribute it and/or modify
17 it under the terms of the GNU General Public License as published by
18 the Free Software Foundation; either version 2 of the License, or
19 (at your option) any later version.
20
21 This program is distributed in the hope that it will be useful,
22 but WITHOUT ANY WARRANTY; without even the implied warranty of
23 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 GNU General Public License for more details.
25
26 You should have received a copy of the GNU General Public License
27 along with this program; if not, write to the Free Software
28 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
29
30 */
31/*
32Driver: das6402
33Description: Keithley Metrabyte DAS6402 (& compatibles)
34Author: Oystein Svendsen <svendsen@pvv.org>
35Status: bitrotten
36Devices: [Keithley Metrabyte] DAS6402 (das6402)
37
38This driver has suffered bitrot.
39*/
40
41#include "../comedidev.h"
42
43#include <linux/ioport.h>
44
45#define DAS6402_SIZE 16
46
47#define N_WORDS 3000*64
48
49#define STOP 0
50#define START 1
51
52#define SCANL 0x3f00
53#define BYTE unsigned char
54#define WORD unsigned short
55
56/*----- register 8 ----*/
57#define CLRINT 0x01
58#define CLRXTR 0x02
59#define CLRXIN 0x04
60#define EXTEND 0x10
61#define ARMED 0x20 /* enable conting of post sample conv */
62#define POSTMODE 0x40
63#define MHZ 0x80 /* 10 MHz clock */
64/*---------------------*/
65
66/*----- register 9 ----*/
67#define IRQ (0x04 << 4) /* these two are */
68#define IRQV 10 /* dependent on each other */
69
70#define CONVSRC 0x03 /* trig src is Intarnal pacer */
71#define BURSTEN 0x04 /* enable burst */
72#define XINTE 0x08 /* use external int. trig */
73#define INTE 0x80 /* enable analog interrupts */
74/*---------------------*/
75
76/*----- register 10 ---*/
77#define TGEN 0x01 /* Use pin DI1 for externl trigging? */
78#define TGSEL 0x02 /* Use edge triggering */
79#define TGPOL 0x04 /* active edge is falling */
80#define PRETRIG 0x08 /* pretrig */
81/*---------------------*/
82
83/*----- register 11 ---*/
84#define EOB 0x0c
85#define FIFOHFULL 0x08
86#define GAIN 0x01
87#define FIFONEPTY 0x04
88#define MODE 0x10
89#define SEM 0x20
90#define BIP 0x40
91/*---------------------*/
92
93#define M0 0x00
94#define M2 0x04
95
96#define C0 0x00
97#define C1 0x40
98#define C2 0x80
99#define RWLH 0x30
100
da91b269
BP
101static int das6402_attach(struct comedi_device *dev, struct comedi_devconfig *it);
102static int das6402_detach(struct comedi_device *dev);
139dfbdf 103static struct comedi_driver driver_das6402 = {
68c3dbff
BP
104 .driver_name = "das6402",
105 .module = THIS_MODULE,
106 .attach = das6402_attach,
107 .detach = das6402_detach,
48f16b6a
OS
108};
109
110COMEDI_INITCLEANUP(driver_das6402);
111
c7b8bb98 112struct das6402_private {
48f16b6a
OS
113 int ai_bytes_to_read;
114
115 int das6402_ignoreirq;
c7b8bb98
BP
116};
117#define devpriv ((struct das6402_private *)dev->private)
48f16b6a 118
da91b269 119static void das6402_ai_fifo_dregs(struct comedi_device *dev, struct comedi_subdevice *s);
48f16b6a 120
da91b269 121static void das6402_setcounter(struct comedi_device *dev)
48f16b6a
OS
122{
123 BYTE p;
124 unsigned short ctrlwrd;
125
126 /* set up counter0 first, mode 0 */
127 p = M0 | C0 | RWLH;
128 outb_p(p, dev->iobase + 15);
129 ctrlwrd = 2000;
130 p = (BYTE) (0xff & ctrlwrd);
131 outb_p(p, dev->iobase + 12);
132 p = (BYTE) (0xff & (ctrlwrd >> 8));
133 outb_p(p, dev->iobase + 12);
134
135 /* set up counter1, mode 2 */
136 p = M2 | C1 | RWLH;
137 outb_p(p, dev->iobase + 15);
138 ctrlwrd = 10;
139 p = (BYTE) (0xff & ctrlwrd);
140 outb_p(p, dev->iobase + 13);
141 p = (BYTE) (0xff & (ctrlwrd >> 8));
142 outb_p(p, dev->iobase + 13);
143
144 /* set up counter1, mode 2 */
145 p = M2 | C2 | RWLH;
146 outb_p(p, dev->iobase + 15);
147 ctrlwrd = 1000;
148 p = (BYTE) (0xff & ctrlwrd);
149 outb_p(p, dev->iobase + 14);
150 p = (BYTE) (0xff & (ctrlwrd >> 8));
151 outb_p(p, dev->iobase + 14);
152}
153
70265d24 154static irqreturn_t intr_handler(int irq, void *d)
48f16b6a 155{
71b5f4f1 156 struct comedi_device *dev = d;
34c43922 157 struct comedi_subdevice *s = dev->subdevices;
48f16b6a
OS
158
159 if (!dev->attached || devpriv->das6402_ignoreirq) {
160 printk("das6402: BUG: spurious interrupt\n");
161 return IRQ_HANDLED;
162 }
163#ifdef DEBUG
164 printk("das6402: interrupt! das6402_irqcount=%i\n",
165 devpriv->das6402_irqcount);
166 printk("das6402: iobase+2=%i\n", inw_p(dev->iobase + 2));
167#endif
168
169 das6402_ai_fifo_dregs(dev, s);
170
171 if (s->async->buf_write_count >= devpriv->ai_bytes_to_read) {
172 outw_p(SCANL, dev->iobase + 2); /* clears the fifo */
173 outb(0x07, dev->iobase + 8); /* clears all flip-flops */
174#ifdef DEBUG
175 printk("das6402: Got %i samples\n\n",
176 devpriv->das6402_wordsread - diff);
177#endif
178 s->async->events |= COMEDI_CB_EOA;
179 comedi_event(dev, s);
180 }
181
182 outb(0x01, dev->iobase + 8); /* clear only the interrupt flip-flop */
183
184 comedi_event(dev, s);
185 return IRQ_HANDLED;
186}
187
188#if 0
da91b269 189static void das6402_ai_fifo_read(struct comedi_device *dev, short *data, int n)
48f16b6a
OS
190{
191 int i;
192
193 for (i = 0; i < n; i++)
194 data[i] = inw(dev->iobase);
195}
196#endif
197
da91b269 198static void das6402_ai_fifo_dregs(struct comedi_device *dev, struct comedi_subdevice *s)
48f16b6a
OS
199{
200 while (1) {
201 if (!(inb(dev->iobase + 8) & 0x01))
202 return;
203 comedi_buf_put(s->async, inw(dev->iobase));
204 }
205}
206
da91b269 207static int das6402_ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
48f16b6a
OS
208{
209 /*
210 * This function should reset the board from whatever condition it
211 * is in (i.e., acquiring data), to a non-active state.
212 */
213
214 devpriv->das6402_ignoreirq = 1;
215#ifdef DEBUG
216 printk("das6402: Stopping acquisition\n");
217#endif
218 devpriv->das6402_ignoreirq = 1;
219 outb_p(0x02, dev->iobase + 10); /* disable external trigging */
220 outw_p(SCANL, dev->iobase + 2); /* resets the card fifo */
221 outb_p(0, dev->iobase + 9); /* disables interrupts */
222
223 outw_p(SCANL, dev->iobase + 2);
224
225 return 0;
226}
227
228#ifdef unused
da91b269
BP
229static int das6402_ai_mode2(struct comedi_device *dev, struct comedi_subdevice *s,
230 comedi_trig *it)
48f16b6a
OS
231{
232 devpriv->das6402_ignoreirq = 1;
233
234#ifdef DEBUG
235 printk("das6402: Starting acquisition\n");
236#endif
237 outb_p(0x03, dev->iobase + 10); /* enable external trigging */
238 outw_p(SCANL, dev->iobase + 2); /* resets the card fifo */
239 outb_p(IRQ | CONVSRC | BURSTEN | INTE, dev->iobase + 9);
240
790c5541 241 devpriv->ai_bytes_to_read = it->n * sizeof(short);
48f16b6a
OS
242
243 /* um... ignoreirq is a nasty race condition */
244 devpriv->das6402_ignoreirq = 0;
245
246 outw_p(SCANL, dev->iobase + 2);
247
248 return 0;
249}
250#endif
251
da91b269 252static int board_init(struct comedi_device *dev)
48f16b6a
OS
253{
254 BYTE b;
255
256 devpriv->das6402_ignoreirq = 1;
257
258 outb(0x07, dev->iobase + 8);
259
260 /* register 11 */
261 outb_p(MODE, dev->iobase + 11);
262 b = BIP | SEM | MODE | GAIN | FIFOHFULL;
263 outb_p(b, dev->iobase + 11);
264
265 /* register 8 */
266 outb_p(EXTEND, dev->iobase + 8);
267 b = EXTEND | MHZ;
268 outb_p(b, dev->iobase + 8);
269 b = MHZ | CLRINT | CLRXTR | CLRXIN;
270 outb_p(b, dev->iobase + 8);
271
272 /* register 9 */
273 b = IRQ | CONVSRC | BURSTEN | INTE;
274 outb_p(b, dev->iobase + 9);
275
276 /* register 10 */
277 b = TGSEL | TGEN;
278 outb_p(b, dev->iobase + 10);
279
280 b = 0x07;
281 outb_p(b, dev->iobase + 8);
282
283 das6402_setcounter(dev);
284
285 outw_p(SCANL, dev->iobase + 2); /* reset card fifo */
286
287 devpriv->das6402_ignoreirq = 0;
288
289 return 0;
290}
291
da91b269 292static int das6402_detach(struct comedi_device *dev)
48f16b6a
OS
293{
294 if (dev->irq)
5f74ea14 295 free_irq(dev->irq, dev);
48f16b6a
OS
296 if (dev->iobase)
297 release_region(dev->iobase, DAS6402_SIZE);
298
299 return 0;
300}
301
da91b269 302static int das6402_attach(struct comedi_device *dev, struct comedi_devconfig *it)
48f16b6a
OS
303{
304 unsigned int irq;
305 unsigned long iobase;
306 int ret;
34c43922 307 struct comedi_subdevice *s;
48f16b6a
OS
308
309 dev->board_name = "das6402";
310
311 iobase = it->options[0];
312 if (iobase == 0)
313 iobase = 0x300;
314
315 printk("comedi%d: das6402: 0x%04lx", dev->minor, iobase);
316
317 if (!request_region(iobase, DAS6402_SIZE, "das6402")) {
318 printk(" I/O port conflict\n");
319 return -EIO;
320 }
321 dev->iobase = iobase;
322
323 /* should do a probe here */
324
325 irq = it->options[0];
326 printk(" ( irq = %u )", irq);
5f74ea14 327 ret = request_irq(irq, intr_handler, 0, "das6402", dev);
48f16b6a
OS
328 if (ret < 0) {
329 printk("irq conflict\n");
330 return ret;
331 }
332 dev->irq = irq;
333
c3744138
BP
334 ret = alloc_private(dev, sizeof(struct das6402_private));
335 if (ret < 0)
48f16b6a
OS
336 return ret;
337
c3744138
BP
338 ret = alloc_subdevices(dev, 1);
339 if (ret < 0)
48f16b6a
OS
340 return ret;
341
342 /* ai subdevice */
343 s = dev->subdevices + 0;
344 s->type = COMEDI_SUBD_AI;
345 s->subdev_flags = SDF_READABLE | SDF_GROUND;
346 s->n_chan = 8;
2696fb57 347 /* s->trig[2]=das6402_ai_mode2; */
48f16b6a
OS
348 s->cancel = das6402_ai_cancel;
349 s->maxdata = (1 << 12) - 1;
350 s->len_chanlist = 16; /* ? */
351 s->range_table = &range_unknown;
352
353 board_init(dev);
354
355 return 0;
356}
This page took 0.072354 seconds and 5 git commands to generate.