2 comedi/drivers/ni_660x.c
3 Hardware driver for NI 660x devices
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 Description: National Instruments 660x counter/timer boards
24 [National Instruments] PCI-6601 (ni_660x), PCI-6602, PXI-6602,
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: Thu Oct 18 12:56:06 EDT 2007
34 Encoders work. PulseGeneration (both single pulse and pulse train)
35 works. Buffered commands work for input but not output.
38 DAQ 660x Register-Level Programmer Manual (NI 370505A-01)
39 DAQ 6601/6602 User Manual (NI 322137B-01)
43 #include "../comedidev.h"
47 enum ni_660x_constants
{
48 min_counter_pfi_chan
= 8,
49 max_dio_pfi_chan
= 31,
53 #define NUM_PFI_CHANNELS 40
54 /* really there are only up to 3 dma channels, but the register layout allows for 4 */
55 #define MAX_DMA_CHANNEL 4
57 /* See Register-Level Programmer Manual page 3.1 */
58 enum NI_660x_Register
{
59 G0InterruptAcknowledge
,
61 G1InterruptAcknowledge
,
74 G01JointStatus1Register
,
78 G01JointStatus2Register
,
82 G0InputSelectRegister
,
83 G1InputSelectRegister
,
84 G0AutoincrementRegister
,
85 G1AutoincrementRegister
,
86 G01JointResetRegister
,
89 G0CountingModeRegister
,
90 G1CountingModeRegister
,
97 G2InterruptAcknowledge
,
99 G3InterruptAcknowledge
,
109 G23JointStatus1Register
,
112 G23JointStatus2Register
,
116 G2InputSelectRegister
,
117 G3InputSelectRegister
,
118 G2AutoincrementRegister
,
119 G3AutoincrementRegister
,
120 G23JointResetRegister
,
123 G2CountingModeRegister
,
124 G3CountingModeRegister
,
125 G3SecondGateRegister
,
126 G2SecondGateRegister
,
134 GlobalInterruptStatusRegister
,
136 GlobalInterruptConfigRegister
,
160 static inline unsigned IOConfigReg(unsigned pfi_channel
)
162 unsigned reg
= IOConfigReg0_1
+ pfi_channel
/ 2;
163 BUG_ON(reg
> IOConfigReg38_39
);
167 enum ni_660x_register_width
{
173 enum ni_660x_register_direction
{
179 enum ni_660x_pfi_output_select
{
180 pfi_output_select_high_Z
= 0,
181 pfi_output_select_counter
= 1,
182 pfi_output_select_do
= 2,
183 num_pfi_output_selects
186 enum ni_660x_subdevices
{
187 NI_660X_DIO_SUBDEV
= 1,
188 NI_660X_GPCT_SUBDEV_0
= 2
190 static inline unsigned NI_660X_GPCT_SUBDEV(unsigned index
)
192 return NI_660X_GPCT_SUBDEV_0
+ index
;
195 struct NI_660xRegisterData
{
197 const char *name
; /* Register Name */
198 int offset
; /* Offset from base address from GPCT chip */
199 enum ni_660x_register_direction direction
;
200 enum ni_660x_register_width size
; /* 1 byte, 2 bytes, or 4 bytes */
204 static const struct NI_660xRegisterData registerData
[NumRegisters
] = {
205 {"G0 Interrupt Acknowledge", 0x004, NI_660x_WRITE
, DATA_2B
},
206 {"G0 Status Register", 0x004, NI_660x_READ
, DATA_2B
},
207 {"G1 Interrupt Acknowledge", 0x006, NI_660x_WRITE
, DATA_2B
},
208 {"G1 Status Register", 0x006, NI_660x_READ
, DATA_2B
},
209 {"G01 Status Register ", 0x008, NI_660x_READ
, DATA_2B
},
210 {"G0 Command Register", 0x00C, NI_660x_WRITE
, DATA_2B
},
211 {"STC DIO Parallel Input", 0x00E, NI_660x_READ
, DATA_2B
},
212 {"G1 Command Register", 0x00E, NI_660x_WRITE
, DATA_2B
},
213 {"G0 HW Save Register", 0x010, NI_660x_READ
, DATA_4B
},
214 {"G1 HW Save Register", 0x014, NI_660x_READ
, DATA_4B
},
215 {"STC DIO Output", 0x014, NI_660x_WRITE
, DATA_2B
},
216 {"STC DIO Control", 0x016, NI_660x_WRITE
, DATA_2B
},
217 {"G0 SW Save Register", 0x018, NI_660x_READ
, DATA_4B
},
218 {"G1 SW Save Register", 0x01C, NI_660x_READ
, DATA_4B
},
219 {"G0 Mode Register", 0x034, NI_660x_WRITE
, DATA_2B
},
220 {"G01 Joint Status 1 Register", 0x036, NI_660x_READ
, DATA_2B
},
221 {"G1 Mode Register", 0x036, NI_660x_WRITE
, DATA_2B
},
222 {"STC DIO Serial Input", 0x038, NI_660x_READ
, DATA_2B
},
223 {"G0 Load A Register", 0x038, NI_660x_WRITE
, DATA_4B
},
224 {"G01 Joint Status 2 Register", 0x03A, NI_660x_READ
, DATA_2B
},
225 {"G0 Load B Register", 0x03C, NI_660x_WRITE
, DATA_4B
},
226 {"G1 Load A Register", 0x040, NI_660x_WRITE
, DATA_4B
},
227 {"G1 Load B Register", 0x044, NI_660x_WRITE
, DATA_4B
},
228 {"G0 Input Select Register", 0x048, NI_660x_WRITE
, DATA_2B
},
229 {"G1 Input Select Register", 0x04A, NI_660x_WRITE
, DATA_2B
},
230 {"G0 Autoincrement Register", 0x088, NI_660x_WRITE
, DATA_2B
},
231 {"G1 Autoincrement Register", 0x08A, NI_660x_WRITE
, DATA_2B
},
232 {"G01 Joint Reset Register", 0x090, NI_660x_WRITE
, DATA_2B
},
233 {"G0 Interrupt Enable", 0x092, NI_660x_WRITE
, DATA_2B
},
234 {"G1 Interrupt Enable", 0x096, NI_660x_WRITE
, DATA_2B
},
235 {"G0 Counting Mode Register", 0x0B0, NI_660x_WRITE
, DATA_2B
},
236 {"G1 Counting Mode Register", 0x0B2, NI_660x_WRITE
, DATA_2B
},
237 {"G0 Second Gate Register", 0x0B4, NI_660x_WRITE
, DATA_2B
},
238 {"G1 Second Gate Register", 0x0B6, NI_660x_WRITE
, DATA_2B
},
239 {"G0 DMA Config Register", 0x0B8, NI_660x_WRITE
, DATA_2B
},
240 {"G0 DMA Status Register", 0x0B8, NI_660x_READ
, DATA_2B
},
241 {"G1 DMA Config Register", 0x0BA, NI_660x_WRITE
, DATA_2B
},
242 {"G1 DMA Status Register", 0x0BA, NI_660x_READ
, DATA_2B
},
243 {"G2 Interrupt Acknowledge", 0x104, NI_660x_WRITE
, DATA_2B
},
244 {"G2 Status Register", 0x104, NI_660x_READ
, DATA_2B
},
245 {"G3 Interrupt Acknowledge", 0x106, NI_660x_WRITE
, DATA_2B
},
246 {"G3 Status Register", 0x106, NI_660x_READ
, DATA_2B
},
247 {"G23 Status Register", 0x108, NI_660x_READ
, DATA_2B
},
248 {"G2 Command Register", 0x10C, NI_660x_WRITE
, DATA_2B
},
249 {"G3 Command Register", 0x10E, NI_660x_WRITE
, DATA_2B
},
250 {"G2 HW Save Register", 0x110, NI_660x_READ
, DATA_4B
},
251 {"G3 HW Save Register", 0x114, NI_660x_READ
, DATA_4B
},
252 {"G2 SW Save Register", 0x118, NI_660x_READ
, DATA_4B
},
253 {"G3 SW Save Register", 0x11C, NI_660x_READ
, DATA_4B
},
254 {"G2 Mode Register", 0x134, NI_660x_WRITE
, DATA_2B
},
255 {"G23 Joint Status 1 Register", 0x136, NI_660x_READ
, DATA_2B
},
256 {"G3 Mode Register", 0x136, NI_660x_WRITE
, DATA_2B
},
257 {"G2 Load A Register", 0x138, NI_660x_WRITE
, DATA_4B
},
258 {"G23 Joint Status 2 Register", 0x13A, NI_660x_READ
, DATA_2B
},
259 {"G2 Load B Register", 0x13C, NI_660x_WRITE
, DATA_4B
},
260 {"G3 Load A Register", 0x140, NI_660x_WRITE
, DATA_4B
},
261 {"G3 Load B Register", 0x144, NI_660x_WRITE
, DATA_4B
},
262 {"G2 Input Select Register", 0x148, NI_660x_WRITE
, DATA_2B
},
263 {"G3 Input Select Register", 0x14A, NI_660x_WRITE
, DATA_2B
},
264 {"G2 Autoincrement Register", 0x188, NI_660x_WRITE
, DATA_2B
},
265 {"G3 Autoincrement Register", 0x18A, NI_660x_WRITE
, DATA_2B
},
266 {"G23 Joint Reset Register", 0x190, NI_660x_WRITE
, DATA_2B
},
267 {"G2 Interrupt Enable", 0x192, NI_660x_WRITE
, DATA_2B
},
268 {"G3 Interrupt Enable", 0x196, NI_660x_WRITE
, DATA_2B
},
269 {"G2 Counting Mode Register", 0x1B0, NI_660x_WRITE
, DATA_2B
},
270 {"G3 Counting Mode Register", 0x1B2, NI_660x_WRITE
, DATA_2B
},
271 {"G3 Second Gate Register", 0x1B6, NI_660x_WRITE
, DATA_2B
},
272 {"G2 Second Gate Register", 0x1B4, NI_660x_WRITE
, DATA_2B
},
273 {"G2 DMA Config Register", 0x1B8, NI_660x_WRITE
, DATA_2B
},
274 {"G2 DMA Status Register", 0x1B8, NI_660x_READ
, DATA_2B
},
275 {"G3 DMA Config Register", 0x1BA, NI_660x_WRITE
, DATA_2B
},
276 {"G3 DMA Status Register", 0x1BA, NI_660x_READ
, DATA_2B
},
277 {"32 bit Digital Input", 0x414, NI_660x_READ
, DATA_4B
},
278 {"32 bit Digital Output", 0x510, NI_660x_WRITE
, DATA_4B
},
279 {"Clock Config Register", 0x73C, NI_660x_WRITE
, DATA_4B
},
280 {"Global Interrupt Status Register", 0x754, NI_660x_READ
, DATA_4B
},
281 {"DMA Configuration Register", 0x76C, NI_660x_WRITE
, DATA_4B
},
282 {"Global Interrupt Config Register", 0x770, NI_660x_WRITE
, DATA_4B
},
283 {"IO Config Register 0-1", 0x77C, NI_660x_READ_WRITE
, DATA_2B
},
284 {"IO Config Register 2-3", 0x77E, NI_660x_READ_WRITE
, DATA_2B
},
285 {"IO Config Register 4-5", 0x780, NI_660x_READ_WRITE
, DATA_2B
},
286 {"IO Config Register 6-7", 0x782, NI_660x_READ_WRITE
, DATA_2B
},
287 {"IO Config Register 8-9", 0x784, NI_660x_READ_WRITE
, DATA_2B
},
288 {"IO Config Register 10-11", 0x786, NI_660x_READ_WRITE
, DATA_2B
},
289 {"IO Config Register 12-13", 0x788, NI_660x_READ_WRITE
, DATA_2B
},
290 {"IO Config Register 14-15", 0x78A, NI_660x_READ_WRITE
, DATA_2B
},
291 {"IO Config Register 16-17", 0x78C, NI_660x_READ_WRITE
, DATA_2B
},
292 {"IO Config Register 18-19", 0x78E, NI_660x_READ_WRITE
, DATA_2B
},
293 {"IO Config Register 20-21", 0x790, NI_660x_READ_WRITE
, DATA_2B
},
294 {"IO Config Register 22-23", 0x792, NI_660x_READ_WRITE
, DATA_2B
},
295 {"IO Config Register 24-25", 0x794, NI_660x_READ_WRITE
, DATA_2B
},
296 {"IO Config Register 26-27", 0x796, NI_660x_READ_WRITE
, DATA_2B
},
297 {"IO Config Register 28-29", 0x798, NI_660x_READ_WRITE
, DATA_2B
},
298 {"IO Config Register 30-31", 0x79A, NI_660x_READ_WRITE
, DATA_2B
},
299 {"IO Config Register 32-33", 0x79C, NI_660x_READ_WRITE
, DATA_2B
},
300 {"IO Config Register 34-35", 0x79E, NI_660x_READ_WRITE
, DATA_2B
},
301 {"IO Config Register 36-37", 0x7A0, NI_660x_READ_WRITE
, DATA_2B
},
302 {"IO Config Register 38-39", 0x7A2, NI_660x_READ_WRITE
, DATA_2B
}
305 /* kind of ENABLE for the second counter */
306 enum clock_config_register_bits
{
307 CounterSwap
= 0x1 << 21
311 static inline unsigned ioconfig_bitshift(unsigned pfi_channel
)
318 static inline unsigned pfi_output_select_mask(unsigned pfi_channel
)
320 return 0x3 << ioconfig_bitshift(pfi_channel
);
322 static inline unsigned pfi_output_select_bits(unsigned pfi_channel
,
323 unsigned output_select
)
325 return (output_select
& 0x3) << ioconfig_bitshift(pfi_channel
);
327 static inline unsigned pfi_input_select_mask(unsigned pfi_channel
)
329 return 0x7 << (4 + ioconfig_bitshift(pfi_channel
));
331 static inline unsigned pfi_input_select_bits(unsigned pfi_channel
,
332 unsigned input_select
)
334 return (input_select
& 0x7) << (4 + ioconfig_bitshift(pfi_channel
));
337 /* dma configuration register bits */
338 static inline unsigned dma_select_mask(unsigned dma_channel
)
340 BUG_ON(dma_channel
>= MAX_DMA_CHANNEL
);
341 return 0x1f << (8 * dma_channel
);
344 dma_selection_none
= 0x1f,
346 static inline unsigned dma_selection_counter(unsigned counter_index
)
348 BUG_ON(counter_index
>= counters_per_chip
);
349 return counter_index
;
351 static inline unsigned dma_select_bits(unsigned dma_channel
, unsigned selection
)
353 BUG_ON(dma_channel
>= MAX_DMA_CHANNEL
);
354 return (selection
<< (8 * dma_channel
)) & dma_select_mask(dma_channel
);
356 static inline unsigned dma_reset_bit(unsigned dma_channel
)
358 BUG_ON(dma_channel
>= MAX_DMA_CHANNEL
);
359 return 0x80 << (8 * dma_channel
);
362 enum global_interrupt_status_register_bits
{
363 Counter_0_Int_Bit
= 0x100,
364 Counter_1_Int_Bit
= 0x200,
365 Counter_2_Int_Bit
= 0x400,
366 Counter_3_Int_Bit
= 0x800,
367 Cascade_Int_Bit
= 0x20000000,
368 Global_Int_Bit
= 0x80000000
371 enum global_interrupt_config_register_bits
{
372 Cascade_Int_Enable_Bit
= 0x20000000,
373 Global_Int_Polarity_Bit
= 0x40000000,
374 Global_Int_Enable_Bit
= 0x80000000
377 /* Offset of the GPCT chips from the base-adress of the card */
378 static const unsigned GPCT_OFFSET
[2] = { 0x0, 0x800 }; /* First chip is at base-address +
381 /* Board description*/
382 struct ni_660x_board
{
383 unsigned short dev_id
; /* `lspci` will show you this */
385 unsigned n_chips
; /* total number of TIO chips */
388 static const struct ni_660x_board ni_660x_boards
[] = {
411 #define NI_660X_MAX_NUM_CHIPS 2
412 #define NI_660X_MAX_NUM_COUNTERS (NI_660X_MAX_NUM_CHIPS * counters_per_chip)
414 static DEFINE_PCI_DEVICE_TABLE(ni_660x_pci_table
) = {
415 {PCI_VENDOR_ID_NATINST
, 0x2c60, PCI_ANY_ID
, PCI_ANY_ID
, 0, 0, 0},
416 {PCI_VENDOR_ID_NATINST
, 0x1310, PCI_ANY_ID
, PCI_ANY_ID
, 0, 0, 0},
417 {PCI_VENDOR_ID_NATINST
, 0x1360, PCI_ANY_ID
, PCI_ANY_ID
, 0, 0, 0},
418 {PCI_VENDOR_ID_NATINST
, 0x2cc0, PCI_ANY_ID
, PCI_ANY_ID
, 0, 0, 0},
422 MODULE_DEVICE_TABLE(pci
, ni_660x_pci_table
);
424 struct ni_660x_private
{
425 struct mite_struct
*mite
;
426 struct ni_gpct_device
*counter_dev
;
427 uint64_t pfi_direction_bits
;
428 struct mite_dma_descriptor_ring
429 *mite_rings
[NI_660X_MAX_NUM_CHIPS
][counters_per_chip
];
430 spinlock_t mite_channel_lock
;
431 /* interrupt_lock prevents races between interrupt and comedi_poll */
432 spinlock_t interrupt_lock
;
433 unsigned dma_configuration_soft_copies
[NI_660X_MAX_NUM_CHIPS
];
434 spinlock_t soft_reg_copy_lock
;
435 unsigned short pfi_output_selects
[NUM_PFI_CHANNELS
];
438 static inline struct ni_660x_private
*private(struct comedi_device
* dev
)
443 /* initialized in ni_660x_find_device() */
444 static inline const struct ni_660x_board
*board(struct comedi_device
* dev
)
446 return dev
->board_ptr
;
449 #define n_ni_660x_boards (sizeof(ni_660x_boards)/sizeof(ni_660x_boards[0]))
451 static int ni_660x_attach(struct comedi_device
*dev
, struct comedi_devconfig
*it
);
452 static int ni_660x_detach(struct comedi_device
*dev
);
453 static void init_tio_chip(struct comedi_device
*dev
, int chipset
);
454 static void ni_660x_select_pfi_output(struct comedi_device
*dev
, unsigned pfi_channel
,
455 unsigned output_select
);
457 static struct comedi_driver driver_ni_660x
= {
458 .driver_name
= "ni_660x",
459 .module
= THIS_MODULE
,
460 .attach
= ni_660x_attach
,
461 .detach
= ni_660x_detach
,
464 COMEDI_PCI_INITCLEANUP(driver_ni_660x
, ni_660x_pci_table
);
466 static int ni_660x_find_device(struct comedi_device
*dev
, int bus
, int slot
);
467 static int ni_660x_set_pfi_routing(struct comedi_device
*dev
, unsigned chan
,
470 /* Possible instructions for a GPCT */
471 static int ni_660x_GPCT_rinsn(struct comedi_device
*dev
,
472 struct comedi_subdevice
*s
, struct comedi_insn
*insn
, unsigned int *data
);
473 static int ni_660x_GPCT_insn_config(struct comedi_device
*dev
,
474 struct comedi_subdevice
*s
, struct comedi_insn
*insn
, unsigned int *data
);
475 static int ni_660x_GPCT_winsn(struct comedi_device
*dev
,
476 struct comedi_subdevice
*s
, struct comedi_insn
*insn
, unsigned int *data
);
478 /* Possible instructions for Digital IO */
479 static int ni_660x_dio_insn_config(struct comedi_device
*dev
,
480 struct comedi_subdevice
*s
, struct comedi_insn
*insn
, unsigned int *data
);
481 static int ni_660x_dio_insn_bits(struct comedi_device
*dev
,
482 struct comedi_subdevice
*s
, struct comedi_insn
*insn
, unsigned int *data
);
484 static inline unsigned ni_660x_num_counters(struct comedi_device
*dev
)
486 return board(dev
)->n_chips
* counters_per_chip
;
489 static enum NI_660x_Register
ni_gpct_to_660x_register(enum ni_gpct_register reg
)
491 enum NI_660x_Register ni_660x_register
;
493 case NITIO_G0_Autoincrement_Reg
:
494 ni_660x_register
= G0AutoincrementRegister
;
496 case NITIO_G1_Autoincrement_Reg
:
497 ni_660x_register
= G1AutoincrementRegister
;
499 case NITIO_G2_Autoincrement_Reg
:
500 ni_660x_register
= G2AutoincrementRegister
;
502 case NITIO_G3_Autoincrement_Reg
:
503 ni_660x_register
= G3AutoincrementRegister
;
505 case NITIO_G0_Command_Reg
:
506 ni_660x_register
= G0CommandRegister
;
508 case NITIO_G1_Command_Reg
:
509 ni_660x_register
= G1CommandRegister
;
511 case NITIO_G2_Command_Reg
:
512 ni_660x_register
= G2CommandRegister
;
514 case NITIO_G3_Command_Reg
:
515 ni_660x_register
= G3CommandRegister
;
517 case NITIO_G0_HW_Save_Reg
:
518 ni_660x_register
= G0HWSaveRegister
;
520 case NITIO_G1_HW_Save_Reg
:
521 ni_660x_register
= G1HWSaveRegister
;
523 case NITIO_G2_HW_Save_Reg
:
524 ni_660x_register
= G2HWSaveRegister
;
526 case NITIO_G3_HW_Save_Reg
:
527 ni_660x_register
= G3HWSaveRegister
;
529 case NITIO_G0_SW_Save_Reg
:
530 ni_660x_register
= G0SWSaveRegister
;
532 case NITIO_G1_SW_Save_Reg
:
533 ni_660x_register
= G1SWSaveRegister
;
535 case NITIO_G2_SW_Save_Reg
:
536 ni_660x_register
= G2SWSaveRegister
;
538 case NITIO_G3_SW_Save_Reg
:
539 ni_660x_register
= G3SWSaveRegister
;
541 case NITIO_G0_Mode_Reg
:
542 ni_660x_register
= G0ModeRegister
;
544 case NITIO_G1_Mode_Reg
:
545 ni_660x_register
= G1ModeRegister
;
547 case NITIO_G2_Mode_Reg
:
548 ni_660x_register
= G2ModeRegister
;
550 case NITIO_G3_Mode_Reg
:
551 ni_660x_register
= G3ModeRegister
;
553 case NITIO_G0_LoadA_Reg
:
554 ni_660x_register
= G0LoadARegister
;
556 case NITIO_G1_LoadA_Reg
:
557 ni_660x_register
= G1LoadARegister
;
559 case NITIO_G2_LoadA_Reg
:
560 ni_660x_register
= G2LoadARegister
;
562 case NITIO_G3_LoadA_Reg
:
563 ni_660x_register
= G3LoadARegister
;
565 case NITIO_G0_LoadB_Reg
:
566 ni_660x_register
= G0LoadBRegister
;
568 case NITIO_G1_LoadB_Reg
:
569 ni_660x_register
= G1LoadBRegister
;
571 case NITIO_G2_LoadB_Reg
:
572 ni_660x_register
= G2LoadBRegister
;
574 case NITIO_G3_LoadB_Reg
:
575 ni_660x_register
= G3LoadBRegister
;
577 case NITIO_G0_Input_Select_Reg
:
578 ni_660x_register
= G0InputSelectRegister
;
580 case NITIO_G1_Input_Select_Reg
:
581 ni_660x_register
= G1InputSelectRegister
;
583 case NITIO_G2_Input_Select_Reg
:
584 ni_660x_register
= G2InputSelectRegister
;
586 case NITIO_G3_Input_Select_Reg
:
587 ni_660x_register
= G3InputSelectRegister
;
589 case NITIO_G01_Status_Reg
:
590 ni_660x_register
= G01StatusRegister
;
592 case NITIO_G23_Status_Reg
:
593 ni_660x_register
= G23StatusRegister
;
595 case NITIO_G01_Joint_Reset_Reg
:
596 ni_660x_register
= G01JointResetRegister
;
598 case NITIO_G23_Joint_Reset_Reg
:
599 ni_660x_register
= G23JointResetRegister
;
601 case NITIO_G01_Joint_Status1_Reg
:
602 ni_660x_register
= G01JointStatus1Register
;
604 case NITIO_G23_Joint_Status1_Reg
:
605 ni_660x_register
= G23JointStatus1Register
;
607 case NITIO_G01_Joint_Status2_Reg
:
608 ni_660x_register
= G01JointStatus2Register
;
610 case NITIO_G23_Joint_Status2_Reg
:
611 ni_660x_register
= G23JointStatus2Register
;
613 case NITIO_G0_Counting_Mode_Reg
:
614 ni_660x_register
= G0CountingModeRegister
;
616 case NITIO_G1_Counting_Mode_Reg
:
617 ni_660x_register
= G1CountingModeRegister
;
619 case NITIO_G2_Counting_Mode_Reg
:
620 ni_660x_register
= G2CountingModeRegister
;
622 case NITIO_G3_Counting_Mode_Reg
:
623 ni_660x_register
= G3CountingModeRegister
;
625 case NITIO_G0_Second_Gate_Reg
:
626 ni_660x_register
= G0SecondGateRegister
;
628 case NITIO_G1_Second_Gate_Reg
:
629 ni_660x_register
= G1SecondGateRegister
;
631 case NITIO_G2_Second_Gate_Reg
:
632 ni_660x_register
= G2SecondGateRegister
;
634 case NITIO_G3_Second_Gate_Reg
:
635 ni_660x_register
= G3SecondGateRegister
;
637 case NITIO_G0_DMA_Config_Reg
:
638 ni_660x_register
= G0DMAConfigRegister
;
640 case NITIO_G0_DMA_Status_Reg
:
641 ni_660x_register
= G0DMAStatusRegister
;
643 case NITIO_G1_DMA_Config_Reg
:
644 ni_660x_register
= G1DMAConfigRegister
;
646 case NITIO_G1_DMA_Status_Reg
:
647 ni_660x_register
= G1DMAStatusRegister
;
649 case NITIO_G2_DMA_Config_Reg
:
650 ni_660x_register
= G2DMAConfigRegister
;
652 case NITIO_G2_DMA_Status_Reg
:
653 ni_660x_register
= G2DMAStatusRegister
;
655 case NITIO_G3_DMA_Config_Reg
:
656 ni_660x_register
= G3DMAConfigRegister
;
658 case NITIO_G3_DMA_Status_Reg
:
659 ni_660x_register
= G3DMAStatusRegister
;
661 case NITIO_G0_Interrupt_Acknowledge_Reg
:
662 ni_660x_register
= G0InterruptAcknowledge
;
664 case NITIO_G1_Interrupt_Acknowledge_Reg
:
665 ni_660x_register
= G1InterruptAcknowledge
;
667 case NITIO_G2_Interrupt_Acknowledge_Reg
:
668 ni_660x_register
= G2InterruptAcknowledge
;
670 case NITIO_G3_Interrupt_Acknowledge_Reg
:
671 ni_660x_register
= G3InterruptAcknowledge
;
673 case NITIO_G0_Status_Reg
:
674 ni_660x_register
= G0StatusRegister
;
676 case NITIO_G1_Status_Reg
:
677 ni_660x_register
= G0StatusRegister
;
679 case NITIO_G2_Status_Reg
:
680 ni_660x_register
= G0StatusRegister
;
682 case NITIO_G3_Status_Reg
:
683 ni_660x_register
= G0StatusRegister
;
685 case NITIO_G0_Interrupt_Enable_Reg
:
686 ni_660x_register
= G0InterruptEnable
;
688 case NITIO_G1_Interrupt_Enable_Reg
:
689 ni_660x_register
= G1InterruptEnable
;
691 case NITIO_G2_Interrupt_Enable_Reg
:
692 ni_660x_register
= G2InterruptEnable
;
694 case NITIO_G3_Interrupt_Enable_Reg
:
695 ni_660x_register
= G3InterruptEnable
;
698 printk("%s: unhandled register 0x%x in switch.\n",
704 return ni_660x_register
;
707 static inline void ni_660x_write_register(struct comedi_device
*dev
,
708 unsigned chip_index
, unsigned bits
, enum NI_660x_Register reg
)
710 void *const write_address
=
711 private(dev
)->mite
->daq_io_addr
+ GPCT_OFFSET
[chip_index
] +
712 registerData
[reg
].offset
;
714 switch (registerData
[reg
].size
) {
716 writew(bits
, write_address
);
719 writel(bits
, write_address
);
722 printk("%s: %s: bug! unhandled case (reg=0x%x) in switch.\n",
723 __FILE__
, __func__
, reg
);
729 static inline unsigned ni_660x_read_register(struct comedi_device
*dev
,
730 unsigned chip_index
, enum NI_660x_Register reg
)
732 void *const read_address
=
733 private(dev
)->mite
->daq_io_addr
+ GPCT_OFFSET
[chip_index
] +
734 registerData
[reg
].offset
;
736 switch (registerData
[reg
].size
) {
738 return readw(read_address
);
741 return readl(read_address
);
744 printk("%s: %s: bug! unhandled case (reg=0x%x) in switch.\n",
745 __FILE__
, __func__
, reg
);
752 static void ni_gpct_write_register(struct ni_gpct
*counter
, unsigned bits
,
753 enum ni_gpct_register reg
)
755 struct comedi_device
*dev
= counter
->counter_dev
->dev
;
756 enum NI_660x_Register ni_660x_register
= ni_gpct_to_660x_register(reg
);
757 ni_660x_write_register(dev
, counter
->chip_index
, bits
,
761 static unsigned ni_gpct_read_register(struct ni_gpct
*counter
,
762 enum ni_gpct_register reg
)
764 struct comedi_device
*dev
= counter
->counter_dev
->dev
;
765 enum NI_660x_Register ni_660x_register
= ni_gpct_to_660x_register(reg
);
766 return ni_660x_read_register(dev
, counter
->chip_index
,
770 static inline struct mite_dma_descriptor_ring
*mite_ring(struct ni_660x_private
* priv
,
771 struct ni_gpct
*counter
)
773 return priv
->mite_rings
[counter
->chip_index
][counter
->counter_index
];
776 static inline void ni_660x_set_dma_channel(struct comedi_device
*dev
,
777 unsigned mite_channel
, struct ni_gpct
*counter
)
780 spin_lock_irqsave(&private(dev
)->soft_reg_copy_lock
, flags
);
781 private(dev
)->dma_configuration_soft_copies
[counter
->chip_index
] &=
782 ~dma_select_mask(mite_channel
);
783 private(dev
)->dma_configuration_soft_copies
[counter
->chip_index
] |=
784 dma_select_bits(mite_channel
,
785 dma_selection_counter(counter
->counter_index
));
786 ni_660x_write_register(dev
, counter
->chip_index
,
787 private(dev
)->dma_configuration_soft_copies
[counter
->
788 chip_index
] | dma_reset_bit(mite_channel
),
791 spin_unlock_irqrestore(&private(dev
)->soft_reg_copy_lock
, flags
);
794 static inline void ni_660x_unset_dma_channel(struct comedi_device
*dev
,
795 unsigned mite_channel
, struct ni_gpct
*counter
)
798 spin_lock_irqsave(&private(dev
)->soft_reg_copy_lock
, flags
);
799 private(dev
)->dma_configuration_soft_copies
[counter
->chip_index
] &=
800 ~dma_select_mask(mite_channel
);
801 private(dev
)->dma_configuration_soft_copies
[counter
->chip_index
] |=
802 dma_select_bits(mite_channel
, dma_selection_none
);
803 ni_660x_write_register(dev
, counter
->chip_index
,
804 private(dev
)->dma_configuration_soft_copies
[counter
->
805 chip_index
], DMAConfigRegister
);
807 spin_unlock_irqrestore(&private(dev
)->soft_reg_copy_lock
, flags
);
810 static int ni_660x_request_mite_channel(struct comedi_device
*dev
,
811 struct ni_gpct
*counter
, enum comedi_io_direction direction
)
814 struct mite_channel
*mite_chan
;
816 spin_lock_irqsave(&private(dev
)->mite_channel_lock
, flags
);
817 BUG_ON(counter
->mite_chan
);
819 mite_request_channel(private(dev
)->mite
, mite_ring(private(dev
),
821 if (mite_chan
== NULL
) {
822 spin_unlock_irqrestore(&private(dev
)->mite_channel_lock
,
825 "failed to reserve mite dma channel for counter.");
828 mite_chan
->dir
= direction
;
829 ni_tio_set_mite_channel(counter
, mite_chan
);
830 ni_660x_set_dma_channel(dev
, mite_chan
->channel
, counter
);
831 spin_unlock_irqrestore(&private(dev
)->mite_channel_lock
, flags
);
835 void ni_660x_release_mite_channel(struct comedi_device
*dev
, struct ni_gpct
*counter
)
839 spin_lock_irqsave(&private(dev
)->mite_channel_lock
, flags
);
840 if (counter
->mite_chan
) {
841 struct mite_channel
*mite_chan
= counter
->mite_chan
;
843 ni_660x_unset_dma_channel(dev
, mite_chan
->channel
, counter
);
844 ni_tio_set_mite_channel(counter
, NULL
);
845 mite_release_channel(mite_chan
);
847 spin_unlock_irqrestore(&private(dev
)->mite_channel_lock
, flags
);
850 static int ni_660x_cmd(struct comedi_device
*dev
, struct comedi_subdevice
*s
)
854 struct ni_gpct
*counter
= subdev_to_counter(s
);
855 /* const struct comedi_cmd *cmd = &s->async->cmd; */
857 retval
= ni_660x_request_mite_channel(dev
, counter
, COMEDI_INPUT
);
860 "no dma channel available for use by counter");
863 ni_tio_acknowledge_and_confirm(counter
, NULL
, NULL
, NULL
, NULL
);
864 retval
= ni_tio_cmd(counter
, s
->async
);
869 static int ni_660x_cmdtest(struct comedi_device
*dev
, struct comedi_subdevice
*s
,
870 struct comedi_cmd
*cmd
)
872 struct ni_gpct
*counter
= subdev_to_counter(s
);
874 return ni_tio_cmdtest(counter
, cmd
);
877 static int ni_660x_cancel(struct comedi_device
*dev
, struct comedi_subdevice
*s
)
879 struct ni_gpct
*counter
= subdev_to_counter(s
);
882 retval
= ni_tio_cancel(counter
);
883 ni_660x_release_mite_channel(dev
, counter
);
887 static void set_tio_counterswap(struct comedi_device
*dev
, int chipset
)
889 /* See P. 3.5 of the Register-Level Programming manual. The
890 CounterSwap bit has to be set on the second chip, otherwise
891 it will try to use the same pins as the first chip.
894 ni_660x_write_register(dev
, chipset
, CounterSwap
,
895 ClockConfigRegister
);
897 ni_660x_write_register(dev
, chipset
, 0, ClockConfigRegister
);
900 static void ni_660x_handle_gpct_interrupt(struct comedi_device
*dev
,
901 struct comedi_subdevice
*s
)
903 ni_tio_handle_interrupt(subdev_to_counter(s
), s
);
904 if (s
->async
->events
) {
906 events
& (COMEDI_CB_EOA
| COMEDI_CB_ERROR
|
907 COMEDI_CB_OVERFLOW
)) {
908 ni_660x_cancel(dev
, s
);
910 comedi_event(dev
, s
);
914 static irqreturn_t
ni_660x_interrupt(int irq
, void *d
)
916 struct comedi_device
*dev
= d
;
917 struct comedi_subdevice
*s
;
921 if (dev
->attached
== 0)
923 /* lock to avoid race with comedi_poll */
924 spin_lock_irqsave(&private(dev
)->interrupt_lock
, flags
);
926 for (i
= 0; i
< ni_660x_num_counters(dev
); ++i
) {
927 s
= dev
->subdevices
+ NI_660X_GPCT_SUBDEV(i
);
928 ni_660x_handle_gpct_interrupt(dev
, s
);
930 spin_unlock_irqrestore(&private(dev
)->interrupt_lock
, flags
);
934 static int ni_660x_input_poll(struct comedi_device
*dev
,
935 struct comedi_subdevice
*s
)
938 /* lock to avoid race with comedi_poll */
939 spin_lock_irqsave(&private(dev
)->interrupt_lock
, flags
);
940 mite_sync_input_dma(subdev_to_counter(s
)->mite_chan
, s
->async
);
941 spin_unlock_irqrestore(&private(dev
)->interrupt_lock
, flags
);
942 return comedi_buf_read_n_available(s
->async
);
945 static int ni_660x_buf_change(struct comedi_device
*dev
, struct comedi_subdevice
*s
,
946 unsigned long new_size
)
950 ret
= mite_buf_change(mite_ring(private(dev
), subdev_to_counter(s
)),
958 static int ni_660x_allocate_private(struct comedi_device
*dev
)
963 retval
= alloc_private(dev
, sizeof(struct ni_660x_private
));
967 spin_lock_init(&private(dev
)->mite_channel_lock
);
968 spin_lock_init(&private(dev
)->interrupt_lock
);
969 spin_lock_init(&private(dev
)->soft_reg_copy_lock
);
970 for (i
= 0; i
< NUM_PFI_CHANNELS
; ++i
) {
971 private(dev
)->pfi_output_selects
[i
] = pfi_output_select_counter
;
976 static int ni_660x_alloc_mite_rings(struct comedi_device
*dev
)
981 for (i
= 0; i
< board(dev
)->n_chips
; ++i
) {
982 for (j
= 0; j
< counters_per_chip
; ++j
) {
983 private(dev
)->mite_rings
[i
][j
] =
984 mite_alloc_ring(private(dev
)->mite
);
985 if (private(dev
)->mite_rings
[i
][j
] == NULL
) {
993 static void ni_660x_free_mite_rings(struct comedi_device
*dev
)
998 for (i
= 0; i
< board(dev
)->n_chips
; ++i
) {
999 for (j
= 0; j
< counters_per_chip
; ++j
) {
1000 mite_free_ring(private(dev
)->mite_rings
[i
][j
]);
1005 static int ni_660x_attach(struct comedi_device
*dev
, struct comedi_devconfig
*it
)
1007 struct comedi_subdevice
*s
;
1010 unsigned global_interrupt_config_bits
;
1012 printk("comedi%d: ni_660x: ", dev
->minor
);
1014 ret
= ni_660x_allocate_private(dev
);
1017 ret
= ni_660x_find_device(dev
, it
->options
[0], it
->options
[1]);
1021 dev
->board_name
= board(dev
)->name
;
1023 ret
= mite_setup2(private(dev
)->mite
, 1);
1025 printk("error setting up mite\n");
1028 comedi_set_hw_dev(dev
, &private(dev
)->mite
->pcidev
->dev
);
1029 ret
= ni_660x_alloc_mite_rings(dev
);
1033 printk(" %s ", dev
->board_name
);
1035 dev
->n_subdevices
= 2 + NI_660X_MAX_NUM_COUNTERS
;
1037 if (alloc_subdevices(dev
, dev
->n_subdevices
) < 0)
1040 s
= dev
->subdevices
+ 0;
1041 /* Old GENERAL-PURPOSE COUNTER/TIME (GPCT) subdevice, no longer used */
1042 s
->type
= COMEDI_SUBD_UNUSED
;
1044 s
= dev
->subdevices
+ NI_660X_DIO_SUBDEV
;
1045 /* DIGITAL I/O SUBDEVICE */
1046 s
->type
= COMEDI_SUBD_DIO
;
1047 s
->subdev_flags
= SDF_READABLE
| SDF_WRITABLE
;
1048 s
->n_chan
= NUM_PFI_CHANNELS
;
1050 s
->range_table
= &range_digital
;
1051 s
->insn_bits
= ni_660x_dio_insn_bits
;
1052 s
->insn_config
= ni_660x_dio_insn_config
;
1053 s
->io_bits
= 0; /* all bits default to input */
1054 /* we use the ioconfig registers to control dio direction, so zero output enables in stc dio control reg */
1055 ni_660x_write_register(dev
, 0, 0, STCDIOControl
);
1057 private(dev
)->counter_dev
= ni_gpct_device_construct(dev
,
1058 &ni_gpct_write_register
, &ni_gpct_read_register
,
1059 ni_gpct_variant_660x
, ni_660x_num_counters(dev
));
1060 if (private(dev
)->counter_dev
== NULL
)
1062 for (i
= 0; i
< NI_660X_MAX_NUM_COUNTERS
; ++i
) {
1063 s
= dev
->subdevices
+ NI_660X_GPCT_SUBDEV(i
);
1064 if (i
< ni_660x_num_counters(dev
)) {
1065 s
->type
= COMEDI_SUBD_COUNTER
;
1067 SDF_READABLE
| SDF_WRITABLE
| SDF_LSAMPL
|
1068 SDF_CMD_READ
/* | SDF_CMD_WRITE */ ;
1070 s
->maxdata
= 0xffffffff;
1071 s
->insn_read
= ni_660x_GPCT_rinsn
;
1072 s
->insn_write
= ni_660x_GPCT_winsn
;
1073 s
->insn_config
= ni_660x_GPCT_insn_config
;
1074 s
->do_cmd
= &ni_660x_cmd
;
1075 s
->len_chanlist
= 1;
1076 s
->do_cmdtest
= &ni_660x_cmdtest
;
1077 s
->cancel
= &ni_660x_cancel
;
1078 s
->poll
= &ni_660x_input_poll
;
1079 s
->async_dma_dir
= DMA_BIDIRECTIONAL
;
1080 s
->buf_change
= &ni_660x_buf_change
;
1081 s
->private = &private(dev
)->counter_dev
->counters
[i
];
1083 private(dev
)->counter_dev
->counters
[i
].chip_index
=
1084 i
/ counters_per_chip
;
1085 private(dev
)->counter_dev
->counters
[i
].counter_index
=
1086 i
% counters_per_chip
;
1088 s
->type
= COMEDI_SUBD_UNUSED
;
1091 for (i
= 0; i
< board(dev
)->n_chips
; ++i
) {
1092 init_tio_chip(dev
, i
);
1094 for (i
= 0; i
< ni_660x_num_counters(dev
); ++i
) {
1095 ni_tio_init_counter(&private(dev
)->counter_dev
->counters
[i
]);
1097 for (i
= 0; i
< NUM_PFI_CHANNELS
; ++i
) {
1098 if (i
< min_counter_pfi_chan
)
1099 ni_660x_set_pfi_routing(dev
, i
, pfi_output_select_do
);
1101 ni_660x_set_pfi_routing(dev
, i
,
1102 pfi_output_select_counter
);
1103 ni_660x_select_pfi_output(dev
, i
, pfi_output_select_high_Z
);
1105 /* to be safe, set counterswap bits on tio chips after all the counter
1106 outputs have been set to high impedance mode */
1107 for (i
= 0; i
< board(dev
)->n_chips
; ++i
) {
1108 set_tio_counterswap(dev
, i
);
1110 ret
= request_irq(mite_irq(private(dev
)->mite
), ni_660x_interrupt
,
1111 IRQF_SHARED
, "ni_660x", dev
);
1113 printk(" irq not available\n");
1116 dev
->irq
= mite_irq(private(dev
)->mite
);
1117 global_interrupt_config_bits
= Global_Int_Enable_Bit
;
1118 if (board(dev
)->n_chips
> 1)
1119 global_interrupt_config_bits
|= Cascade_Int_Enable_Bit
;
1120 ni_660x_write_register(dev
, 0, global_interrupt_config_bits
,
1121 GlobalInterruptConfigRegister
);
1122 printk("attached\n");
1126 static int ni_660x_detach(struct comedi_device
*dev
)
1128 printk("comedi%d: ni_660x: remove\n", dev
->minor
);
1132 free_irq(dev
->irq
, dev
);
1135 if (private(dev
)->counter_dev
)
1136 ni_gpct_device_destroy(private(dev
)->counter_dev
);
1137 if (private(dev
)->mite
) {
1138 ni_660x_free_mite_rings(dev
);
1139 mite_unsetup(private(dev
)->mite
);
1146 ni_660x_GPCT_rinsn(struct comedi_device
*dev
, struct comedi_subdevice
*s
,
1147 struct comedi_insn
*insn
, unsigned int *data
)
1149 return ni_tio_rinsn(subdev_to_counter(s
), insn
, data
);
1152 static void init_tio_chip(struct comedi_device
*dev
, int chipset
)
1156 /* init dma configuration register */
1157 private(dev
)->dma_configuration_soft_copies
[chipset
] = 0;
1158 for (i
= 0; i
< MAX_DMA_CHANNEL
; ++i
) {
1159 private(dev
)->dma_configuration_soft_copies
[chipset
] |=
1161 dma_selection_none
) & dma_select_mask(i
);
1163 ni_660x_write_register(dev
, chipset
,
1164 private(dev
)->dma_configuration_soft_copies
[chipset
],
1166 for (i
= 0; i
< NUM_PFI_CHANNELS
; ++i
)
1168 ni_660x_write_register(dev
, chipset
, 0, IOConfigReg(i
));
1173 ni_660x_GPCT_insn_config(struct comedi_device
*dev
, struct comedi_subdevice
*s
,
1174 struct comedi_insn
*insn
, unsigned int *data
)
1176 return ni_tio_insn_config(subdev_to_counter(s
), insn
, data
);
1179 static int ni_660x_GPCT_winsn(struct comedi_device
*dev
,
1180 struct comedi_subdevice
*s
, struct comedi_insn
*insn
, unsigned int *data
)
1182 return ni_tio_winsn(subdev_to_counter(s
), insn
, data
);
1185 static int ni_660x_find_device(struct comedi_device
*dev
, int bus
, int slot
)
1187 struct mite_struct
*mite
;
1190 for (mite
= mite_devices
; mite
; mite
= mite
->next
) {
1194 if (bus
!= mite
->pcidev
->bus
->number
||
1195 slot
!= PCI_SLOT(mite
->pcidev
->devfn
))
1199 for (i
= 0; i
< n_ni_660x_boards
; i
++) {
1200 if (mite_device_id(mite
) == ni_660x_boards
[i
].dev_id
) {
1201 dev
->board_ptr
= ni_660x_boards
+ i
;
1202 private(dev
)->mite
= mite
;
1207 printk("no device found\n");
1208 mite_list_devices();
1212 static int ni_660x_dio_insn_bits(struct comedi_device
*dev
,
1213 struct comedi_subdevice
*s
, struct comedi_insn
*insn
, unsigned int *data
)
1215 unsigned base_bitfield_channel
= CR_CHAN(insn
->chanspec
);
1217 /* Check if we have to write some bits */
1219 s
->state
&= ~(data
[0] << base_bitfield_channel
);
1220 s
->state
|= (data
[0] & data
[1]) << base_bitfield_channel
;
1221 /* Write out the new digital output lines */
1222 ni_660x_write_register(dev
, 0, s
->state
, DIO32Output
);
1224 /* on return, data[1] contains the value of the digital
1225 * input and output lines. */
1227 (ni_660x_read_register(dev
, 0,
1228 DIO32Input
) >> base_bitfield_channel
);
1232 static void ni_660x_select_pfi_output(struct comedi_device
*dev
, unsigned pfi_channel
,
1233 unsigned output_select
)
1235 static const unsigned counter_4_7_first_pfi
= 8;
1236 static const unsigned counter_4_7_last_pfi
= 23;
1237 unsigned active_chipset
= 0;
1238 unsigned idle_chipset
= 0;
1239 unsigned active_bits
;
1242 if (board (dev
)->n_chips
> 1) {
1243 if (output_select
== pfi_output_select_counter
&&
1244 pfi_channel
>= counter_4_7_first_pfi
&&
1245 pfi_channel
<= counter_4_7_last_pfi
) {
1254 if (idle_chipset
!= active_chipset
) {
1255 idle_bits
= ni_660x_read_register(dev
, idle_chipset
, IOConfigReg(pfi_channel
));
1256 idle_bits
&= ~pfi_output_select_mask(pfi_channel
);
1257 idle_bits
|= pfi_output_select_bits(pfi_channel
, pfi_output_select_high_Z
);
1258 ni_660x_write_register(dev
, idle_chipset
, idle_bits
, IOConfigReg(pfi_channel
));
1261 active_bits
= ni_660x_read_register(dev
, active_chipset
, IOConfigReg(pfi_channel
));
1262 active_bits
&= ~pfi_output_select_mask(pfi_channel
);
1263 active_bits
|= pfi_output_select_bits(pfi_channel
, output_select
);
1264 ni_660x_write_register(dev
, active_chipset
, active_bits
, IOConfigReg(pfi_channel
));
1267 static int ni_660x_set_pfi_routing(struct comedi_device
*dev
, unsigned chan
,
1270 if (source
> num_pfi_output_selects
)
1272 if (source
== pfi_output_select_high_Z
)
1274 if (chan
< min_counter_pfi_chan
) {
1275 if (source
== pfi_output_select_counter
)
1277 } else if (chan
> max_dio_pfi_chan
) {
1278 if (source
== pfi_output_select_do
)
1281 BUG_ON(chan
>= NUM_PFI_CHANNELS
);
1283 private(dev
)->pfi_output_selects
[chan
] = source
;
1284 if (private(dev
)->pfi_direction_bits
& (((uint64_t) 1) << chan
))
1285 ni_660x_select_pfi_output(dev
, chan
,
1286 private(dev
)->pfi_output_selects
[chan
]);
1290 static unsigned ni_660x_get_pfi_routing(struct comedi_device
*dev
, unsigned chan
)
1292 BUG_ON(chan
>= NUM_PFI_CHANNELS
);
1293 return private(dev
)->pfi_output_selects
[chan
];
1296 static void ni660x_config_filter(struct comedi_device
*dev
, unsigned pfi_channel
,
1297 enum ni_gpct_filter_select filter
)
1299 unsigned bits
= ni_660x_read_register(dev
, 0, IOConfigReg(pfi_channel
));
1300 bits
&= ~pfi_input_select_mask(pfi_channel
);
1301 bits
|= pfi_input_select_bits(pfi_channel
, filter
);
1302 ni_660x_write_register(dev
, 0, bits
, IOConfigReg(pfi_channel
));
1305 static int ni_660x_dio_insn_config(struct comedi_device
*dev
,
1306 struct comedi_subdevice
*s
, struct comedi_insn
*insn
, unsigned int *data
)
1308 int chan
= CR_CHAN(insn
->chanspec
);
1310 /* The input or output configuration of each digital line is
1311 * configured by a special insn_config instruction. chanspec
1312 * contains the channel to be changed, and data[0] contains the
1313 * value COMEDI_INPUT or COMEDI_OUTPUT. */
1316 case INSN_CONFIG_DIO_OUTPUT
:
1317 private(dev
)->pfi_direction_bits
|= ((uint64_t) 1) << chan
;
1318 ni_660x_select_pfi_output(dev
, chan
,
1319 private(dev
)->pfi_output_selects
[chan
]);
1321 case INSN_CONFIG_DIO_INPUT
:
1322 private(dev
)->pfi_direction_bits
&= ~(((uint64_t) 1) << chan
);
1323 ni_660x_select_pfi_output(dev
, chan
, pfi_output_select_high_Z
);
1325 case INSN_CONFIG_DIO_QUERY
:
1328 pfi_direction_bits
& (((uint64_t) 1) << chan
)) ?
1329 COMEDI_OUTPUT
: COMEDI_INPUT
;
1331 case INSN_CONFIG_SET_ROUTING
:
1332 return ni_660x_set_pfi_routing(dev
, chan
, data
[1]);
1334 case INSN_CONFIG_GET_ROUTING
:
1335 data
[1] = ni_660x_get_pfi_routing(dev
, chan
);
1337 case INSN_CONFIG_FILTER
:
1338 ni660x_config_filter(dev
, chan
, data
[1]);