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.
21 Description: National Instruments AT-A2150
22 Author: Frank Mori Hess
24 Devices: [National Instruments] AT-A2150C (at_a2150c), AT-2150S (at_a2150s)
26 If you want to ac couple the board's inputs, use AREF_OTHER.
28 Configuration options:
29 [0] - I/O port base address
30 [1] - IRQ (optional, required for timed conversions)
31 [2] - DMA (optional, required for timed conversions)
35 Yet another driver for obsolete hardware brought to you by Frank Hess.
36 Testing and debugging help provided by Dave Andruczyk.
38 This driver supports the boards:
43 The only difference is their master clock frequencies.
50 References (from ftp://ftp.natinst.com/support/manuals):
52 320360.pdf AT-A2150 User Manual
56 analog level triggering
61 #include <linux/module.h>
62 #include <linux/delay.h>
63 #include <linux/interrupt.h>
64 #include <linux/slab.h>
67 #include "../comedidev.h"
69 #include "comedi_isadma.h"
70 #include "comedi_8254.h"
72 #define A2150_DMA_BUFFER_SIZE 0xff00 /* size in bytes of dma buffer */
74 /* Registers and bits */
75 #define CONFIG_REG 0x0
76 #define CHANNEL_BITS(x) ((x) & 0x7)
77 #define CHANNEL_MASK 0x7
78 #define CLOCK_SELECT_BITS(x) (((x) & 0x3) << 3)
79 #define CLOCK_DIVISOR_BITS(x) (((x) & 0x3) << 5)
80 #define CLOCK_MASK (0xf << 3)
81 #define ENABLE0_BIT 0x80 /* enable (don't internally ground) channels 0 and 1 */
82 #define ENABLE1_BIT 0x100 /* enable (don't internally ground) channels 2 and 3 */
83 #define AC0_BIT 0x200 /* ac couple channels 0,1 */
84 #define AC1_BIT 0x400 /* ac couple channels 2,3 */
85 #define APD_BIT 0x800 /* analog power down */
86 #define DPD_BIT 0x1000 /* digital power down */
87 #define TRIGGER_REG 0x2 /* trigger config register */
88 #define POST_TRIGGER_BITS 0x2
89 #define DELAY_TRIGGER_BITS 0x3
90 #define HW_TRIG_EN 0x10 /* enable hardware trigger */
91 #define FIFO_START_REG 0x6 /* software start aquistion trigger */
92 #define FIFO_RESET_REG 0x8 /* clears fifo + fifo flags */
93 #define FIFO_DATA_REG 0xa /* read data */
94 #define DMA_TC_CLEAR_REG 0xe /* clear dma terminal count interrupt */
95 #define STATUS_REG 0x12 /* read only */
96 #define FNE_BIT 0x1 /* fifo not empty */
97 #define OVFL_BIT 0x8 /* fifo overflow */
98 #define EDAQ_BIT 0x10 /* end of acquisition interrupt */
99 #define DCAL_BIT 0x20 /* offset calibration in progress */
100 #define INTR_BIT 0x40 /* interrupt has occurred */
101 #define DMA_TC_BIT 0x80 /* dma terminal count interrupt has occurred */
102 #define ID_BITS(x) (((x) >> 8) & 0x3)
103 #define IRQ_DMA_CNTRL_REG 0x12 /* write only */
104 #define DMA_CHAN_BITS(x) ((x) & 0x7) /* sets dma channel */
105 #define DMA_EN_BIT 0x8 /* enables dma */
106 #define IRQ_LVL_BITS(x) (((x) & 0xf) << 4) /* sets irq level */
107 #define FIFO_INTR_EN_BIT 0x100 /* enable fifo interrupts */
108 #define FIFO_INTR_FHF_BIT 0x200 /* interrupt fifo half full */
109 #define DMA_INTR_EN_BIT 0x800 /* enable interrupt on dma terminal count */
110 #define DMA_DEM_EN_BIT 0x1000 /* enables demand mode dma */
111 #define I8253_BASE_REG 0x14
115 int clock
[4]; /* master clock periods, in nanoseconds */
116 int num_clocks
; /* number of available master clock speeds */
117 int ai_speed
; /* maximum conversion rate in nanoseconds */
120 /* analog input range */
121 static const struct comedi_lrange range_a2150
= {
127 /* enum must match board indices */
128 enum { a2150_c
, a2150_s
};
129 static const struct a2150_board a2150_boards
[] = {
132 .clock
= {31250, 22676, 20833, 19531},
138 .clock
= {62500, 50000, 41667, 0},
144 struct a2150_private
{
145 struct comedi_isadma
*dma
;
146 unsigned int count
; /* number of data points left to be taken */
147 int irq_dma_bits
; /* irq/dma register bits */
148 int config_bits
; /* config register bits */
151 /* interrupt service routine */
152 static irqreturn_t
a2150_interrupt(int irq
, void *d
)
154 struct comedi_device
*dev
= d
;
155 struct a2150_private
*devpriv
= dev
->private;
156 struct comedi_isadma
*dma
= devpriv
->dma
;
157 struct comedi_isadma_desc
*desc
= &dma
->desc
[0];
158 struct comedi_subdevice
*s
= dev
->read_subdev
;
159 struct comedi_async
*async
= s
->async
;
160 struct comedi_cmd
*cmd
= &async
->cmd
;
161 unsigned short *buf
= desc
->virt_addr
;
162 unsigned int max_points
, num_points
, residue
, leftover
;
170 status
= inw(dev
->iobase
+ STATUS_REG
);
171 if ((status
& INTR_BIT
) == 0)
174 if (status
& OVFL_BIT
) {
175 async
->events
|= COMEDI_CB_ERROR
;
176 comedi_handle_events(dev
, s
);
179 if ((status
& DMA_TC_BIT
) == 0) {
180 async
->events
|= COMEDI_CB_ERROR
;
181 comedi_handle_events(dev
, s
);
186 * residue is the number of bytes left to be done on the dma
187 * transfer. It should always be zero at this point unless
188 * the stop_src is set to external triggering.
190 residue
= comedi_isadma_disable(desc
->chan
);
192 /* figure out how many points to read */
193 max_points
= comedi_bytes_to_samples(s
, desc
->size
);
194 num_points
= max_points
- comedi_bytes_to_samples(s
, residue
);
195 if (devpriv
->count
< num_points
&& cmd
->stop_src
== TRIG_COUNT
)
196 num_points
= devpriv
->count
;
198 /* figure out how many points will be stored next time */
200 if (cmd
->stop_src
== TRIG_NONE
) {
201 leftover
= comedi_bytes_to_samples(s
, desc
->size
);
202 } else if (devpriv
->count
> max_points
) {
203 leftover
= devpriv
->count
- max_points
;
204 if (leftover
> max_points
)
205 leftover
= max_points
;
207 /* there should only be a residue if collection was stopped by having
208 * the stop_src set to an external trigger, in which case there
209 * will be no more data
214 for (i
= 0; i
< num_points
; i
++) {
215 /* write data point to comedi buffer */
217 /* convert from 2's complement to unsigned coding */
219 comedi_buf_write_samples(s
, &dpnt
, 1);
220 if (cmd
->stop_src
== TRIG_COUNT
) {
221 if (--devpriv
->count
== 0) { /* end of acquisition */
222 async
->events
|= COMEDI_CB_EOA
;
229 desc
->size
= comedi_samples_to_bytes(s
, leftover
);
230 comedi_isadma_program(desc
);
233 comedi_handle_events(dev
, s
);
235 /* clear interrupt */
236 outw(0x00, dev
->iobase
+ DMA_TC_CLEAR_REG
);
241 static int a2150_cancel(struct comedi_device
*dev
, struct comedi_subdevice
*s
)
243 struct a2150_private
*devpriv
= dev
->private;
244 struct comedi_isadma
*dma
= devpriv
->dma
;
245 struct comedi_isadma_desc
*desc
= &dma
->desc
[0];
247 /* disable dma on card */
248 devpriv
->irq_dma_bits
&= ~DMA_INTR_EN_BIT
& ~DMA_EN_BIT
;
249 outw(devpriv
->irq_dma_bits
, dev
->iobase
+ IRQ_DMA_CNTRL_REG
);
251 /* disable computer's dma */
252 comedi_isadma_disable(desc
->chan
);
254 /* clear fifo and reset triggering circuitry */
255 outw(0, dev
->iobase
+ FIFO_RESET_REG
);
261 * sets bits in devpriv->clock_bits to nearest approximation of requested
262 * period, adjusts requested period to actual timing.
264 static int a2150_get_timing(struct comedi_device
*dev
, unsigned int *period
,
267 const struct a2150_board
*board
= dev
->board_ptr
;
268 struct a2150_private
*devpriv
= dev
->private;
270 int lub_divisor_shift
, lub_index
, glb_divisor_shift
, glb_index
;
273 /* initialize greatest lower and least upper bounds */
274 lub_divisor_shift
= 3;
276 lub
= board
->clock
[lub_index
] * (1 << lub_divisor_shift
);
277 glb_divisor_shift
= 0;
278 glb_index
= board
->num_clocks
- 1;
279 glb
= board
->clock
[glb_index
] * (1 << glb_divisor_shift
);
281 /* make sure period is in available range */
287 /* we can multiply period by 1, 2, 4, or 8, using (1 << i) */
288 for (i
= 0; i
< 4; i
++) {
289 /* there are a maximum of 4 master clocks */
290 for (j
= 0; j
< board
->num_clocks
; j
++) {
291 /* temp is the period in nanosec we are evaluating */
292 temp
= board
->clock
[j
] * (1 << i
);
293 /* if it is the best match yet */
294 if (temp
< lub
&& temp
>= *period
) {
295 lub_divisor_shift
= i
;
299 if (temp
> glb
&& temp
<= *period
) {
300 glb_divisor_shift
= i
;
306 switch (flags
& CMDF_ROUND_MASK
) {
307 case CMDF_ROUND_NEAREST
:
309 /* if least upper bound is better approximation */
310 if (lub
- *period
< *period
- glb
)
318 case CMDF_ROUND_DOWN
:
323 /* set clock bits for config register appropriately */
324 devpriv
->config_bits
&= ~CLOCK_MASK
;
325 if (*period
== lub
) {
326 devpriv
->config_bits
|=
327 CLOCK_SELECT_BITS(lub_index
) |
328 CLOCK_DIVISOR_BITS(lub_divisor_shift
);
330 devpriv
->config_bits
|=
331 CLOCK_SELECT_BITS(glb_index
) |
332 CLOCK_DIVISOR_BITS(glb_divisor_shift
);
338 static int a2150_set_chanlist(struct comedi_device
*dev
,
339 unsigned int start_channel
,
340 unsigned int num_channels
)
342 struct a2150_private
*devpriv
= dev
->private;
344 if (start_channel
+ num_channels
> 4)
347 devpriv
->config_bits
&= ~CHANNEL_MASK
;
349 switch (num_channels
) {
351 devpriv
->config_bits
|= CHANNEL_BITS(0x4 | start_channel
);
354 if (start_channel
== 0)
355 devpriv
->config_bits
|= CHANNEL_BITS(0x2);
356 else if (start_channel
== 2)
357 devpriv
->config_bits
|= CHANNEL_BITS(0x3);
362 devpriv
->config_bits
|= CHANNEL_BITS(0x1);
371 static int a2150_ai_check_chanlist(struct comedi_device
*dev
,
372 struct comedi_subdevice
*s
,
373 struct comedi_cmd
*cmd
)
375 unsigned int chan0
= CR_CHAN(cmd
->chanlist
[0]);
376 unsigned int aref0
= CR_AREF(cmd
->chanlist
[0]);
379 if (cmd
->chanlist_len
== 2 && (chan0
== 1 || chan0
== 3)) {
380 dev_dbg(dev
->class_dev
,
381 "length 2 chanlist must be channels 0,1 or channels 2,3\n");
385 if (cmd
->chanlist_len
== 3) {
386 dev_dbg(dev
->class_dev
,
387 "chanlist must have 1,2 or 4 channels\n");
391 for (i
= 1; i
< cmd
->chanlist_len
; i
++) {
392 unsigned int chan
= CR_CHAN(cmd
->chanlist
[i
]);
393 unsigned int aref
= CR_AREF(cmd
->chanlist
[i
]);
395 if (chan
!= (chan0
+ i
)) {
396 dev_dbg(dev
->class_dev
,
397 "entries in chanlist must be consecutive channels, counting upwards\n");
404 dev_dbg(dev
->class_dev
,
405 "channels 0/1 and 2/3 must have the same analog reference\n");
413 static int a2150_ai_cmdtest(struct comedi_device
*dev
,
414 struct comedi_subdevice
*s
, struct comedi_cmd
*cmd
)
416 const struct a2150_board
*board
= dev
->board_ptr
;
420 /* Step 1 : check if triggers are trivially valid */
422 err
|= comedi_check_trigger_src(&cmd
->start_src
, TRIG_NOW
| TRIG_EXT
);
423 err
|= comedi_check_trigger_src(&cmd
->scan_begin_src
, TRIG_TIMER
);
424 err
|= comedi_check_trigger_src(&cmd
->convert_src
, TRIG_NOW
);
425 err
|= comedi_check_trigger_src(&cmd
->scan_end_src
, TRIG_COUNT
);
426 err
|= comedi_check_trigger_src(&cmd
->stop_src
, TRIG_COUNT
| TRIG_NONE
);
431 /* Step 2a : make sure trigger sources are unique */
433 err
|= comedi_check_trigger_is_unique(cmd
->start_src
);
434 err
|= comedi_check_trigger_is_unique(cmd
->stop_src
);
436 /* Step 2b : and mutually compatible */
441 /* Step 3: check if arguments are trivially valid */
443 err
|= comedi_check_trigger_arg_is(&cmd
->start_arg
, 0);
445 if (cmd
->convert_src
== TRIG_TIMER
) {
446 err
|= comedi_check_trigger_arg_min(&cmd
->convert_arg
,
450 err
|= comedi_check_trigger_arg_min(&cmd
->chanlist_len
, 1);
451 err
|= comedi_check_trigger_arg_is(&cmd
->scan_end_arg
,
454 if (cmd
->stop_src
== TRIG_COUNT
)
455 err
|= comedi_check_trigger_arg_min(&cmd
->stop_arg
, 1);
457 err
|= comedi_check_trigger_arg_is(&cmd
->stop_arg
, 0);
462 /* step 4: fix up any arguments */
464 if (cmd
->scan_begin_src
== TRIG_TIMER
) {
465 arg
= cmd
->scan_begin_arg
;
466 a2150_get_timing(dev
, &arg
, cmd
->flags
);
467 err
|= comedi_check_trigger_arg_is(&cmd
->scan_begin_arg
, arg
);
473 /* Step 5: check channel list if it exists */
474 if (cmd
->chanlist
&& cmd
->chanlist_len
> 0)
475 err
|= a2150_ai_check_chanlist(dev
, s
, cmd
);
483 static int a2150_ai_cmd(struct comedi_device
*dev
, struct comedi_subdevice
*s
)
485 struct a2150_private
*devpriv
= dev
->private;
486 struct comedi_isadma
*dma
= devpriv
->dma
;
487 struct comedi_isadma_desc
*desc
= &dma
->desc
[0];
488 struct comedi_async
*async
= s
->async
;
489 struct comedi_cmd
*cmd
= &async
->cmd
;
490 unsigned int old_config_bits
= devpriv
->config_bits
;
491 unsigned int trigger_bits
;
493 if (cmd
->flags
& CMDF_PRIORITY
) {
494 dev_err(dev
->class_dev
,
495 "dma incompatible with hard real-time interrupt (CMDF_PRIORITY), aborting\n");
498 /* clear fifo and reset triggering circuitry */
499 outw(0, dev
->iobase
+ FIFO_RESET_REG
);
502 if (a2150_set_chanlist(dev
, CR_CHAN(cmd
->chanlist
[0]),
503 cmd
->chanlist_len
) < 0)
506 /* setup ac/dc coupling */
507 if (CR_AREF(cmd
->chanlist
[0]) == AREF_OTHER
)
508 devpriv
->config_bits
|= AC0_BIT
;
510 devpriv
->config_bits
&= ~AC0_BIT
;
511 if (CR_AREF(cmd
->chanlist
[2]) == AREF_OTHER
)
512 devpriv
->config_bits
|= AC1_BIT
;
514 devpriv
->config_bits
&= ~AC1_BIT
;
517 a2150_get_timing(dev
, &cmd
->scan_begin_arg
, cmd
->flags
);
519 /* send timing, channel, config bits */
520 outw(devpriv
->config_bits
, dev
->iobase
+ CONFIG_REG
);
522 /* initialize number of samples remaining */
523 devpriv
->count
= cmd
->stop_arg
* cmd
->chanlist_len
;
525 comedi_isadma_disable(desc
->chan
);
527 /* set size of transfer to fill in 1/3 second */
528 #define ONE_THIRD_SECOND 333333333
529 desc
->size
= comedi_bytes_per_sample(s
) * cmd
->chanlist_len
*
530 ONE_THIRD_SECOND
/ cmd
->scan_begin_arg
;
531 if (desc
->size
> desc
->maxsize
)
532 desc
->size
= desc
->maxsize
;
533 if (desc
->size
< comedi_bytes_per_sample(s
))
534 desc
->size
= comedi_bytes_per_sample(s
);
535 desc
->size
-= desc
->size
% comedi_bytes_per_sample(s
);
537 comedi_isadma_program(desc
);
539 /* clear dma interrupt before enabling it, to try and get rid of that
540 * one spurious interrupt that has been happening */
541 outw(0x00, dev
->iobase
+ DMA_TC_CLEAR_REG
);
543 /* enable dma on card */
544 devpriv
->irq_dma_bits
|= DMA_INTR_EN_BIT
| DMA_EN_BIT
;
545 outw(devpriv
->irq_dma_bits
, dev
->iobase
+ IRQ_DMA_CNTRL_REG
);
547 /* may need to wait 72 sampling periods if timing was changed */
548 comedi_8254_load(dev
->pacer
, 2, 72, I8254_MODE0
| I8254_BINARY
);
550 /* setup start triggering */
552 /* decide if we need to wait 72 periods for valid data */
553 if (cmd
->start_src
== TRIG_NOW
&&
554 (old_config_bits
& CLOCK_MASK
) !=
555 (devpriv
->config_bits
& CLOCK_MASK
)) {
556 /* set trigger source to delay trigger */
557 trigger_bits
|= DELAY_TRIGGER_BITS
;
559 /* otherwise no delay */
560 trigger_bits
|= POST_TRIGGER_BITS
;
562 /* enable external hardware trigger */
563 if (cmd
->start_src
== TRIG_EXT
) {
564 trigger_bits
|= HW_TRIG_EN
;
565 } else if (cmd
->start_src
== TRIG_OTHER
) {
566 /* XXX add support for level/slope start trigger using TRIG_OTHER */
567 dev_err(dev
->class_dev
, "you shouldn't see this?\n");
569 /* send trigger config bits */
570 outw(trigger_bits
, dev
->iobase
+ TRIGGER_REG
);
572 /* start acquisition for soft trigger */
573 if (cmd
->start_src
== TRIG_NOW
)
574 outw(0, dev
->iobase
+ FIFO_START_REG
);
579 static int a2150_ai_eoc(struct comedi_device
*dev
,
580 struct comedi_subdevice
*s
,
581 struct comedi_insn
*insn
,
582 unsigned long context
)
586 status
= inw(dev
->iobase
+ STATUS_REG
);
587 if (status
& FNE_BIT
)
592 static int a2150_ai_rinsn(struct comedi_device
*dev
, struct comedi_subdevice
*s
,
593 struct comedi_insn
*insn
, unsigned int *data
)
595 struct a2150_private
*devpriv
= dev
->private;
599 /* clear fifo and reset triggering circuitry */
600 outw(0, dev
->iobase
+ FIFO_RESET_REG
);
603 if (a2150_set_chanlist(dev
, CR_CHAN(insn
->chanspec
), 1) < 0)
606 /* set dc coupling */
607 devpriv
->config_bits
&= ~AC0_BIT
;
608 devpriv
->config_bits
&= ~AC1_BIT
;
610 /* send timing, channel, config bits */
611 outw(devpriv
->config_bits
, dev
->iobase
+ CONFIG_REG
);
613 /* disable dma on card */
614 devpriv
->irq_dma_bits
&= ~DMA_INTR_EN_BIT
& ~DMA_EN_BIT
;
615 outw(devpriv
->irq_dma_bits
, dev
->iobase
+ IRQ_DMA_CNTRL_REG
);
617 /* setup start triggering */
618 outw(0, dev
->iobase
+ TRIGGER_REG
);
620 /* start acquisition for soft trigger */
621 outw(0, dev
->iobase
+ FIFO_START_REG
);
624 * there is a 35.6 sample delay for data to get through the
627 for (n
= 0; n
< 36; n
++) {
628 ret
= comedi_timeout(dev
, s
, insn
, a2150_ai_eoc
, 0);
632 inw(dev
->iobase
+ FIFO_DATA_REG
);
636 for (n
= 0; n
< insn
->n
; n
++) {
637 ret
= comedi_timeout(dev
, s
, insn
, a2150_ai_eoc
, 0);
641 data
[n
] = inw(dev
->iobase
+ FIFO_DATA_REG
);
645 /* clear fifo and reset triggering circuitry */
646 outw(0, dev
->iobase
+ FIFO_RESET_REG
);
651 static void a2150_alloc_irq_and_dma(struct comedi_device
*dev
,
652 struct comedi_devconfig
*it
)
654 struct a2150_private
*devpriv
= dev
->private;
655 unsigned int irq_num
= it
->options
[1];
656 unsigned int dma_chan
= it
->options
[2];
659 * Only IRQs 15, 14, 12-9, and 7-3 are valid.
660 * Only DMA channels 7-5 and 3-0 are valid.
662 if (irq_num
> 15 || dma_chan
> 7 ||
663 !((1 << irq_num
) & 0xdef8) || !((1 << dma_chan
) & 0xef))
666 if (request_irq(irq_num
, a2150_interrupt
, 0, dev
->board_name
, dev
))
669 /* DMA uses 1 buffer */
670 devpriv
->dma
= comedi_isadma_alloc(dev
, 1, dma_chan
, dma_chan
,
671 A2150_DMA_BUFFER_SIZE
,
674 free_irq(irq_num
, dev
);
677 devpriv
->irq_dma_bits
= IRQ_LVL_BITS(irq_num
) |
678 DMA_CHAN_BITS(dma_chan
);
682 static void a2150_free_dma(struct comedi_device
*dev
)
684 struct a2150_private
*devpriv
= dev
->private;
687 comedi_isadma_free(devpriv
->dma
);
690 static const struct a2150_board
*a2150_probe(struct comedi_device
*dev
)
692 int id
= ID_BITS(inw(dev
->iobase
+ STATUS_REG
));
694 if (id
>= ARRAY_SIZE(a2150_boards
))
697 return &a2150_boards
[id
];
700 static int a2150_attach(struct comedi_device
*dev
, struct comedi_devconfig
*it
)
702 const struct a2150_board
*board
;
703 struct a2150_private
*devpriv
;
704 struct comedi_subdevice
*s
;
705 static const int timeout
= 2000;
709 devpriv
= comedi_alloc_devpriv(dev
, sizeof(*devpriv
));
713 ret
= comedi_request_region(dev
, it
->options
[0], 0x1c);
717 board
= a2150_probe(dev
);
720 dev
->board_ptr
= board
;
721 dev
->board_name
= board
->name
;
723 /* an IRQ and DMA are required to support async commands */
724 a2150_alloc_irq_and_dma(dev
, it
);
726 dev
->pacer
= comedi_8254_init(dev
->iobase
+ I8253_BASE_REG
,
731 ret
= comedi_alloc_subdevices(dev
, 1);
735 /* analog input subdevice */
736 s
= &dev
->subdevices
[0];
737 s
->type
= COMEDI_SUBD_AI
;
738 s
->subdev_flags
= SDF_READABLE
| SDF_GROUND
| SDF_OTHER
;
741 s
->range_table
= &range_a2150
;
742 s
->insn_read
= a2150_ai_rinsn
;
744 dev
->read_subdev
= s
;
745 s
->subdev_flags
|= SDF_CMD_READ
;
746 s
->len_chanlist
= s
->n_chan
;
747 s
->do_cmd
= a2150_ai_cmd
;
748 s
->do_cmdtest
= a2150_ai_cmdtest
;
749 s
->cancel
= a2150_cancel
;
752 /* set card's irq and dma levels */
753 outw(devpriv
->irq_dma_bits
, dev
->iobase
+ IRQ_DMA_CNTRL_REG
);
755 /* reset and sync adc clock circuitry */
756 outw_p(DPD_BIT
| APD_BIT
, dev
->iobase
+ CONFIG_REG
);
757 outw_p(DPD_BIT
, dev
->iobase
+ CONFIG_REG
);
758 /* initialize configuration register */
759 devpriv
->config_bits
= 0;
760 outw(devpriv
->config_bits
, dev
->iobase
+ CONFIG_REG
);
761 /* wait until offset calibration is done, then enable analog inputs */
762 for (i
= 0; i
< timeout
; i
++) {
763 if ((DCAL_BIT
& inw(dev
->iobase
+ STATUS_REG
)) == 0)
768 dev_err(dev
->class_dev
,
769 "timed out waiting for offset calibration to complete\n");
772 devpriv
->config_bits
|= ENABLE0_BIT
| ENABLE1_BIT
;
773 outw(devpriv
->config_bits
, dev
->iobase
+ CONFIG_REG
);
778 static void a2150_detach(struct comedi_device
*dev
)
781 outw(APD_BIT
| DPD_BIT
, dev
->iobase
+ CONFIG_REG
);
783 comedi_legacy_detach(dev
);
786 static struct comedi_driver ni_at_a2150_driver
= {
787 .driver_name
= "ni_at_a2150",
788 .module
= THIS_MODULE
,
789 .attach
= a2150_attach
,
790 .detach
= a2150_detach
,
792 module_comedi_driver(ni_at_a2150_driver
);
794 MODULE_AUTHOR("Comedi http://www.comedi.org");
795 MODULE_DESCRIPTION("Comedi low-level driver");
796 MODULE_LICENSE("GPL");