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 ************************************************************************
27 Description: National Instruments AT-A2150
28 Author: Frank Mori Hess
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:
49 The only difference is their master clock frequencies.
56 References (from ftp://ftp.natinst.com/support/manuals):
58 320360.pdf AT-A2150 User Manual
62 analog level triggering
67 #include <linux/interrupt.h>
68 #include <linux/slab.h>
69 #include "../comedidev.h"
71 #include <linux/ioport.h>
76 #include "comedi_fc.h"
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 */
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[] = {
145 .clock = {31250, 22676, 20833, 19531},
151 .clock = {62500, 50000, 41667, 0},
157 struct a2150_private {
159 volatile unsigned int count; /* number of data points left to be taken */
160 unsigned int dma; /* dma channel */
161 s16 *dma_buffer; /* dma buffer */
162 unsigned int dma_transfer_size; /* size in bytes of dma transfers */
163 int irq_dma_bits; /* irq/dma register bits */
164 int config_bits; /* config register bits */
167 static int a2150_cancel(struct comedi_device *dev, struct comedi_subdevice *s);
169 static int a2150_get_timing(struct comedi_device *dev, unsigned int *period,
171 static int a2150_set_chanlist(struct comedi_device *dev,
172 unsigned int start_channel,
173 unsigned int num_channels);
176 static void ni_dump_regs(struct comedi_device *dev)
178 struct a2150_private *devpriv = dev->private;
180 printk("config bits 0x%x\n", devpriv->config_bits);
181 printk("irq dma bits 0x%x\n", devpriv->irq_dma_bits);
182 printk("status bits 0x%x\n", inw(dev->iobase + STATUS_REG));
187 /* interrupt service routine */
188 static irqreturn_t a2150_interrupt(int irq, void *d)
193 struct comedi_device *dev = d;
194 struct a2150_private *devpriv = dev->private;
195 struct comedi_subdevice *s = dev->read_subdev;
196 struct comedi_async *async;
197 struct comedi_cmd *cmd;
198 unsigned int max_points, num_points, residue, leftover;
200 static const int sample_size = sizeof(devpriv->dma_buffer[0]);
202 if (!dev->attached) {
203 comedi_error(dev, "premature interrupt");
206 /* initialize async here to make sure s is not NULL */
211 status = inw(dev->iobase + STATUS_REG);
213 if ((status & INTR_BIT) == 0) {
214 comedi_error(dev, "spurious interrupt");
218 if (status & OVFL_BIT) {
219 comedi_error(dev, "fifo overflow");
220 a2150_cancel(dev, s);
221 async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
224 if ((status & DMA_TC_BIT) == 0) {
225 comedi_error(dev, "caught non-dma interrupt? Aborting.");
226 a2150_cancel(dev, s);
227 async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
228 comedi_event(dev, s);
232 flags = claim_dma_lock();
233 disable_dma(devpriv->dma);
234 /* clear flip-flop to make sure 2-byte registers for
235 * count and address get set correctly */
236 clear_dma_ff(devpriv->dma);
238 /* figure out how many points to read */
239 max_points = devpriv->dma_transfer_size / sample_size;
240 /* residue is the number of points left to be done on the dma
241 * transfer. It should always be zero at this point unless
242 * the stop_src is set to external triggering.
244 residue = get_dma_residue(devpriv->dma) / sample_size;
245 num_points = max_points - residue;
246 if (devpriv->count < num_points && cmd->stop_src == TRIG_COUNT)
247 num_points = devpriv->count;
249 /* figure out how many points will be stored next time */
251 if (cmd->stop_src == TRIG_NONE) {
252 leftover = devpriv->dma_transfer_size / sample_size;
253 } else if (devpriv->count > max_points) {
254 leftover = devpriv->count - max_points;
255 if (leftover > max_points)
256 leftover = max_points;
258 /* there should only be a residue if collection was stopped by having
259 * the stop_src set to an external trigger, in which case there
260 * will be no more data
265 for (i = 0; i < num_points; i++) {
266 /* write data point to comedi buffer */
267 dpnt = devpriv->dma_buffer[i];
268 /* convert from 2's complement to unsigned coding */
270 cfc_write_to_buffer(s, dpnt);
271 if (cmd->stop_src == TRIG_COUNT) {
272 if (--devpriv->count == 0) { /* end of acquisition */
273 a2150_cancel(dev, s);
274 async->events |= COMEDI_CB_EOA;
281 set_dma_addr(devpriv->dma, virt_to_bus(devpriv->dma_buffer));
282 set_dma_count(devpriv->dma, leftover * sample_size);
283 enable_dma(devpriv->dma);
285 release_dma_lock(flags);
287 async->events |= COMEDI_CB_BLOCK;
289 comedi_event(dev, s);
291 /* clear interrupt */
292 outw(0x00, dev->iobase + DMA_TC_CLEAR_REG);
297 static int a2150_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
299 struct a2150_private *devpriv = dev->private;
301 /* disable dma on card */
302 devpriv->irq_dma_bits &= ~DMA_INTR_EN_BIT & ~DMA_EN_BIT;
303 outw(devpriv->irq_dma_bits, dev->iobase + IRQ_DMA_CNTRL_REG);
305 /* disable computer's dma */
306 disable_dma(devpriv->dma);
308 /* clear fifo and reset triggering circuitry */
309 outw(0, dev->iobase + FIFO_RESET_REG);
314 static int a2150_ai_cmdtest(struct comedi_device *dev,
315 struct comedi_subdevice *s, struct comedi_cmd *cmd)
317 const struct a2150_board *thisboard = comedi_board(dev);
323 /* Step 1 : check if triggers are trivially valid */
325 err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_EXT);
326 err |= cfc_check_trigger_src(&cmd->scan_begin_src, TRIG_TIMER);
327 err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_NOW);
328 err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
329 err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE);
334 /* Step 2a : make sure trigger sources are unique */
336 err |= cfc_check_trigger_is_unique(cmd->start_src);
337 err |= cfc_check_trigger_is_unique(cmd->stop_src);
339 /* Step 2b : and mutually compatible */
344 /* Step 3: check if arguments are trivially valid */
346 err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
348 if (cmd->convert_src == TRIG_TIMER)
349 err |= cfc_check_trigger_arg_min(&cmd->convert_arg,
350 thisboard->ai_speed);
352 err |= cfc_check_trigger_arg_min(&cmd->chanlist_len, 1);
353 err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
355 if (cmd->stop_src == TRIG_COUNT)
356 err |= cfc_check_trigger_arg_min(&cmd->stop_arg, 1);
358 err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
363 /* step 4: fix up any arguments */
365 if (cmd->scan_begin_src == TRIG_TIMER) {
366 tmp = cmd->scan_begin_arg;
367 a2150_get_timing(dev, &cmd->scan_begin_arg, cmd->flags);
368 if (tmp != cmd->scan_begin_arg)
375 /* check channel/gain list against card's limitations */
377 startChan = CR_CHAN(cmd->chanlist[0]);
378 for (i = 1; i < cmd->chanlist_len; i++) {
379 if (CR_CHAN(cmd->chanlist[i]) != (startChan + i)) {
381 "entries in chanlist must be consecutive channels, counting upwards\n");
385 if (cmd->chanlist_len == 2 && CR_CHAN(cmd->chanlist[0]) == 1) {
387 "length 2 chanlist must be channels 0,1 or channels 2,3");
390 if (cmd->chanlist_len == 3) {
392 "chanlist must have 1,2 or 4 channels");
395 if (CR_AREF(cmd->chanlist[0]) != CR_AREF(cmd->chanlist[1]) ||
396 CR_AREF(cmd->chanlist[2]) != CR_AREF(cmd->chanlist[3])) {
398 "channels 0/1 and 2/3 must have the same analog reference");
409 static int a2150_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
411 struct a2150_private *devpriv = dev->private;
412 struct comedi_async *async = s->async;
413 struct comedi_cmd *cmd = &async->cmd;
414 unsigned long lock_flags;
415 unsigned int old_config_bits = devpriv->config_bits;
416 unsigned int trigger_bits;
418 if (!dev->irq || !devpriv->dma) {
420 " irq and dma required, cannot do hardware conversions");
423 if (cmd->flags & TRIG_RT) {
425 " dma incompatible with hard real-time interrupt (TRIG_RT), aborting");
428 /* clear fifo and reset triggering circuitry */
429 outw(0, dev->iobase + FIFO_RESET_REG);
432 if (a2150_set_chanlist(dev, CR_CHAN(cmd->chanlist[0]),
433 cmd->chanlist_len) < 0)
436 /* setup ac/dc coupling */
437 if (CR_AREF(cmd->chanlist[0]) == AREF_OTHER)
438 devpriv->config_bits |= AC0_BIT;
440 devpriv->config_bits &= ~AC0_BIT;
441 if (CR_AREF(cmd->chanlist[2]) == AREF_OTHER)
442 devpriv->config_bits |= AC1_BIT;
444 devpriv->config_bits &= ~AC1_BIT;
447 a2150_get_timing(dev, &cmd->scan_begin_arg, cmd->flags);
449 /* send timing, channel, config bits */
450 outw(devpriv->config_bits, dev->iobase + CONFIG_REG);
452 /* initialize number of samples remaining */
453 devpriv->count = cmd->stop_arg * cmd->chanlist_len;
455 /* enable computer's dma */
456 lock_flags = claim_dma_lock();
457 disable_dma(devpriv->dma);
458 /* clear flip-flop to make sure 2-byte registers for
459 * count and address get set correctly */
460 clear_dma_ff(devpriv->dma);
461 set_dma_addr(devpriv->dma, virt_to_bus(devpriv->dma_buffer));
462 /* set size of transfer to fill in 1/3 second */
463 #define ONE_THIRD_SECOND 333333333
464 devpriv->dma_transfer_size =
465 sizeof(devpriv->dma_buffer[0]) * cmd->chanlist_len *
466 ONE_THIRD_SECOND / cmd->scan_begin_arg;
467 if (devpriv->dma_transfer_size > A2150_DMA_BUFFER_SIZE)
468 devpriv->dma_transfer_size = A2150_DMA_BUFFER_SIZE;
469 if (devpriv->dma_transfer_size < sizeof(devpriv->dma_buffer[0]))
470 devpriv->dma_transfer_size = sizeof(devpriv->dma_buffer[0]);
471 devpriv->dma_transfer_size -=
472 devpriv->dma_transfer_size % sizeof(devpriv->dma_buffer[0]);
473 set_dma_count(devpriv->dma, devpriv->dma_transfer_size);
474 enable_dma(devpriv->dma);
475 release_dma_lock(lock_flags);
477 /* clear dma interrupt before enabling it, to try and get rid of that
478 * one spurious interrupt that has been happening */
479 outw(0x00, dev->iobase + DMA_TC_CLEAR_REG);
481 /* enable dma on card */
482 devpriv->irq_dma_bits |= DMA_INTR_EN_BIT | DMA_EN_BIT;
483 outw(devpriv->irq_dma_bits, dev->iobase + IRQ_DMA_CNTRL_REG);
485 /* may need to wait 72 sampling periods if timing was changed */
486 i8254_load(dev->iobase + I8253_BASE_REG, 0, 2, 72, 0);
488 /* setup start triggering */
490 /* decide if we need to wait 72 periods for valid data */
491 if (cmd->start_src == TRIG_NOW &&
492 (old_config_bits & CLOCK_MASK) !=
493 (devpriv->config_bits & CLOCK_MASK)) {
494 /* set trigger source to delay trigger */
495 trigger_bits |= DELAY_TRIGGER_BITS;
497 /* otherwise no delay */
498 trigger_bits |= POST_TRIGGER_BITS;
500 /* enable external hardware trigger */
501 if (cmd->start_src == TRIG_EXT) {
502 trigger_bits |= HW_TRIG_EN;
503 } else if (cmd->start_src == TRIG_OTHER) {
504 /* XXX add support for level/slope start trigger using TRIG_OTHER */
505 comedi_error(dev, "you shouldn't see this?");
507 /* send trigger config bits */
508 outw(trigger_bits, dev->iobase + TRIGGER_REG);
510 /* start acquisition for soft trigger */
511 if (cmd->start_src == TRIG_NOW)
512 outw(0, dev->iobase + FIFO_START_REG);
520 static int a2150_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
521 struct comedi_insn *insn, unsigned int *data)
523 struct a2150_private *devpriv = dev->private;
525 static const int timeout = 100000;
526 static const int filter_delay = 36;
528 /* clear fifo and reset triggering circuitry */
529 outw(0, dev->iobase + FIFO_RESET_REG);
532 if (a2150_set_chanlist(dev, CR_CHAN(insn->chanspec), 1) < 0)
535 /* set dc coupling */
536 devpriv->config_bits &= ~AC0_BIT;
537 devpriv->config_bits &= ~AC1_BIT;
539 /* send timing, channel, config bits */
540 outw(devpriv->config_bits, dev->iobase + CONFIG_REG);
542 /* disable dma on card */
543 devpriv->irq_dma_bits &= ~DMA_INTR_EN_BIT & ~DMA_EN_BIT;
544 outw(devpriv->irq_dma_bits, dev->iobase + IRQ_DMA_CNTRL_REG);
546 /* setup start triggering */
547 outw(0, dev->iobase + TRIGGER_REG);
549 /* start acquisition for soft trigger */
550 outw(0, dev->iobase + FIFO_START_REG);
553 * there is a 35.6 sample delay for data to get through the
556 for (n = 0; n < filter_delay; n++) {
557 for (i = 0; i < timeout; i++) {
558 if (inw(dev->iobase + STATUS_REG) & FNE_BIT)
563 comedi_error(dev, "timeout");
566 inw(dev->iobase + FIFO_DATA_REG);
570 for (n = 0; n < insn->n; n++) {
571 for (i = 0; i < timeout; i++) {
572 if (inw(dev->iobase + STATUS_REG) & FNE_BIT)
577 comedi_error(dev, "timeout");
583 data[n] = inw(dev->iobase + FIFO_DATA_REG);
585 printk(" data is %i\n", data[n]);
590 /* clear fifo and reset triggering circuitry */
591 outw(0, dev->iobase + FIFO_RESET_REG);
597 * sets bits in devpriv->clock_bits to nearest approximation of requested
598 * period, adjusts requested period to actual timing.
600 static int a2150_get_timing(struct comedi_device *dev, unsigned int *period,
603 const struct a2150_board *thisboard = comedi_board(dev);
604 struct a2150_private *devpriv = dev->private;
606 int lub_divisor_shift, lub_index, glb_divisor_shift, glb_index;
609 /* initialize greatest lower and least upper bounds */
610 lub_divisor_shift = 3;
612 lub = thisboard->clock[lub_index] * (1 << lub_divisor_shift);
613 glb_divisor_shift = 0;
614 glb_index = thisboard->num_clocks - 1;
615 glb = thisboard->clock[glb_index] * (1 << glb_divisor_shift);
617 /* make sure period is in available range */
623 /* we can multiply period by 1, 2, 4, or 8, using (1 << i) */
624 for (i = 0; i < 4; i++) {
625 /* there are a maximum of 4 master clocks */
626 for (j = 0; j < thisboard->num_clocks; j++) {
627 /* temp is the period in nanosec we are evaluating */
628 temp = thisboard->clock[j] * (1 << i);
629 /* if it is the best match yet */
630 if (temp < lub && temp >= *period) {
631 lub_divisor_shift = i;
635 if (temp > glb && temp <= *period) {
636 glb_divisor_shift = i;
642 flags &= TRIG_ROUND_MASK;
644 case TRIG_ROUND_NEAREST:
646 /* if least upper bound is better approximation */
647 if (lub - *period < *period - glb)
655 case TRIG_ROUND_DOWN:
660 /* set clock bits for config register appropriately */
661 devpriv->config_bits &= ~CLOCK_MASK;
662 if (*period == lub) {
663 devpriv->config_bits |=
664 CLOCK_SELECT_BITS(lub_index) |
665 CLOCK_DIVISOR_BITS(lub_divisor_shift);
667 devpriv->config_bits |=
668 CLOCK_SELECT_BITS(glb_index) |
669 CLOCK_DIVISOR_BITS(glb_divisor_shift);
675 static int a2150_set_chanlist(struct comedi_device *dev,
676 unsigned int start_channel,
677 unsigned int num_channels)
679 struct a2150_private *devpriv = dev->private;
681 if (start_channel + num_channels > 4)
684 devpriv->config_bits &= ~CHANNEL_MASK;
686 switch (num_channels) {
688 devpriv->config_bits |= CHANNEL_BITS(0x4 | start_channel);
691 if (start_channel == 0) {
692 devpriv->config_bits |= CHANNEL_BITS(0x2);
693 } else if (start_channel == 2) {
694 devpriv->config_bits |= CHANNEL_BITS(0x3);
700 devpriv->config_bits |= CHANNEL_BITS(0x1);
710 /* probes board type, returns offset */
711 static int a2150_probe(struct comedi_device *dev)
713 int status = inw(dev->iobase + STATUS_REG);
714 return ID_BITS(status);
717 static int a2150_attach(struct comedi_device *dev, struct comedi_devconfig *it)
719 const struct a2150_board *thisboard = comedi_board(dev);
720 struct a2150_private *devpriv;
721 struct comedi_subdevice *s;
722 unsigned int irq = it->options[1];
723 unsigned int dma = it->options[2];
724 static const int timeout = 2000;
728 devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
731 dev->private = devpriv;
733 ret = comedi_request_region(dev, it->options[0], A2150_SIZE);
739 /* check that irq is supported */
740 if (irq < 3 || irq == 8 || irq == 13 || irq > 15) {
741 printk(" invalid irq line %u\n", irq);
744 if (request_irq(irq, a2150_interrupt, 0,
745 dev->driver->driver_name, dev)) {
746 printk("unable to allocate irq %u\n", irq);
749 devpriv->irq_dma_bits |= IRQ_LVL_BITS(irq);
754 if (dma == 4 || dma > 7) {
755 printk(" invalid dma channel %u\n", dma);
758 if (request_dma(dma, dev->driver->driver_name)) {
759 printk(" failed to allocate dma channel %u\n", dma);
763 devpriv->dma_buffer =
764 kmalloc(A2150_DMA_BUFFER_SIZE, GFP_KERNEL | GFP_DMA);
765 if (devpriv->dma_buffer == NULL)
769 set_dma_mode(dma, DMA_MODE_READ);
771 devpriv->irq_dma_bits |= DMA_CHAN_BITS(dma);
774 dev->board_ptr = a2150_boards + a2150_probe(dev);
775 thisboard = comedi_board(dev);
776 dev->board_name = thisboard->name;
778 ret = comedi_alloc_subdevices(dev, 1);
782 /* analog input subdevice */
783 s = &dev->subdevices[0];
784 dev->read_subdev = s;
785 s->type = COMEDI_SUBD_AI;
786 s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_OTHER | SDF_CMD_READ;
790 s->range_table = &range_a2150;
791 s->do_cmd = a2150_ai_cmd;
792 s->do_cmdtest = a2150_ai_cmdtest;
793 s->insn_read = a2150_ai_rinsn;
794 s->cancel = a2150_cancel;
796 /* need to do this for software counting of completed conversions, to
797 * prevent hardware count from stopping acquisition */
798 outw(HW_COUNT_DISABLE, dev->iobase + I8253_MODE_REG);
800 /* set card's irq and dma levels */
801 outw(devpriv->irq_dma_bits, dev->iobase + IRQ_DMA_CNTRL_REG);
803 /* reset and sync adc clock circuitry */
804 outw_p(DPD_BIT | APD_BIT, dev->iobase + CONFIG_REG);
805 outw_p(DPD_BIT, dev->iobase + CONFIG_REG);
806 /* initialize configuration register */
807 devpriv->config_bits = 0;
808 outw(devpriv->config_bits, dev->iobase + CONFIG_REG);
809 /* wait until offset calibration is done, then enable analog inputs */
810 for (i = 0; i < timeout; i++) {
811 if ((DCAL_BIT & inw(dev->iobase + STATUS_REG)) == 0)
817 (" timed out waiting for offset calibration to complete\n");
820 devpriv->config_bits |= ENABLE0_BIT | ENABLE1_BIT;
821 outw(devpriv->config_bits, dev->iobase + CONFIG_REG);
826 static void a2150_detach(struct comedi_device *dev)
828 struct a2150_private *devpriv = dev->private;
831 outw(APD_BIT | DPD_BIT, dev->iobase + CONFIG_REG);
834 free_dma(devpriv->dma);
835 kfree(devpriv->dma_buffer);
837 comedi_legacy_detach(dev);
840 static struct comedi_driver ni_at_a2150_driver = {
841 .driver_name = "ni_at_a2150",
842 .module = THIS_MODULE,
843 .attach = a2150_attach,
844 .detach = a2150_detach,
846 module_comedi_driver(ni_at_a2150_driver);
848 MODULE_AUTHOR("Comedi http://www.comedi.org");
849 MODULE_DESCRIPTION("Comedi low-level driver");
850 MODULE_LICENSE("GPL");