Staging: comedi: fix sched.h build breakage
[linux-2.6/mini2440.git] / drivers / staging / comedi / drivers / ni_at_a2150.c
blobdd75dfb34309f793e52a6f0528a8180417c4892b
1 /*
2 comedi/drivers/ni_at_a2150.c
3 Driver for National Instruments AT-A2150 boards
4 Copyright (C) 2001, 2002 Frank Mori Hess <fmhess@users.sourceforge.net>
6 COMEDI - Linux Control and Measurement Device Interface
7 Copyright (C) 2000 David A. Schleef <ds@schleef.org>
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 ************************************************************************
26 Driver: ni_at_a2150
27 Description: National Instruments AT-A2150
28 Author: Frank Mori Hess
29 Status: works
30 Devices: [National Instruments] AT-A2150C (at_a2150c), AT-2150S (at_a2150s)
32 If you want to ac couple the board's inputs, use AREF_OTHER.
34 Configuration options:
35 [0] - I/O port base address
36 [1] - IRQ (optional, required for timed conversions)
37 [2] - DMA (optional, required for timed conversions)
41 Yet another driver for obsolete hardware brought to you by Frank Hess.
42 Testing and debugging help provided by Dave Andruczyk.
44 This driver supports the boards:
46 AT-A2150C
47 AT-A2150S
49 The only difference is their master clock frequencies.
51 Options:
52 [0] - base io address
53 [1] - irq
54 [2] - dma channel
56 References (from ftp://ftp.natinst.com/support/manuals):
58 320360.pdf AT-A2150 User Manual
60 TODO:
62 analog level triggering
63 TRIG_WAKE_EOS
67 #include <linux/interrupt.h>
68 #include "../comedidev.h"
70 #include <linux/ioport.h>
71 #include <asm/dma.h>
73 #include "8253.h"
74 #include "comedi_fc.h"
76 #define A2150_SIZE 28
77 #define A2150_DMA_BUFFER_SIZE 0xff00 /* size in bytes of dma buffer */
79 /* #define A2150_DEBUG enable debugging code */
80 #undef A2150_DEBUG /* disable debugging code */
82 /* Registers and bits */
83 #define CONFIG_REG 0x0
84 #define CHANNEL_BITS(x) ((x) & 0x7)
85 #define CHANNEL_MASK 0x7
86 #define CLOCK_SELECT_BITS(x) (((x) & 0x3) << 3)
87 #define CLOCK_DIVISOR_BITS(x) (((x) & 0x3) << 5)
88 #define CLOCK_MASK (0xf << 3)
89 #define ENABLE0_BIT 0x80 /* enable (don't internally ground) channels 0 and 1 */
90 #define ENABLE1_BIT 0x100 /* enable (don't internally ground) channels 2 and 3 */
91 #define AC0_BIT 0x200 /* ac couple channels 0,1 */
92 #define AC1_BIT 0x400 /* ac couple channels 2,3 */
93 #define APD_BIT 0x800 /* analog power down */
94 #define DPD_BIT 0x1000 /* digital power down */
95 #define TRIGGER_REG 0x2 /* trigger config register */
96 #define POST_TRIGGER_BITS 0x2
97 #define DELAY_TRIGGER_BITS 0x3
98 #define HW_TRIG_EN 0x10 /* enable hardware trigger */
99 #define FIFO_START_REG 0x6 /* software start aquistion trigger */
100 #define FIFO_RESET_REG 0x8 /* clears fifo + fifo flags */
101 #define FIFO_DATA_REG 0xa /* read data */
102 #define DMA_TC_CLEAR_REG 0xe /* clear dma terminal count interrupt */
103 #define STATUS_REG 0x12 /* read only */
104 #define FNE_BIT 0x1 /* fifo not empty */
105 #define OVFL_BIT 0x8 /* fifo overflow */
106 #define EDAQ_BIT 0x10 /* end of aquisition interrupt */
107 #define DCAL_BIT 0x20 /* offset calibration in progress */
108 #define INTR_BIT 0x40 /* interrupt has occured */
109 #define DMA_TC_BIT 0x80 /* dma terminal count interrupt has occured */
110 #define ID_BITS(x) (((x) >> 8) & 0x3)
111 #define IRQ_DMA_CNTRL_REG 0x12 /* write only */
112 #define DMA_CHAN_BITS(x) ((x) & 0x7) /* sets dma channel */
113 #define DMA_EN_BIT 0x8 /* enables dma */
114 #define IRQ_LVL_BITS(x) (((x) & 0xf) << 4) /* sets irq level */
115 #define FIFO_INTR_EN_BIT 0x100 /* enable fifo interrupts */
116 #define FIFO_INTR_FHF_BIT 0x200 /* interrupt fifo half full */
117 #define DMA_INTR_EN_BIT 0x800 /* enable interrupt on dma terminal count */
118 #define DMA_DEM_EN_BIT 0x1000 /* enables demand mode dma */
119 #define I8253_BASE_REG 0x14
120 #define I8253_MODE_REG 0x17
121 #define HW_COUNT_DISABLE 0x30 /* disable hardware counting of conversions */
123 struct a2150_board {
124 const char *name;
125 int clock[4]; /* master clock periods, in nanoseconds */
126 int num_clocks; /* number of available master clock speeds */
127 int ai_speed; /* maximum conversion rate in nanoseconds */
130 /* analog input range */
131 static const struct comedi_lrange range_a2150 = {
134 RANGE(-2.828, 2.828),
138 /* enum must match board indices */
139 enum { a2150_c, a2150_s };
140 static const struct a2150_board a2150_boards[] = {
142 .name = "at-a2150c",
143 .clock = {31250, 22676, 20833, 19531},
144 .num_clocks = 4,
145 .ai_speed = 19531,
148 .name = "at-a2150s",
149 .clock = {62500, 50000, 41667, 0},
150 .num_clocks = 3,
151 .ai_speed = 41667,
156 * Useful for shorthand access to the particular board structure
158 #define thisboard ((const struct a2150_board *)dev->board_ptr)
160 struct a2150_private {
162 volatile unsigned int count; /* number of data points left to be taken */
163 unsigned int dma; /* dma channel */
164 s16 *dma_buffer; /* dma buffer */
165 unsigned int dma_transfer_size; /* size in bytes of dma transfers */
166 int irq_dma_bits; /* irq/dma register bits */
167 int config_bits; /* config register bits */
170 #define devpriv ((struct a2150_private *)dev->private)
172 static int a2150_attach(struct comedi_device *dev, struct comedi_devconfig *it);
173 static int a2150_detach(struct comedi_device *dev);
174 static int a2150_cancel(struct comedi_device *dev, struct comedi_subdevice *s);
176 static struct comedi_driver driver_a2150 = {
177 .driver_name = "ni_at_a2150",
178 .module = THIS_MODULE,
179 .attach = a2150_attach,
180 .detach = a2150_detach,
183 static irqreturn_t a2150_interrupt(int irq, void *d);
184 static int a2150_ai_cmdtest(struct comedi_device *dev,
185 struct comedi_subdevice *s, struct comedi_cmd *cmd);
186 static int a2150_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s);
187 static int a2150_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
188 struct comedi_insn *insn, unsigned int *data);
189 static int a2150_get_timing(struct comedi_device *dev, unsigned int *period,
190 int flags);
191 static int a2150_probe(struct comedi_device *dev);
192 static int a2150_set_chanlist(struct comedi_device *dev,
193 unsigned int start_channel,
194 unsigned int num_channels);
196 * A convenient macro that defines init_module() and cleanup_module(),
197 * as necessary.
199 COMEDI_INITCLEANUP(driver_a2150);
201 #ifdef A2150_DEBUG
203 static void ni_dump_regs(struct comedi_device *dev)
205 printk("config bits 0x%x\n", devpriv->config_bits);
206 printk("irq dma bits 0x%x\n", devpriv->irq_dma_bits);
207 printk("status bits 0x%x\n", inw(dev->iobase + STATUS_REG));
210 #endif
212 /* interrupt service routine */
213 static irqreturn_t a2150_interrupt(int irq, void *d)
215 int i;
216 int status;
217 unsigned long flags;
218 struct comedi_device *dev = d;
219 struct comedi_subdevice *s = dev->read_subdev;
220 struct comedi_async *async;
221 struct comedi_cmd *cmd;
222 unsigned int max_points, num_points, residue, leftover;
223 short dpnt;
224 static const int sample_size = sizeof(devpriv->dma_buffer[0]);
226 if (dev->attached == 0) {
227 comedi_error(dev, "premature interrupt");
228 return IRQ_HANDLED;
230 /* initialize async here to make sure s is not NULL */
231 async = s->async;
232 async->events = 0;
233 cmd = &async->cmd;
235 status = inw(dev->iobase + STATUS_REG);
237 if ((status & INTR_BIT) == 0) {
238 comedi_error(dev, "spurious interrupt");
239 return IRQ_NONE;
242 if (status & OVFL_BIT) {
243 comedi_error(dev, "fifo overflow");
244 a2150_cancel(dev, s);
245 async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
248 if ((status & DMA_TC_BIT) == 0) {
249 comedi_error(dev, "caught non-dma interrupt? Aborting.");
250 a2150_cancel(dev, s);
251 async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
252 comedi_event(dev, s);
253 return IRQ_HANDLED;
256 flags = claim_dma_lock();
257 disable_dma(devpriv->dma);
258 /* clear flip-flop to make sure 2-byte registers for
259 * count and address get set correctly */
260 clear_dma_ff(devpriv->dma);
262 /* figure out how many points to read */
263 max_points = devpriv->dma_transfer_size / sample_size;
264 /* residue is the number of points left to be done on the dma
265 * transfer. It should always be zero at this point unless
266 * the stop_src is set to external triggering.
268 residue = get_dma_residue(devpriv->dma) / sample_size;
269 num_points = max_points - residue;
270 if (devpriv->count < num_points && cmd->stop_src == TRIG_COUNT)
271 num_points = devpriv->count;
273 /* figure out how many points will be stored next time */
274 leftover = 0;
275 if (cmd->stop_src == TRIG_NONE) {
276 leftover = devpriv->dma_transfer_size / sample_size;
277 } else if (devpriv->count > max_points) {
278 leftover = devpriv->count - max_points;
279 if (leftover > max_points)
280 leftover = max_points;
282 /* there should only be a residue if collection was stopped by having
283 * the stop_src set to an external trigger, in which case there
284 * will be no more data
286 if (residue)
287 leftover = 0;
289 for (i = 0; i < num_points; i++) {
290 /* write data point to comedi buffer */
291 dpnt = devpriv->dma_buffer[i];
292 /* convert from 2's complement to unsigned coding */
293 dpnt ^= 0x8000;
294 cfc_write_to_buffer(s, dpnt);
295 if (cmd->stop_src == TRIG_COUNT) {
296 if (--devpriv->count == 0) { /* end of acquisition */
297 a2150_cancel(dev, s);
298 async->events |= COMEDI_CB_EOA;
299 break;
303 /* re-enable dma */
304 if (leftover) {
305 set_dma_addr(devpriv->dma, virt_to_bus(devpriv->dma_buffer));
306 set_dma_count(devpriv->dma, leftover * sample_size);
307 enable_dma(devpriv->dma);
309 release_dma_lock(flags);
311 async->events |= COMEDI_CB_BLOCK;
313 comedi_event(dev, s);
315 /* clear interrupt */
316 outw(0x00, dev->iobase + DMA_TC_CLEAR_REG);
318 return IRQ_HANDLED;
321 /* probes board type, returns offset */
322 static int a2150_probe(struct comedi_device *dev)
324 int status = inw(dev->iobase + STATUS_REG);
325 return ID_BITS(status);
328 static int a2150_attach(struct comedi_device *dev, struct comedi_devconfig *it)
330 struct comedi_subdevice *s;
331 unsigned long iobase = it->options[0];
332 unsigned int irq = it->options[1];
333 unsigned int dma = it->options[2];
334 static const int timeout = 2000;
335 int i;
337 printk("comedi%d: %s: io 0x%lx", dev->minor, driver_a2150.driver_name,
338 iobase);
339 if (irq) {
340 printk(", irq %u", irq);
341 } else {
342 printk(", no irq");
344 if (dma) {
345 printk(", dma %u", dma);
346 } else {
347 printk(", no dma");
349 printk("\n");
351 /* allocate and initialize dev->private */
352 if (alloc_private(dev, sizeof(struct a2150_private)) < 0)
353 return -ENOMEM;
355 if (iobase == 0) {
356 printk(" io base address required\n");
357 return -EINVAL;
360 /* check if io addresses are available */
361 if (!request_region(iobase, A2150_SIZE, driver_a2150.driver_name)) {
362 printk(" I/O port conflict\n");
363 return -EIO;
365 dev->iobase = iobase;
367 /* grab our IRQ */
368 if (irq) {
369 /* check that irq is supported */
370 if (irq < 3 || irq == 8 || irq == 13 || irq > 15) {
371 printk(" invalid irq line %u\n", irq);
372 return -EINVAL;
374 if (request_irq(irq, a2150_interrupt, 0,
375 driver_a2150.driver_name, dev)) {
376 printk("unable to allocate irq %u\n", irq);
377 return -EINVAL;
379 devpriv->irq_dma_bits |= IRQ_LVL_BITS(irq);
380 dev->irq = irq;
382 /* initialize dma */
383 if (dma) {
384 if (dma == 4 || dma > 7) {
385 printk(" invalid dma channel %u\n", dma);
386 return -EINVAL;
388 if (request_dma(dma, driver_a2150.driver_name)) {
389 printk(" failed to allocate dma channel %u\n", dma);
390 return -EINVAL;
392 devpriv->dma = dma;
393 devpriv->dma_buffer =
394 kmalloc(A2150_DMA_BUFFER_SIZE, GFP_KERNEL | GFP_DMA);
395 if (devpriv->dma_buffer == NULL)
396 return -ENOMEM;
398 disable_dma(dma);
399 set_dma_mode(dma, DMA_MODE_READ);
401 devpriv->irq_dma_bits |= DMA_CHAN_BITS(dma);
404 dev->board_ptr = a2150_boards + a2150_probe(dev);
405 dev->board_name = thisboard->name;
407 if (alloc_subdevices(dev, 1) < 0)
408 return -ENOMEM;
410 /* analog input subdevice */
411 s = dev->subdevices + 0;
412 dev->read_subdev = s;
413 s->type = COMEDI_SUBD_AI;
414 s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_OTHER | SDF_CMD_READ;
415 s->n_chan = 4;
416 s->len_chanlist = 4;
417 s->maxdata = 0xffff;
418 s->range_table = &range_a2150;
419 s->do_cmd = a2150_ai_cmd;
420 s->do_cmdtest = a2150_ai_cmdtest;
421 s->insn_read = a2150_ai_rinsn;
422 s->cancel = a2150_cancel;
424 /* need to do this for software counting of completed conversions, to
425 * prevent hardware count from stopping aquisition */
426 outw(HW_COUNT_DISABLE, dev->iobase + I8253_MODE_REG);
428 /* set card's irq and dma levels */
429 outw(devpriv->irq_dma_bits, dev->iobase + IRQ_DMA_CNTRL_REG);
431 /* reset and sync adc clock circuitry */
432 outw_p(DPD_BIT | APD_BIT, dev->iobase + CONFIG_REG);
433 outw_p(DPD_BIT, dev->iobase + CONFIG_REG);
434 /* initialize configuration register */
435 devpriv->config_bits = 0;
436 outw(devpriv->config_bits, dev->iobase + CONFIG_REG);
437 /* wait until offset calibration is done, then enable analog inputs */
438 for (i = 0; i < timeout; i++) {
439 if ((DCAL_BIT & inw(dev->iobase + STATUS_REG)) == 0)
440 break;
441 udelay(1000);
443 if (i == timeout) {
444 printk
445 (" timed out waiting for offset calibration to complete\n");
446 return -ETIME;
448 devpriv->config_bits |= ENABLE0_BIT | ENABLE1_BIT;
449 outw(devpriv->config_bits, dev->iobase + CONFIG_REG);
451 return 0;
454 static int a2150_detach(struct comedi_device *dev)
456 printk("comedi%d: %s: remove\n", dev->minor, driver_a2150.driver_name);
458 /* only free stuff if it has been allocated by _attach */
459 if (dev->iobase) {
460 /* put board in power-down mode */
461 outw(APD_BIT | DPD_BIT, dev->iobase + CONFIG_REG);
462 release_region(dev->iobase, A2150_SIZE);
465 if (dev->irq)
466 free_irq(dev->irq, dev);
467 if (devpriv) {
468 if (devpriv->dma)
469 free_dma(devpriv->dma);
470 if (devpriv->dma_buffer)
471 kfree(devpriv->dma_buffer);
474 return 0;
477 static int a2150_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
479 /* disable dma on card */
480 devpriv->irq_dma_bits &= ~DMA_INTR_EN_BIT & ~DMA_EN_BIT;
481 outw(devpriv->irq_dma_bits, dev->iobase + IRQ_DMA_CNTRL_REG);
483 /* disable computer's dma */
484 disable_dma(devpriv->dma);
486 /* clear fifo and reset triggering circuitry */
487 outw(0, dev->iobase + FIFO_RESET_REG);
489 return 0;
492 static int a2150_ai_cmdtest(struct comedi_device *dev,
493 struct comedi_subdevice *s, struct comedi_cmd *cmd)
495 int err = 0;
496 int tmp;
497 int startChan;
498 int i;
500 /* step 1: make sure trigger sources are trivially valid */
502 tmp = cmd->start_src;
503 cmd->start_src &= TRIG_NOW | TRIG_EXT;
504 if (!cmd->start_src || tmp != cmd->start_src)
505 err++;
507 tmp = cmd->scan_begin_src;
508 cmd->scan_begin_src &= TRIG_TIMER;
509 if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
510 err++;
512 tmp = cmd->convert_src;
513 cmd->convert_src &= TRIG_NOW;
514 if (!cmd->convert_src || tmp != cmd->convert_src)
515 err++;
517 tmp = cmd->scan_end_src;
518 cmd->scan_end_src &= TRIG_COUNT;
519 if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
520 err++;
522 tmp = cmd->stop_src;
523 cmd->stop_src &= TRIG_COUNT | TRIG_NONE;
524 if (!cmd->stop_src || tmp != cmd->stop_src)
525 err++;
527 if (err)
528 return 1;
530 /* step 2: make sure trigger sources are unique and mutually compatible */
532 if (cmd->start_src != TRIG_NOW && cmd->start_src != TRIG_EXT)
533 err++;
534 if (cmd->stop_src != TRIG_COUNT && cmd->stop_src != TRIG_NONE)
535 err++;
537 if (err)
538 return 2;
540 /* step 3: make sure arguments are trivially compatible */
542 if (cmd->start_arg != 0) {
543 cmd->start_arg = 0;
544 err++;
546 if (cmd->convert_src == TRIG_TIMER) {
547 if (cmd->convert_arg < thisboard->ai_speed) {
548 cmd->convert_arg = thisboard->ai_speed;
549 err++;
552 if (!cmd->chanlist_len) {
553 cmd->chanlist_len = 1;
554 err++;
556 if (cmd->scan_end_arg != cmd->chanlist_len) {
557 cmd->scan_end_arg = cmd->chanlist_len;
558 err++;
560 if (cmd->stop_src == TRIG_COUNT) {
561 if (!cmd->stop_arg) {
562 cmd->stop_arg = 1;
563 err++;
565 } else { /* TRIG_NONE */
566 if (cmd->stop_arg != 0) {
567 cmd->stop_arg = 0;
568 err++;
572 if (err)
573 return 3;
575 /* step 4: fix up any arguments */
577 if (cmd->scan_begin_src == TRIG_TIMER) {
578 tmp = cmd->scan_begin_arg;
579 a2150_get_timing(dev, &cmd->scan_begin_arg, cmd->flags);
580 if (tmp != cmd->scan_begin_arg)
581 err++;
584 if (err)
585 return 4;
587 /* check channel/gain list against card's limitations */
588 if (cmd->chanlist) {
589 startChan = CR_CHAN(cmd->chanlist[0]);
590 for (i = 1; i < cmd->chanlist_len; i++) {
591 if (CR_CHAN(cmd->chanlist[i]) != (startChan + i)) {
592 comedi_error(dev,
593 "entries in chanlist must be consecutive channels, counting upwards\n");
594 err++;
597 if (cmd->chanlist_len == 2 && CR_CHAN(cmd->chanlist[0]) == 1) {
598 comedi_error(dev,
599 "length 2 chanlist must be channels 0,1 or channels 2,3");
600 err++;
602 if (cmd->chanlist_len == 3) {
603 comedi_error(dev,
604 "chanlist must have 1,2 or 4 channels");
605 err++;
607 if (CR_AREF(cmd->chanlist[0]) != CR_AREF(cmd->chanlist[1]) ||
608 CR_AREF(cmd->chanlist[2]) != CR_AREF(cmd->chanlist[3])) {
609 comedi_error(dev,
610 "channels 0/1 and 2/3 must have the same analog reference");
611 err++;
615 if (err)
616 return 5;
618 return 0;
621 static int a2150_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
623 struct comedi_async *async = s->async;
624 struct comedi_cmd *cmd = &async->cmd;
625 unsigned long lock_flags;
626 unsigned int old_config_bits = devpriv->config_bits;
627 unsigned int trigger_bits;
629 if (!dev->irq || !devpriv->dma) {
630 comedi_error(dev,
631 " irq and dma required, cannot do hardware conversions");
632 return -1;
634 if (cmd->flags & TRIG_RT) {
635 comedi_error(dev,
636 " dma incompatible with hard real-time interrupt (TRIG_RT), aborting");
637 return -1;
639 /* clear fifo and reset triggering circuitry */
640 outw(0, dev->iobase + FIFO_RESET_REG);
642 /* setup chanlist */
643 if (a2150_set_chanlist(dev, CR_CHAN(cmd->chanlist[0]),
644 cmd->chanlist_len) < 0)
645 return -1;
647 /* setup ac/dc coupling */
648 if (CR_AREF(cmd->chanlist[0]) == AREF_OTHER)
649 devpriv->config_bits |= AC0_BIT;
650 else
651 devpriv->config_bits &= ~AC0_BIT;
652 if (CR_AREF(cmd->chanlist[2]) == AREF_OTHER)
653 devpriv->config_bits |= AC1_BIT;
654 else
655 devpriv->config_bits &= ~AC1_BIT;
657 /* setup timing */
658 a2150_get_timing(dev, &cmd->scan_begin_arg, cmd->flags);
660 /* send timing, channel, config bits */
661 outw(devpriv->config_bits, dev->iobase + CONFIG_REG);
663 /* initialize number of samples remaining */
664 devpriv->count = cmd->stop_arg * cmd->chanlist_len;
666 /* enable computer's dma */
667 lock_flags = claim_dma_lock();
668 disable_dma(devpriv->dma);
669 /* clear flip-flop to make sure 2-byte registers for
670 * count and address get set correctly */
671 clear_dma_ff(devpriv->dma);
672 set_dma_addr(devpriv->dma, virt_to_bus(devpriv->dma_buffer));
673 /* set size of transfer to fill in 1/3 second */
674 #define ONE_THIRD_SECOND 333333333
675 devpriv->dma_transfer_size =
676 sizeof(devpriv->dma_buffer[0]) * cmd->chanlist_len *
677 ONE_THIRD_SECOND / cmd->scan_begin_arg;
678 if (devpriv->dma_transfer_size > A2150_DMA_BUFFER_SIZE)
679 devpriv->dma_transfer_size = A2150_DMA_BUFFER_SIZE;
680 if (devpriv->dma_transfer_size < sizeof(devpriv->dma_buffer[0]))
681 devpriv->dma_transfer_size = sizeof(devpriv->dma_buffer[0]);
682 devpriv->dma_transfer_size -=
683 devpriv->dma_transfer_size % sizeof(devpriv->dma_buffer[0]);
684 set_dma_count(devpriv->dma, devpriv->dma_transfer_size);
685 enable_dma(devpriv->dma);
686 release_dma_lock(lock_flags);
688 /* clear dma interrupt before enabling it, to try and get rid of that
689 * one spurious interrupt that has been happening */
690 outw(0x00, dev->iobase + DMA_TC_CLEAR_REG);
692 /* enable dma on card */
693 devpriv->irq_dma_bits |= DMA_INTR_EN_BIT | DMA_EN_BIT;
694 outw(devpriv->irq_dma_bits, dev->iobase + IRQ_DMA_CNTRL_REG);
696 /* may need to wait 72 sampling periods if timing was changed */
697 i8254_load(dev->iobase + I8253_BASE_REG, 0, 2, 72, 0);
699 /* setup start triggering */
700 trigger_bits = 0;
701 /* decide if we need to wait 72 periods for valid data */
702 if (cmd->start_src == TRIG_NOW &&
703 (old_config_bits & CLOCK_MASK) !=
704 (devpriv->config_bits & CLOCK_MASK)) {
705 /* set trigger source to delay trigger */
706 trigger_bits |= DELAY_TRIGGER_BITS;
707 } else {
708 /* otherwise no delay */
709 trigger_bits |= POST_TRIGGER_BITS;
711 /* enable external hardware trigger */
712 if (cmd->start_src == TRIG_EXT) {
713 trigger_bits |= HW_TRIG_EN;
714 } else if (cmd->start_src == TRIG_OTHER) {
715 /* XXX add support for level/slope start trigger using TRIG_OTHER */
716 comedi_error(dev, "you shouldn't see this?");
718 /* send trigger config bits */
719 outw(trigger_bits, dev->iobase + TRIGGER_REG);
721 /* start aquisition for soft trigger */
722 if (cmd->start_src == TRIG_NOW) {
723 outw(0, dev->iobase + FIFO_START_REG);
725 #ifdef A2150_DEBUG
726 ni_dump_regs(dev);
727 #endif
729 return 0;
732 static int a2150_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
733 struct comedi_insn *insn, unsigned int *data)
735 unsigned int i, n;
736 static const int timeout = 100000;
737 static const int filter_delay = 36;
739 /* clear fifo and reset triggering circuitry */
740 outw(0, dev->iobase + FIFO_RESET_REG);
742 /* setup chanlist */
743 if (a2150_set_chanlist(dev, CR_CHAN(insn->chanspec), 1) < 0)
744 return -1;
746 /* set dc coupling */
747 devpriv->config_bits &= ~AC0_BIT;
748 devpriv->config_bits &= ~AC1_BIT;
750 /* send timing, channel, config bits */
751 outw(devpriv->config_bits, dev->iobase + CONFIG_REG);
753 /* disable dma on card */
754 devpriv->irq_dma_bits &= ~DMA_INTR_EN_BIT & ~DMA_EN_BIT;
755 outw(devpriv->irq_dma_bits, dev->iobase + IRQ_DMA_CNTRL_REG);
757 /* setup start triggering */
758 outw(0, dev->iobase + TRIGGER_REG);
760 /* start aquisition for soft trigger */
761 outw(0, dev->iobase + FIFO_START_REG);
763 /* there is a 35.6 sample delay for data to get through the antialias filter */
764 for (n = 0; n < filter_delay; n++) {
765 for (i = 0; i < timeout; i++) {
766 if (inw(dev->iobase + STATUS_REG) & FNE_BIT)
767 break;
768 udelay(1);
770 if (i == timeout) {
771 comedi_error(dev, "timeout");
772 return -ETIME;
774 inw(dev->iobase + FIFO_DATA_REG);
777 /* read data */
778 for (n = 0; n < insn->n; n++) {
779 for (i = 0; i < timeout; i++) {
780 if (inw(dev->iobase + STATUS_REG) & FNE_BIT)
781 break;
782 udelay(1);
784 if (i == timeout) {
785 comedi_error(dev, "timeout");
786 return -ETIME;
788 #ifdef A2150_DEBUG
789 ni_dump_regs(dev);
790 #endif
791 data[n] = inw(dev->iobase + FIFO_DATA_REG);
792 #ifdef A2150_DEBUG
793 printk(" data is %i\n", data[n]);
794 #endif
795 data[n] ^= 0x8000;
798 /* clear fifo and reset triggering circuitry */
799 outw(0, dev->iobase + FIFO_RESET_REG);
801 return n;
804 /* sets bits in devpriv->clock_bits to nearest approximation of requested period,
805 * adjusts requested period to actual timing. */
806 static int a2150_get_timing(struct comedi_device *dev, unsigned int *period,
807 int flags)
809 int lub, glb, temp;
810 int lub_divisor_shift, lub_index, glb_divisor_shift, glb_index;
811 int i, j;
813 /* initialize greatest lower and least upper bounds */
814 lub_divisor_shift = 3;
815 lub_index = 0;
816 lub = thisboard->clock[lub_index] * (1 << lub_divisor_shift);
817 glb_divisor_shift = 0;
818 glb_index = thisboard->num_clocks - 1;
819 glb = thisboard->clock[glb_index] * (1 << glb_divisor_shift);
821 /* make sure period is in available range */
822 if (*period < glb)
823 *period = glb;
824 if (*period > lub)
825 *period = lub;
827 /* we can multiply period by 1, 2, 4, or 8, using (1 << i) */
828 for (i = 0; i < 4; i++) {
829 /* there are a maximum of 4 master clocks */
830 for (j = 0; j < thisboard->num_clocks; j++) {
831 /* temp is the period in nanosec we are evaluating */
832 temp = thisboard->clock[j] * (1 << i);
833 /* if it is the best match yet */
834 if (temp < lub && temp >= *period) {
835 lub_divisor_shift = i;
836 lub_index = j;
837 lub = temp;
839 if (temp > glb && temp <= *period) {
840 glb_divisor_shift = i;
841 glb_index = j;
842 glb = temp;
846 flags &= TRIG_ROUND_MASK;
847 switch (flags) {
848 case TRIG_ROUND_NEAREST:
849 default:
850 /* if least upper bound is better approximation */
851 if (lub - *period < *period - glb) {
852 *period = lub;
853 } else {
854 *period = glb;
856 break;
857 case TRIG_ROUND_UP:
858 *period = lub;
859 break;
860 case TRIG_ROUND_DOWN:
861 *period = glb;
862 break;
865 /* set clock bits for config register appropriately */
866 devpriv->config_bits &= ~CLOCK_MASK;
867 if (*period == lub) {
868 devpriv->config_bits |=
869 CLOCK_SELECT_BITS(lub_index) |
870 CLOCK_DIVISOR_BITS(lub_divisor_shift);
871 } else {
872 devpriv->config_bits |=
873 CLOCK_SELECT_BITS(glb_index) |
874 CLOCK_DIVISOR_BITS(glb_divisor_shift);
877 return 0;
880 static int a2150_set_chanlist(struct comedi_device *dev,
881 unsigned int start_channel,
882 unsigned int num_channels)
884 if (start_channel + num_channels > 4)
885 return -1;
887 devpriv->config_bits &= ~CHANNEL_MASK;
889 switch (num_channels) {
890 case 1:
891 devpriv->config_bits |= CHANNEL_BITS(0x4 | start_channel);
892 break;
893 case 2:
894 if (start_channel == 0) {
895 devpriv->config_bits |= CHANNEL_BITS(0x2);
896 } else if (start_channel == 2) {
897 devpriv->config_bits |= CHANNEL_BITS(0x3);
898 } else {
899 return -1;
901 break;
902 case 4:
903 devpriv->config_bits |= CHANNEL_BITS(0x1);
904 break;
905 default:
906 return -1;
907 break;
910 return 0;