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 "../comedidev.h"
69 #include <linux/ioport.h>
73 #include "comedi_fc.h"
76 #define A2150_DMA_BUFFER_SIZE 0xff00 // size in bytes of dma buffer
78 //#define A2150_DEBUG // enable debugging code
79 #undef A2150_DEBUG // disable debugging code
81 /* Registers and bits */
82 #define CONFIG_REG 0x0
83 #define CHANNEL_BITS(x) ((x) & 0x7)
84 #define CHANNEL_MASK 0x7
85 #define CLOCK_SELECT_BITS(x) (((x) & 0x3) << 3)
86 #define CLOCK_DIVISOR_BITS(x) (((x) & 0x3) << 5)
87 #define CLOCK_MASK (0xf << 3)
88 #define ENABLE0_BIT 0x80 // enable (don't internally ground) channels 0 and 1
89 #define ENABLE1_BIT 0x100 // enable (don't internally ground) channels 2 and 3
90 #define AC0_BIT 0x200 // ac couple channels 0,1
91 #define AC1_BIT 0x400 // ac couple channels 2,3
92 #define APD_BIT 0x800 // analog power down
93 #define DPD_BIT 0x1000 // digital power down
94 #define TRIGGER_REG 0x2 // trigger config register
95 #define POST_TRIGGER_BITS 0x2
96 #define DELAY_TRIGGER_BITS 0x3
97 #define HW_TRIG_EN 0x10 // enable hardware trigger
98 #define FIFO_START_REG 0x6 // software start aquistion trigger
99 #define FIFO_RESET_REG 0x8 // clears fifo + fifo flags
100 #define FIFO_DATA_REG 0xa // read data
101 #define DMA_TC_CLEAR_REG 0xe // clear dma terminal count interrupt
102 #define STATUS_REG 0x12 // read only
103 #define FNE_BIT 0x1 // fifo not empty
104 #define OVFL_BIT 0x8 // fifo overflow
105 #define EDAQ_BIT 0x10 // end of aquisition interrupt
106 #define DCAL_BIT 0x20 // offset calibration in progress
107 #define INTR_BIT 0x40 // interrupt has occured
108 #define DMA_TC_BIT 0x80 // dma terminal count interrupt has occured
109 #define ID_BITS(x) (((x) >> 8) & 0x3)
110 #define IRQ_DMA_CNTRL_REG 0x12 // write only
111 #define DMA_CHAN_BITS(x) ((x) & 0x7) // sets dma channel
112 #define DMA_EN_BIT 0x8 // enables dma
113 #define IRQ_LVL_BITS(x) (((x) & 0xf) << 4) // sets irq level
114 #define FIFO_INTR_EN_BIT 0x100 // enable fifo interrupts
115 #define FIFO_INTR_FHF_BIT 0x200 // interrupt fifo half full
116 #define DMA_INTR_EN_BIT 0x800 // enable interrupt on dma terminal count
117 #define DMA_DEM_EN_BIT 0x1000 // enables demand mode dma
118 #define I8253_BASE_REG 0x14
119 #define I8253_MODE_REG 0x17
120 #define HW_COUNT_DISABLE 0x30 // disable hardware counting of conversions
122 typedef struct a2150_board_struct
{
124 int clock
[4]; // master clock periods, in nanoseconds
125 int num_clocks
; // number of available master clock speeds
126 int ai_speed
; // maximum conversion rate in nanoseconds
130 static const struct comedi_lrange range_a2150
= {
133 RANGE(-2.828, 2.828),
137 // enum must match board indices
138 enum { a2150_c
, a2150_s
};
139 static const a2150_board a2150_boards
[] = {
142 clock
: {31250, 22676, 20833, 19531},
148 clock
: {62500, 50000, 41667, 0},
155 * Useful for shorthand access to the particular board structure
157 #define thisboard ((const a2150_board *)dev->board_ptr)
160 volatile unsigned int count
; /* number of data points left to be taken */
161 unsigned int dma
; // dma channel
162 s16
*dma_buffer
; // dma buffer
163 unsigned int dma_transfer_size
; // size in bytes of dma transfers
164 int irq_dma_bits
; // irq/dma register bits
165 int config_bits
; // config register bits
168 #define devpriv ((a2150_private *)dev->private)
170 static int a2150_attach(struct comedi_device
* dev
, struct comedi_devconfig
* it
);
171 static int a2150_detach(struct comedi_device
* dev
);
172 static int a2150_cancel(struct comedi_device
* dev
, struct comedi_subdevice
* s
);
174 static struct comedi_driver driver_a2150
= {
175 driver_name
:"ni_at_a2150",
181 static irqreturn_t
a2150_interrupt(int irq
, void *d PT_REGS_ARG
);
182 static int a2150_ai_cmdtest(struct comedi_device
* dev
, struct comedi_subdevice
* s
,
183 struct comedi_cmd
* cmd
);
184 static int a2150_ai_cmd(struct comedi_device
* dev
, struct comedi_subdevice
* s
);
185 static int a2150_ai_rinsn(struct comedi_device
* dev
, struct comedi_subdevice
* s
,
186 struct comedi_insn
* insn
, unsigned int * data
);
187 static int a2150_get_timing(struct comedi_device
* dev
, unsigned int *period
,
189 static int a2150_probe(struct comedi_device
* dev
);
190 static int a2150_set_chanlist(struct comedi_device
* dev
, unsigned int start_channel
,
191 unsigned int num_channels
);
193 * A convenient macro that defines init_module() and cleanup_module(),
196 COMEDI_INITCLEANUP(driver_a2150
);
200 static void ni_dump_regs(struct comedi_device
* dev
)
202 rt_printk("config bits 0x%x\n", devpriv
->config_bits
);
203 rt_printk("irq dma bits 0x%x\n", devpriv
->irq_dma_bits
);
204 rt_printk("status bits 0x%x\n", inw(dev
->iobase
+ STATUS_REG
));
209 /* interrupt service routine */
210 static irqreturn_t
a2150_interrupt(int irq
, void *d PT_REGS_ARG
)
215 struct comedi_device
*dev
= d
;
216 struct comedi_subdevice
*s
= dev
->read_subdev
;
217 struct comedi_async
*async
;
218 struct comedi_cmd
*cmd
;
219 unsigned int max_points
, num_points
, residue
, leftover
;
221 static const int sample_size
= sizeof(devpriv
->dma_buffer
[0]);
223 if (dev
->attached
== 0) {
224 comedi_error(dev
, "premature interrupt");
227 // initialize async here to make sure s is not NULL
232 status
= inw(dev
->iobase
+ STATUS_REG
);
234 if ((status
& INTR_BIT
) == 0) {
235 comedi_error(dev
, "spurious interrupt");
239 if (status
& OVFL_BIT
) {
240 comedi_error(dev
, "fifo overflow");
241 a2150_cancel(dev
, s
);
242 async
->events
|= COMEDI_CB_ERROR
| COMEDI_CB_EOA
;
245 if ((status
& DMA_TC_BIT
) == 0) {
246 comedi_error(dev
, "caught non-dma interrupt? Aborting.");
247 a2150_cancel(dev
, s
);
248 async
->events
|= COMEDI_CB_ERROR
| COMEDI_CB_EOA
;
249 comedi_event(dev
, s
);
253 flags
= claim_dma_lock();
254 disable_dma(devpriv
->dma
);
255 /* clear flip-flop to make sure 2-byte registers for
256 * count and address get set correctly */
257 clear_dma_ff(devpriv
->dma
);
259 // figure out how many points to read
260 max_points
= devpriv
->dma_transfer_size
/ sample_size
;
261 /* residue is the number of points left to be done on the dma
262 * transfer. It should always be zero at this point unless
263 * the stop_src is set to external triggering.
265 residue
= get_dma_residue(devpriv
->dma
) / sample_size
;
266 num_points
= max_points
- residue
;
267 if (devpriv
->count
< num_points
&& cmd
->stop_src
== TRIG_COUNT
)
268 num_points
= devpriv
->count
;
270 // figure out how many points will be stored next time
272 if (cmd
->stop_src
== TRIG_NONE
) {
273 leftover
= devpriv
->dma_transfer_size
/ sample_size
;
274 } else if (devpriv
->count
> max_points
) {
275 leftover
= devpriv
->count
- max_points
;
276 if (leftover
> max_points
)
277 leftover
= max_points
;
279 /* there should only be a residue if collection was stopped by having
280 * the stop_src set to an external trigger, in which case there
281 * will be no more data
286 for (i
= 0; i
< num_points
; i
++) {
287 /* write data point to comedi buffer */
288 dpnt
= devpriv
->dma_buffer
[i
];
289 // convert from 2's complement to unsigned coding
291 cfc_write_to_buffer(s
, dpnt
);
292 if (cmd
->stop_src
== TRIG_COUNT
) {
293 if (--devpriv
->count
== 0) { /* end of acquisition */
294 a2150_cancel(dev
, s
);
295 async
->events
|= COMEDI_CB_EOA
;
302 set_dma_addr(devpriv
->dma
, virt_to_bus(devpriv
->dma_buffer
));
303 set_dma_count(devpriv
->dma
, leftover
* sample_size
);
304 enable_dma(devpriv
->dma
);
306 release_dma_lock(flags
);
308 async
->events
|= COMEDI_CB_BLOCK
;
310 comedi_event(dev
, s
);
312 /* clear interrupt */
313 outw(0x00, dev
->iobase
+ DMA_TC_CLEAR_REG
);
318 // probes board type, returns offset
319 static int a2150_probe(struct comedi_device
* dev
)
321 int status
= inw(dev
->iobase
+ STATUS_REG
);
322 return ID_BITS(status
);
325 static int a2150_attach(struct comedi_device
* dev
, struct comedi_devconfig
* it
)
327 struct comedi_subdevice
*s
;
328 unsigned long iobase
= it
->options
[0];
329 unsigned int irq
= it
->options
[1];
330 unsigned int dma
= it
->options
[2];
331 static const int timeout
= 2000;
334 printk("comedi%d: %s: io 0x%lx", dev
->minor
, driver_a2150
.driver_name
,
337 printk(", irq %u", irq
);
342 printk(", dma %u", dma
);
348 /* allocate and initialize dev->private */
349 if (alloc_private(dev
, sizeof(a2150_private
)) < 0)
353 printk(" io base address required\n");
357 /* check if io addresses are available */
358 if (!request_region(iobase
, A2150_SIZE
, driver_a2150
.driver_name
)) {
359 printk(" I/O port conflict\n");
362 dev
->iobase
= iobase
;
366 // check that irq is supported
367 if (irq
< 3 || irq
== 8 || irq
== 13 || irq
> 15) {
368 printk(" invalid irq line %u\n", irq
);
371 if (comedi_request_irq(irq
, a2150_interrupt
, 0,
372 driver_a2150
.driver_name
, dev
)) {
373 printk("unable to allocate irq %u\n", irq
);
376 devpriv
->irq_dma_bits
|= IRQ_LVL_BITS(irq
);
381 if (dma
== 4 || dma
> 7) {
382 printk(" invalid dma channel %u\n", dma
);
385 if (request_dma(dma
, driver_a2150
.driver_name
)) {
386 printk(" failed to allocate dma channel %u\n", dma
);
390 devpriv
->dma_buffer
=
391 kmalloc(A2150_DMA_BUFFER_SIZE
, GFP_KERNEL
| GFP_DMA
);
392 if (devpriv
->dma_buffer
== NULL
)
396 set_dma_mode(dma
, DMA_MODE_READ
);
398 devpriv
->irq_dma_bits
|= DMA_CHAN_BITS(dma
);
401 dev
->board_ptr
= a2150_boards
+ a2150_probe(dev
);
402 dev
->board_name
= thisboard
->name
;
404 if (alloc_subdevices(dev
, 1) < 0)
407 /* analog input subdevice */
408 s
= dev
->subdevices
+ 0;
409 dev
->read_subdev
= s
;
410 s
->type
= COMEDI_SUBD_AI
;
411 s
->subdev_flags
= SDF_READABLE
| SDF_GROUND
| SDF_OTHER
| SDF_CMD_READ
;
415 s
->range_table
= &range_a2150
;
416 s
->do_cmd
= a2150_ai_cmd
;
417 s
->do_cmdtest
= a2150_ai_cmdtest
;
418 s
->insn_read
= a2150_ai_rinsn
;
419 s
->cancel
= a2150_cancel
;
421 /* need to do this for software counting of completed conversions, to
422 * prevent hardware count from stopping aquisition */
423 outw(HW_COUNT_DISABLE
, dev
->iobase
+ I8253_MODE_REG
);
425 // set card's irq and dma levels
426 outw(devpriv
->irq_dma_bits
, dev
->iobase
+ IRQ_DMA_CNTRL_REG
);
428 // reset and sync adc clock circuitry
429 outw_p(DPD_BIT
| APD_BIT
, dev
->iobase
+ CONFIG_REG
);
430 outw_p(DPD_BIT
, dev
->iobase
+ CONFIG_REG
);
431 // initialize configuration register
432 devpriv
->config_bits
= 0;
433 outw(devpriv
->config_bits
, dev
->iobase
+ CONFIG_REG
);
434 // wait until offset calibration is done, then enable analog inputs
435 for (i
= 0; i
< timeout
; i
++) {
436 if ((DCAL_BIT
& inw(dev
->iobase
+ STATUS_REG
)) == 0)
441 printk(" timed out waiting for offset calibration to complete\n");
444 devpriv
->config_bits
|= ENABLE0_BIT
| ENABLE1_BIT
;
445 outw(devpriv
->config_bits
, dev
->iobase
+ CONFIG_REG
);
450 static int a2150_detach(struct comedi_device
* dev
)
452 printk("comedi%d: %s: remove\n", dev
->minor
, driver_a2150
.driver_name
);
454 /* only free stuff if it has been allocated by _attach */
456 // put board in power-down mode
457 outw(APD_BIT
| DPD_BIT
, dev
->iobase
+ CONFIG_REG
);
458 release_region(dev
->iobase
, A2150_SIZE
);
462 comedi_free_irq(dev
->irq
, dev
);
465 free_dma(devpriv
->dma
);
466 if (devpriv
->dma_buffer
)
467 kfree(devpriv
->dma_buffer
);
473 static int a2150_cancel(struct comedi_device
* dev
, struct comedi_subdevice
* s
)
475 // disable dma on card
476 devpriv
->irq_dma_bits
&= ~DMA_INTR_EN_BIT
& ~DMA_EN_BIT
;
477 outw(devpriv
->irq_dma_bits
, dev
->iobase
+ IRQ_DMA_CNTRL_REG
);
479 // disable computer's dma
480 disable_dma(devpriv
->dma
);
482 // clear fifo and reset triggering circuitry
483 outw(0, dev
->iobase
+ FIFO_RESET_REG
);
488 static int a2150_ai_cmdtest(struct comedi_device
* dev
, struct comedi_subdevice
* s
,
489 struct comedi_cmd
* cmd
)
496 /* step 1: make sure trigger sources are trivially valid */
498 tmp
= cmd
->start_src
;
499 cmd
->start_src
&= TRIG_NOW
| TRIG_EXT
;
500 if (!cmd
->start_src
|| tmp
!= cmd
->start_src
)
503 tmp
= cmd
->scan_begin_src
;
504 cmd
->scan_begin_src
&= TRIG_TIMER
;
505 if (!cmd
->scan_begin_src
|| tmp
!= cmd
->scan_begin_src
)
508 tmp
= cmd
->convert_src
;
509 cmd
->convert_src
&= TRIG_NOW
;
510 if (!cmd
->convert_src
|| tmp
!= cmd
->convert_src
)
513 tmp
= cmd
->scan_end_src
;
514 cmd
->scan_end_src
&= TRIG_COUNT
;
515 if (!cmd
->scan_end_src
|| tmp
!= cmd
->scan_end_src
)
519 cmd
->stop_src
&= TRIG_COUNT
| TRIG_NONE
;
520 if (!cmd
->stop_src
|| tmp
!= cmd
->stop_src
)
526 /* step 2: make sure trigger sources are unique and mutually compatible */
528 if (cmd
->start_src
!= TRIG_NOW
&& cmd
->start_src
!= TRIG_EXT
)
530 if (cmd
->stop_src
!= TRIG_COUNT
&& cmd
->stop_src
!= TRIG_NONE
)
536 /* step 3: make sure arguments are trivially compatible */
538 if (cmd
->start_arg
!= 0) {
542 if (cmd
->convert_src
== TRIG_TIMER
) {
543 if (cmd
->convert_arg
< thisboard
->ai_speed
) {
544 cmd
->convert_arg
= thisboard
->ai_speed
;
548 if (!cmd
->chanlist_len
) {
549 cmd
->chanlist_len
= 1;
552 if (cmd
->scan_end_arg
!= cmd
->chanlist_len
) {
553 cmd
->scan_end_arg
= cmd
->chanlist_len
;
556 if (cmd
->stop_src
== TRIG_COUNT
) {
557 if (!cmd
->stop_arg
) {
561 } else { /* TRIG_NONE */
562 if (cmd
->stop_arg
!= 0) {
571 /* step 4: fix up any arguments */
573 if (cmd
->scan_begin_src
== TRIG_TIMER
) {
574 tmp
= cmd
->scan_begin_arg
;
575 a2150_get_timing(dev
, &cmd
->scan_begin_arg
, cmd
->flags
);
576 if (tmp
!= cmd
->scan_begin_arg
)
583 // check channel/gain list against card's limitations
585 startChan
= CR_CHAN(cmd
->chanlist
[0]);
586 for (i
= 1; i
< cmd
->chanlist_len
; i
++) {
587 if (CR_CHAN(cmd
->chanlist
[i
]) != (startChan
+ i
)) {
589 "entries in chanlist must be consecutive channels, counting upwards\n");
593 if (cmd
->chanlist_len
== 2 && CR_CHAN(cmd
->chanlist
[0]) == 1) {
595 "length 2 chanlist must be channels 0,1 or channels 2,3");
598 if (cmd
->chanlist_len
== 3) {
600 "chanlist must have 1,2 or 4 channels");
603 if (CR_AREF(cmd
->chanlist
[0]) != CR_AREF(cmd
->chanlist
[1]) ||
604 CR_AREF(cmd
->chanlist
[2]) != CR_AREF(cmd
->chanlist
[3]))
607 "channels 0/1 and 2/3 must have the same analog reference");
618 static int a2150_ai_cmd(struct comedi_device
* dev
, struct comedi_subdevice
* s
)
620 struct comedi_async
*async
= s
->async
;
621 struct comedi_cmd
*cmd
= &async
->cmd
;
622 unsigned long lock_flags
;
623 unsigned int old_config_bits
= devpriv
->config_bits
;
624 unsigned int trigger_bits
;
626 if (!dev
->irq
|| !devpriv
->dma
) {
628 " irq and dma required, cannot do hardware conversions");
631 if (cmd
->flags
& TRIG_RT
) {
633 " dma incompatible with hard real-time interrupt (TRIG_RT), aborting");
636 // clear fifo and reset triggering circuitry
637 outw(0, dev
->iobase
+ FIFO_RESET_REG
);
640 if (a2150_set_chanlist(dev
, CR_CHAN(cmd
->chanlist
[0]),
641 cmd
->chanlist_len
) < 0)
644 // setup ac/dc coupling
645 if (CR_AREF(cmd
->chanlist
[0]) == AREF_OTHER
)
646 devpriv
->config_bits
|= AC0_BIT
;
648 devpriv
->config_bits
&= ~AC0_BIT
;
649 if (CR_AREF(cmd
->chanlist
[2]) == AREF_OTHER
)
650 devpriv
->config_bits
|= AC1_BIT
;
652 devpriv
->config_bits
&= ~AC1_BIT
;
655 a2150_get_timing(dev
, &cmd
->scan_begin_arg
, cmd
->flags
);
657 // send timing, channel, config bits
658 outw(devpriv
->config_bits
, dev
->iobase
+ CONFIG_REG
);
660 // initialize number of samples remaining
661 devpriv
->count
= cmd
->stop_arg
* cmd
->chanlist_len
;
663 // enable computer's dma
664 lock_flags
= claim_dma_lock();
665 disable_dma(devpriv
->dma
);
666 /* clear flip-flop to make sure 2-byte registers for
667 * count and address get set correctly */
668 clear_dma_ff(devpriv
->dma
);
669 set_dma_addr(devpriv
->dma
, virt_to_bus(devpriv
->dma_buffer
));
670 // set size of transfer to fill in 1/3 second
671 #define ONE_THIRD_SECOND 333333333
672 devpriv
->dma_transfer_size
=
673 sizeof(devpriv
->dma_buffer
[0]) * cmd
->chanlist_len
*
674 ONE_THIRD_SECOND
/ cmd
->scan_begin_arg
;
675 if (devpriv
->dma_transfer_size
> A2150_DMA_BUFFER_SIZE
)
676 devpriv
->dma_transfer_size
= A2150_DMA_BUFFER_SIZE
;
677 if (devpriv
->dma_transfer_size
< sizeof(devpriv
->dma_buffer
[0]))
678 devpriv
->dma_transfer_size
= sizeof(devpriv
->dma_buffer
[0]);
679 devpriv
->dma_transfer_size
-=
680 devpriv
->dma_transfer_size
% sizeof(devpriv
->dma_buffer
[0]);
681 set_dma_count(devpriv
->dma
, devpriv
->dma_transfer_size
);
682 enable_dma(devpriv
->dma
);
683 release_dma_lock(lock_flags
);
685 /* clear dma interrupt before enabling it, to try and get rid of that
686 * one spurious interrupt that has been happening */
687 outw(0x00, dev
->iobase
+ DMA_TC_CLEAR_REG
);
689 // enable dma on card
690 devpriv
->irq_dma_bits
|= DMA_INTR_EN_BIT
| DMA_EN_BIT
;
691 outw(devpriv
->irq_dma_bits
, dev
->iobase
+ IRQ_DMA_CNTRL_REG
);
693 // may need to wait 72 sampling periods if timing was changed
694 i8254_load(dev
->iobase
+ I8253_BASE_REG
, 0, 2, 72, 0);
696 // setup start triggering
698 // decide if we need to wait 72 periods for valid data
699 if (cmd
->start_src
== TRIG_NOW
&&
700 (old_config_bits
& CLOCK_MASK
) !=
701 (devpriv
->config_bits
& CLOCK_MASK
)) {
702 // set trigger source to delay trigger
703 trigger_bits
|= DELAY_TRIGGER_BITS
;
705 // otherwise no delay
706 trigger_bits
|= POST_TRIGGER_BITS
;
708 // enable external hardware trigger
709 if (cmd
->start_src
== TRIG_EXT
) {
710 trigger_bits
|= HW_TRIG_EN
;
711 } else if (cmd
->start_src
== TRIG_OTHER
) {
712 // XXX add support for level/slope start trigger using TRIG_OTHER
713 comedi_error(dev
, "you shouldn't see this?");
715 // send trigger config bits
716 outw(trigger_bits
, dev
->iobase
+ TRIGGER_REG
);
718 // start aquisition for soft trigger
719 if (cmd
->start_src
== TRIG_NOW
) {
720 outw(0, dev
->iobase
+ FIFO_START_REG
);
729 static int a2150_ai_rinsn(struct comedi_device
* dev
, struct comedi_subdevice
* s
,
730 struct comedi_insn
* insn
, unsigned int * data
)
733 static const int timeout
= 100000;
734 static const int filter_delay
= 36;
736 // clear fifo and reset triggering circuitry
737 outw(0, dev
->iobase
+ FIFO_RESET_REG
);
740 if (a2150_set_chanlist(dev
, CR_CHAN(insn
->chanspec
), 1) < 0)
744 devpriv
->config_bits
&= ~AC0_BIT
;
745 devpriv
->config_bits
&= ~AC1_BIT
;
747 // send timing, channel, config bits
748 outw(devpriv
->config_bits
, dev
->iobase
+ CONFIG_REG
);
750 // disable dma on card
751 devpriv
->irq_dma_bits
&= ~DMA_INTR_EN_BIT
& ~DMA_EN_BIT
;
752 outw(devpriv
->irq_dma_bits
, dev
->iobase
+ IRQ_DMA_CNTRL_REG
);
754 // setup start triggering
755 outw(0, dev
->iobase
+ TRIGGER_REG
);
757 // start aquisition for soft trigger
758 outw(0, dev
->iobase
+ FIFO_START_REG
);
760 /* there is a 35.6 sample delay for data to get through the antialias filter */
761 for (n
= 0; n
< filter_delay
; n
++) {
762 for (i
= 0; i
< timeout
; i
++) {
763 if (inw(dev
->iobase
+ STATUS_REG
) & FNE_BIT
)
768 comedi_error(dev
, "timeout");
771 inw(dev
->iobase
+ FIFO_DATA_REG
);
775 for (n
= 0; n
< insn
->n
; n
++) {
776 for (i
= 0; i
< timeout
; i
++) {
777 if (inw(dev
->iobase
+ STATUS_REG
) & FNE_BIT
)
782 comedi_error(dev
, "timeout");
788 data
[n
] = inw(dev
->iobase
+ FIFO_DATA_REG
);
790 rt_printk(" data is %i\n", data
[n
]);
795 // clear fifo and reset triggering circuitry
796 outw(0, dev
->iobase
+ FIFO_RESET_REG
);
801 /* sets bits in devpriv->clock_bits to nearest approximation of requested period,
802 * adjusts requested period to actual timing. */
803 static int a2150_get_timing(struct comedi_device
* dev
, unsigned int *period
,
807 int lub_divisor_shift
, lub_index
, glb_divisor_shift
, glb_index
;
810 // initialize greatest lower and least upper bounds
811 lub_divisor_shift
= 3;
813 lub
= thisboard
->clock
[lub_index
] * (1 << lub_divisor_shift
);
814 glb_divisor_shift
= 0;
815 glb_index
= thisboard
->num_clocks
- 1;
816 glb
= thisboard
->clock
[glb_index
] * (1 << glb_divisor_shift
);
818 // make sure period is in available range
824 // we can multiply period by 1, 2, 4, or 8, using (1 << i)
825 for (i
= 0; i
< 4; i
++) {
826 // there are a maximum of 4 master clocks
827 for (j
= 0; j
< thisboard
->num_clocks
; j
++) {
828 // temp is the period in nanosec we are evaluating
829 temp
= thisboard
->clock
[j
] * (1 << i
);
830 // if it is the best match yet
831 if (temp
< lub
&& temp
>= *period
) {
832 lub_divisor_shift
= i
;
836 if (temp
> glb
&& temp
<= *period
) {
837 glb_divisor_shift
= i
;
843 flags
&= TRIG_ROUND_MASK
;
845 case TRIG_ROUND_NEAREST
:
847 // if least upper bound is better approximation
848 if (lub
- *period
< *period
- glb
) {
857 case TRIG_ROUND_DOWN
:
862 // set clock bits for config register appropriately
863 devpriv
->config_bits
&= ~CLOCK_MASK
;
864 if (*period
== lub
) {
865 devpriv
->config_bits
|=
866 CLOCK_SELECT_BITS(lub_index
) |
867 CLOCK_DIVISOR_BITS(lub_divisor_shift
);
869 devpriv
->config_bits
|=
870 CLOCK_SELECT_BITS(glb_index
) |
871 CLOCK_DIVISOR_BITS(glb_divisor_shift
);
877 static int a2150_set_chanlist(struct comedi_device
* dev
, unsigned int start_channel
,
878 unsigned int num_channels
)
880 if (start_channel
+ num_channels
> 4)
883 devpriv
->config_bits
&= ~CHANNEL_MASK
;
885 switch (num_channels
) {
887 devpriv
->config_bits
|= CHANNEL_BITS(0x4 | start_channel
);
890 if (start_channel
== 0) {
891 devpriv
->config_bits
|= CHANNEL_BITS(0x2);
892 } else if (start_channel
== 2) {
893 devpriv
->config_bits
|= CHANNEL_BITS(0x3);
899 devpriv
->config_bits
|= CHANNEL_BITS(0x1);