ni_660x.c revision 790c55415aa31f4c732729f94d2c3a54f7d3bfc2
1/*
2  comedi/drivers/ni_660x.c
3  Hardware driver for NI 660x devices
4
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.
9
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.
14
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.
18*/
19
20/*
21Driver: ni_660x
22Description: National Instruments 660x counter/timer boards
23Devices:
24[National Instruments] PCI-6601 (ni_660x), PCI-6602, PXI-6602,
25	PXI-6608
26Author: 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>
31Updated: Thu Oct 18 12:56:06 EDT 2007
32Status: experimental
33
34Encoders work.  PulseGeneration (both single pulse and pulse train)
35works. Buffered commands work for input but not output.
36
37References:
38DAQ 660x Register-Level Programmer Manual  (NI 370505A-01)
39DAQ 6601/6602 User Manual (NI 322137B-01)
40
41*/
42
43#include "../comedidev.h"
44#include "mite.h"
45#include "ni_tio.h"
46
47enum ni_660x_constants {
48	min_counter_pfi_chan = 8,
49	max_dio_pfi_chan = 31,
50	counters_per_chip = 4
51};
52
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
56
57/* See Register-Level Programmer Manual page 3.1 */
58typedef enum {
59	G0InterruptAcknowledge,
60	G0StatusRegister,
61	G1InterruptAcknowledge,
62	G1StatusRegister,
63	G01StatusRegister,
64	G0CommandRegister,
65	STCDIOParallelInput,
66	G1CommandRegister,
67	G0HWSaveRegister,
68	G1HWSaveRegister,
69	STCDIOOutput,
70	STCDIOControl,
71	G0SWSaveRegister,
72	G1SWSaveRegister,
73	G0ModeRegister,
74	G01JointStatus1Register,
75	G1ModeRegister,
76	STCDIOSerialInput,
77	G0LoadARegister,
78	G01JointStatus2Register,
79	G0LoadBRegister,
80	G1LoadARegister,
81	G1LoadBRegister,
82	G0InputSelectRegister,
83	G1InputSelectRegister,
84	G0AutoincrementRegister,
85	G1AutoincrementRegister,
86	G01JointResetRegister,
87	G0InterruptEnable,
88	G1InterruptEnable,
89	G0CountingModeRegister,
90	G1CountingModeRegister,
91	G0SecondGateRegister,
92	G1SecondGateRegister,
93	G0DMAConfigRegister,
94	G0DMAStatusRegister,
95	G1DMAConfigRegister,
96	G1DMAStatusRegister,
97	G2InterruptAcknowledge,
98	G2StatusRegister,
99	G3InterruptAcknowledge,
100	G3StatusRegister,
101	G23StatusRegister,
102	G2CommandRegister,
103	G3CommandRegister,
104	G2HWSaveRegister,
105	G3HWSaveRegister,
106	G2SWSaveRegister,
107	G3SWSaveRegister,
108	G2ModeRegister,
109	G23JointStatus1Register,
110	G3ModeRegister,
111	G2LoadARegister,
112	G23JointStatus2Register,
113	G2LoadBRegister,
114	G3LoadARegister,
115	G3LoadBRegister,
116	G2InputSelectRegister,
117	G3InputSelectRegister,
118	G2AutoincrementRegister,
119	G3AutoincrementRegister,
120	G23JointResetRegister,
121	G2InterruptEnable,
122	G3InterruptEnable,
123	G2CountingModeRegister,
124	G3CountingModeRegister,
125	G3SecondGateRegister,
126	G2SecondGateRegister,
127	G2DMAConfigRegister,
128	G2DMAStatusRegister,
129	G3DMAConfigRegister,
130	G3DMAStatusRegister,
131	DIO32Input,
132	DIO32Output,
133	ClockConfigRegister,
134	GlobalInterruptStatusRegister,
135	DMAConfigRegister,
136	GlobalInterruptConfigRegister,
137	IOConfigReg0_1,
138	IOConfigReg2_3,
139	IOConfigReg4_5,
140	IOConfigReg6_7,
141	IOConfigReg8_9,
142	IOConfigReg10_11,
143	IOConfigReg12_13,
144	IOConfigReg14_15,
145	IOConfigReg16_17,
146	IOConfigReg18_19,
147	IOConfigReg20_21,
148	IOConfigReg22_23,
149	IOConfigReg24_25,
150	IOConfigReg26_27,
151	IOConfigReg28_29,
152	IOConfigReg30_31,
153	IOConfigReg32_33,
154	IOConfigReg34_35,
155	IOConfigReg36_37,
156	IOConfigReg38_39,
157	NumRegisters,
158} NI_660x_Register;
159
160static inline unsigned IOConfigReg(unsigned pfi_channel)
161{
162	unsigned reg = IOConfigReg0_1 + pfi_channel / 2;
163	BUG_ON(reg > IOConfigReg38_39);
164	return reg;
165}
166
167enum ni_660x_register_width {
168	DATA_1B,
169	DATA_2B,
170	DATA_4B
171};
172
173enum ni_660x_register_direction {
174	NI_660x_READ,
175	NI_660x_WRITE,
176	NI_660x_READ_WRITE
177};
178
179enum 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
184};
185
186enum ni_660x_subdevices {
187	NI_660X_DIO_SUBDEV = 1,
188	NI_660X_GPCT_SUBDEV_0 = 2
189};
190static inline unsigned NI_660X_GPCT_SUBDEV(unsigned index)
191{
192	return NI_660X_GPCT_SUBDEV_0 + index;
193}
194
195typedef struct {
196	const char *name;	// Register Name
197	int offset;		// Offset from base address from GPCT chip
198	enum ni_660x_register_direction direction;
199	enum ni_660x_register_width size;	// 1 byte, 2 bytes, or 4 bytes
200} NI_660xRegisterData;
201
202static const NI_660xRegisterData registerData[NumRegisters] = {
203	{"G0 Interrupt Acknowledge", 0x004, NI_660x_WRITE, DATA_2B},
204	{"G0 Status Register", 0x004, NI_660x_READ, DATA_2B},
205	{"G1 Interrupt Acknowledge", 0x006, NI_660x_WRITE, DATA_2B},
206	{"G1 Status Register", 0x006, NI_660x_READ, DATA_2B},
207	{"G01 Status Register ", 0x008, NI_660x_READ, DATA_2B},
208	{"G0 Command Register", 0x00C, NI_660x_WRITE, DATA_2B},
209	{"STC DIO Parallel Input", 0x00E, NI_660x_READ, DATA_2B},
210	{"G1 Command Register", 0x00E, NI_660x_WRITE, DATA_2B},
211	{"G0 HW Save Register", 0x010, NI_660x_READ, DATA_4B},
212	{"G1 HW Save Register", 0x014, NI_660x_READ, DATA_4B},
213	{"STC DIO Output", 0x014, NI_660x_WRITE, DATA_2B},
214	{"STC DIO Control", 0x016, NI_660x_WRITE, DATA_2B},
215	{"G0 SW Save Register", 0x018, NI_660x_READ, DATA_4B},
216	{"G1 SW Save Register", 0x01C, NI_660x_READ, DATA_4B},
217	{"G0 Mode Register", 0x034, NI_660x_WRITE, DATA_2B},
218	{"G01 Joint Status 1 Register", 0x036, NI_660x_READ, DATA_2B},
219	{"G1 Mode Register", 0x036, NI_660x_WRITE, DATA_2B},
220	{"STC DIO Serial Input", 0x038, NI_660x_READ, DATA_2B},
221	{"G0 Load A Register", 0x038, NI_660x_WRITE, DATA_4B},
222	{"G01 Joint Status 2 Register", 0x03A, NI_660x_READ, DATA_2B},
223	{"G0 Load B Register", 0x03C, NI_660x_WRITE, DATA_4B},
224	{"G1 Load A Register", 0x040, NI_660x_WRITE, DATA_4B},
225	{"G1 Load B Register", 0x044, NI_660x_WRITE, DATA_4B},
226	{"G0 Input Select Register", 0x048, NI_660x_WRITE, DATA_2B},
227	{"G1 Input Select Register", 0x04A, NI_660x_WRITE, DATA_2B},
228	{"G0 Autoincrement Register", 0x088, NI_660x_WRITE, DATA_2B},
229	{"G1 Autoincrement Register", 0x08A, NI_660x_WRITE, DATA_2B},
230	{"G01 Joint Reset Register", 0x090, NI_660x_WRITE, DATA_2B},
231	{"G0 Interrupt Enable", 0x092, NI_660x_WRITE, DATA_2B},
232	{"G1 Interrupt Enable", 0x096, NI_660x_WRITE, DATA_2B},
233	{"G0 Counting Mode Register", 0x0B0, NI_660x_WRITE, DATA_2B},
234	{"G1 Counting Mode Register", 0x0B2, NI_660x_WRITE, DATA_2B},
235	{"G0 Second Gate Register", 0x0B4, NI_660x_WRITE, DATA_2B},
236	{"G1 Second Gate Register", 0x0B6, NI_660x_WRITE, DATA_2B},
237	{"G0 DMA Config Register", 0x0B8, NI_660x_WRITE, DATA_2B},
238	{"G0 DMA Status Register", 0x0B8, NI_660x_READ, DATA_2B},
239	{"G1 DMA Config Register", 0x0BA, NI_660x_WRITE, DATA_2B},
240	{"G1 DMA Status Register", 0x0BA, NI_660x_READ, DATA_2B},
241	{"G2 Interrupt Acknowledge", 0x104, NI_660x_WRITE, DATA_2B},
242	{"G2 Status Register", 0x104, NI_660x_READ, DATA_2B},
243	{"G3 Interrupt Acknowledge", 0x106, NI_660x_WRITE, DATA_2B},
244	{"G3 Status Register", 0x106, NI_660x_READ, DATA_2B},
245	{"G23 Status Register", 0x108, NI_660x_READ, DATA_2B},
246	{"G2 Command Register", 0x10C, NI_660x_WRITE, DATA_2B},
247	{"G3 Command Register", 0x10E, NI_660x_WRITE, DATA_2B},
248	{"G2 HW Save Register", 0x110, NI_660x_READ, DATA_4B},
249	{"G3 HW Save Register", 0x114, NI_660x_READ, DATA_4B},
250	{"G2 SW Save Register", 0x118, NI_660x_READ, DATA_4B},
251	{"G3 SW Save Register", 0x11C, NI_660x_READ, DATA_4B},
252	{"G2 Mode Register", 0x134, NI_660x_WRITE, DATA_2B},
253	{"G23 Joint Status 1 Register", 0x136, NI_660x_READ, DATA_2B},
254	{"G3 Mode Register", 0x136, NI_660x_WRITE, DATA_2B},
255	{"G2 Load A Register", 0x138, NI_660x_WRITE, DATA_4B},
256	{"G23 Joint Status 2 Register", 0x13A, NI_660x_READ, DATA_2B},
257	{"G2 Load B Register", 0x13C, NI_660x_WRITE, DATA_4B},
258	{"G3 Load A Register", 0x140, NI_660x_WRITE, DATA_4B},
259	{"G3 Load B Register", 0x144, NI_660x_WRITE, DATA_4B},
260	{"G2 Input Select Register", 0x148, NI_660x_WRITE, DATA_2B},
261	{"G3 Input Select Register", 0x14A, NI_660x_WRITE, DATA_2B},
262	{"G2 Autoincrement Register", 0x188, NI_660x_WRITE, DATA_2B},
263	{"G3 Autoincrement Register", 0x18A, NI_660x_WRITE, DATA_2B},
264	{"G23 Joint Reset Register", 0x190, NI_660x_WRITE, DATA_2B},
265	{"G2 Interrupt Enable", 0x192, NI_660x_WRITE, DATA_2B},
266	{"G3 Interrupt Enable", 0x196, NI_660x_WRITE, DATA_2B},
267	{"G2 Counting Mode Register", 0x1B0, NI_660x_WRITE, DATA_2B},
268	{"G3 Counting Mode Register", 0x1B2, NI_660x_WRITE, DATA_2B},
269	{"G3 Second Gate Register", 0x1B6, NI_660x_WRITE, DATA_2B},
270	{"G2 Second Gate Register", 0x1B4, NI_660x_WRITE, DATA_2B},
271	{"G2 DMA Config Register", 0x1B8, NI_660x_WRITE, DATA_2B},
272	{"G2 DMA Status Register", 0x1B8, NI_660x_READ, DATA_2B},
273	{"G3 DMA Config Register", 0x1BA, NI_660x_WRITE, DATA_2B},
274	{"G3 DMA Status Register", 0x1BA, NI_660x_READ, DATA_2B},
275	{"32 bit Digital Input", 0x414, NI_660x_READ, DATA_4B},
276	{"32 bit Digital Output", 0x510, NI_660x_WRITE, DATA_4B},
277	{"Clock Config Register", 0x73C, NI_660x_WRITE, DATA_4B},
278	{"Global Interrupt Status Register", 0x754, NI_660x_READ, DATA_4B},
279	{"DMA Configuration Register", 0x76C, NI_660x_WRITE, DATA_4B},
280	{"Global Interrupt Config Register", 0x770, NI_660x_WRITE, DATA_4B},
281	{"IO Config Register 0-1", 0x77C, NI_660x_READ_WRITE, DATA_2B},
282	{"IO Config Register 2-3", 0x77E, NI_660x_READ_WRITE, DATA_2B},
283	{"IO Config Register 4-5", 0x780, NI_660x_READ_WRITE, DATA_2B},
284	{"IO Config Register 6-7", 0x782, NI_660x_READ_WRITE, DATA_2B},
285	{"IO Config Register 8-9", 0x784, NI_660x_READ_WRITE, DATA_2B},
286	{"IO Config Register 10-11", 0x786, NI_660x_READ_WRITE, DATA_2B},
287	{"IO Config Register 12-13", 0x788, NI_660x_READ_WRITE, DATA_2B},
288	{"IO Config Register 14-15", 0x78A, NI_660x_READ_WRITE, DATA_2B},
289	{"IO Config Register 16-17", 0x78C, NI_660x_READ_WRITE, DATA_2B},
290	{"IO Config Register 18-19", 0x78E, NI_660x_READ_WRITE, DATA_2B},
291	{"IO Config Register 20-21", 0x790, NI_660x_READ_WRITE, DATA_2B},
292	{"IO Config Register 22-23", 0x792, NI_660x_READ_WRITE, DATA_2B},
293	{"IO Config Register 24-25", 0x794, NI_660x_READ_WRITE, DATA_2B},
294	{"IO Config Register 26-27", 0x796, NI_660x_READ_WRITE, DATA_2B},
295	{"IO Config Register 28-29", 0x798, NI_660x_READ_WRITE, DATA_2B},
296	{"IO Config Register 30-31", 0x79A, NI_660x_READ_WRITE, DATA_2B},
297	{"IO Config Register 32-33", 0x79C, NI_660x_READ_WRITE, DATA_2B},
298	{"IO Config Register 34-35", 0x79E, NI_660x_READ_WRITE, DATA_2B},
299	{"IO Config Register 36-37", 0x7A0, NI_660x_READ_WRITE, DATA_2B},
300	{"IO Config Register 38-39", 0x7A2, NI_660x_READ_WRITE, DATA_2B}
301};
302
303// kind of ENABLE for the second counter
304enum clock_config_register_bits {
305	CounterSwap = 0x1 << 21
306};
307
308// ioconfigreg
309static inline unsigned ioconfig_bitshift(unsigned pfi_channel)
310{
311	if (pfi_channel % 2)
312		return 0;
313	else
314		return 8;
315}
316static inline unsigned pfi_output_select_mask(unsigned pfi_channel)
317{
318	return 0x3 << ioconfig_bitshift(pfi_channel);
319}
320static inline unsigned pfi_output_select_bits(unsigned pfi_channel,
321	unsigned output_select)
322{
323	return (output_select & 0x3) << ioconfig_bitshift(pfi_channel);
324}
325static inline unsigned pfi_input_select_mask(unsigned pfi_channel)
326{
327	return 0x7 << (4 + ioconfig_bitshift(pfi_channel));
328}
329static inline unsigned pfi_input_select_bits(unsigned pfi_channel,
330	unsigned input_select)
331{
332	return (input_select & 0x7) << (4 + ioconfig_bitshift(pfi_channel));
333}
334
335// dma configuration register bits
336static inline unsigned dma_select_mask(unsigned dma_channel)
337{
338	BUG_ON(dma_channel >= MAX_DMA_CHANNEL);
339	return 0x1f << (8 * dma_channel);
340}
341enum dma_selection {
342	dma_selection_none = 0x1f,
343};
344static inline unsigned dma_selection_counter(unsigned counter_index)
345{
346	BUG_ON(counter_index >= counters_per_chip);
347	return counter_index;
348}
349static inline unsigned dma_select_bits(unsigned dma_channel, unsigned selection)
350{
351	BUG_ON(dma_channel >= MAX_DMA_CHANNEL);
352	return (selection << (8 * dma_channel)) & dma_select_mask(dma_channel);
353}
354static inline unsigned dma_reset_bit(unsigned dma_channel)
355{
356	BUG_ON(dma_channel >= MAX_DMA_CHANNEL);
357	return 0x80 << (8 * dma_channel);
358}
359
360enum global_interrupt_status_register_bits {
361	Counter_0_Int_Bit = 0x100,
362	Counter_1_Int_Bit = 0x200,
363	Counter_2_Int_Bit = 0x400,
364	Counter_3_Int_Bit = 0x800,
365	Cascade_Int_Bit = 0x20000000,
366	Global_Int_Bit = 0x80000000
367};
368
369enum global_interrupt_config_register_bits {
370	Cascade_Int_Enable_Bit = 0x20000000,
371	Global_Int_Polarity_Bit = 0x40000000,
372	Global_Int_Enable_Bit = 0x80000000
373};
374
375// Offset of the GPCT chips from the base-adress of the card
376static const unsigned GPCT_OFFSET[2] = { 0x0, 0x800 };	/* First chip is at base-address +
377							   0x00, etc. */
378
379/* Board description*/
380typedef struct {
381	unsigned short dev_id;	/* `lspci` will show you this */
382	const char *name;
383	unsigned n_chips;	/* total number of TIO chips */
384} ni_660x_board;
385
386static const ni_660x_board ni_660x_boards[] = {
387	{
388	      dev_id:	0x2c60,
389	      name:	"PCI-6601",
390	      n_chips:	1,
391		},
392	{
393	      dev_id:	0x1310,
394	      name:	"PCI-6602",
395	      n_chips:	2,
396		},
397	{
398	      dev_id:	0x1360,
399	      name:	"PXI-6602",
400	      n_chips:	2,
401		},
402	{
403	      dev_id:	0x2cc0,
404	      name:	"PXI-6608",
405	      n_chips:	2,
406		},
407};
408
409#define NI_660X_MAX_NUM_CHIPS 2
410#define NI_660X_MAX_NUM_COUNTERS (NI_660X_MAX_NUM_CHIPS * counters_per_chip)
411
412static DEFINE_PCI_DEVICE_TABLE(ni_660x_pci_table) = {
413	{PCI_VENDOR_ID_NATINST, 0x2c60, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
414	{PCI_VENDOR_ID_NATINST, 0x1310, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
415	{PCI_VENDOR_ID_NATINST, 0x1360, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
416	{PCI_VENDOR_ID_NATINST, 0x2cc0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
417	{0}
418};
419
420MODULE_DEVICE_TABLE(pci, ni_660x_pci_table);
421
422typedef struct {
423	struct mite_struct *mite;
424	struct ni_gpct_device *counter_dev;
425	uint64_t pfi_direction_bits;
426	struct mite_dma_descriptor_ring
427	*mite_rings[NI_660X_MAX_NUM_CHIPS][counters_per_chip];
428	spinlock_t mite_channel_lock;
429	unsigned dma_configuration_soft_copies[NI_660X_MAX_NUM_CHIPS];
430	spinlock_t soft_reg_copy_lock;
431	unsigned short pfi_output_selects[NUM_PFI_CHANNELS];
432} ni_660x_private;
433
434static inline ni_660x_private *private(comedi_device * dev)
435{
436	return dev->private;
437}
438
439/* initialized in ni_660x_find_device() */
440static inline const ni_660x_board *board(comedi_device * dev)
441{
442	return dev->board_ptr;
443}
444
445#define n_ni_660x_boards (sizeof(ni_660x_boards)/sizeof(ni_660x_boards[0]))
446
447static int ni_660x_attach(comedi_device * dev, comedi_devconfig * it);
448static int ni_660x_detach(comedi_device * dev);
449static void init_tio_chip(comedi_device * dev, int chipset);
450static void ni_660x_select_pfi_output(comedi_device * dev, unsigned pfi_channel,
451	unsigned output_select);
452
453static comedi_driver driver_ni_660x = {
454      driver_name:"ni_660x",
455      module:THIS_MODULE,
456      attach:ni_660x_attach,
457      detach:ni_660x_detach,
458};
459
460COMEDI_PCI_INITCLEANUP(driver_ni_660x, ni_660x_pci_table);
461
462static int ni_660x_find_device(comedi_device * dev, int bus, int slot);
463static int ni_660x_set_pfi_routing(comedi_device * dev, unsigned chan,
464	unsigned source);
465
466/* Possible instructions for a GPCT */
467static int ni_660x_GPCT_rinsn(comedi_device * dev,
468	comedi_subdevice * s, comedi_insn * insn, unsigned int * data);
469static int ni_660x_GPCT_insn_config(comedi_device * dev,
470	comedi_subdevice * s, comedi_insn * insn, unsigned int * data);
471static int ni_660x_GPCT_winsn(comedi_device * dev,
472	comedi_subdevice * s, comedi_insn * insn, unsigned int * data);
473
474/* Possible instructions for Digital IO */
475static int ni_660x_dio_insn_config(comedi_device * dev,
476	comedi_subdevice * s, comedi_insn * insn, unsigned int * data);
477static int ni_660x_dio_insn_bits(comedi_device * dev,
478	comedi_subdevice * s, comedi_insn * insn, unsigned int * data);
479
480static inline unsigned ni_660x_num_counters(comedi_device * dev)
481{
482	return board(dev)->n_chips * counters_per_chip;
483}
484
485static NI_660x_Register ni_gpct_to_660x_register(enum ni_gpct_register reg)
486{
487	NI_660x_Register ni_660x_register;
488	switch (reg) {
489	case NITIO_G0_Autoincrement_Reg:
490		ni_660x_register = G0AutoincrementRegister;
491		break;
492	case NITIO_G1_Autoincrement_Reg:
493		ni_660x_register = G1AutoincrementRegister;
494		break;
495	case NITIO_G2_Autoincrement_Reg:
496		ni_660x_register = G2AutoincrementRegister;
497		break;
498	case NITIO_G3_Autoincrement_Reg:
499		ni_660x_register = G3AutoincrementRegister;
500		break;
501	case NITIO_G0_Command_Reg:
502		ni_660x_register = G0CommandRegister;
503		break;
504	case NITIO_G1_Command_Reg:
505		ni_660x_register = G1CommandRegister;
506		break;
507	case NITIO_G2_Command_Reg:
508		ni_660x_register = G2CommandRegister;
509		break;
510	case NITIO_G3_Command_Reg:
511		ni_660x_register = G3CommandRegister;
512		break;
513	case NITIO_G0_HW_Save_Reg:
514		ni_660x_register = G0HWSaveRegister;
515		break;
516	case NITIO_G1_HW_Save_Reg:
517		ni_660x_register = G1HWSaveRegister;
518		break;
519	case NITIO_G2_HW_Save_Reg:
520		ni_660x_register = G2HWSaveRegister;
521		break;
522	case NITIO_G3_HW_Save_Reg:
523		ni_660x_register = G3HWSaveRegister;
524		break;
525	case NITIO_G0_SW_Save_Reg:
526		ni_660x_register = G0SWSaveRegister;
527		break;
528	case NITIO_G1_SW_Save_Reg:
529		ni_660x_register = G1SWSaveRegister;
530		break;
531	case NITIO_G2_SW_Save_Reg:
532		ni_660x_register = G2SWSaveRegister;
533		break;
534	case NITIO_G3_SW_Save_Reg:
535		ni_660x_register = G3SWSaveRegister;
536		break;
537	case NITIO_G0_Mode_Reg:
538		ni_660x_register = G0ModeRegister;
539		break;
540	case NITIO_G1_Mode_Reg:
541		ni_660x_register = G1ModeRegister;
542		break;
543	case NITIO_G2_Mode_Reg:
544		ni_660x_register = G2ModeRegister;
545		break;
546	case NITIO_G3_Mode_Reg:
547		ni_660x_register = G3ModeRegister;
548		break;
549	case NITIO_G0_LoadA_Reg:
550		ni_660x_register = G0LoadARegister;
551		break;
552	case NITIO_G1_LoadA_Reg:
553		ni_660x_register = G1LoadARegister;
554		break;
555	case NITIO_G2_LoadA_Reg:
556		ni_660x_register = G2LoadARegister;
557		break;
558	case NITIO_G3_LoadA_Reg:
559		ni_660x_register = G3LoadARegister;
560		break;
561	case NITIO_G0_LoadB_Reg:
562		ni_660x_register = G0LoadBRegister;
563		break;
564	case NITIO_G1_LoadB_Reg:
565		ni_660x_register = G1LoadBRegister;
566		break;
567	case NITIO_G2_LoadB_Reg:
568		ni_660x_register = G2LoadBRegister;
569		break;
570	case NITIO_G3_LoadB_Reg:
571		ni_660x_register = G3LoadBRegister;
572		break;
573	case NITIO_G0_Input_Select_Reg:
574		ni_660x_register = G0InputSelectRegister;
575		break;
576	case NITIO_G1_Input_Select_Reg:
577		ni_660x_register = G1InputSelectRegister;
578		break;
579	case NITIO_G2_Input_Select_Reg:
580		ni_660x_register = G2InputSelectRegister;
581		break;
582	case NITIO_G3_Input_Select_Reg:
583		ni_660x_register = G3InputSelectRegister;
584		break;
585	case NITIO_G01_Status_Reg:
586		ni_660x_register = G01StatusRegister;
587		break;
588	case NITIO_G23_Status_Reg:
589		ni_660x_register = G23StatusRegister;
590		break;
591	case NITIO_G01_Joint_Reset_Reg:
592		ni_660x_register = G01JointResetRegister;
593		break;
594	case NITIO_G23_Joint_Reset_Reg:
595		ni_660x_register = G23JointResetRegister;
596		break;
597	case NITIO_G01_Joint_Status1_Reg:
598		ni_660x_register = G01JointStatus1Register;
599		break;
600	case NITIO_G23_Joint_Status1_Reg:
601		ni_660x_register = G23JointStatus1Register;
602		break;
603	case NITIO_G01_Joint_Status2_Reg:
604		ni_660x_register = G01JointStatus2Register;
605		break;
606	case NITIO_G23_Joint_Status2_Reg:
607		ni_660x_register = G23JointStatus2Register;
608		break;
609	case NITIO_G0_Counting_Mode_Reg:
610		ni_660x_register = G0CountingModeRegister;
611		break;
612	case NITIO_G1_Counting_Mode_Reg:
613		ni_660x_register = G1CountingModeRegister;
614		break;
615	case NITIO_G2_Counting_Mode_Reg:
616		ni_660x_register = G2CountingModeRegister;
617		break;
618	case NITIO_G3_Counting_Mode_Reg:
619		ni_660x_register = G3CountingModeRegister;
620		break;
621	case NITIO_G0_Second_Gate_Reg:
622		ni_660x_register = G0SecondGateRegister;
623		break;
624	case NITIO_G1_Second_Gate_Reg:
625		ni_660x_register = G1SecondGateRegister;
626		break;
627	case NITIO_G2_Second_Gate_Reg:
628		ni_660x_register = G2SecondGateRegister;
629		break;
630	case NITIO_G3_Second_Gate_Reg:
631		ni_660x_register = G3SecondGateRegister;
632		break;
633	case NITIO_G0_DMA_Config_Reg:
634		ni_660x_register = G0DMAConfigRegister;
635		break;
636	case NITIO_G0_DMA_Status_Reg:
637		ni_660x_register = G0DMAStatusRegister;
638		break;
639	case NITIO_G1_DMA_Config_Reg:
640		ni_660x_register = G1DMAConfigRegister;
641		break;
642	case NITIO_G1_DMA_Status_Reg:
643		ni_660x_register = G1DMAStatusRegister;
644		break;
645	case NITIO_G2_DMA_Config_Reg:
646		ni_660x_register = G2DMAConfigRegister;
647		break;
648	case NITIO_G2_DMA_Status_Reg:
649		ni_660x_register = G2DMAStatusRegister;
650		break;
651	case NITIO_G3_DMA_Config_Reg:
652		ni_660x_register = G3DMAConfigRegister;
653		break;
654	case NITIO_G3_DMA_Status_Reg:
655		ni_660x_register = G3DMAStatusRegister;
656		break;
657	case NITIO_G0_Interrupt_Acknowledge_Reg:
658		ni_660x_register = G0InterruptAcknowledge;
659		break;
660	case NITIO_G1_Interrupt_Acknowledge_Reg:
661		ni_660x_register = G1InterruptAcknowledge;
662		break;
663	case NITIO_G2_Interrupt_Acknowledge_Reg:
664		ni_660x_register = G2InterruptAcknowledge;
665		break;
666	case NITIO_G3_Interrupt_Acknowledge_Reg:
667		ni_660x_register = G3InterruptAcknowledge;
668		break;
669	case NITIO_G0_Status_Reg:
670		ni_660x_register = G0StatusRegister;
671		break;
672	case NITIO_G1_Status_Reg:
673		ni_660x_register = G0StatusRegister;
674		break;
675	case NITIO_G2_Status_Reg:
676		ni_660x_register = G0StatusRegister;
677		break;
678	case NITIO_G3_Status_Reg:
679		ni_660x_register = G0StatusRegister;
680		break;
681	case NITIO_G0_Interrupt_Enable_Reg:
682		ni_660x_register = G0InterruptEnable;
683		break;
684	case NITIO_G1_Interrupt_Enable_Reg:
685		ni_660x_register = G1InterruptEnable;
686		break;
687	case NITIO_G2_Interrupt_Enable_Reg:
688		ni_660x_register = G2InterruptEnable;
689		break;
690	case NITIO_G3_Interrupt_Enable_Reg:
691		ni_660x_register = G3InterruptEnable;
692		break;
693	default:
694		rt_printk("%s: unhandled register 0x%x in switch.\n",
695			__FUNCTION__, reg);
696		BUG();
697		return 0;
698		break;
699	}
700	return ni_660x_register;
701}
702
703static inline void ni_660x_write_register(comedi_device * dev,
704	unsigned chip_index, unsigned bits, NI_660x_Register reg)
705{
706	void *const write_address =
707		private(dev)->mite->daq_io_addr + GPCT_OFFSET[chip_index] +
708		registerData[reg].offset;
709
710	switch (registerData[reg].size) {
711	case DATA_2B:
712		writew(bits, write_address);
713		break;
714	case DATA_4B:
715		writel(bits, write_address);
716		break;
717	default:
718		rt_printk("%s: %s: bug! unhandled case (reg=0x%x) in switch.\n",
719			__FILE__, __FUNCTION__, reg);
720		BUG();
721		break;
722	}
723}
724
725static inline unsigned ni_660x_read_register(comedi_device * dev,
726	unsigned chip_index, NI_660x_Register reg)
727{
728	void *const read_address =
729		private(dev)->mite->daq_io_addr + GPCT_OFFSET[chip_index] +
730		registerData[reg].offset;
731
732	switch (registerData[reg].size) {
733	case DATA_2B:
734		return readw(read_address);
735		break;
736	case DATA_4B:
737		return readl(read_address);
738		break;
739	default:
740		rt_printk("%s: %s: bug! unhandled case (reg=0x%x) in switch.\n",
741			__FILE__, __FUNCTION__, reg);
742		BUG();
743		break;
744	}
745	return 0;
746}
747
748static void ni_gpct_write_register(struct ni_gpct *counter, unsigned bits,
749	enum ni_gpct_register reg)
750{
751	comedi_device *dev = counter->counter_dev->dev;
752	NI_660x_Register ni_660x_register = ni_gpct_to_660x_register(reg);
753	ni_660x_write_register(dev, counter->chip_index, bits,
754		ni_660x_register);
755}
756
757static unsigned ni_gpct_read_register(struct ni_gpct *counter,
758	enum ni_gpct_register reg)
759{
760	comedi_device *dev = counter->counter_dev->dev;
761	NI_660x_Register ni_660x_register = ni_gpct_to_660x_register(reg);
762	return ni_660x_read_register(dev, counter->chip_index,
763		ni_660x_register);
764}
765
766static inline struct mite_dma_descriptor_ring *mite_ring(ni_660x_private * priv,
767	struct ni_gpct *counter)
768{
769	return priv->mite_rings[counter->chip_index][counter->counter_index];
770}
771
772static inline void ni_660x_set_dma_channel(comedi_device * dev,
773	unsigned mite_channel, struct ni_gpct *counter)
774{
775	unsigned long flags;
776	comedi_spin_lock_irqsave(&private(dev)->soft_reg_copy_lock, flags);
777	private(dev)->dma_configuration_soft_copies[counter->chip_index] &=
778		~dma_select_mask(mite_channel);
779	private(dev)->dma_configuration_soft_copies[counter->chip_index] |=
780		dma_select_bits(mite_channel,
781		dma_selection_counter(counter->counter_index));
782	ni_660x_write_register(dev, counter->chip_index,
783		private(dev)->dma_configuration_soft_copies[counter->
784			chip_index] | dma_reset_bit(mite_channel),
785		DMAConfigRegister);
786	mmiowb();
787	comedi_spin_unlock_irqrestore(&private(dev)->soft_reg_copy_lock, flags);
788}
789
790static inline void ni_660x_unset_dma_channel(comedi_device * dev,
791	unsigned mite_channel, struct ni_gpct *counter)
792{
793	unsigned long flags;
794	comedi_spin_lock_irqsave(&private(dev)->soft_reg_copy_lock, flags);
795	private(dev)->dma_configuration_soft_copies[counter->chip_index] &=
796		~dma_select_mask(mite_channel);
797	private(dev)->dma_configuration_soft_copies[counter->chip_index] |=
798		dma_select_bits(mite_channel, dma_selection_none);
799	ni_660x_write_register(dev, counter->chip_index,
800		private(dev)->dma_configuration_soft_copies[counter->
801			chip_index], DMAConfigRegister);
802	mmiowb();
803	comedi_spin_unlock_irqrestore(&private(dev)->soft_reg_copy_lock, flags);
804}
805
806static int ni_660x_request_mite_channel(comedi_device * dev,
807	struct ni_gpct *counter, enum comedi_io_direction direction)
808{
809	unsigned long flags;
810	struct mite_channel *mite_chan;
811
812	comedi_spin_lock_irqsave(&private(dev)->mite_channel_lock, flags);
813	BUG_ON(counter->mite_chan);
814	mite_chan =
815		mite_request_channel(private(dev)->mite, mite_ring(private(dev),
816			counter));
817	if (mite_chan == NULL) {
818		comedi_spin_unlock_irqrestore(&private(dev)->mite_channel_lock,
819			flags);
820		comedi_error(dev,
821			"failed to reserve mite dma channel for counter.");
822		return -EBUSY;
823	}
824	mite_chan->dir = direction;
825	ni_tio_set_mite_channel(counter, mite_chan);
826	ni_660x_set_dma_channel(dev, mite_chan->channel, counter);
827	comedi_spin_unlock_irqrestore(&private(dev)->mite_channel_lock, flags);
828	return 0;
829}
830
831void ni_660x_release_mite_channel(comedi_device * dev, struct ni_gpct *counter)
832{
833	unsigned long flags;
834
835	comedi_spin_lock_irqsave(&private(dev)->mite_channel_lock, flags);
836	if (counter->mite_chan) {
837		struct mite_channel *mite_chan = counter->mite_chan;
838
839		ni_660x_unset_dma_channel(dev, mite_chan->channel, counter);
840		ni_tio_set_mite_channel(counter, NULL);
841		mite_release_channel(mite_chan);
842	}
843	comedi_spin_unlock_irqrestore(&private(dev)->mite_channel_lock, flags);
844}
845
846static int ni_660x_cmd(comedi_device * dev, comedi_subdevice * s)
847{
848	int retval;
849
850	struct ni_gpct *counter = subdev_to_counter(s);
851//      const comedi_cmd *cmd = &s->async->cmd;
852
853	retval = ni_660x_request_mite_channel(dev, counter, COMEDI_INPUT);
854	if (retval) {
855		comedi_error(dev,
856			"no dma channel available for use by counter");
857		return retval;
858	}
859	ni_tio_acknowledge_and_confirm(counter, NULL, NULL, NULL, NULL);
860	retval = ni_tio_cmd(counter, s->async);
861
862	return retval;
863}
864
865static int ni_660x_cmdtest(comedi_device * dev, comedi_subdevice * s,
866	comedi_cmd * cmd)
867{
868	struct ni_gpct *counter = subdev_to_counter(s);
869
870	return ni_tio_cmdtest(counter, cmd);
871}
872
873static int ni_660x_cancel(comedi_device * dev, comedi_subdevice * s)
874{
875	struct ni_gpct *counter = subdev_to_counter(s);
876	int retval;
877
878	retval = ni_tio_cancel(counter);
879	ni_660x_release_mite_channel(dev, counter);
880	return retval;
881}
882
883static void set_tio_counterswap(comedi_device * dev, int chipset)
884{
885	/* See P. 3.5 of the Register-Level Programming manual.  The
886	   CounterSwap bit has to be set on the second chip, otherwise
887	   it will try to use the same pins as the first chip.
888	 */
889	if (chipset)
890		ni_660x_write_register(dev, chipset, CounterSwap,
891			ClockConfigRegister);
892	else
893		ni_660x_write_register(dev, chipset, 0, ClockConfigRegister);
894}
895
896static void ni_660x_handle_gpct_interrupt(comedi_device * dev,
897	comedi_subdevice * s)
898{
899	ni_tio_handle_interrupt(subdev_to_counter(s), s);
900	if (s->async->events) {
901		if (s->async->
902			events & (COMEDI_CB_EOA | COMEDI_CB_ERROR |
903				COMEDI_CB_OVERFLOW)) {
904			ni_660x_cancel(dev, s);
905		}
906		comedi_event(dev, s);
907	}
908}
909
910static irqreturn_t ni_660x_interrupt(int irq, void *d PT_REGS_ARG)
911{
912	comedi_device *dev = d;
913	comedi_subdevice *s;
914	unsigned i;
915
916	if (dev->attached == 0)
917		return IRQ_NONE;
918	smp_mb();
919	for (i = 0; i < ni_660x_num_counters(dev); ++i) {
920		s = dev->subdevices + NI_660X_GPCT_SUBDEV(i);
921		ni_660x_handle_gpct_interrupt(dev, s);
922	}
923	return IRQ_HANDLED;
924}
925
926static int ni_660x_buf_change(comedi_device * dev, comedi_subdevice * s,
927	unsigned long new_size)
928{
929	int ret;
930
931	ret = mite_buf_change(mite_ring(private(dev), subdev_to_counter(s)),
932		s->async);
933	if (ret < 0)
934		return ret;
935
936	return 0;
937}
938
939static int ni_660x_allocate_private(comedi_device * dev)
940{
941	int retval;
942	unsigned i;
943
944	if ((retval = alloc_private(dev, sizeof(ni_660x_private))) < 0)
945		return retval;
946	spin_lock_init(&private(dev)->mite_channel_lock);
947	spin_lock_init(&private(dev)->soft_reg_copy_lock);
948	for (i = 0; i < NUM_PFI_CHANNELS; ++i) {
949		private(dev)->pfi_output_selects[i] = pfi_output_select_counter;
950	}
951	return 0;
952}
953
954static int ni_660x_alloc_mite_rings(comedi_device * dev)
955{
956	unsigned i;
957	unsigned j;
958
959	for (i = 0; i < board(dev)->n_chips; ++i) {
960		for (j = 0; j < counters_per_chip; ++j) {
961			private(dev)->mite_rings[i][j] =
962				mite_alloc_ring(private(dev)->mite);
963			if (private(dev)->mite_rings[i][j] == NULL) {
964				return -ENOMEM;
965			}
966		}
967	}
968	return 0;
969}
970
971static void ni_660x_free_mite_rings(comedi_device * dev)
972{
973	unsigned i;
974	unsigned j;
975
976	for (i = 0; i < board(dev)->n_chips; ++i) {
977		for (j = 0; j < counters_per_chip; ++j) {
978			mite_free_ring(private(dev)->mite_rings[i][j]);
979		}
980	}
981}
982
983static int ni_660x_attach(comedi_device * dev, comedi_devconfig * it)
984{
985	comedi_subdevice *s;
986	int ret;
987	unsigned i;
988	unsigned global_interrupt_config_bits;
989
990	printk("comedi%d: ni_660x: ", dev->minor);
991
992	ret = ni_660x_allocate_private(dev);
993	if (ret < 0)
994		return ret;
995	ret = ni_660x_find_device(dev, it->options[0], it->options[1]);
996	if (ret < 0)
997		return ret;
998
999	dev->board_name = board(dev)->name;
1000
1001	ret = mite_setup2(private(dev)->mite, 1);
1002	if (ret < 0) {
1003		printk("error setting up mite\n");
1004		return ret;
1005	}
1006	comedi_set_hw_dev(dev, &private(dev)->mite->pcidev->dev);
1007	ret = ni_660x_alloc_mite_rings(dev);
1008	if (ret < 0)
1009		return ret;
1010
1011	printk(" %s ", dev->board_name);
1012
1013	dev->n_subdevices = 2 + NI_660X_MAX_NUM_COUNTERS;
1014
1015	if (alloc_subdevices(dev, dev->n_subdevices) < 0)
1016		return -ENOMEM;
1017
1018	s = dev->subdevices + 0;
1019	/* Old GENERAL-PURPOSE COUNTER/TIME (GPCT) subdevice, no longer used */
1020	s->type = COMEDI_SUBD_UNUSED;
1021
1022	s = dev->subdevices + NI_660X_DIO_SUBDEV;
1023	/* DIGITAL I/O SUBDEVICE */
1024	s->type = COMEDI_SUBD_DIO;
1025	s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
1026	s->n_chan = NUM_PFI_CHANNELS;
1027	s->maxdata = 1;
1028	s->range_table = &range_digital;
1029	s->insn_bits = ni_660x_dio_insn_bits;
1030	s->insn_config = ni_660x_dio_insn_config;
1031	s->io_bits = 0;		/* all bits default to input */
1032	// we use the ioconfig registers to control dio direction, so zero output enables in stc dio control reg
1033	ni_660x_write_register(dev, 0, 0, STCDIOControl);
1034
1035	private(dev)->counter_dev = ni_gpct_device_construct(dev,
1036		&ni_gpct_write_register, &ni_gpct_read_register,
1037		ni_gpct_variant_660x, ni_660x_num_counters(dev));
1038	if (private(dev)->counter_dev == NULL)
1039		return -ENOMEM;
1040	for (i = 0; i < NI_660X_MAX_NUM_COUNTERS; ++i) {
1041		s = dev->subdevices + NI_660X_GPCT_SUBDEV(i);
1042		if (i < ni_660x_num_counters(dev)) {
1043			s->type = COMEDI_SUBD_COUNTER;
1044			s->subdev_flags =
1045				SDF_READABLE | SDF_WRITABLE | SDF_LSAMPL |
1046				SDF_CMD_READ /* | SDF_CMD_WRITE */ ;
1047			s->n_chan = 3;
1048			s->maxdata = 0xffffffff;
1049			s->insn_read = ni_660x_GPCT_rinsn;
1050			s->insn_write = ni_660x_GPCT_winsn;
1051			s->insn_config = ni_660x_GPCT_insn_config;
1052			s->do_cmd = &ni_660x_cmd;
1053			s->len_chanlist = 1;
1054			s->do_cmdtest = &ni_660x_cmdtest;
1055			s->cancel = &ni_660x_cancel;
1056			s->async_dma_dir = DMA_BIDIRECTIONAL;
1057			s->buf_change = &ni_660x_buf_change;
1058			s->private = &private(dev)->counter_dev->counters[i];
1059
1060			private(dev)->counter_dev->counters[i].chip_index =
1061				i / counters_per_chip;
1062			private(dev)->counter_dev->counters[i].counter_index =
1063				i % counters_per_chip;
1064		} else {
1065			s->type = COMEDI_SUBD_UNUSED;
1066		}
1067	}
1068	for (i = 0; i < board(dev)->n_chips; ++i) {
1069		init_tio_chip(dev, i);
1070	}
1071	for (i = 0; i < ni_660x_num_counters(dev); ++i) {
1072		ni_tio_init_counter(&private(dev)->counter_dev->counters[i]);
1073	}
1074	for (i = 0; i < NUM_PFI_CHANNELS; ++i) {
1075		if (i < min_counter_pfi_chan)
1076			ni_660x_set_pfi_routing(dev, i, pfi_output_select_do);
1077		else
1078			ni_660x_set_pfi_routing(dev, i,
1079				pfi_output_select_counter);
1080		ni_660x_select_pfi_output(dev, i, pfi_output_select_high_Z);
1081	}
1082	/* to be safe, set counterswap bits on tio chips after all the counter
1083	   outputs have been set to high impedance mode */
1084	for (i = 0; i < board(dev)->n_chips; ++i) {
1085		set_tio_counterswap(dev, i);
1086	}
1087	if ((ret = comedi_request_irq(mite_irq(private(dev)->mite),
1088				&ni_660x_interrupt, IRQF_SHARED, "ni_660x",
1089				dev)) < 0) {
1090		printk(" irq not available\n");
1091		return ret;
1092	}
1093	dev->irq = mite_irq(private(dev)->mite);
1094	global_interrupt_config_bits = Global_Int_Enable_Bit;
1095	if (board(dev)->n_chips > 1)
1096		global_interrupt_config_bits |= Cascade_Int_Enable_Bit;
1097	ni_660x_write_register(dev, 0, global_interrupt_config_bits,
1098		GlobalInterruptConfigRegister);
1099	printk("attached\n");
1100	return 0;
1101}
1102
1103static int ni_660x_detach(comedi_device * dev)
1104{
1105	printk("comedi%d: ni_660x: remove\n", dev->minor);
1106
1107	/* Free irq */
1108	if (dev->irq)
1109		comedi_free_irq(dev->irq, dev);
1110
1111	if (dev->private) {
1112		if (private(dev)->counter_dev)
1113			ni_gpct_device_destroy(private(dev)->counter_dev);
1114		if (private(dev)->mite) {
1115			ni_660x_free_mite_rings(dev);
1116			mite_unsetup(private(dev)->mite);
1117		}
1118	}
1119	return 0;
1120}
1121
1122static int
1123ni_660x_GPCT_rinsn(comedi_device * dev, comedi_subdevice * s,
1124	comedi_insn * insn, unsigned int * data)
1125{
1126	return ni_tio_rinsn(subdev_to_counter(s), insn, data);
1127}
1128
1129static void init_tio_chip(comedi_device * dev, int chipset)
1130{
1131	unsigned i;
1132
1133	// init dma configuration register
1134	private(dev)->dma_configuration_soft_copies[chipset] = 0;
1135	for (i = 0; i < MAX_DMA_CHANNEL; ++i) {
1136		private(dev)->dma_configuration_soft_copies[chipset] |=
1137			dma_select_bits(i,
1138			dma_selection_none) & dma_select_mask(i);
1139	}
1140	ni_660x_write_register(dev, chipset,
1141		private(dev)->dma_configuration_soft_copies[chipset],
1142		DMAConfigRegister);
1143	for(i = 0; i < NUM_PFI_CHANNELS; ++i)
1144	{
1145		ni_660x_write_register(dev, chipset, 0, IOConfigReg(i));
1146	}
1147}
1148
1149static int
1150ni_660x_GPCT_insn_config(comedi_device * dev, comedi_subdevice * s,
1151	comedi_insn * insn, unsigned int * data)
1152{
1153	return ni_tio_insn_config(subdev_to_counter(s), insn, data);
1154}
1155
1156static int ni_660x_GPCT_winsn(comedi_device * dev,
1157	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
1158{
1159	return ni_tio_winsn(subdev_to_counter(s), insn, data);
1160}
1161
1162static int ni_660x_find_device(comedi_device * dev, int bus, int slot)
1163{
1164	struct mite_struct *mite;
1165	int i;
1166
1167	for (mite = mite_devices; mite; mite = mite->next) {
1168		if (mite->used)
1169			continue;
1170		if (bus || slot) {
1171			if (bus != mite->pcidev->bus->number ||
1172				slot != PCI_SLOT(mite->pcidev->devfn))
1173				continue;
1174		}
1175
1176		for (i = 0; i < n_ni_660x_boards; i++) {
1177			if (mite_device_id(mite) == ni_660x_boards[i].dev_id) {
1178				dev->board_ptr = ni_660x_boards + i;
1179				private(dev)->mite = mite;
1180				return 0;
1181			}
1182		}
1183	}
1184	printk("no device found\n");
1185	mite_list_devices();
1186	return -EIO;
1187}
1188
1189static int ni_660x_dio_insn_bits(comedi_device * dev,
1190	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
1191{
1192	unsigned base_bitfield_channel = CR_CHAN(insn->chanspec);
1193
1194	// Check if we have to write some bits
1195	if (data[0]) {
1196		s->state &= ~(data[0] << base_bitfield_channel);
1197		s->state |= (data[0] & data[1]) << base_bitfield_channel;
1198		/* Write out the new digital output lines */
1199		ni_660x_write_register(dev, 0, s->state, DIO32Output);
1200	}
1201	/* on return, data[1] contains the value of the digital
1202	 * input and output lines. */
1203	data[1] =
1204		(ni_660x_read_register(dev, 0,
1205			DIO32Input) >> base_bitfield_channel);
1206	return 2;
1207}
1208
1209static void ni_660x_select_pfi_output(comedi_device * dev, unsigned pfi_channel,
1210	unsigned output_select)
1211{
1212	static const unsigned counter_4_7_first_pfi = 8;
1213	static const unsigned counter_4_7_last_pfi = 23;
1214	unsigned active_chipset = 0;
1215	unsigned idle_chipset = 0;
1216	unsigned active_bits;
1217	unsigned idle_bits;
1218
1219	if(board(dev)->n_chips > 1) {
1220		if(output_select == pfi_output_select_counter &&
1221			pfi_channel >= counter_4_7_first_pfi &&
1222			pfi_channel <= counter_4_7_last_pfi) {
1223			active_chipset = 1;
1224			idle_chipset = 0;
1225		}else {
1226			active_chipset = 0;
1227			idle_chipset = 1;
1228		}
1229	}
1230
1231	if(idle_chipset != active_chipset) {
1232		idle_bits = ni_660x_read_register(dev, idle_chipset, IOConfigReg(pfi_channel));
1233		idle_bits &= ~pfi_output_select_mask(pfi_channel);
1234		idle_bits |= pfi_output_select_bits(pfi_channel, pfi_output_select_high_Z);
1235		ni_660x_write_register(dev, idle_chipset, idle_bits, IOConfigReg(pfi_channel));
1236	}
1237
1238	active_bits = ni_660x_read_register(dev, active_chipset, IOConfigReg(pfi_channel));
1239	active_bits &= ~pfi_output_select_mask(pfi_channel);
1240	active_bits |= pfi_output_select_bits(pfi_channel, output_select);
1241	ni_660x_write_register(dev, active_chipset, active_bits, IOConfigReg(pfi_channel));
1242}
1243
1244static int ni_660x_set_pfi_routing(comedi_device * dev, unsigned chan,
1245	unsigned source)
1246{
1247	if (source > num_pfi_output_selects)
1248		return -EINVAL;
1249	if (source == pfi_output_select_high_Z)
1250		return -EINVAL;
1251	if (chan < min_counter_pfi_chan) {
1252		if (source == pfi_output_select_counter)
1253			return -EINVAL;
1254	} else if (chan > max_dio_pfi_chan) {
1255		if (source == pfi_output_select_do)
1256			return -EINVAL;
1257	}
1258	BUG_ON(chan >= NUM_PFI_CHANNELS);
1259
1260	private(dev)->pfi_output_selects[chan] = source;
1261	if (private(dev)->pfi_direction_bits & (((uint64_t) 1) << chan))
1262		ni_660x_select_pfi_output(dev, chan,
1263			private(dev)->pfi_output_selects[chan]);
1264	return 0;
1265}
1266
1267static unsigned ni_660x_get_pfi_routing(comedi_device * dev, unsigned chan)
1268{
1269	BUG_ON(chan >= NUM_PFI_CHANNELS);
1270	return private(dev)->pfi_output_selects[chan];
1271}
1272
1273static void ni660x_config_filter(comedi_device * dev, unsigned pfi_channel,
1274	enum ni_gpct_filter_select filter)
1275{
1276	unsigned bits = ni_660x_read_register(dev, 0, IOConfigReg(pfi_channel));
1277	bits &= ~pfi_input_select_mask(pfi_channel);
1278	bits |= pfi_input_select_bits(pfi_channel, filter);
1279	ni_660x_write_register(dev, 0, bits, IOConfigReg(pfi_channel));
1280}
1281
1282static int ni_660x_dio_insn_config(comedi_device * dev,
1283	comedi_subdevice * s, comedi_insn * insn, unsigned int * data)
1284{
1285	int chan = CR_CHAN(insn->chanspec);
1286
1287	/* The input or output configuration of each digital line is
1288	 * configured by a special insn_config instruction.  chanspec
1289	 * contains the channel to be changed, and data[0] contains the
1290	 * value COMEDI_INPUT or COMEDI_OUTPUT. */
1291
1292	switch (data[0]) {
1293	case INSN_CONFIG_DIO_OUTPUT:
1294		private(dev)->pfi_direction_bits |= ((uint64_t) 1) << chan;
1295		ni_660x_select_pfi_output(dev, chan,
1296			private(dev)->pfi_output_selects[chan]);
1297		break;
1298	case INSN_CONFIG_DIO_INPUT:
1299		private(dev)->pfi_direction_bits &= ~(((uint64_t) 1) << chan);
1300		ni_660x_select_pfi_output(dev, chan, pfi_output_select_high_Z);
1301		break;
1302	case INSN_CONFIG_DIO_QUERY:
1303		data[1] =
1304			(private(dev)->
1305			pfi_direction_bits & (((uint64_t) 1) << chan)) ?
1306			COMEDI_OUTPUT : COMEDI_INPUT;
1307		return 0;
1308	case INSN_CONFIG_SET_ROUTING:
1309		return ni_660x_set_pfi_routing(dev, chan, data[1]);
1310		break;
1311	case INSN_CONFIG_GET_ROUTING:
1312		data[1] = ni_660x_get_pfi_routing(dev, chan);
1313		break;
1314	case INSN_CONFIG_FILTER:
1315		ni660x_config_filter(dev, chan, data[1]);
1316		break;
1317	default:
1318		return -EINVAL;
1319		break;
1320	};
1321	return 0;
1322}
1323