2 comedi/drivers/ni_tiocmd.c
3 Command support for NI general purpose counters
5 Copyright (C) 2006 Frank Mori Hess <fmhess@users.sourceforge.net>
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 Description: National Instruments general purpose counters command support
26 Author: J.P. Mellor <jpmellor@rose-hulman.edu>,
27 Herman.Bruyninckx@mech.kuleuven.ac.be,
28 Wim.Meeussen@mech.kuleuven.ac.be,
29 Klaas.Gadeyne@mech.kuleuven.ac.be,
30 Frank Mori Hess <fmhess@users.sourceforge.net>
31 Updated: Fri, 11 Apr 2008 12:32:35 +0100
34 This module is not used directly by end-users. Rather, it
35 is used by other drivers (for example ni_660x and ni_pcimio)
36 to provide command support for NI's general purpose counters.
37 It was originally split out of ni_tio.c to stop the 'ni_tio'
38 module depending on the 'mite' module.
41 DAQ 660x Register-Level Programmer Manual (NI 370505A-01)
42 DAQ 6601/6602 User Manual (NI 322137B-01)
43 340934b.pdf DAQ-STC reference manual
48 Support use of both banks X and Y
51 #include "ni_tio_internal.h"
54 MODULE_AUTHOR("Comedi <comedi@comedi.org>");
55 MODULE_DESCRIPTION("Comedi command support for NI general-purpose counters");
56 MODULE_LICENSE("GPL");
58 static void ni_tio_configure_dma(struct ni_gpct
*counter
, short enable
,
61 struct ni_gpct_device
*counter_dev
= counter
->counter_dev
;
62 unsigned input_select_bits
= 0;
66 input_select_bits
|= Gi_Read_Acknowledges_Irq
;
68 input_select_bits
|= Gi_Write_Acknowledges_Irq
;
71 ni_tio_set_bits(counter
,
72 NITIO_Gi_Input_Select_Reg(counter
->counter_index
),
73 Gi_Read_Acknowledges_Irq
| Gi_Write_Acknowledges_Irq
,
75 switch (counter_dev
->variant
) {
76 case ni_gpct_variant_e_series
:
78 case ni_gpct_variant_m_series
:
79 case ni_gpct_variant_660x
:
81 unsigned gi_dma_config_bits
= 0;
84 gi_dma_config_bits
|= Gi_DMA_Enable_Bit
;
85 gi_dma_config_bits
|= Gi_DMA_Int_Bit
;
87 if (read_not_write
== 0) {
88 gi_dma_config_bits
|= Gi_DMA_Write_Bit
;
90 ni_tio_set_bits(counter
,
91 NITIO_Gi_DMA_Config_Reg(counter
->
93 Gi_DMA_Enable_Bit
| Gi_DMA_Int_Bit
|
94 Gi_DMA_Write_Bit
, gi_dma_config_bits
);
100 static int ni_tio_input_inttrig(struct comedi_device
*dev
,
101 struct comedi_subdevice
*s
,
102 unsigned int trignum
)
106 struct ni_gpct
*counter
= s
->private;
108 BUG_ON(counter
== NULL
);
112 spin_lock_irqsave(&counter
->lock
, flags
);
113 if (counter
->mite_chan
)
114 mite_dma_arm(counter
->mite_chan
);
117 spin_unlock_irqrestore(&counter
->lock
, flags
);
120 retval
= ni_tio_arm(counter
, 1, NI_GPCT_ARM_IMMEDIATE
);
121 s
->async
->inttrig
= NULL
;
126 static int ni_tio_input_cmd(struct ni_gpct
*counter
, struct comedi_async
*async
)
128 struct ni_gpct_device
*counter_dev
= counter
->counter_dev
;
129 struct comedi_cmd
*cmd
= &async
->cmd
;
132 /* write alloc the entire buffer */
133 comedi_buf_write_alloc(async
, async
->prealloc_bufsz
);
134 counter
->mite_chan
->dir
= COMEDI_INPUT
;
135 switch (counter_dev
->variant
) {
136 case ni_gpct_variant_m_series
:
137 case ni_gpct_variant_660x
:
138 mite_prep_dma(counter
->mite_chan
, 32, 32);
140 case ni_gpct_variant_e_series
:
141 mite_prep_dma(counter
->mite_chan
, 16, 32);
147 ni_tio_set_bits(counter
, NITIO_Gi_Command_Reg(counter
->counter_index
),
148 Gi_Save_Trace_Bit
, 0);
149 ni_tio_configure_dma(counter
, 1, 1);
150 switch (cmd
->start_src
) {
152 async
->inttrig
= NULL
;
153 mite_dma_arm(counter
->mite_chan
);
154 retval
= ni_tio_arm(counter
, 1, NI_GPCT_ARM_IMMEDIATE
);
157 async
->inttrig
= &ni_tio_input_inttrig
;
160 async
->inttrig
= NULL
;
161 mite_dma_arm(counter
->mite_chan
);
162 retval
= ni_tio_arm(counter
, 1, cmd
->start_arg
);
164 async
->inttrig
= NULL
;
165 mite_dma_arm(counter
->mite_chan
);
174 static int ni_tio_output_cmd(struct ni_gpct
*counter
,
175 struct comedi_async
*async
)
177 printk("ni_tio: output commands not yet implemented.\n");
180 counter
->mite_chan
->dir
= COMEDI_OUTPUT
;
181 mite_prep_dma(counter
->mite_chan
, 32, 32);
182 ni_tio_configure_dma(counter
, 1, 0);
183 mite_dma_arm(counter
->mite_chan
);
184 return ni_tio_arm(counter
, 1, NI_GPCT_ARM_IMMEDIATE
);
187 static int ni_tio_cmd_setup(struct ni_gpct
*counter
, struct comedi_async
*async
)
189 struct comedi_cmd
*cmd
= &async
->cmd
;
190 int set_gate_source
= 0;
191 unsigned gate_source
;
194 if (cmd
->scan_begin_src
== TRIG_EXT
) {
196 gate_source
= cmd
->scan_begin_arg
;
197 } else if (cmd
->convert_src
== TRIG_EXT
) {
199 gate_source
= cmd
->convert_arg
;
201 if (set_gate_source
) {
202 retval
= ni_tio_set_gate_src(counter
, 0, gate_source
);
204 if (cmd
->flags
& TRIG_WAKE_EOS
) {
205 ni_tio_set_bits(counter
,
206 NITIO_Gi_Interrupt_Enable_Reg(counter
->
208 Gi_Gate_Interrupt_Enable_Bit(counter
->
210 Gi_Gate_Interrupt_Enable_Bit(counter
->
216 int ni_tio_cmd(struct ni_gpct
*counter
, struct comedi_async
*async
)
218 struct comedi_cmd
*cmd
= &async
->cmd
;
222 spin_lock_irqsave(&counter
->lock
, flags
);
223 if (counter
->mite_chan
== NULL
) {
225 ("ni_tio: commands only supported with DMA. Interrupt-driven commands not yet implemented.\n");
228 retval
= ni_tio_cmd_setup(counter
, async
);
230 if (cmd
->flags
& CMDF_WRITE
) {
231 retval
= ni_tio_output_cmd(counter
, async
);
233 retval
= ni_tio_input_cmd(counter
, async
);
237 spin_unlock_irqrestore(&counter
->lock
, flags
);
241 int ni_tio_cmdtest(struct ni_gpct
*counter
, struct comedi_cmd
*cmd
)
247 /* step 1: make sure trigger sources are trivially valid */
249 tmp
= cmd
->start_src
;
250 sources
= TRIG_NOW
| TRIG_INT
| TRIG_OTHER
;
251 if (ni_tio_counting_mode_registers_present(counter
->counter_dev
))
253 cmd
->start_src
&= sources
;
254 if (!cmd
->start_src
|| tmp
!= cmd
->start_src
)
257 tmp
= cmd
->scan_begin_src
;
258 cmd
->scan_begin_src
&= TRIG_FOLLOW
| TRIG_EXT
| TRIG_OTHER
;
259 if (!cmd
->scan_begin_src
|| tmp
!= cmd
->scan_begin_src
)
262 tmp
= cmd
->convert_src
;
263 sources
= TRIG_NOW
| TRIG_EXT
| TRIG_OTHER
;
264 cmd
->convert_src
&= sources
;
265 if (!cmd
->convert_src
|| tmp
!= cmd
->convert_src
)
268 tmp
= cmd
->scan_end_src
;
269 cmd
->scan_end_src
&= TRIG_COUNT
;
270 if (!cmd
->scan_end_src
|| tmp
!= cmd
->scan_end_src
)
274 cmd
->stop_src
&= TRIG_NONE
;
275 if (!cmd
->stop_src
|| tmp
!= cmd
->stop_src
)
281 /* step 2: make sure trigger sources are unique... */
283 if (cmd
->start_src
!= TRIG_NOW
&&
284 cmd
->start_src
!= TRIG_INT
&&
285 cmd
->start_src
!= TRIG_EXT
&& cmd
->start_src
!= TRIG_OTHER
)
287 if (cmd
->scan_begin_src
!= TRIG_FOLLOW
&&
288 cmd
->scan_begin_src
!= TRIG_EXT
&&
289 cmd
->scan_begin_src
!= TRIG_OTHER
)
291 if (cmd
->convert_src
!= TRIG_OTHER
&&
292 cmd
->convert_src
!= TRIG_EXT
&& cmd
->convert_src
!= TRIG_NOW
)
294 if (cmd
->stop_src
!= TRIG_NONE
)
296 /* ... and mutually compatible */
297 if (cmd
->convert_src
!= TRIG_NOW
&& cmd
->scan_begin_src
!= TRIG_FOLLOW
)
303 /* step 3: make sure arguments are trivially compatible */
304 if (cmd
->start_src
!= TRIG_EXT
) {
305 if (cmd
->start_arg
!= 0) {
310 if (cmd
->scan_begin_src
!= TRIG_EXT
) {
311 if (cmd
->scan_begin_arg
) {
312 cmd
->scan_begin_arg
= 0;
316 if (cmd
->convert_src
!= TRIG_EXT
) {
317 if (cmd
->convert_arg
) {
318 cmd
->convert_arg
= 0;
323 if (cmd
->scan_end_arg
!= cmd
->chanlist_len
) {
324 cmd
->scan_end_arg
= cmd
->chanlist_len
;
328 if (cmd
->stop_src
== TRIG_NONE
) {
329 if (cmd
->stop_arg
!= 0) {
338 /* step 4: fix up any arguments */
346 int ni_tio_cancel(struct ni_gpct
*counter
)
350 ni_tio_arm(counter
, 0, 0);
351 spin_lock_irqsave(&counter
->lock
, flags
);
352 if (counter
->mite_chan
) {
353 mite_dma_disarm(counter
->mite_chan
);
355 spin_unlock_irqrestore(&counter
->lock
, flags
);
356 ni_tio_configure_dma(counter
, 0, 0);
358 ni_tio_set_bits(counter
,
359 NITIO_Gi_Interrupt_Enable_Reg(counter
->counter_index
),
360 Gi_Gate_Interrupt_Enable_Bit(counter
->counter_index
),
365 /* During buffered input counter operation for e-series, the gate interrupt is acked
366 automatically by the dma controller, due to the Gi_Read/Write_Acknowledges_IRQ bits
367 in the input select register. */
368 static int should_ack_gate(struct ni_gpct
*counter
)
373 switch (counter
->counter_dev
->variant
) {
374 case ni_gpct_variant_m_series
:
375 case ni_gpct_variant_660x
: /* not sure if 660x really supports gate interrupts (the bits are not listed in register-level manual) */
378 case ni_gpct_variant_e_series
:
379 spin_lock_irqsave(&counter
->lock
, flags
);
381 if (counter
->mite_chan
== NULL
||
382 counter
->mite_chan
->dir
!= COMEDI_INPUT
||
383 (mite_done(counter
->mite_chan
))) {
387 spin_unlock_irqrestore(&counter
->lock
, flags
);
393 void ni_tio_acknowledge_and_confirm(struct ni_gpct
*counter
, int *gate_error
,
394 int *tc_error
, int *perm_stale_data
,
397 const unsigned short gxx_status
= read_register(counter
,
401 const unsigned short gi_status
= read_register(counter
,
412 *perm_stale_data
= 0;
416 if (gxx_status
& Gi_Gate_Error_Bit(counter
->counter_index
)) {
417 ack
|= Gi_Gate_Error_Confirm_Bit(counter
->counter_index
);
419 /*660x don't support automatic acknowledgement of gate interrupt via dma read/write
420 and report bogus gate errors */
421 if (counter
->counter_dev
->variant
!=
422 ni_gpct_variant_660x
) {
427 if (gxx_status
& Gi_TC_Error_Bit(counter
->counter_index
)) {
428 ack
|= Gi_TC_Error_Confirm_Bit(counter
->counter_index
);
432 if (gi_status
& Gi_TC_Bit
) {
433 ack
|= Gi_TC_Interrupt_Ack_Bit
;
435 if (gi_status
& Gi_Gate_Interrupt_Bit
) {
436 if (should_ack_gate(counter
))
437 ack
|= Gi_Gate_Interrupt_Ack_Bit
;
440 write_register(counter
, ack
,
441 NITIO_Gi_Interrupt_Acknowledge_Reg
442 (counter
->counter_index
));
443 if (ni_tio_get_soft_copy
445 NITIO_Gi_Mode_Reg(counter
->counter_index
)) &
446 Gi_Loading_On_Gate_Bit
) {
447 if (gxx_status
& Gi_Stale_Data_Bit(counter
->counter_index
)) {
451 if (read_register(counter
,
452 NITIO_Gxx_Joint_Status2_Reg
453 (counter
->counter_index
)) &
454 Gi_Permanent_Stale_Bit(counter
->counter_index
)) {
455 printk("%s: Gi_Permanent_Stale_Data detected.\n",
458 *perm_stale_data
= 1;
463 void ni_tio_handle_interrupt(struct ni_gpct
*counter
,
464 struct comedi_subdevice
*s
)
466 unsigned gpct_mite_status
;
472 ni_tio_acknowledge_and_confirm(counter
, &gate_error
, &tc_error
,
473 &perm_stale_data
, NULL
);
475 printk("%s: Gi_Gate_Error detected.\n", __FUNCTION__
);
476 s
->async
->events
|= COMEDI_CB_OVERFLOW
;
478 if (perm_stale_data
) {
479 s
->async
->events
|= COMEDI_CB_ERROR
;
481 switch (counter
->counter_dev
->variant
) {
482 case ni_gpct_variant_m_series
:
483 case ni_gpct_variant_660x
:
484 if (read_register(counter
,
485 NITIO_Gi_DMA_Status_Reg
486 (counter
->counter_index
)) & Gi_DRQ_Error_Bit
)
488 printk("%s: Gi_DRQ_Error detected.\n", __FUNCTION__
);
489 s
->async
->events
|= COMEDI_CB_OVERFLOW
;
492 case ni_gpct_variant_e_series
:
495 spin_lock_irqsave(&counter
->lock
, flags
);
496 if (counter
->mite_chan
== NULL
) {
497 spin_unlock_irqrestore(&counter
->lock
, flags
);
500 gpct_mite_status
= mite_get_status(counter
->mite_chan
);
501 if (gpct_mite_status
& CHSR_LINKC
) {
503 counter
->mite_chan
->mite
->mite_io_addr
+
504 MITE_CHOR(counter
->mite_chan
->channel
));
506 mite_sync_input_dma(counter
->mite_chan
, s
->async
);
507 spin_unlock_irqrestore(&counter
->lock
, flags
);
510 void ni_tio_set_mite_channel(struct ni_gpct
*counter
,
511 struct mite_channel
*mite_chan
)
515 spin_lock_irqsave(&counter
->lock
, flags
);
516 counter
->mite_chan
= mite_chan
;
517 spin_unlock_irqrestore(&counter
->lock
, flags
);
520 static int __init
ni_tiocmd_init_module(void)
525 module_init(ni_tiocmd_init_module
);
527 static void __exit
ni_tiocmd_cleanup_module(void)
531 module_exit(ni_tiocmd_cleanup_module
);
533 EXPORT_SYMBOL_GPL(ni_tio_cmd
);
534 EXPORT_SYMBOL_GPL(ni_tio_cmdtest
);
535 EXPORT_SYMBOL_GPL(ni_tio_cancel
);
536 EXPORT_SYMBOL_GPL(ni_tio_handle_interrupt
);
537 EXPORT_SYMBOL_GPL(ni_tio_set_mite_channel
);
538 EXPORT_SYMBOL_GPL(ni_tio_acknowledge_and_confirm
);