Staging: comedi: add #include <linux/io.h> to a bunch of drivers
[linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git] / drivers / staging / comedi / drivers / ni_at_a2150.c
blob32e675e3f0b98708d3c22f4e7f87165706ef2037
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 <linux/slab.h>
69 #include "../comedidev.h"
71 #include <linux/ioport.h>
72 #include <linux/io.h>
73 #include <asm/dma.h>
75 #include "8253.h"
76 #include "comedi_fc.h"
78 #define A2150_SIZE 28
79 #define A2150_DMA_BUFFER_SIZE 0xff00 /* size in bytes of dma buffer */
81 /* #define A2150_DEBUG enable debugging code */
82 #undef A2150_DEBUG /* disable debugging code */
84 /* Registers and bits */
85 #define CONFIG_REG 0x0
86 #define CHANNEL_BITS(x) ((x) & 0x7)
87 #define CHANNEL_MASK 0x7
88 #define CLOCK_SELECT_BITS(x) (((x) & 0x3) << 3)
89 #define CLOCK_DIVISOR_BITS(x) (((x) & 0x3) << 5)
90 #define CLOCK_MASK (0xf << 3)
91 #define ENABLE0_BIT 0x80 /* enable (don't internally ground) channels 0 and 1 */
92 #define ENABLE1_BIT 0x100 /* enable (don't internally ground) channels 2 and 3 */
93 #define AC0_BIT 0x200 /* ac couple channels 0,1 */
94 #define AC1_BIT 0x400 /* ac couple channels 2,3 */
95 #define APD_BIT 0x800 /* analog power down */
96 #define DPD_BIT 0x1000 /* digital power down */
97 #define TRIGGER_REG 0x2 /* trigger config register */
98 #define POST_TRIGGER_BITS 0x2
99 #define DELAY_TRIGGER_BITS 0x3
100 #define HW_TRIG_EN 0x10 /* enable hardware trigger */
101 #define FIFO_START_REG 0x6 /* software start aquistion trigger */
102 #define FIFO_RESET_REG 0x8 /* clears fifo + fifo flags */
103 #define FIFO_DATA_REG 0xa /* read data */
104 #define DMA_TC_CLEAR_REG 0xe /* clear dma terminal count interrupt */
105 #define STATUS_REG 0x12 /* read only */
106 #define FNE_BIT 0x1 /* fifo not empty */
107 #define OVFL_BIT 0x8 /* fifo overflow */
108 #define EDAQ_BIT 0x10 /* end of acquisition interrupt */
109 #define DCAL_BIT 0x20 /* offset calibration in progress */
110 #define INTR_BIT 0x40 /* interrupt has occurred */
111 #define DMA_TC_BIT 0x80 /* dma terminal count interrupt has occurred */
112 #define ID_BITS(x) (((x) >> 8) & 0x3)
113 #define IRQ_DMA_CNTRL_REG 0x12 /* write only */
114 #define DMA_CHAN_BITS(x) ((x) & 0x7) /* sets dma channel */
115 #define DMA_EN_BIT 0x8 /* enables dma */
116 #define IRQ_LVL_BITS(x) (((x) & 0xf) << 4) /* sets irq level */
117 #define FIFO_INTR_EN_BIT 0x100 /* enable fifo interrupts */
118 #define FIFO_INTR_FHF_BIT 0x200 /* interrupt fifo half full */
119 #define DMA_INTR_EN_BIT 0x800 /* enable interrupt on dma terminal count */
120 #define DMA_DEM_EN_BIT 0x1000 /* enables demand mode dma */
121 #define I8253_BASE_REG 0x14
122 #define I8253_MODE_REG 0x17
123 #define HW_COUNT_DISABLE 0x30 /* disable hardware counting of conversions */
125 struct a2150_board {
126 const char *name;
127 int clock[4]; /* master clock periods, in nanoseconds */
128 int num_clocks; /* number of available master clock speeds */
129 int ai_speed; /* maximum conversion rate in nanoseconds */
132 /* analog input range */
133 static const struct comedi_lrange range_a2150 = {
136 RANGE(-2.828, 2.828),
140 /* enum must match board indices */
141 enum { a2150_c, a2150_s };
142 static const struct a2150_board a2150_boards[] = {
144 .name = "at-a2150c",
145 .clock = {31250, 22676, 20833, 19531},
146 .num_clocks = 4,
147 .ai_speed = 19531,
150 .name = "at-a2150s",
151 .clock = {62500, 50000, 41667, 0},
152 .num_clocks = 3,
153 .ai_speed = 41667,
158 * Useful for shorthand access to the particular board structure
160 #define thisboard ((const struct a2150_board *)dev->board_ptr)
162 struct a2150_private {
164 volatile unsigned int count; /* number of data points left to be taken */
165 unsigned int dma; /* dma channel */
166 s16 *dma_buffer; /* dma buffer */
167 unsigned int dma_transfer_size; /* size in bytes of dma transfers */
168 int irq_dma_bits; /* irq/dma register bits */
169 int config_bits; /* config register bits */
172 #define devpriv ((struct a2150_private *)dev->private)
174 static int a2150_attach(struct comedi_device *dev, struct comedi_devconfig *it);
175 static int a2150_detach(struct comedi_device *dev);
176 static int a2150_cancel(struct comedi_device *dev, struct comedi_subdevice *s);
178 static struct comedi_driver driver_a2150 = {
179 .driver_name = "ni_at_a2150",
180 .module = THIS_MODULE,
181 .attach = a2150_attach,
182 .detach = a2150_detach,
185 static irqreturn_t a2150_interrupt(int irq, void *d);
186 static int a2150_ai_cmdtest(struct comedi_device *dev,
187 struct comedi_subdevice *s, struct comedi_cmd *cmd);
188 static int a2150_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s);
189 static int a2150_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
190 struct comedi_insn *insn, unsigned int *data);
191 static int a2150_get_timing(struct comedi_device *dev, unsigned int *period,
192 int flags);
193 static int a2150_probe(struct comedi_device *dev);
194 static int a2150_set_chanlist(struct comedi_device *dev,
195 unsigned int start_channel,
196 unsigned int num_channels);
198 * A convenient macro that defines init_module() and cleanup_module(),
199 * as necessary.
201 static int __init driver_a2150_init_module(void)
203 return comedi_driver_register(&driver_a2150);
206 static void __exit driver_a2150_cleanup_module(void)
208 comedi_driver_unregister(&driver_a2150);
211 module_init(driver_a2150_init_module);
212 module_exit(driver_a2150_cleanup_module);
214 #ifdef A2150_DEBUG
216 static void ni_dump_regs(struct comedi_device *dev)
218 printk("config bits 0x%x\n", devpriv->config_bits);
219 printk("irq dma bits 0x%x\n", devpriv->irq_dma_bits);
220 printk("status bits 0x%x\n", inw(dev->iobase + STATUS_REG));
223 #endif
225 /* interrupt service routine */
226 static irqreturn_t a2150_interrupt(int irq, void *d)
228 int i;
229 int status;
230 unsigned long flags;
231 struct comedi_device *dev = d;
232 struct comedi_subdevice *s = dev->read_subdev;
233 struct comedi_async *async;
234 struct comedi_cmd *cmd;
235 unsigned int max_points, num_points, residue, leftover;
236 short dpnt;
237 static const int sample_size = sizeof(devpriv->dma_buffer[0]);
239 if (dev->attached == 0) {
240 comedi_error(dev, "premature interrupt");
241 return IRQ_HANDLED;
243 /* initialize async here to make sure s is not NULL */
244 async = s->async;
245 async->events = 0;
246 cmd = &async->cmd;
248 status = inw(dev->iobase + STATUS_REG);
250 if ((status & INTR_BIT) == 0) {
251 comedi_error(dev, "spurious interrupt");
252 return IRQ_NONE;
255 if (status & OVFL_BIT) {
256 comedi_error(dev, "fifo overflow");
257 a2150_cancel(dev, s);
258 async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
261 if ((status & DMA_TC_BIT) == 0) {
262 comedi_error(dev, "caught non-dma interrupt? Aborting.");
263 a2150_cancel(dev, s);
264 async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
265 comedi_event(dev, s);
266 return IRQ_HANDLED;
269 flags = claim_dma_lock();
270 disable_dma(devpriv->dma);
271 /* clear flip-flop to make sure 2-byte registers for
272 * count and address get set correctly */
273 clear_dma_ff(devpriv->dma);
275 /* figure out how many points to read */
276 max_points = devpriv->dma_transfer_size / sample_size;
277 /* residue is the number of points left to be done on the dma
278 * transfer. It should always be zero at this point unless
279 * the stop_src is set to external triggering.
281 residue = get_dma_residue(devpriv->dma) / sample_size;
282 num_points = max_points - residue;
283 if (devpriv->count < num_points && cmd->stop_src == TRIG_COUNT)
284 num_points = devpriv->count;
286 /* figure out how many points will be stored next time */
287 leftover = 0;
288 if (cmd->stop_src == TRIG_NONE) {
289 leftover = devpriv->dma_transfer_size / sample_size;
290 } else if (devpriv->count > max_points) {
291 leftover = devpriv->count - max_points;
292 if (leftover > max_points)
293 leftover = max_points;
295 /* there should only be a residue if collection was stopped by having
296 * the stop_src set to an external trigger, in which case there
297 * will be no more data
299 if (residue)
300 leftover = 0;
302 for (i = 0; i < num_points; i++) {
303 /* write data point to comedi buffer */
304 dpnt = devpriv->dma_buffer[i];
305 /* convert from 2's complement to unsigned coding */
306 dpnt ^= 0x8000;
307 cfc_write_to_buffer(s, dpnt);
308 if (cmd->stop_src == TRIG_COUNT) {
309 if (--devpriv->count == 0) { /* end of acquisition */
310 a2150_cancel(dev, s);
311 async->events |= COMEDI_CB_EOA;
312 break;
316 /* re-enable dma */
317 if (leftover) {
318 set_dma_addr(devpriv->dma, virt_to_bus(devpriv->dma_buffer));
319 set_dma_count(devpriv->dma, leftover * sample_size);
320 enable_dma(devpriv->dma);
322 release_dma_lock(flags);
324 async->events |= COMEDI_CB_BLOCK;
326 comedi_event(dev, s);
328 /* clear interrupt */
329 outw(0x00, dev->iobase + DMA_TC_CLEAR_REG);
331 return IRQ_HANDLED;
334 /* probes board type, returns offset */
335 static int a2150_probe(struct comedi_device *dev)
337 int status = inw(dev->iobase + STATUS_REG);
338 return ID_BITS(status);
341 static int a2150_attach(struct comedi_device *dev, struct comedi_devconfig *it)
343 struct comedi_subdevice *s;
344 unsigned long iobase = it->options[0];
345 unsigned int irq = it->options[1];
346 unsigned int dma = it->options[2];
347 static const int timeout = 2000;
348 int i;
350 printk("comedi%d: %s: io 0x%lx", dev->minor, driver_a2150.driver_name,
351 iobase);
352 if (irq) {
353 printk(", irq %u", irq);
354 } else {
355 printk(", no irq");
357 if (dma) {
358 printk(", dma %u", dma);
359 } else {
360 printk(", no dma");
362 printk("\n");
364 /* allocate and initialize dev->private */
365 if (alloc_private(dev, sizeof(struct a2150_private)) < 0)
366 return -ENOMEM;
368 if (iobase == 0) {
369 printk(" io base address required\n");
370 return -EINVAL;
373 /* check if io addresses are available */
374 if (!request_region(iobase, A2150_SIZE, driver_a2150.driver_name)) {
375 printk(" I/O port conflict\n");
376 return -EIO;
378 dev->iobase = iobase;
380 /* grab our IRQ */
381 if (irq) {
382 /* check that irq is supported */
383 if (irq < 3 || irq == 8 || irq == 13 || irq > 15) {
384 printk(" invalid irq line %u\n", irq);
385 return -EINVAL;
387 if (request_irq(irq, a2150_interrupt, 0,
388 driver_a2150.driver_name, dev)) {
389 printk("unable to allocate irq %u\n", irq);
390 return -EINVAL;
392 devpriv->irq_dma_bits |= IRQ_LVL_BITS(irq);
393 dev->irq = irq;
395 /* initialize dma */
396 if (dma) {
397 if (dma == 4 || dma > 7) {
398 printk(" invalid dma channel %u\n", dma);
399 return -EINVAL;
401 if (request_dma(dma, driver_a2150.driver_name)) {
402 printk(" failed to allocate dma channel %u\n", dma);
403 return -EINVAL;
405 devpriv->dma = dma;
406 devpriv->dma_buffer =
407 kmalloc(A2150_DMA_BUFFER_SIZE, GFP_KERNEL | GFP_DMA);
408 if (devpriv->dma_buffer == NULL)
409 return -ENOMEM;
411 disable_dma(dma);
412 set_dma_mode(dma, DMA_MODE_READ);
414 devpriv->irq_dma_bits |= DMA_CHAN_BITS(dma);
417 dev->board_ptr = a2150_boards + a2150_probe(dev);
418 dev->board_name = thisboard->name;
420 if (alloc_subdevices(dev, 1) < 0)
421 return -ENOMEM;
423 /* analog input subdevice */
424 s = dev->subdevices + 0;
425 dev->read_subdev = s;
426 s->type = COMEDI_SUBD_AI;
427 s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_OTHER | SDF_CMD_READ;
428 s->n_chan = 4;
429 s->len_chanlist = 4;
430 s->maxdata = 0xffff;
431 s->range_table = &range_a2150;
432 s->do_cmd = a2150_ai_cmd;
433 s->do_cmdtest = a2150_ai_cmdtest;
434 s->insn_read = a2150_ai_rinsn;
435 s->cancel = a2150_cancel;
437 /* need to do this for software counting of completed conversions, to
438 * prevent hardware count from stopping acquisition */
439 outw(HW_COUNT_DISABLE, dev->iobase + I8253_MODE_REG);
441 /* set card's irq and dma levels */
442 outw(devpriv->irq_dma_bits, dev->iobase + IRQ_DMA_CNTRL_REG);
444 /* reset and sync adc clock circuitry */
445 outw_p(DPD_BIT | APD_BIT, dev->iobase + CONFIG_REG);
446 outw_p(DPD_BIT, dev->iobase + CONFIG_REG);
447 /* initialize configuration register */
448 devpriv->config_bits = 0;
449 outw(devpriv->config_bits, dev->iobase + CONFIG_REG);
450 /* wait until offset calibration is done, then enable analog inputs */
451 for (i = 0; i < timeout; i++) {
452 if ((DCAL_BIT & inw(dev->iobase + STATUS_REG)) == 0)
453 break;
454 udelay(1000);
456 if (i == timeout) {
457 printk
458 (" timed out waiting for offset calibration to complete\n");
459 return -ETIME;
461 devpriv->config_bits |= ENABLE0_BIT | ENABLE1_BIT;
462 outw(devpriv->config_bits, dev->iobase + CONFIG_REG);
464 return 0;
467 static int a2150_detach(struct comedi_device *dev)
469 printk("comedi%d: %s: remove\n", dev->minor, driver_a2150.driver_name);
471 /* only free stuff if it has been allocated by _attach */
472 if (dev->iobase) {
473 /* put board in power-down mode */
474 outw(APD_BIT | DPD_BIT, dev->iobase + CONFIG_REG);
475 release_region(dev->iobase, A2150_SIZE);
478 if (dev->irq)
479 free_irq(dev->irq, dev);
480 if (devpriv) {
481 if (devpriv->dma)
482 free_dma(devpriv->dma);
483 kfree(devpriv->dma_buffer);
486 return 0;
489 static int a2150_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
491 /* disable dma on card */
492 devpriv->irq_dma_bits &= ~DMA_INTR_EN_BIT & ~DMA_EN_BIT;
493 outw(devpriv->irq_dma_bits, dev->iobase + IRQ_DMA_CNTRL_REG);
495 /* disable computer's dma */
496 disable_dma(devpriv->dma);
498 /* clear fifo and reset triggering circuitry */
499 outw(0, dev->iobase + FIFO_RESET_REG);
501 return 0;
504 static int a2150_ai_cmdtest(struct comedi_device *dev,
505 struct comedi_subdevice *s, struct comedi_cmd *cmd)
507 int err = 0;
508 int tmp;
509 int startChan;
510 int i;
512 /* step 1: make sure trigger sources are trivially valid */
514 tmp = cmd->start_src;
515 cmd->start_src &= TRIG_NOW | TRIG_EXT;
516 if (!cmd->start_src || tmp != cmd->start_src)
517 err++;
519 tmp = cmd->scan_begin_src;
520 cmd->scan_begin_src &= TRIG_TIMER;
521 if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
522 err++;
524 tmp = cmd->convert_src;
525 cmd->convert_src &= TRIG_NOW;
526 if (!cmd->convert_src || tmp != cmd->convert_src)
527 err++;
529 tmp = cmd->scan_end_src;
530 cmd->scan_end_src &= TRIG_COUNT;
531 if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
532 err++;
534 tmp = cmd->stop_src;
535 cmd->stop_src &= TRIG_COUNT | TRIG_NONE;
536 if (!cmd->stop_src || tmp != cmd->stop_src)
537 err++;
539 if (err)
540 return 1;
542 /* step 2: make sure trigger sources are unique and mutually compatible */
544 if (cmd->start_src != TRIG_NOW && cmd->start_src != TRIG_EXT)
545 err++;
546 if (cmd->stop_src != TRIG_COUNT && cmd->stop_src != TRIG_NONE)
547 err++;
549 if (err)
550 return 2;
552 /* step 3: make sure arguments are trivially compatible */
554 if (cmd->start_arg != 0) {
555 cmd->start_arg = 0;
556 err++;
558 if (cmd->convert_src == TRIG_TIMER) {
559 if (cmd->convert_arg < thisboard->ai_speed) {
560 cmd->convert_arg = thisboard->ai_speed;
561 err++;
564 if (!cmd->chanlist_len) {
565 cmd->chanlist_len = 1;
566 err++;
568 if (cmd->scan_end_arg != cmd->chanlist_len) {
569 cmd->scan_end_arg = cmd->chanlist_len;
570 err++;
572 if (cmd->stop_src == TRIG_COUNT) {
573 if (!cmd->stop_arg) {
574 cmd->stop_arg = 1;
575 err++;
577 } else { /* TRIG_NONE */
578 if (cmd->stop_arg != 0) {
579 cmd->stop_arg = 0;
580 err++;
584 if (err)
585 return 3;
587 /* step 4: fix up any arguments */
589 if (cmd->scan_begin_src == TRIG_TIMER) {
590 tmp = cmd->scan_begin_arg;
591 a2150_get_timing(dev, &cmd->scan_begin_arg, cmd->flags);
592 if (tmp != cmd->scan_begin_arg)
593 err++;
596 if (err)
597 return 4;
599 /* check channel/gain list against card's limitations */
600 if (cmd->chanlist) {
601 startChan = CR_CHAN(cmd->chanlist[0]);
602 for (i = 1; i < cmd->chanlist_len; i++) {
603 if (CR_CHAN(cmd->chanlist[i]) != (startChan + i)) {
604 comedi_error(dev,
605 "entries in chanlist must be consecutive channels, counting upwards\n");
606 err++;
609 if (cmd->chanlist_len == 2 && CR_CHAN(cmd->chanlist[0]) == 1) {
610 comedi_error(dev,
611 "length 2 chanlist must be channels 0,1 or channels 2,3");
612 err++;
614 if (cmd->chanlist_len == 3) {
615 comedi_error(dev,
616 "chanlist must have 1,2 or 4 channels");
617 err++;
619 if (CR_AREF(cmd->chanlist[0]) != CR_AREF(cmd->chanlist[1]) ||
620 CR_AREF(cmd->chanlist[2]) != CR_AREF(cmd->chanlist[3])) {
621 comedi_error(dev,
622 "channels 0/1 and 2/3 must have the same analog reference");
623 err++;
627 if (err)
628 return 5;
630 return 0;
633 static int a2150_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
635 struct comedi_async *async = s->async;
636 struct comedi_cmd *cmd = &async->cmd;
637 unsigned long lock_flags;
638 unsigned int old_config_bits = devpriv->config_bits;
639 unsigned int trigger_bits;
641 if (!dev->irq || !devpriv->dma) {
642 comedi_error(dev,
643 " irq and dma required, cannot do hardware conversions");
644 return -1;
646 if (cmd->flags & TRIG_RT) {
647 comedi_error(dev,
648 " dma incompatible with hard real-time interrupt (TRIG_RT), aborting");
649 return -1;
651 /* clear fifo and reset triggering circuitry */
652 outw(0, dev->iobase + FIFO_RESET_REG);
654 /* setup chanlist */
655 if (a2150_set_chanlist(dev, CR_CHAN(cmd->chanlist[0]),
656 cmd->chanlist_len) < 0)
657 return -1;
659 /* setup ac/dc coupling */
660 if (CR_AREF(cmd->chanlist[0]) == AREF_OTHER)
661 devpriv->config_bits |= AC0_BIT;
662 else
663 devpriv->config_bits &= ~AC0_BIT;
664 if (CR_AREF(cmd->chanlist[2]) == AREF_OTHER)
665 devpriv->config_bits |= AC1_BIT;
666 else
667 devpriv->config_bits &= ~AC1_BIT;
669 /* setup timing */
670 a2150_get_timing(dev, &cmd->scan_begin_arg, cmd->flags);
672 /* send timing, channel, config bits */
673 outw(devpriv->config_bits, dev->iobase + CONFIG_REG);
675 /* initialize number of samples remaining */
676 devpriv->count = cmd->stop_arg * cmd->chanlist_len;
678 /* enable computer's dma */
679 lock_flags = claim_dma_lock();
680 disable_dma(devpriv->dma);
681 /* clear flip-flop to make sure 2-byte registers for
682 * count and address get set correctly */
683 clear_dma_ff(devpriv->dma);
684 set_dma_addr(devpriv->dma, virt_to_bus(devpriv->dma_buffer));
685 /* set size of transfer to fill in 1/3 second */
686 #define ONE_THIRD_SECOND 333333333
687 devpriv->dma_transfer_size =
688 sizeof(devpriv->dma_buffer[0]) * cmd->chanlist_len *
689 ONE_THIRD_SECOND / cmd->scan_begin_arg;
690 if (devpriv->dma_transfer_size > A2150_DMA_BUFFER_SIZE)
691 devpriv->dma_transfer_size = A2150_DMA_BUFFER_SIZE;
692 if (devpriv->dma_transfer_size < sizeof(devpriv->dma_buffer[0]))
693 devpriv->dma_transfer_size = sizeof(devpriv->dma_buffer[0]);
694 devpriv->dma_transfer_size -=
695 devpriv->dma_transfer_size % sizeof(devpriv->dma_buffer[0]);
696 set_dma_count(devpriv->dma, devpriv->dma_transfer_size);
697 enable_dma(devpriv->dma);
698 release_dma_lock(lock_flags);
700 /* clear dma interrupt before enabling it, to try and get rid of that
701 * one spurious interrupt that has been happening */
702 outw(0x00, dev->iobase + DMA_TC_CLEAR_REG);
704 /* enable dma on card */
705 devpriv->irq_dma_bits |= DMA_INTR_EN_BIT | DMA_EN_BIT;
706 outw(devpriv->irq_dma_bits, dev->iobase + IRQ_DMA_CNTRL_REG);
708 /* may need to wait 72 sampling periods if timing was changed */
709 i8254_load(dev->iobase + I8253_BASE_REG, 0, 2, 72, 0);
711 /* setup start triggering */
712 trigger_bits = 0;
713 /* decide if we need to wait 72 periods for valid data */
714 if (cmd->start_src == TRIG_NOW &&
715 (old_config_bits & CLOCK_MASK) !=
716 (devpriv->config_bits & CLOCK_MASK)) {
717 /* set trigger source to delay trigger */
718 trigger_bits |= DELAY_TRIGGER_BITS;
719 } else {
720 /* otherwise no delay */
721 trigger_bits |= POST_TRIGGER_BITS;
723 /* enable external hardware trigger */
724 if (cmd->start_src == TRIG_EXT) {
725 trigger_bits |= HW_TRIG_EN;
726 } else if (cmd->start_src == TRIG_OTHER) {
727 /* XXX add support for level/slope start trigger using TRIG_OTHER */
728 comedi_error(dev, "you shouldn't see this?");
730 /* send trigger config bits */
731 outw(trigger_bits, dev->iobase + TRIGGER_REG);
733 /* start acquisition for soft trigger */
734 if (cmd->start_src == TRIG_NOW) {
735 outw(0, dev->iobase + FIFO_START_REG);
737 #ifdef A2150_DEBUG
738 ni_dump_regs(dev);
739 #endif
741 return 0;
744 static int a2150_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
745 struct comedi_insn *insn, unsigned int *data)
747 unsigned int i, n;
748 static const int timeout = 100000;
749 static const int filter_delay = 36;
751 /* clear fifo and reset triggering circuitry */
752 outw(0, dev->iobase + FIFO_RESET_REG);
754 /* setup chanlist */
755 if (a2150_set_chanlist(dev, CR_CHAN(insn->chanspec), 1) < 0)
756 return -1;
758 /* set dc coupling */
759 devpriv->config_bits &= ~AC0_BIT;
760 devpriv->config_bits &= ~AC1_BIT;
762 /* send timing, channel, config bits */
763 outw(devpriv->config_bits, dev->iobase + CONFIG_REG);
765 /* disable dma on card */
766 devpriv->irq_dma_bits &= ~DMA_INTR_EN_BIT & ~DMA_EN_BIT;
767 outw(devpriv->irq_dma_bits, dev->iobase + IRQ_DMA_CNTRL_REG);
769 /* setup start triggering */
770 outw(0, dev->iobase + TRIGGER_REG);
772 /* start acquisition for soft trigger */
773 outw(0, dev->iobase + FIFO_START_REG);
775 /* there is a 35.6 sample delay for data to get through the antialias filter */
776 for (n = 0; n < filter_delay; n++) {
777 for (i = 0; i < timeout; i++) {
778 if (inw(dev->iobase + STATUS_REG) & FNE_BIT)
779 break;
780 udelay(1);
782 if (i == timeout) {
783 comedi_error(dev, "timeout");
784 return -ETIME;
786 inw(dev->iobase + FIFO_DATA_REG);
789 /* read data */
790 for (n = 0; n < insn->n; n++) {
791 for (i = 0; i < timeout; i++) {
792 if (inw(dev->iobase + STATUS_REG) & FNE_BIT)
793 break;
794 udelay(1);
796 if (i == timeout) {
797 comedi_error(dev, "timeout");
798 return -ETIME;
800 #ifdef A2150_DEBUG
801 ni_dump_regs(dev);
802 #endif
803 data[n] = inw(dev->iobase + FIFO_DATA_REG);
804 #ifdef A2150_DEBUG
805 printk(" data is %i\n", data[n]);
806 #endif
807 data[n] ^= 0x8000;
810 /* clear fifo and reset triggering circuitry */
811 outw(0, dev->iobase + FIFO_RESET_REG);
813 return n;
816 /* sets bits in devpriv->clock_bits to nearest approximation of requested period,
817 * adjusts requested period to actual timing. */
818 static int a2150_get_timing(struct comedi_device *dev, unsigned int *period,
819 int flags)
821 int lub, glb, temp;
822 int lub_divisor_shift, lub_index, glb_divisor_shift, glb_index;
823 int i, j;
825 /* initialize greatest lower and least upper bounds */
826 lub_divisor_shift = 3;
827 lub_index = 0;
828 lub = thisboard->clock[lub_index] * (1 << lub_divisor_shift);
829 glb_divisor_shift = 0;
830 glb_index = thisboard->num_clocks - 1;
831 glb = thisboard->clock[glb_index] * (1 << glb_divisor_shift);
833 /* make sure period is in available range */
834 if (*period < glb)
835 *period = glb;
836 if (*period > lub)
837 *period = lub;
839 /* we can multiply period by 1, 2, 4, or 8, using (1 << i) */
840 for (i = 0; i < 4; i++) {
841 /* there are a maximum of 4 master clocks */
842 for (j = 0; j < thisboard->num_clocks; j++) {
843 /* temp is the period in nanosec we are evaluating */
844 temp = thisboard->clock[j] * (1 << i);
845 /* if it is the best match yet */
846 if (temp < lub && temp >= *period) {
847 lub_divisor_shift = i;
848 lub_index = j;
849 lub = temp;
851 if (temp > glb && temp <= *period) {
852 glb_divisor_shift = i;
853 glb_index = j;
854 glb = temp;
858 flags &= TRIG_ROUND_MASK;
859 switch (flags) {
860 case TRIG_ROUND_NEAREST:
861 default:
862 /* if least upper bound is better approximation */
863 if (lub - *period < *period - glb) {
864 *period = lub;
865 } else {
866 *period = glb;
868 break;
869 case TRIG_ROUND_UP:
870 *period = lub;
871 break;
872 case TRIG_ROUND_DOWN:
873 *period = glb;
874 break;
877 /* set clock bits for config register appropriately */
878 devpriv->config_bits &= ~CLOCK_MASK;
879 if (*period == lub) {
880 devpriv->config_bits |=
881 CLOCK_SELECT_BITS(lub_index) |
882 CLOCK_DIVISOR_BITS(lub_divisor_shift);
883 } else {
884 devpriv->config_bits |=
885 CLOCK_SELECT_BITS(glb_index) |
886 CLOCK_DIVISOR_BITS(glb_divisor_shift);
889 return 0;
892 static int a2150_set_chanlist(struct comedi_device *dev,
893 unsigned int start_channel,
894 unsigned int num_channels)
896 if (start_channel + num_channels > 4)
897 return -1;
899 devpriv->config_bits &= ~CHANNEL_MASK;
901 switch (num_channels) {
902 case 1:
903 devpriv->config_bits |= CHANNEL_BITS(0x4 | start_channel);
904 break;
905 case 2:
906 if (start_channel == 0) {
907 devpriv->config_bits |= CHANNEL_BITS(0x2);
908 } else if (start_channel == 2) {
909 devpriv->config_bits |= CHANNEL_BITS(0x3);
910 } else {
911 return -1;
913 break;
914 case 4:
915 devpriv->config_bits |= CHANNEL_BITS(0x1);
916 break;
917 default:
918 return -1;
919 break;
922 return 0;
925 MODULE_AUTHOR("Comedi http://www.comedi.org");
926 MODULE_DESCRIPTION("Comedi low-level driver");
927 MODULE_LICENSE("GPL");