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