Made some changes to async buffer, to better accommodate output dma
[comedi.git] / comedi / drivers / ni_660x.c
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 /*
21 Driver: ni_660x.o
22 Description: National Instruments 660x counter/timer boards
23 Devices:
24 [National Instruments] PCI-6601 (ni_660x), PCI-6602
25 Author: J.P. Mellor <jpmellor@rose-hulman.edu>,
26         Herman.Bruyninckx@mech.kuleuven.ac.be,
27         Wim.Meeussen@mech.kuleuven.ac.be,
28         Klaas.Gadeyne@mech.kuleuven.ac.be,
29         Frank Mori Hess <fmhess@users.sourceforge.net>
30 Updated: Sun Nov 16 18:46:11 UTC 2003
31 Status: experimental
32
33 Encoders work, but only with instructions, commands are not
34 supported yet.  PulseGeneration (both single pulse and pulse train)
35 works. DIO is experimental (8 channels only). Interrupts do not
36 work.
37
38 References:
39 DAQ 660x Register-Level Programmer Manual  (NI 370505A-01)
40 DAQ 6601/6602 User Manual (NI 322137B-01)
41
42 Things to do:
43 - Add DMA support (see mite.c and ni_pcidio.c for examples)
44 - Add commands (copy from ni_pcidio.c ?)
45 - Add interrupts
46 */
47
48 #include <linux/comedidev.h>
49 #include "mite.h"
50 #include "ni_tio.h"
51
52 #define CTRS_PER_CHIP 4 // The number of counters per ni-tio chip
53 #define NUM_PFI_CHANNELS 40
54
55 /* See Register-Level Programmer Manual page 3.1 */
56 typedef enum
57 {
58         G0InterruptAcknowledge,
59         G0StatusRegister,
60         G1InterruptAcknowledge,
61         G1StatusRegister,
62         G01StatusRegister,
63         G0CommandRegister,
64         G1CommandRegister,
65         G0HWSaveRegister,
66         G1HWSaveRegister,
67         G0SWSaveRegister,
68         G1SWSaveRegister,
69         G0ModeRegister,
70         G01JointStatus1Register,
71         G1ModeRegister,
72         G0LoadARegister,
73         G01JointStatus2Register,
74         G0LoadBRegister,
75         G1LoadARegister,
76         G1LoadBRegister,
77         G0InputSelectRegister,
78         G1InputSelectRegister,
79         G0AutoincrementRegister,
80         G1AutoincrementRegister,
81         G01JointResetRegister,
82         G0InterruptEnable,
83         G1InterruptEnable,
84         G0CountingModeRegister,
85         G1CountingModeRegister,
86         G0SecondGateRegister,
87         G1SecondGateRegister,
88         G0DMAConfigRegister,
89         G0DMAStatusRegister,
90         G1DMAConfigRegister,
91         G1DMAStatusRegister,
92         G2InterruptAcknowledge,
93         G2StatusRegister,
94         G3InterruptAcknowledge,
95         G3StatusRegister,
96         G23StatusRegister,
97         G2CommandRegister,
98         G3CommandRegister,
99         G2HWSaveRegister,
100         G3HWSaveRegister,
101         G2SWSaveRegister,
102         G3SWSaveRegister,
103         G2ModeRegister,
104         G23JointStatus1Register,
105         G3ModeRegister,
106         G2LoadARegister,
107         G23JointStatus2Register,
108         G2LoadBRegister,
109         G3LoadARegister,
110         G3LoadBRegister,
111         G2InputSelectRegister,
112         G3InputSelectRegister,
113         G2AutoincrementRegister,
114         G3AutoincrementRegister,
115         G23JointResetRegister,
116         G2InterruptEnable,
117         G3InterruptEnable,
118         G2CountingModeRegister,
119         G3CountingModeRegister,
120         G3SecondGateRegister,
121         G2SecondGateRegister,
122         G2DMAConfigRegister,
123         G2DMAStatusRegister,
124         G3DMAConfigRegister,
125         G3DMAStatusRegister,
126         ClockConfigRegister,
127         IOConfigReg0_1,
128         IOConfigReg2_3,
129         IOConfigReg4_5,
130         IOConfigReg6_7,
131         IOConfigReg8_9,
132         IOConfigReg10_11,
133         IOConfigReg12_13,
134         IOConfigReg14_15,
135         IOConfigReg16_17,
136         IOConfigReg18_19,
137         IOConfigReg20_21,
138         IOConfigReg22_23,
139         IOConfigReg24_25,
140         IOConfigReg26_27,
141         IOConfigReg28_29,
142         IOConfigReg30_31,
143         IOConfigReg32_33,
144         IOConfigReg34_35,
145         IOConfigReg36_37,
146         IOConfigReg38_39,
147         STCDIOParallelInput,
148         STCDIOOutput,
149         STCDIOControl,
150         STCDIOSerialInput,
151         NumRegisters,
152 } NI_660x_Register;
153
154 static inline unsigned IOConfigReg(unsigned pfi_channel)
155 {
156         unsigned reg = IOConfigReg0_1 + pfi_channel / 2;
157         BUG_ON(reg > IOConfigReg38_39);
158         return reg;
159 }
160
161 enum ni_660x_register_width
162 {
163         DATA_1B,
164         DATA_2B,
165         DATA_4B
166 };
167
168 enum ni_660x_register_direction
169 {
170         NI_660x_READ,
171         NI_660x_WRITE,
172         NI_660x_READ_WRITE
173 };
174
175 typedef struct
176 {
177         const char *name; // Register Name
178         int offset; // Offset from base address from GPCT chip
179         enum ni_660x_register_direction direction;
180         enum ni_660x_register_width size; // 1 byte, 2 bytes, or 4 bytes
181 } NI_660xRegisterData;
182
183
184 static const NI_660xRegisterData registerData[NumRegisters] =
185 {
186         {"G0 Interrupt Acknowledge", 0x004, NI_660x_WRITE, DATA_2B},
187         {"G0 Status Register", 0x004, NI_660x_READ, DATA_2B},
188         {"G1 Interrupt Acknowledge", 0x006, NI_660x_WRITE, DATA_2B},
189         {"G1 Status Register", 0x006, NI_660x_READ, DATA_2B},
190         {"G01 Status Register ", 0x008, NI_660x_READ, DATA_2B},
191         {"G0 Command Register", 0x00C, NI_660x_WRITE, DATA_2B},
192         {"G1 Command Register", 0x00E, NI_660x_WRITE, DATA_2B},
193         {"G0 HW Save Register", 0x010, NI_660x_READ, DATA_4B},
194         {"G1 HW Save Register", 0x014, NI_660x_READ, DATA_4B},
195         {"G0 SW Save Register", 0x018, NI_660x_READ, DATA_4B},
196         {"G1 SW Save Register", 0x01C, NI_660x_READ, DATA_4B},
197         {"G0 Mode Register", 0x034, NI_660x_WRITE, DATA_2B},
198         {"G01 Joint Status 1 Register", 0x036, NI_660x_READ, DATA_2B},
199         {"G1 Mode Register", 0x036, NI_660x_WRITE, DATA_2B},
200         {"G0 Load A Register", 0x038, NI_660x_WRITE, DATA_4B},
201         {"G01 Joint Status 2 Register", 0x03A, NI_660x_READ, DATA_2B},
202         {"G0 Load B Register", 0x03C, NI_660x_WRITE, DATA_4B},
203         {"G1 Load A Register", 0x040, NI_660x_WRITE, DATA_4B},
204         {"G1 Load B Register", 0x044, NI_660x_WRITE, DATA_4B},
205         {"G0 Input Select Register", 0x048, NI_660x_WRITE, DATA_2B},
206         {"G1 Input Select Register", 0x04A, NI_660x_WRITE, DATA_2B},
207         {"G0 Autoincrement Register", 0x088, NI_660x_WRITE, DATA_2B},
208         {"G1 Autoincrement Register", 0x08A, NI_660x_WRITE, DATA_2B},
209         {"G01 Joint Reset Register", 0x090, NI_660x_WRITE, DATA_2B},
210         {"G0 Interrupt Enable", 0x092, NI_660x_WRITE, DATA_2B},
211         {"G1 Interrupt Enable", 0x096, NI_660x_WRITE, DATA_2B},
212         {"G0 Counting Mode Register", 0x0B0, NI_660x_WRITE, DATA_2B},
213         {"G1 Counting Mode Register", 0x0B2, NI_660x_WRITE, DATA_2B},
214         {"G0 Second Gate Register", 0x0B4, NI_660x_WRITE, DATA_2B},
215         {"G1 Second Gate Register", 0x0B6, NI_660x_WRITE, DATA_2B},
216         {"G0 DMA Config Register", 0x0B8, NI_660x_WRITE, DATA_2B},
217         {"G0 DMA Status Register", 0x0B8, NI_660x_READ, DATA_2B},
218         {"G1 DMA Config Register", 0x0BA, NI_660x_WRITE, DATA_2B},
219         {"G1 DMA Status Register", 0x0BA, NI_660x_READ, DATA_2B},
220         {"G2 Interrupt Acknowledge", 0x104, NI_660x_WRITE, DATA_2B},
221         {"G2 Status Register", 0x104, NI_660x_READ, DATA_2B},
222         {"G3 Interrupt Acknowledge", 0x106, NI_660x_WRITE, DATA_2B},
223         {"G3 Status Register", 0x106, NI_660x_READ, DATA_2B},
224         {"G23 Status Register", 0x108, NI_660x_READ, DATA_2B},
225         {"G2 Command Register", 0x10C, NI_660x_WRITE, DATA_2B},
226         {"G3 Command Register", 0x10E, NI_660x_WRITE, DATA_2B},
227         {"G2 HW Save Register", 0x110, NI_660x_READ, DATA_4B},
228         {"G3 HW Save Register", 0x114, NI_660x_READ, DATA_4B},
229         {"G2 SW Save Register", 0x118, NI_660x_READ, DATA_4B},
230         {"G3 SW Save Register", 0x11C, NI_660x_READ, DATA_4B},
231         {"G2 Mode Register", 0x134, NI_660x_WRITE, DATA_2B},
232         {"G23 Joint Status 1 Register", 0x136, NI_660x_READ, DATA_2B},
233         {"G3 Mode Register", 0x136, NI_660x_WRITE, DATA_2B},
234         {"G2 Load A Register", 0x138, NI_660x_WRITE, DATA_4B},
235         {"G23 Joint Status 2 Register", 0x13A, NI_660x_READ, DATA_2B},
236         {"G2 Load B Register", 0x13C, NI_660x_WRITE, DATA_4B},
237         {"G3 Load A Register", 0x140, NI_660x_WRITE, DATA_4B},
238         {"G3 Load B Register", 0x144, NI_660x_WRITE, DATA_4B},
239         {"G2 Input Select Register", 0x148, NI_660x_WRITE, DATA_2B},
240         {"G3 Input Select Register", 0x14A, NI_660x_WRITE, DATA_2B},
241         {"G2 Autoincrement Register", 0x188, NI_660x_WRITE, DATA_2B},
242         {"G3 Autoincrement Register", 0x18A, NI_660x_WRITE, DATA_2B},
243         {"G23 Joint Reset Register", 0x190, NI_660x_WRITE, DATA_2B},
244         {"G2 Interrupt Enable", 0x192, NI_660x_WRITE, DATA_2B},
245         {"G3 Interrupt Enable", 0x196, NI_660x_WRITE, DATA_2B},
246         {"G2 Counting Mode Register", 0x1B0, NI_660x_WRITE, DATA_2B},
247         {"G3 Counting Mode Register", 0x1B2, NI_660x_WRITE, DATA_2B},
248         {"G3 Second Gate Register", 0x1B6, NI_660x_WRITE, DATA_2B},
249         {"G2 Second Gate Register", 0x1B4, NI_660x_WRITE, DATA_2B},
250         {"G2 DMA Config Register", 0x1B8, NI_660x_WRITE, DATA_2B},
251         {"G2 DMA Status Register", 0x1B8, NI_660x_READ, DATA_2B},
252         {"G3 DMA Config Register", 0x1BA, NI_660x_WRITE, DATA_2B},
253         {"G3 DMA Status Register", 0x1BA, NI_660x_READ, DATA_2B},
254         {"Clock Config Register", 0x73C, NI_660x_WRITE, DATA_4B},
255         {"IO Config Register 0-1", 0x77C, NI_660x_READ_WRITE, DATA_2B}, // READWRITE
256         {"IO Config Register 2-3", 0x77E, NI_660x_READ_WRITE, DATA_2B},
257         {"IO Config Register 4-5", 0x780, NI_660x_READ_WRITE, DATA_2B},
258         {"IO Config Register 6-7", 0x782, NI_660x_READ_WRITE, DATA_2B},
259         {"IO Config Register 8-9", 0x784, NI_660x_READ_WRITE, DATA_2B},
260         {"IO Config Register 10-11", 0x786, NI_660x_READ_WRITE, DATA_2B},
261         {"IO Config Register 12-13", 0x788, NI_660x_READ_WRITE, DATA_2B},
262         {"IO Config Register 14-15", 0x78A, NI_660x_READ_WRITE, DATA_2B},
263         {"IO Config Register 16-17", 0x78C, NI_660x_READ_WRITE, DATA_2B},
264         {"IO Config Register 18-19", 0x78E, NI_660x_READ_WRITE, DATA_2B},
265         {"IO Config Register 20-21", 0x790, NI_660x_READ_WRITE, DATA_2B},
266         {"IO Config Register 22-23", 0x792, NI_660x_READ_WRITE, DATA_2B},
267         {"IO Config Register 24-25", 0x794, NI_660x_READ_WRITE, DATA_2B},
268         {"IO Config Register 26-27", 0x796, NI_660x_READ_WRITE, DATA_2B},
269         {"IO Config Register 28-29", 0x798, NI_660x_READ_WRITE, DATA_2B},
270         {"IO Config Register 30-31", 0x79A, NI_660x_READ_WRITE, DATA_2B},
271         {"IO Config Register 32-33", 0x79C, NI_660x_READ_WRITE, DATA_2B},
272         {"IO Config Register 34-35", 0x79E, NI_660x_READ_WRITE, DATA_2B},
273         {"IO Config Register 36-37", 0x7A0, NI_660x_READ_WRITE, DATA_2B},
274         {"IO Config Register 38-39", 0x7A2, NI_660x_READ_WRITE, DATA_2B},
275         {"STD DIO Parallel Input", 0x00E, NI_660x_READ, DATA_2B},
276         {"STD DIO Output", 0x014, NI_660x_WRITE, DATA_2B},
277         {"STD DIO Control", 0x016, NI_660x_WRITE, DATA_2B},
278         {"STD DIO Serial Input", 0x038, NI_660x_READ, DATA_2B},
279 };
280
281 #define GateSelectPin38         0x1<<8 // Take internal time-based 20
282
283 // kind of ENABLE for the second counter
284 #define CounterSwap             0x1<<21
285
286 // ioconfigreg
287 static inline unsigned pfi_output_select_mask(unsigned pfi_channel)
288 {
289         return 0x3 << (8 * (pfi_channel % 2));
290 }
291 static inline unsigned pfi_output_select_bits(unsigned pfi_channel, unsigned output_select)
292 {
293         return (output_select & 0x3) << (8 * (pfi_channel % 2));
294 }
295 static inline unsigned pfi_input_select_mask(unsigned pfi_channel)
296 {
297         return 0x7 << (4 + 8 * (pfi_channel % 2));
298 }
299 static inline unsigned pfi_input_select_bits(unsigned pfi_channel, unsigned input_select)
300 {
301         return (input_select & 0x7) << (4 + 8 * (pfi_channel % 2));
302 }
303
304 // Offset of the GPCT chips from the base-adress of the card
305 static const unsigned GPCT_OFFSET[2] = {0x0, 0x800}; /* First chip is at base-adress +
306                                            0x00, etc. */
307
308 /* Board description*/
309 typedef struct
310 {
311         unsigned short dev_id; /* `lspci` will show you this */
312         const char *name;
313         int n_ctrs; /* total number of counters */
314         int cnt_bits; /* number of bits in each counter */
315 } ni_660x_board;
316
317 static ni_660x_board ni_660x_boards[] =
318 {
319         {
320                 dev_id       : 0x2c60,
321                 name         : "PCI-6601",
322                 n_ctrs       : 1*CTRS_PER_CHIP,
323                 cnt_bits     : 32,
324         },
325         {
326                 dev_id       : 0x1310,
327                 name         : "PCI-6602",
328                 n_ctrs       : 2*CTRS_PER_CHIP,
329                 cnt_bits     : 32,
330         },
331 };
332 #define NI_660X_MAX_NUM_COUNTERS 8
333
334 static struct pci_device_id ni_660x_pci_table[] __devinitdata = {
335         { PCI_VENDOR_ID_NATINST, 0x2c60, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
336         { PCI_VENDOR_ID_NATINST, 0x1310, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
337         { 0 }
338 };
339 MODULE_DEVICE_TABLE(pci, ni_660x_pci_table);
340
341 #define thisboard ((ni_660x_board *)dev->board_ptr)
342 /* initialized in ni_660x_find_device() */
343
344 typedef struct
345 {
346         struct mite_struct *mite;
347         int boardtype;
348         struct ni_gpct counters[NI_660X_MAX_NUM_COUNTERS];
349         uint64_t pfi_direction_bits;
350 }ni_660x_private;
351
352 #define devpriv ((ni_660x_private *)dev->private)
353 #define n_ni_660x_boards (sizeof(ni_660x_boards)/sizeof(ni_660x_boards[0]))
354
355 static int ni_660x_attach(comedi_device *dev,comedi_devconfig *it);
356 static int ni_660x_detach(comedi_device *dev);
357 static void init_tio_chip(comedi_device *dev, int chipset);
358
359 static comedi_driver driver_ni_660x=
360 {
361         driver_name:    "ni_660x",
362         module:         THIS_MODULE,
363         attach:         ni_660x_attach,
364         detach:         ni_660x_detach,
365 };
366
367 COMEDI_INITCLEANUP(driver_ni_660x);
368
369 static int ni_660x_find_device(comedi_device *dev,int bus,int slot);
370
371 /* Possible instructions for a GPCT */
372 static int ni_660x_GPCT_rinsn(comedi_device *dev,
373                               comedi_subdevice *s,
374                               comedi_insn *insn,
375                               lsampl_t *data);
376 static int ni_660x_GPCT_insn_config(comedi_device *dev,
377                                     comedi_subdevice *s,
378                                     comedi_insn *insn,
379                                     lsampl_t *data);
380 static int ni_660x_GPCT_winsn(comedi_device *dev,
381                               comedi_subdevice *s,
382                               comedi_insn *insn,
383                               lsampl_t * data);
384
385 // NYI
386 static int ni_660x_GPCT_cmdtest(comedi_device *dev,comedi_subdevice *s,
387                                 comedi_cmd *cmd);
388 static int ni_660x_GPCT_cmd(comedi_device *dev,comedi_subdevice *s);
389
390 /* Possible instructions for Digital IO */
391 static int ni_660x_dio_insn_config(comedi_device *dev,
392                                    comedi_subdevice *s,
393                                    comedi_insn *insn,
394                                    lsampl_t *data);
395 static int ni_660x_dio_insn_bits(comedi_device *dev,
396                                  comedi_subdevice *s,
397                                  comedi_insn *insn,
398                                  lsampl_t *data);
399
400 static int ni_660x_GPCT_cmdtest(comedi_device *dev,comedi_subdevice *s,
401                                 comedi_cmd *cmd)
402 {
403         DPRINTK("NI_660X: COMMANDS not implemented yet for GPCT\n");
404         return -EINVAL;
405 }
406
407 static int ni_660x_GPCT_cmd(comedi_device *dev,comedi_subdevice *s)
408 {
409         DPRINTK("NI_660X: COMMANDS not implemented yet for GPCT\n");
410         return -EINVAL;
411 }
412
413 static NI_660x_Register ni_gpct_to_660x_register(enum ni_gpct_register reg)
414 {
415         NI_660x_Register ni_660x_register;
416         switch(reg)
417         {
418         case NITIO_G0_Autoincrement_Reg:
419                 ni_660x_register = G0AutoincrementRegister;
420                 break;
421         case NITIO_G1_Autoincrement_Reg:
422                 ni_660x_register = G1AutoincrementRegister;
423                 break;
424         case NITIO_G2_Autoincrement_Reg:
425                 ni_660x_register = G2AutoincrementRegister;
426                 break;
427         case NITIO_G3_Autoincrement_Reg:
428                 ni_660x_register = G3AutoincrementRegister;
429                 break;
430         case NITIO_G0_Command_Reg:
431                 ni_660x_register = G0CommandRegister;
432                 break;
433         case NITIO_G1_Command_Reg:
434                 ni_660x_register = G1CommandRegister;
435                 break;
436         case NITIO_G2_Command_Reg:
437                 ni_660x_register = G2CommandRegister;
438                 break;
439         case NITIO_G3_Command_Reg:
440                 ni_660x_register = G3CommandRegister;
441                 break;
442         case NITIO_G0_HW_Save_Reg:
443                 ni_660x_register = G0HWSaveRegister;
444                 break;
445         case NITIO_G1_HW_Save_Reg:
446                 ni_660x_register = G1HWSaveRegister;
447                 break;
448         case NITIO_G2_HW_Save_Reg:
449                 ni_660x_register = G2HWSaveRegister;
450                 break;
451         case NITIO_G3_HW_Save_Reg:
452                 ni_660x_register = G3HWSaveRegister;
453                 break;
454         case NITIO_G0_SW_Save_Reg:
455                 ni_660x_register = G0SWSaveRegister;
456                 break;
457         case NITIO_G1_SW_Save_Reg:
458                 ni_660x_register = G1SWSaveRegister;
459                 break;
460         case NITIO_G2_SW_Save_Reg:
461                 ni_660x_register = G2SWSaveRegister;
462                 break;
463         case NITIO_G3_SW_Save_Reg:
464                 ni_660x_register = G3SWSaveRegister;
465                 break;
466         case NITIO_G0_Mode_Reg:
467                 ni_660x_register = G0ModeRegister;
468                 break;
469         case NITIO_G1_Mode_Reg:
470                 ni_660x_register = G1ModeRegister;
471                 break;
472         case NITIO_G2_Mode_Reg:
473                 ni_660x_register = G2ModeRegister;
474                 break;
475         case NITIO_G3_Mode_Reg:
476                 ni_660x_register = G3ModeRegister;
477                 break;
478         case NITIO_G0_LoadA_Reg:
479                 ni_660x_register = G0LoadARegister;
480                 break;
481         case NITIO_G1_LoadA_Reg:
482                 ni_660x_register = G1LoadARegister;
483                 break;
484         case NITIO_G2_LoadA_Reg:
485                 ni_660x_register = G2LoadARegister;
486                 break;
487         case NITIO_G3_LoadA_Reg:
488                 ni_660x_register = G3LoadARegister;
489                 break;
490         case NITIO_G0_LoadB_Reg:
491                 ni_660x_register = G0LoadBRegister;
492                 break;
493         case NITIO_G1_LoadB_Reg:
494                 ni_660x_register = G1LoadBRegister;
495                 break;
496         case NITIO_G2_LoadB_Reg:
497                 ni_660x_register = G2LoadBRegister;
498                 break;
499         case NITIO_G3_LoadB_Reg:
500                 ni_660x_register = G3LoadBRegister;
501                 break;
502         case NITIO_G0_Input_Select_Reg:
503                 ni_660x_register = G0InputSelectRegister;
504                 break;
505         case NITIO_G1_Input_Select_Reg:
506                 ni_660x_register = G1InputSelectRegister;
507                 break;
508         case NITIO_G2_Input_Select_Reg:
509                 ni_660x_register = G2InputSelectRegister;
510                 break;
511         case NITIO_G3_Input_Select_Reg:
512                 ni_660x_register = G3InputSelectRegister;
513                 break;
514         case NITIO_G01_Status_Reg:
515                 ni_660x_register = G01StatusRegister;
516                 break;
517         case NITIO_G23_Status_Reg:
518                 ni_660x_register = G23StatusRegister;
519                 break;
520         case NITIO_G01_Joint_Reset_Reg:
521                 ni_660x_register = G01JointResetRegister;
522                 break;
523         case NITIO_G23_Joint_Reset_Reg:
524                 ni_660x_register = G23JointResetRegister;
525                 break;
526         case NITIO_G01_Joint_Status1_Reg:
527                 ni_660x_register = G01JointStatus1Register;
528                 break;
529         case NITIO_G23_Joint_Status1_Reg:
530                 ni_660x_register = G23JointStatus1Register;
531                 break;
532         case NITIO_G01_Joint_Status2_Reg:
533                 ni_660x_register = G01JointStatus2Register;
534                 break;
535         case NITIO_G23_Joint_Status2_Reg:
536                 ni_660x_register = G23JointStatus2Register;
537                 break;
538         case NITIO_G0_Counting_Mode_Reg:
539                 ni_660x_register = G0CountingModeRegister;
540                 break;
541         case NITIO_G1_Counting_Mode_Reg:
542                 ni_660x_register = G1CountingModeRegister;
543                 break;
544         case NITIO_G2_Counting_Mode_Reg:
545                 ni_660x_register = G2CountingModeRegister;
546                 break;
547         case NITIO_G3_Counting_Mode_Reg:
548                 ni_660x_register = G3CountingModeRegister;
549                 break;
550         case NITIO_G0_Second_Gate_Reg:
551                 ni_660x_register = G0SecondGateRegister;
552                 break;
553         case NITIO_G1_Second_Gate_Reg:
554                 ni_660x_register = G1SecondGateRegister;
555                 break;
556         case NITIO_G2_Second_Gate_Reg:
557                 ni_660x_register = G2SecondGateRegister;
558                 break;
559         case NITIO_G3_Second_Gate_Reg:
560                 ni_660x_register = G3SecondGateRegister;
561                 break;
562         default:
563                 rt_printk("%s: unhandled register 0x%x in switch.\n", __FUNCTION__, reg);
564                 BUG();
565                 return 0;
566                 break;
567         }
568         return ni_660x_register;
569 }
570
571 static void ni_gpct_write_register(struct ni_gpct *counter, unsigned bits, enum ni_gpct_register reg)
572 {
573         NI_660x_Register ni_660x_register = ni_gpct_to_660x_register(reg);
574         comedi_device *dev = counter->dev;
575         void * const write_address = devpriv->mite->daq_io_addr + GPCT_OFFSET[counter->chip_index] + registerData[ni_660x_register].offset;
576
577         switch(registerData[ni_660x_register].size)
578         {
579         case DATA_2B:
580                 writew(bits, write_address);
581                 break;
582         case DATA_4B:
583                 writel(bits, write_address);
584                 break;
585         default:
586                 rt_printk("%s: %s: bug! unhandled case = 0x%x in switch.\n", __FILE__, __FUNCTION__, reg);
587                 BUG();
588                 break;
589         }
590 }
591
592 static unsigned ni_gpct_read_register(struct ni_gpct *counter, enum ni_gpct_register reg)
593 {
594         NI_660x_Register ni_660x_register = ni_gpct_to_660x_register(reg);
595         comedi_device *dev = counter->dev;
596         void * const read_address = devpriv->mite->daq_io_addr + GPCT_OFFSET[counter->chip_index] + registerData[ni_660x_register].offset;
597
598         switch(registerData[ni_660x_register].size)
599         {
600         case DATA_2B:
601                 return readw(read_address);
602                 break;
603         case DATA_4B:
604                 return readl(read_address);
605                 break;
606         default:
607                 rt_printk("%s: %s: bug! unhandled case = 0x%x in switch.\n", __FILE__, __FUNCTION__, reg);
608                 BUG();
609                 break;
610         }
611         return 0;
612 }
613
614 static int ni_660x_attach(comedi_device *dev,comedi_devconfig *it)
615 {
616         comedi_subdevice *s;
617         int ret;
618         unsigned i;
619
620         printk("comedi%d: ni_660x: ",dev->minor);
621
622         if ((ret=alloc_private(dev,sizeof(ni_660x_private))) < 0) return ret;
623
624         ret = ni_660x_find_device(dev, it->options[0], it->options[1]);
625         if (ret<0) return ret;
626
627         ret = mite_setup(devpriv->mite);
628         if (ret < 0) {
629         printk("error setting up mite\n");
630         return ret;
631         }
632         dev->board_name = thisboard->name;
633         /* we don't support the interrupt yet */
634         //dev->irq = mite_irq(devpriv->mite);
635
636         printk(" %s ", dev->board_name);
637
638         dev->n_subdevices = 2 + NI_660X_MAX_NUM_COUNTERS;
639
640         if(alloc_subdevices(dev, dev->n_subdevices) < 0) return -ENOMEM;
641
642         s = dev->subdevices + 0;
643         /* Old GENERAL-PURPOSE COUNTER/TIME (GPCT) subdevice, no longer used */
644         s->type = COMEDI_SUBD_UNUSED;
645
646         s = dev->subdevices + 1;
647         /* DIGITAL I/O SUBDEVICE */
648         s->type   = COMEDI_SUBD_DIO;
649         s->subdev_flags = SDF_READABLE|SDF_WRITABLE;
650         s->n_chan       = NUM_PFI_CHANNELS;
651         s->maxdata      = 1;
652         s->range_table  = &range_digital;
653         s->insn_bits    = ni_660x_dio_insn_bits;
654         s->insn_config  = ni_660x_dio_insn_config;
655         s->io_bits      = 0;     /* all bits default to input */
656         // we use the ioconfig registers to control dio direction, so zero output enables in stc dio control reg
657         writew(0, devpriv->mite->daq_io_addr + registerData[STCDIOControl].offset);
658
659         for(i = 0; i < NI_660X_MAX_NUM_COUNTERS; ++i)
660         {
661                 s = dev->subdevices + 2 + i;
662                 if(i < thisboard->n_ctrs)
663                 {
664                         s->type = COMEDI_SUBD_COUNTER;
665                         s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
666                         s->n_chan = 3;
667                         s->maxdata = 0xffffffff;
668                         s->insn_read = ni_660x_GPCT_rinsn;
669                         s->insn_write = ni_660x_GPCT_winsn;
670                         s->insn_config = ni_660x_GPCT_insn_config;
671                         s->private = &devpriv->counters[i];
672
673                         devpriv->counters[i].dev = dev;
674                         devpriv->counters[i].chip_index = i / CTRS_PER_CHIP;
675                         devpriv->counters[i].counter_index = i % CTRS_PER_CHIP;
676                         devpriv->counters[i].write_register = ni_gpct_write_register;
677                         devpriv->counters[i].read_register = ni_gpct_read_register;
678                         devpriv->counters[i].variant = ni_gpct_variant_660x;
679                         devpriv->counters[i].clock_period_ps = 0;
680                         devpriv->counters[i].mite = devpriv->mite;
681                         devpriv->counters[i].mite_channel = -1;
682                 }else
683                 {
684                         s->type = COMEDI_SUBD_UNUSED;
685                 }
686         }
687         for(i = 0; i < thisboard->n_ctrs / CTRS_PER_CHIP; ++i)
688         {
689                 init_tio_chip(dev, i);
690         }
691         for(i = 0; i < thisboard->n_ctrs; ++i)
692         {
693                 ni_tio_init_counter(&devpriv->counters[i]);
694         }
695
696         printk("attached\n");
697         return 0;
698 }
699
700
701 static int
702 ni_660x_detach(comedi_device *dev)
703 {
704         printk("comedi%d: ni_660x: remove\n",dev->minor);
705
706         if (dev->private && devpriv->mite)
707                 mite_unsetup(devpriv->mite);
708
709         /* Free irq */
710
711         if(dev->irq) comedi_free_irq(dev->irq,dev);
712
713         /* Same question as with attach ... */
714         return 0;
715 }
716
717 static int
718 ni_660x_GPCT_rinsn(comedi_device *dev, comedi_subdevice *s,
719         comedi_insn *insn, lsampl_t *data)
720 {
721         struct ni_gpct *counter = s->private;
722         return ni_tio_rinsn(counter, insn, data);
723 }
724
725 static void init_tio_chip(comedi_device *dev, int chipset)
726 {
727         /* See P. 3.5 of the Register-Level Programming manual.  The
728                 CounterSwap bit has to be set on the second chip, otherwise
729                 it will try to use the same pins as the first chip.
730         */
731         if(chipset)
732                 writel(CounterSwap,devpriv->mite->daq_io_addr + GPCT_OFFSET[1]
733                         + registerData[ClockConfigRegister].offset);
734         else
735                 writel(0,devpriv->mite->daq_io_addr + GPCT_OFFSET[0]
736                         + registerData[ClockConfigRegister].offset);
737 }
738
739 static int
740 ni_660x_GPCT_insn_config(comedi_device *dev, comedi_subdevice *s,
741         comedi_insn *insn, lsampl_t *data)
742 {
743         struct ni_gpct *counter = s->private;
744         return ni_tio_insn_config(counter, insn, data);
745 }
746
747 static int ni_660x_GPCT_winsn(comedi_device *dev,
748         comedi_subdevice *s,
749         comedi_insn *insn,
750         lsampl_t * data)
751 {
752         struct ni_gpct *counter = s->private;
753         return ni_tio_winsn(counter, insn, data);
754 }
755
756 static int
757 ni_660x_find_device(comedi_device *dev, int bus, int slot)
758 {
759         struct mite_struct *mite;
760         int i;
761
762         for (mite=mite_devices; mite; mite=mite->next) {
763                 if (mite->used) continue;
764                 if (bus || slot) {
765                         if (bus!=mite->pcidev->bus->number ||
766                                 slot!=PCI_SLOT(mite->pcidev->devfn)) continue;
767                 }
768
769                 for (i=0; i<n_ni_660x_boards; i++) {
770                         if (mite_device_id(mite)==ni_660x_boards[i].dev_id) {
771                                 dev->board_ptr=ni_660x_boards+i;
772                                 devpriv->mite=mite;
773                                 return 0;
774                         }
775                 }
776         }
777         printk("no device found\n");
778         mite_list_devices();
779         return -EIO;
780 }
781
782
783 static int ni_660x_dio_insn_bits(comedi_device *dev,
784         comedi_subdevice *s,
785         comedi_insn *insn,
786         lsampl_t *data)
787 {
788         unsigned base_bitfield_channel = CR_CHAN(insn->chanspec);
789
790         // Check if we have to write some bits
791         if(data[0])
792         {
793                 /* Only the first 8 lines can be read/written.  The rest can
794                 only have their input/output configuration changed (although
795                 the user manual implies the first 32 channels can be used as
796                 general purpose dio, the register manual doesn't tell you how
797                 this can be accomplished. */
798                 if((data[0] << base_bitfield_channel) > 0xff)
799                 {
800                         return -EINVAL;
801                 }
802                 s->state &= ~(data[0] << base_bitfield_channel);
803                 s->state |= (data[0] & data[1]) << base_bitfield_channel;
804                 /* Write out the new digital output lines */
805                 writew(s->state,devpriv->mite->daq_io_addr + registerData[STCDIOOutput].offset);
806         }
807         /* on return, data[1] contains the value of the digital
808         * input and output lines. */
809         data[1] = (readw(devpriv->mite->daq_io_addr + registerData[STCDIOParallelInput].offset) >> base_bitfield_channel) &
810                 (0xff >> base_bitfield_channel);
811         return 2;
812 }
813
814 static void ni_660x_select_pfi_output(comedi_device *dev, unsigned pfi_channel, unsigned output_select)
815 {
816         unsigned bits = readw(devpriv->mite->daq_io_addr + registerData[IOConfigReg(pfi_channel)].offset);
817         bits &= ~pfi_output_select_mask(pfi_channel);
818         bits |= pfi_output_select_bits(pfi_channel, output_select);
819         writew(bits, devpriv->mite->daq_io_addr + registerData[IOConfigReg(pfi_channel)].offset);
820 }
821
822 static void ni660x_config_filter(comedi_device *dev, unsigned pfi_channel, enum ni_gpct_filter_select filter)
823 {
824         unsigned bits = readw(devpriv->mite->daq_io_addr + registerData[IOConfigReg(pfi_channel)].offset);
825         bits &= ~pfi_input_select_mask(pfi_channel);
826         bits |= pfi_input_select_bits(pfi_channel, filter);
827         writew(bits, devpriv->mite->daq_io_addr + registerData[IOConfigReg(pfi_channel)].offset);
828 }
829
830 static int ni_660x_dio_insn_config(comedi_device *dev,
831         comedi_subdevice *s,
832         comedi_insn *insn,
833         lsampl_t *data)
834 {
835         int chan=CR_CHAN(insn->chanspec);
836
837         /* The input or output configuration of each digital line is
838         * configured by a special insn_config instruction.  chanspec
839         * contains the channel to be changed, and data[0] contains the
840         * value COMEDI_INPUT or COMEDI_OUTPUT. */
841
842         switch(data[0])
843         {
844         case INSN_CONFIG_DIO_OUTPUT:
845                 devpriv->pfi_direction_bits |= ((uint64_t)1) << chan;
846                 ni_660x_select_pfi_output(dev, chan, 1);
847                 break;
848         case INSN_CONFIG_DIO_INPUT:
849                 devpriv->pfi_direction_bits &= ~(((uint64_t)1) << chan);
850                 ni_660x_select_pfi_output(dev, chan, 0);
851                 break;
852         case INSN_CONFIG_DIO_QUERY:
853                 data[1] = (devpriv->pfi_direction_bits & (((uint64_t)1) << chan)) ? COMEDI_OUTPUT : COMEDI_INPUT;
854                 return insn->n;
855         case INSN_CONFIG_FILTER:
856                 ni660x_config_filter(dev, chan, data[1]);
857                 return 0;
858         default:
859                 return -EINVAL;
860                 break;
861         };
862         return insn->n;
863 }
864
865