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
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
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
39 DAQ 660x Register-Level Programmer Manual (NI 370505A-01)
40 DAQ 6601/6602 User Manual (NI 322137B-01)
43 - Add DMA support (see mite.c and ni_pcidio.c for examples)
44 - Add commands (copy from ni_pcidio.c ?)
48 #include <linux/comedidev.h>
52 #define CTRS_PER_CHIP 4 // The number of counters per ni-tio chip
53 #define NUM_PFI_CHANNELS 40
55 /* See Register-Level Programmer Manual page 3.1 */
58 G0InterruptAcknowledge,
60 G1InterruptAcknowledge,
70 G01JointStatus1Register,
73 G01JointStatus2Register,
77 G0InputSelectRegister,
78 G1InputSelectRegister,
79 G0AutoincrementRegister,
80 G1AutoincrementRegister,
81 G01JointResetRegister,
84 G0CountingModeRegister,
85 G1CountingModeRegister,
92 G2InterruptAcknowledge,
94 G3InterruptAcknowledge,
104 G23JointStatus1Register,
107 G23JointStatus2Register,
111 G2InputSelectRegister,
112 G3InputSelectRegister,
113 G2AutoincrementRegister,
114 G3AutoincrementRegister,
115 G23JointResetRegister,
118 G2CountingModeRegister,
119 G3CountingModeRegister,
120 G3SecondGateRegister,
121 G2SecondGateRegister,
154 static inline unsigned IOConfigReg(unsigned pfi_channel)
156 unsigned reg = IOConfigReg0_1 + pfi_channel / 2;
157 BUG_ON(reg > IOConfigReg38_39);
161 enum ni_660x_register_width
168 enum ni_660x_register_direction
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;
184 static const NI_660xRegisterData registerData[NumRegisters] =
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},
281 #define GateSelectPin38 0x1<<8 // Take internal time-based 20
283 // kind of ENABLE for the second counter
284 #define CounterSwap 0x1<<21
287 static inline unsigned pfi_output_select_mask(unsigned pfi_channel)
289 return 0x3 << (8 * (pfi_channel % 2));
291 static inline unsigned pfi_output_select_bits(unsigned pfi_channel, unsigned output_select)
293 return (output_select & 0x3) << (8 * (pfi_channel % 2));
295 static inline unsigned pfi_input_select_mask(unsigned pfi_channel)
297 return 0x7 << (4 + 8 * (pfi_channel % 2));
299 static inline unsigned pfi_input_select_bits(unsigned pfi_channel, unsigned input_select)
301 return (input_select & 0x7) << (4 + 8 * (pfi_channel % 2));
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 +
308 /* Board description*/
311 unsigned short dev_id; /* `lspci` will show you this */
313 int n_ctrs; /* total number of counters */
314 int cnt_bits; /* number of bits in each counter */
317 static ni_660x_board ni_660x_boards[] =
322 n_ctrs : 1*CTRS_PER_CHIP,
328 n_ctrs : 2*CTRS_PER_CHIP,
332 #define NI_660X_MAX_NUM_COUNTERS 8
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 },
339 MODULE_DEVICE_TABLE(pci, ni_660x_pci_table);
341 #define thisboard ((ni_660x_board *)dev->board_ptr)
342 /* initialized in ni_660x_find_device() */
346 struct mite_struct *mite;
348 struct ni_gpct counters[NI_660X_MAX_NUM_COUNTERS];
349 uint64_t pfi_direction_bits;
352 #define devpriv ((ni_660x_private *)dev->private)
353 #define n_ni_660x_boards (sizeof(ni_660x_boards)/sizeof(ni_660x_boards[0]))
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);
359 static comedi_driver driver_ni_660x=
361 driver_name: "ni_660x",
363 attach: ni_660x_attach,
364 detach: ni_660x_detach,
367 COMEDI_INITCLEANUP(driver_ni_660x);
369 static int ni_660x_find_device(comedi_device *dev,int bus,int slot);
371 /* Possible instructions for a GPCT */
372 static int ni_660x_GPCT_rinsn(comedi_device *dev,
376 static int ni_660x_GPCT_insn_config(comedi_device *dev,
380 static int ni_660x_GPCT_winsn(comedi_device *dev,
386 static int ni_660x_GPCT_cmdtest(comedi_device *dev,comedi_subdevice *s,
388 static int ni_660x_GPCT_cmd(comedi_device *dev,comedi_subdevice *s);
390 /* Possible instructions for Digital IO */
391 static int ni_660x_dio_insn_config(comedi_device *dev,
395 static int ni_660x_dio_insn_bits(comedi_device *dev,
400 static int ni_660x_GPCT_cmdtest(comedi_device *dev,comedi_subdevice *s,
403 DPRINTK("NI_660X: COMMANDS not implemented yet for GPCT\n");
407 static int ni_660x_GPCT_cmd(comedi_device *dev,comedi_subdevice *s)
409 DPRINTK("NI_660X: COMMANDS not implemented yet for GPCT\n");
413 static NI_660x_Register ni_gpct_to_660x_register(enum ni_gpct_register reg)
415 NI_660x_Register ni_660x_register;
418 case NITIO_G0_Autoincrement_Reg:
419 ni_660x_register = G0AutoincrementRegister;
421 case NITIO_G1_Autoincrement_Reg:
422 ni_660x_register = G1AutoincrementRegister;
424 case NITIO_G2_Autoincrement_Reg:
425 ni_660x_register = G2AutoincrementRegister;
427 case NITIO_G3_Autoincrement_Reg:
428 ni_660x_register = G3AutoincrementRegister;
430 case NITIO_G0_Command_Reg:
431 ni_660x_register = G0CommandRegister;
433 case NITIO_G1_Command_Reg:
434 ni_660x_register = G1CommandRegister;
436 case NITIO_G2_Command_Reg:
437 ni_660x_register = G2CommandRegister;
439 case NITIO_G3_Command_Reg:
440 ni_660x_register = G3CommandRegister;
442 case NITIO_G0_HW_Save_Reg:
443 ni_660x_register = G0HWSaveRegister;
445 case NITIO_G1_HW_Save_Reg:
446 ni_660x_register = G1HWSaveRegister;
448 case NITIO_G2_HW_Save_Reg:
449 ni_660x_register = G2HWSaveRegister;
451 case NITIO_G3_HW_Save_Reg:
452 ni_660x_register = G3HWSaveRegister;
454 case NITIO_G0_SW_Save_Reg:
455 ni_660x_register = G0SWSaveRegister;
457 case NITIO_G1_SW_Save_Reg:
458 ni_660x_register = G1SWSaveRegister;
460 case NITIO_G2_SW_Save_Reg:
461 ni_660x_register = G2SWSaveRegister;
463 case NITIO_G3_SW_Save_Reg:
464 ni_660x_register = G3SWSaveRegister;
466 case NITIO_G0_Mode_Reg:
467 ni_660x_register = G0ModeRegister;
469 case NITIO_G1_Mode_Reg:
470 ni_660x_register = G1ModeRegister;
472 case NITIO_G2_Mode_Reg:
473 ni_660x_register = G2ModeRegister;
475 case NITIO_G3_Mode_Reg:
476 ni_660x_register = G3ModeRegister;
478 case NITIO_G0_LoadA_Reg:
479 ni_660x_register = G0LoadARegister;
481 case NITIO_G1_LoadA_Reg:
482 ni_660x_register = G1LoadARegister;
484 case NITIO_G2_LoadA_Reg:
485 ni_660x_register = G2LoadARegister;
487 case NITIO_G3_LoadA_Reg:
488 ni_660x_register = G3LoadARegister;
490 case NITIO_G0_LoadB_Reg:
491 ni_660x_register = G0LoadBRegister;
493 case NITIO_G1_LoadB_Reg:
494 ni_660x_register = G1LoadBRegister;
496 case NITIO_G2_LoadB_Reg:
497 ni_660x_register = G2LoadBRegister;
499 case NITIO_G3_LoadB_Reg:
500 ni_660x_register = G3LoadBRegister;
502 case NITIO_G0_Input_Select_Reg:
503 ni_660x_register = G0InputSelectRegister;
505 case NITIO_G1_Input_Select_Reg:
506 ni_660x_register = G1InputSelectRegister;
508 case NITIO_G2_Input_Select_Reg:
509 ni_660x_register = G2InputSelectRegister;
511 case NITIO_G3_Input_Select_Reg:
512 ni_660x_register = G3InputSelectRegister;
514 case NITIO_G01_Status_Reg:
515 ni_660x_register = G01StatusRegister;
517 case NITIO_G23_Status_Reg:
518 ni_660x_register = G23StatusRegister;
520 case NITIO_G01_Joint_Reset_Reg:
521 ni_660x_register = G01JointResetRegister;
523 case NITIO_G23_Joint_Reset_Reg:
524 ni_660x_register = G23JointResetRegister;
526 case NITIO_G01_Joint_Status1_Reg:
527 ni_660x_register = G01JointStatus1Register;
529 case NITIO_G23_Joint_Status1_Reg:
530 ni_660x_register = G23JointStatus1Register;
532 case NITIO_G01_Joint_Status2_Reg:
533 ni_660x_register = G01JointStatus2Register;
535 case NITIO_G23_Joint_Status2_Reg:
536 ni_660x_register = G23JointStatus2Register;
538 case NITIO_G0_Counting_Mode_Reg:
539 ni_660x_register = G0CountingModeRegister;
541 case NITIO_G1_Counting_Mode_Reg:
542 ni_660x_register = G1CountingModeRegister;
544 case NITIO_G2_Counting_Mode_Reg:
545 ni_660x_register = G2CountingModeRegister;
547 case NITIO_G3_Counting_Mode_Reg:
548 ni_660x_register = G3CountingModeRegister;
550 case NITIO_G0_Second_Gate_Reg:
551 ni_660x_register = G0SecondGateRegister;
553 case NITIO_G1_Second_Gate_Reg:
554 ni_660x_register = G1SecondGateRegister;
556 case NITIO_G2_Second_Gate_Reg:
557 ni_660x_register = G2SecondGateRegister;
559 case NITIO_G3_Second_Gate_Reg:
560 ni_660x_register = G3SecondGateRegister;
563 rt_printk("%s: unhandled register 0x%x in switch.\n", __FUNCTION__, reg);
568 return ni_660x_register;
571 static void ni_gpct_write_register(struct ni_gpct *counter, unsigned bits, enum ni_gpct_register reg)
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;
577 switch(registerData[ni_660x_register].size)
580 writew(bits, write_address);
583 writel(bits, write_address);
586 rt_printk("%s: %s: bug! unhandled case = 0x%x in switch.\n", __FILE__, __FUNCTION__, reg);
592 static unsigned ni_gpct_read_register(struct ni_gpct *counter, enum ni_gpct_register reg)
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;
598 switch(registerData[ni_660x_register].size)
601 return readw(read_address);
604 return readl(read_address);
607 rt_printk("%s: %s: bug! unhandled case = 0x%x in switch.\n", __FILE__, __FUNCTION__, reg);
614 static int ni_660x_attach(comedi_device *dev,comedi_devconfig *it)
620 printk("comedi%d: ni_660x: ",dev->minor);
622 if ((ret=alloc_private(dev,sizeof(ni_660x_private))) < 0) return ret;
624 ret = ni_660x_find_device(dev, it->options[0], it->options[1]);
625 if (ret<0) return ret;
627 ret = mite_setup(devpriv->mite);
629 printk("error setting up mite\n");
632 dev->board_name = thisboard->name;
633 /* we don't support the interrupt yet */
634 //dev->irq = mite_irq(devpriv->mite);
636 printk(" %s ", dev->board_name);
638 dev->n_subdevices = 2 + NI_660X_MAX_NUM_COUNTERS;
640 if(alloc_subdevices(dev, dev->n_subdevices) < 0) return -ENOMEM;
642 s = dev->subdevices + 0;
643 /* Old GENERAL-PURPOSE COUNTER/TIME (GPCT) subdevice, no longer used */
644 s->type = COMEDI_SUBD_UNUSED;
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;
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);
659 for(i = 0; i < NI_660X_MAX_NUM_COUNTERS; ++i)
661 s = dev->subdevices + 2 + i;
662 if(i < thisboard->n_ctrs)
664 s->type = COMEDI_SUBD_COUNTER;
665 s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
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];
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;
684 s->type = COMEDI_SUBD_UNUSED;
687 for(i = 0; i < thisboard->n_ctrs / CTRS_PER_CHIP; ++i)
689 init_tio_chip(dev, i);
691 for(i = 0; i < thisboard->n_ctrs; ++i)
693 ni_tio_init_counter(&devpriv->counters[i]);
696 printk("attached\n");
702 ni_660x_detach(comedi_device *dev)
704 printk("comedi%d: ni_660x: remove\n",dev->minor);
706 if (dev->private && devpriv->mite)
707 mite_unsetup(devpriv->mite);
711 if(dev->irq) comedi_free_irq(dev->irq,dev);
713 /* Same question as with attach ... */
718 ni_660x_GPCT_rinsn(comedi_device *dev, comedi_subdevice *s,
719 comedi_insn *insn, lsampl_t *data)
721 struct ni_gpct *counter = s->private;
722 return ni_tio_rinsn(counter, insn, data);
725 static void init_tio_chip(comedi_device *dev, int chipset)
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.
732 writel(CounterSwap,devpriv->mite->daq_io_addr + GPCT_OFFSET[1]
733 + registerData[ClockConfigRegister].offset);
735 writel(0,devpriv->mite->daq_io_addr + GPCT_OFFSET[0]
736 + registerData[ClockConfigRegister].offset);
740 ni_660x_GPCT_insn_config(comedi_device *dev, comedi_subdevice *s,
741 comedi_insn *insn, lsampl_t *data)
743 struct ni_gpct *counter = s->private;
744 return ni_tio_insn_config(counter, insn, data);
747 static int ni_660x_GPCT_winsn(comedi_device *dev,
752 struct ni_gpct *counter = s->private;
753 return ni_tio_winsn(counter, insn, data);
757 ni_660x_find_device(comedi_device *dev, int bus, int slot)
759 struct mite_struct *mite;
762 for (mite=mite_devices; mite; mite=mite->next) {
763 if (mite->used) continue;
765 if (bus!=mite->pcidev->bus->number ||
766 slot!=PCI_SLOT(mite->pcidev->devfn)) continue;
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;
777 printk("no device found\n");
783 static int ni_660x_dio_insn_bits(comedi_device *dev,
788 unsigned base_bitfield_channel = CR_CHAN(insn->chanspec);
790 // Check if we have to write some bits
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)
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);
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);
814 static void ni_660x_select_pfi_output(comedi_device *dev, unsigned pfi_channel, unsigned output_select)
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);
822 static void ni660x_config_filter(comedi_device *dev, unsigned pfi_channel, enum ni_gpct_filter_select filter)
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);
830 static int ni_660x_dio_insn_config(comedi_device *dev,
835 int chan=CR_CHAN(insn->chanspec);
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. */
844 case INSN_CONFIG_DIO_OUTPUT:
845 devpriv->pfi_direction_bits |= ((uint64_t)1) << chan;
846 ni_660x_select_pfi_output(dev, chan, 1);
848 case INSN_CONFIG_DIO_INPUT:
849 devpriv->pfi_direction_bits &= ~(((uint64_t)1) << chan);
850 ni_660x_select_pfi_output(dev, chan, 0);
852 case INSN_CONFIG_DIO_QUERY:
853 data[1] = (devpriv->pfi_direction_bits & (((uint64_t)1) << chan)) ? COMEDI_OUTPUT : COMEDI_INPUT;
855 case INSN_CONFIG_FILTER:
856 ni660x_config_filter(dev, chan, data[1]);