RTXI 1.3
comedi/comedi/drivers/ni_660x.c
Go to the documentation of this file.
00001 /*
00002   comedi/drivers/ni_660x.c
00003   Hardware driver for NI 660x devices
00004 
00005   This program is free software; you can redistribute it and/or modify
00006   it under the terms of the GNU General Public License as published by
00007   the Free Software Foundation; either version 2 of the License, or
00008   (at your option) any later version.
00009 
00010   This program is distributed in the hope that it will be useful,
00011   but WITHOUT ANY WARRANTY; without even the implied warranty of
00012   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013   GNU General Public License for more details.
00014 
00015   You should have received a copy of the GNU General Public License
00016   along with this program; if not, write to the Free Software
00017   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00018 */
00019 
00020 /*
00021 Driver: ni_660x
00022 Description: National Instruments 660x counter/timer boards
00023 Devices:
00024 [National Instruments] PCI-6601 (ni_660x), PCI-6602, PXI-6602,
00025         PXI-6608
00026 Author: J.P. Mellor <jpmellor@rose-hulman.edu>,
00027         Herman.Bruyninckx@mech.kuleuven.ac.be,
00028         Wim.Meeussen@mech.kuleuven.ac.be,
00029         Klaas.Gadeyne@mech.kuleuven.ac.be,
00030         Frank Mori Hess <fmhess@users.sourceforge.net>
00031 Updated: Thu Oct 18 12:56:06 EDT 2007
00032 Status: experimental
00033 
00034 Encoders work.  PulseGeneration (both single pulse and pulse train)
00035 works. Buffered commands work for input but not output.
00036 
00037 References:
00038 DAQ 660x Register-Level Programmer Manual  (NI 370505A-01)
00039 DAQ 6601/6602 User Manual (NI 322137B-01)
00040 
00041 */
00042 
00043 #include <linux/comedidev.h>
00044 #include "mite.h"
00045 #include "ni_tio.h"
00046 
00047 enum ni_660x_constants {
00048         min_counter_pfi_chan = 8,
00049         max_dio_pfi_chan = 31,
00050         counters_per_chip = 4
00051 };
00052 
00053 #define NUM_PFI_CHANNELS 40
00054 // really there are only up to 3 dma channels, but the register layout allows for 4
00055 #define MAX_DMA_CHANNEL 4
00056 
00057 /* See Register-Level Programmer Manual page 3.1 */
00058 typedef enum {
00059         G0InterruptAcknowledge,
00060         G0StatusRegister,
00061         G1InterruptAcknowledge,
00062         G1StatusRegister,
00063         G01StatusRegister,
00064         G0CommandRegister,
00065         STCDIOParallelInput,
00066         G1CommandRegister,
00067         G0HWSaveRegister,
00068         G1HWSaveRegister,
00069         STCDIOOutput,
00070         STCDIOControl,
00071         G0SWSaveRegister,
00072         G1SWSaveRegister,
00073         G0ModeRegister,
00074         G01JointStatus1Register,
00075         G1ModeRegister,
00076         STCDIOSerialInput,
00077         G0LoadARegister,
00078         G01JointStatus2Register,
00079         G0LoadBRegister,
00080         G1LoadARegister,
00081         G1LoadBRegister,
00082         G0InputSelectRegister,
00083         G1InputSelectRegister,
00084         G0AutoincrementRegister,
00085         G1AutoincrementRegister,
00086         G01JointResetRegister,
00087         G0InterruptEnable,
00088         G1InterruptEnable,
00089         G0CountingModeRegister,
00090         G1CountingModeRegister,
00091         G0SecondGateRegister,
00092         G1SecondGateRegister,
00093         G0DMAConfigRegister,
00094         G0DMAStatusRegister,
00095         G1DMAConfigRegister,
00096         G1DMAStatusRegister,
00097         G2InterruptAcknowledge,
00098         G2StatusRegister,
00099         G3InterruptAcknowledge,
00100         G3StatusRegister,
00101         G23StatusRegister,
00102         G2CommandRegister,
00103         G3CommandRegister,
00104         G2HWSaveRegister,
00105         G3HWSaveRegister,
00106         G2SWSaveRegister,
00107         G3SWSaveRegister,
00108         G2ModeRegister,
00109         G23JointStatus1Register,
00110         G3ModeRegister,
00111         G2LoadARegister,
00112         G23JointStatus2Register,
00113         G2LoadBRegister,
00114         G3LoadARegister,
00115         G3LoadBRegister,
00116         G2InputSelectRegister,
00117         G3InputSelectRegister,
00118         G2AutoincrementRegister,
00119         G3AutoincrementRegister,
00120         G23JointResetRegister,
00121         G2InterruptEnable,
00122         G3InterruptEnable,
00123         G2CountingModeRegister,
00124         G3CountingModeRegister,
00125         G3SecondGateRegister,
00126         G2SecondGateRegister,
00127         G2DMAConfigRegister,
00128         G2DMAStatusRegister,
00129         G3DMAConfigRegister,
00130         G3DMAStatusRegister,
00131         DIO32Input,
00132         DIO32Output,
00133         ClockConfigRegister,
00134         GlobalInterruptStatusRegister,
00135         DMAConfigRegister,
00136         GlobalInterruptConfigRegister,
00137         IOConfigReg0_1,
00138         IOConfigReg2_3,
00139         IOConfigReg4_5,
00140         IOConfigReg6_7,
00141         IOConfigReg8_9,
00142         IOConfigReg10_11,
00143         IOConfigReg12_13,
00144         IOConfigReg14_15,
00145         IOConfigReg16_17,
00146         IOConfigReg18_19,
00147         IOConfigReg20_21,
00148         IOConfigReg22_23,
00149         IOConfigReg24_25,
00150         IOConfigReg26_27,
00151         IOConfigReg28_29,
00152         IOConfigReg30_31,
00153         IOConfigReg32_33,
00154         IOConfigReg34_35,
00155         IOConfigReg36_37,
00156         IOConfigReg38_39,
00157         NumRegisters,
00158 } NI_660x_Register;
00159 
00160 static inline unsigned IOConfigReg(unsigned pfi_channel)
00161 {
00162         unsigned reg = IOConfigReg0_1 + pfi_channel / 2;
00163         BUG_ON(reg > IOConfigReg38_39);
00164         return reg;
00165 }
00166 
00167 enum ni_660x_register_width {
00168         DATA_1B,
00169         DATA_2B,
00170         DATA_4B
00171 };
00172 
00173 enum ni_660x_register_direction {
00174         NI_660x_READ,
00175         NI_660x_WRITE,
00176         NI_660x_READ_WRITE
00177 };
00178 
00179 enum ni_660x_pfi_output_select {
00180         pfi_output_select_high_Z = 0,
00181         pfi_output_select_counter = 1,
00182         pfi_output_select_do = 2,
00183         num_pfi_output_selects
00184 };
00185 
00186 enum ni_660x_subdevices {
00187         NI_660X_DIO_SUBDEV = 1,
00188         NI_660X_GPCT_SUBDEV_0 = 2
00189 };
00190 static inline unsigned NI_660X_GPCT_SUBDEV(unsigned index)
00191 {
00192         return NI_660X_GPCT_SUBDEV_0 + index;
00193 }
00194 
00195 typedef struct {
00196         const char *name;       // Register Name
00197         int offset;             // Offset from base address from GPCT chip
00198         enum ni_660x_register_direction direction;
00199         enum ni_660x_register_width size;       // 1 byte, 2 bytes, or 4 bytes
00200 } NI_660xRegisterData;
00201 
00202 static const NI_660xRegisterData registerData[NumRegisters] = {
00203         {"G0 Interrupt Acknowledge", 0x004, NI_660x_WRITE, DATA_2B},
00204         {"G0 Status Register", 0x004, NI_660x_READ, DATA_2B},
00205         {"G1 Interrupt Acknowledge", 0x006, NI_660x_WRITE, DATA_2B},
00206         {"G1 Status Register", 0x006, NI_660x_READ, DATA_2B},
00207         {"G01 Status Register ", 0x008, NI_660x_READ, DATA_2B},
00208         {"G0 Command Register", 0x00C, NI_660x_WRITE, DATA_2B},
00209         {"STC DIO Parallel Input", 0x00E, NI_660x_READ, DATA_2B},
00210         {"G1 Command Register", 0x00E, NI_660x_WRITE, DATA_2B},
00211         {"G0 HW Save Register", 0x010, NI_660x_READ, DATA_4B},
00212         {"G1 HW Save Register", 0x014, NI_660x_READ, DATA_4B},
00213         {"STC DIO Output", 0x014, NI_660x_WRITE, DATA_2B},
00214         {"STC DIO Control", 0x016, NI_660x_WRITE, DATA_2B},
00215         {"G0 SW Save Register", 0x018, NI_660x_READ, DATA_4B},
00216         {"G1 SW Save Register", 0x01C, NI_660x_READ, DATA_4B},
00217         {"G0 Mode Register", 0x034, NI_660x_WRITE, DATA_2B},
00218         {"G01 Joint Status 1 Register", 0x036, NI_660x_READ, DATA_2B},
00219         {"G1 Mode Register", 0x036, NI_660x_WRITE, DATA_2B},
00220         {"STC DIO Serial Input", 0x038, NI_660x_READ, DATA_2B},
00221         {"G0 Load A Register", 0x038, NI_660x_WRITE, DATA_4B},
00222         {"G01 Joint Status 2 Register", 0x03A, NI_660x_READ, DATA_2B},
00223         {"G0 Load B Register", 0x03C, NI_660x_WRITE, DATA_4B},
00224         {"G1 Load A Register", 0x040, NI_660x_WRITE, DATA_4B},
00225         {"G1 Load B Register", 0x044, NI_660x_WRITE, DATA_4B},
00226         {"G0 Input Select Register", 0x048, NI_660x_WRITE, DATA_2B},
00227         {"G1 Input Select Register", 0x04A, NI_660x_WRITE, DATA_2B},
00228         {"G0 Autoincrement Register", 0x088, NI_660x_WRITE, DATA_2B},
00229         {"G1 Autoincrement Register", 0x08A, NI_660x_WRITE, DATA_2B},
00230         {"G01 Joint Reset Register", 0x090, NI_660x_WRITE, DATA_2B},
00231         {"G0 Interrupt Enable", 0x092, NI_660x_WRITE, DATA_2B},
00232         {"G1 Interrupt Enable", 0x096, NI_660x_WRITE, DATA_2B},
00233         {"G0 Counting Mode Register", 0x0B0, NI_660x_WRITE, DATA_2B},
00234         {"G1 Counting Mode Register", 0x0B2, NI_660x_WRITE, DATA_2B},
00235         {"G0 Second Gate Register", 0x0B4, NI_660x_WRITE, DATA_2B},
00236         {"G1 Second Gate Register", 0x0B6, NI_660x_WRITE, DATA_2B},
00237         {"G0 DMA Config Register", 0x0B8, NI_660x_WRITE, DATA_2B},
00238         {"G0 DMA Status Register", 0x0B8, NI_660x_READ, DATA_2B},
00239         {"G1 DMA Config Register", 0x0BA, NI_660x_WRITE, DATA_2B},
00240         {"G1 DMA Status Register", 0x0BA, NI_660x_READ, DATA_2B},
00241         {"G2 Interrupt Acknowledge", 0x104, NI_660x_WRITE, DATA_2B},
00242         {"G2 Status Register", 0x104, NI_660x_READ, DATA_2B},
00243         {"G3 Interrupt Acknowledge", 0x106, NI_660x_WRITE, DATA_2B},
00244         {"G3 Status Register", 0x106, NI_660x_READ, DATA_2B},
00245         {"G23 Status Register", 0x108, NI_660x_READ, DATA_2B},
00246         {"G2 Command Register", 0x10C, NI_660x_WRITE, DATA_2B},
00247         {"G3 Command Register", 0x10E, NI_660x_WRITE, DATA_2B},
00248         {"G2 HW Save Register", 0x110, NI_660x_READ, DATA_4B},
00249         {"G3 HW Save Register", 0x114, NI_660x_READ, DATA_4B},
00250         {"G2 SW Save Register", 0x118, NI_660x_READ, DATA_4B},
00251         {"G3 SW Save Register", 0x11C, NI_660x_READ, DATA_4B},
00252         {"G2 Mode Register", 0x134, NI_660x_WRITE, DATA_2B},
00253         {"G23 Joint Status 1 Register", 0x136, NI_660x_READ, DATA_2B},
00254         {"G3 Mode Register", 0x136, NI_660x_WRITE, DATA_2B},
00255         {"G2 Load A Register", 0x138, NI_660x_WRITE, DATA_4B},
00256         {"G23 Joint Status 2 Register", 0x13A, NI_660x_READ, DATA_2B},
00257         {"G2 Load B Register", 0x13C, NI_660x_WRITE, DATA_4B},
00258         {"G3 Load A Register", 0x140, NI_660x_WRITE, DATA_4B},
00259         {"G3 Load B Register", 0x144, NI_660x_WRITE, DATA_4B},
00260         {"G2 Input Select Register", 0x148, NI_660x_WRITE, DATA_2B},
00261         {"G3 Input Select Register", 0x14A, NI_660x_WRITE, DATA_2B},
00262         {"G2 Autoincrement Register", 0x188, NI_660x_WRITE, DATA_2B},
00263         {"G3 Autoincrement Register", 0x18A, NI_660x_WRITE, DATA_2B},
00264         {"G23 Joint Reset Register", 0x190, NI_660x_WRITE, DATA_2B},
00265         {"G2 Interrupt Enable", 0x192, NI_660x_WRITE, DATA_2B},
00266         {"G3 Interrupt Enable", 0x196, NI_660x_WRITE, DATA_2B},
00267         {"G2 Counting Mode Register", 0x1B0, NI_660x_WRITE, DATA_2B},
00268         {"G3 Counting Mode Register", 0x1B2, NI_660x_WRITE, DATA_2B},
00269         {"G3 Second Gate Register", 0x1B6, NI_660x_WRITE, DATA_2B},
00270         {"G2 Second Gate Register", 0x1B4, NI_660x_WRITE, DATA_2B},
00271         {"G2 DMA Config Register", 0x1B8, NI_660x_WRITE, DATA_2B},
00272         {"G2 DMA Status Register", 0x1B8, NI_660x_READ, DATA_2B},
00273         {"G3 DMA Config Register", 0x1BA, NI_660x_WRITE, DATA_2B},
00274         {"G3 DMA Status Register", 0x1BA, NI_660x_READ, DATA_2B},
00275         {"32 bit Digital Input", 0x414, NI_660x_READ, DATA_4B},
00276         {"32 bit Digital Output", 0x510, NI_660x_WRITE, DATA_4B},
00277         {"Clock Config Register", 0x73C, NI_660x_WRITE, DATA_4B},
00278         {"Global Interrupt Status Register", 0x754, NI_660x_READ, DATA_4B},
00279         {"DMA Configuration Register", 0x76C, NI_660x_WRITE, DATA_4B},
00280         {"Global Interrupt Config Register", 0x770, NI_660x_WRITE, DATA_4B},
00281         {"IO Config Register 0-1", 0x77C, NI_660x_READ_WRITE, DATA_2B},
00282         {"IO Config Register 2-3", 0x77E, NI_660x_READ_WRITE, DATA_2B},
00283         {"IO Config Register 4-5", 0x780, NI_660x_READ_WRITE, DATA_2B},
00284         {"IO Config Register 6-7", 0x782, NI_660x_READ_WRITE, DATA_2B},
00285         {"IO Config Register 8-9", 0x784, NI_660x_READ_WRITE, DATA_2B},
00286         {"IO Config Register 10-11", 0x786, NI_660x_READ_WRITE, DATA_2B},
00287         {"IO Config Register 12-13", 0x788, NI_660x_READ_WRITE, DATA_2B},
00288         {"IO Config Register 14-15", 0x78A, NI_660x_READ_WRITE, DATA_2B},
00289         {"IO Config Register 16-17", 0x78C, NI_660x_READ_WRITE, DATA_2B},
00290         {"IO Config Register 18-19", 0x78E, NI_660x_READ_WRITE, DATA_2B},
00291         {"IO Config Register 20-21", 0x790, NI_660x_READ_WRITE, DATA_2B},
00292         {"IO Config Register 22-23", 0x792, NI_660x_READ_WRITE, DATA_2B},
00293         {"IO Config Register 24-25", 0x794, NI_660x_READ_WRITE, DATA_2B},
00294         {"IO Config Register 26-27", 0x796, NI_660x_READ_WRITE, DATA_2B},
00295         {"IO Config Register 28-29", 0x798, NI_660x_READ_WRITE, DATA_2B},
00296         {"IO Config Register 30-31", 0x79A, NI_660x_READ_WRITE, DATA_2B},
00297         {"IO Config Register 32-33", 0x79C, NI_660x_READ_WRITE, DATA_2B},
00298         {"IO Config Register 34-35", 0x79E, NI_660x_READ_WRITE, DATA_2B},
00299         {"IO Config Register 36-37", 0x7A0, NI_660x_READ_WRITE, DATA_2B},
00300         {"IO Config Register 38-39", 0x7A2, NI_660x_READ_WRITE, DATA_2B}
00301 };
00302 
00303 // kind of ENABLE for the second counter
00304 enum clock_config_register_bits {
00305         CounterSwap = 0x1 << 21
00306 };
00307 
00308 // ioconfigreg
00309 static inline unsigned ioconfig_bitshift(unsigned pfi_channel)
00310 {
00311         if (pfi_channel % 2)
00312                 return 0;
00313         else
00314                 return 8;
00315 }
00316 static inline unsigned pfi_output_select_mask(unsigned pfi_channel)
00317 {
00318         return 0x3 << ioconfig_bitshift(pfi_channel);
00319 }
00320 static inline unsigned pfi_output_select_bits(unsigned pfi_channel,
00321         unsigned output_select)
00322 {
00323         return (output_select & 0x3) << ioconfig_bitshift(pfi_channel);
00324 }
00325 static inline unsigned pfi_input_select_mask(unsigned pfi_channel)
00326 {
00327         return 0x7 << (4 + ioconfig_bitshift(pfi_channel));
00328 }
00329 static inline unsigned pfi_input_select_bits(unsigned pfi_channel,
00330         unsigned input_select)
00331 {
00332         return (input_select & 0x7) << (4 + ioconfig_bitshift(pfi_channel));
00333 }
00334 
00335 // dma configuration register bits
00336 static inline unsigned dma_select_mask(unsigned dma_channel)
00337 {
00338         BUG_ON(dma_channel >= MAX_DMA_CHANNEL);
00339         return 0x1f << (8 * dma_channel);
00340 }
00341 enum dma_selection {
00342         dma_selection_none = 0x1f,
00343 };
00344 static inline unsigned dma_selection_counter(unsigned counter_index)
00345 {
00346         BUG_ON(counter_index >= counters_per_chip);
00347         return counter_index;
00348 }
00349 static inline unsigned dma_select_bits(unsigned dma_channel, unsigned selection)
00350 {
00351         BUG_ON(dma_channel >= MAX_DMA_CHANNEL);
00352         return (selection << (8 * dma_channel)) & dma_select_mask(dma_channel);
00353 }
00354 static inline unsigned dma_reset_bit(unsigned dma_channel)
00355 {
00356         BUG_ON(dma_channel >= MAX_DMA_CHANNEL);
00357         return 0x80 << (8 * dma_channel);
00358 }
00359 
00360 enum global_interrupt_status_register_bits {
00361         Counter_0_Int_Bit = 0x100,
00362         Counter_1_Int_Bit = 0x200,
00363         Counter_2_Int_Bit = 0x400,
00364         Counter_3_Int_Bit = 0x800,
00365         Cascade_Int_Bit = 0x20000000,
00366         Global_Int_Bit = 0x80000000
00367 };
00368 
00369 enum global_interrupt_config_register_bits {
00370         Cascade_Int_Enable_Bit = 0x20000000,
00371         Global_Int_Polarity_Bit = 0x40000000,
00372         Global_Int_Enable_Bit = 0x80000000
00373 };
00374 
00375 // Offset of the GPCT chips from the base-adress of the card
00376 static const unsigned GPCT_OFFSET[2] = { 0x0, 0x800 };  /* First chip is at base-address +
00377                                                            0x00, etc. */
00378 
00379 /* Board description*/
00380 typedef struct {
00381         unsigned short dev_id;  /* `lspci` will show you this */
00382         const char *name;
00383         unsigned n_chips;       /* total number of TIO chips */
00384 } ni_660x_board;
00385 
00386 static const ni_660x_board ni_660x_boards[] = {
00387         {
00388               dev_id:   0x2c60,
00389               name:     "PCI-6601",
00390               n_chips:  1,
00391                 },
00392         {
00393               dev_id:   0x1310,
00394               name:     "PCI-6602",
00395               n_chips:  2,
00396                 },
00397         {
00398               dev_id:   0x1360,
00399               name:     "PXI-6602",
00400               n_chips:  2,
00401                 },
00402         {
00403               dev_id:   0x2cc0,
00404               name:     "PXI-6608",
00405               n_chips:  2,
00406                 },
00407 };
00408 
00409 #define NI_660X_MAX_NUM_CHIPS 2
00410 #define NI_660X_MAX_NUM_COUNTERS (NI_660X_MAX_NUM_CHIPS * counters_per_chip)
00411 
00412 static DEFINE_PCI_DEVICE_TABLE(ni_660x_pci_table) = {
00413         {PCI_VENDOR_ID_NATINST, 0x2c60, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
00414         {PCI_VENDOR_ID_NATINST, 0x1310, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
00415         {PCI_VENDOR_ID_NATINST, 0x1360, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
00416         {PCI_VENDOR_ID_NATINST, 0x2cc0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
00417         {0}
00418 };
00419 
00420 MODULE_DEVICE_TABLE(pci, ni_660x_pci_table);
00421 
00422 typedef struct {
00423         struct mite_struct *mite;
00424         struct ni_gpct_device *counter_dev;
00425         uint64_t pfi_direction_bits;
00426         struct mite_dma_descriptor_ring
00427         *mite_rings[NI_660X_MAX_NUM_CHIPS][counters_per_chip];
00428         spinlock_t mite_channel_lock;
00429         // interrupt_lock prevents races between interrupt and comedi_poll
00430         spinlock_t interrupt_lock;
00431         unsigned dma_configuration_soft_copies[NI_660X_MAX_NUM_CHIPS];
00432         spinlock_t soft_reg_copy_lock;
00433         unsigned short pfi_output_selects[NUM_PFI_CHANNELS];
00434 } ni_660x_private;
00435 
00436 static inline ni_660x_private *private(comedi_device * dev)
00437 {
00438         return dev->private;
00439 }
00440 
00441 /* initialized in ni_660x_find_device() */
00442 static inline const ni_660x_board *board(comedi_device * dev)
00443 {
00444         return dev->board_ptr;
00445 }
00446 
00447 #define n_ni_660x_boards (sizeof(ni_660x_boards)/sizeof(ni_660x_boards[0]))
00448 
00449 static int ni_660x_attach(comedi_device * dev, comedi_devconfig * it);
00450 static int ni_660x_detach(comedi_device * dev);
00451 static void init_tio_chip(comedi_device * dev, int chipset);
00452 static void ni_660x_select_pfi_output(comedi_device * dev, unsigned pfi_channel,
00453         unsigned output_select);
00454 
00455 static comedi_driver driver_ni_660x = {
00456       driver_name:"ni_660x",
00457       module:THIS_MODULE,
00458       attach:ni_660x_attach,
00459       detach:ni_660x_detach,
00460 };
00461 
00462 COMEDI_PCI_INITCLEANUP(driver_ni_660x, ni_660x_pci_table);
00463 
00464 static int ni_660x_find_device(comedi_device * dev, int bus, int slot);
00465 static int ni_660x_set_pfi_routing(comedi_device * dev, unsigned chan,
00466         unsigned source);
00467 
00468 /* Possible instructions for a GPCT */
00469 static int ni_660x_GPCT_rinsn(comedi_device * dev,
00470         comedi_subdevice * s, comedi_insn * insn, lsampl_t * data);
00471 static int ni_660x_GPCT_insn_config(comedi_device * dev,
00472         comedi_subdevice * s, comedi_insn * insn, lsampl_t * data);
00473 static int ni_660x_GPCT_winsn(comedi_device * dev,
00474         comedi_subdevice * s, comedi_insn * insn, lsampl_t * data);
00475 
00476 /* Possible instructions for Digital IO */
00477 static int ni_660x_dio_insn_config(comedi_device * dev,
00478         comedi_subdevice * s, comedi_insn * insn, lsampl_t * data);
00479 static int ni_660x_dio_insn_bits(comedi_device * dev,
00480         comedi_subdevice * s, comedi_insn * insn, lsampl_t * data);
00481 
00482 static inline unsigned ni_660x_num_counters(comedi_device * dev)
00483 {
00484         return board(dev)->n_chips * counters_per_chip;
00485 }
00486 
00487 static NI_660x_Register ni_gpct_to_660x_register(enum ni_gpct_register reg)
00488 {
00489         NI_660x_Register ni_660x_register;
00490         switch (reg) {
00491         case NITIO_G0_Autoincrement_Reg:
00492                 ni_660x_register = G0AutoincrementRegister;
00493                 break;
00494         case NITIO_G1_Autoincrement_Reg:
00495                 ni_660x_register = G1AutoincrementRegister;
00496                 break;
00497         case NITIO_G2_Autoincrement_Reg:
00498                 ni_660x_register = G2AutoincrementRegister;
00499                 break;
00500         case NITIO_G3_Autoincrement_Reg:
00501                 ni_660x_register = G3AutoincrementRegister;
00502                 break;
00503         case NITIO_G0_Command_Reg:
00504                 ni_660x_register = G0CommandRegister;
00505                 break;
00506         case NITIO_G1_Command_Reg:
00507                 ni_660x_register = G1CommandRegister;
00508                 break;
00509         case NITIO_G2_Command_Reg:
00510                 ni_660x_register = G2CommandRegister;
00511                 break;
00512         case NITIO_G3_Command_Reg:
00513                 ni_660x_register = G3CommandRegister;
00514                 break;
00515         case NITIO_G0_HW_Save_Reg:
00516                 ni_660x_register = G0HWSaveRegister;
00517                 break;
00518         case NITIO_G1_HW_Save_Reg:
00519                 ni_660x_register = G1HWSaveRegister;
00520                 break;
00521         case NITIO_G2_HW_Save_Reg:
00522                 ni_660x_register = G2HWSaveRegister;
00523                 break;
00524         case NITIO_G3_HW_Save_Reg:
00525                 ni_660x_register = G3HWSaveRegister;
00526                 break;
00527         case NITIO_G0_SW_Save_Reg:
00528                 ni_660x_register = G0SWSaveRegister;
00529                 break;
00530         case NITIO_G1_SW_Save_Reg:
00531                 ni_660x_register = G1SWSaveRegister;
00532                 break;
00533         case NITIO_G2_SW_Save_Reg:
00534                 ni_660x_register = G2SWSaveRegister;
00535                 break;
00536         case NITIO_G3_SW_Save_Reg:
00537                 ni_660x_register = G3SWSaveRegister;
00538                 break;
00539         case NITIO_G0_Mode_Reg:
00540                 ni_660x_register = G0ModeRegister;
00541                 break;
00542         case NITIO_G1_Mode_Reg:
00543                 ni_660x_register = G1ModeRegister;
00544                 break;
00545         case NITIO_G2_Mode_Reg:
00546                 ni_660x_register = G2ModeRegister;
00547                 break;
00548         case NITIO_G3_Mode_Reg:
00549                 ni_660x_register = G3ModeRegister;
00550                 break;
00551         case NITIO_G0_LoadA_Reg:
00552                 ni_660x_register = G0LoadARegister;
00553                 break;
00554         case NITIO_G1_LoadA_Reg:
00555                 ni_660x_register = G1LoadARegister;
00556                 break;
00557         case NITIO_G2_LoadA_Reg:
00558                 ni_660x_register = G2LoadARegister;
00559                 break;
00560         case NITIO_G3_LoadA_Reg:
00561                 ni_660x_register = G3LoadARegister;
00562                 break;
00563         case NITIO_G0_LoadB_Reg:
00564                 ni_660x_register = G0LoadBRegister;
00565                 break;
00566         case NITIO_G1_LoadB_Reg:
00567                 ni_660x_register = G1LoadBRegister;
00568                 break;
00569         case NITIO_G2_LoadB_Reg:
00570                 ni_660x_register = G2LoadBRegister;
00571                 break;
00572         case NITIO_G3_LoadB_Reg:
00573                 ni_660x_register = G3LoadBRegister;
00574                 break;
00575         case NITIO_G0_Input_Select_Reg:
00576                 ni_660x_register = G0InputSelectRegister;
00577                 break;
00578         case NITIO_G1_Input_Select_Reg:
00579                 ni_660x_register = G1InputSelectRegister;
00580                 break;
00581         case NITIO_G2_Input_Select_Reg:
00582                 ni_660x_register = G2InputSelectRegister;
00583                 break;
00584         case NITIO_G3_Input_Select_Reg:
00585                 ni_660x_register = G3InputSelectRegister;
00586                 break;
00587         case NITIO_G01_Status_Reg:
00588                 ni_660x_register = G01StatusRegister;
00589                 break;
00590         case NITIO_G23_Status_Reg:
00591                 ni_660x_register = G23StatusRegister;
00592                 break;
00593         case NITIO_G01_Joint_Reset_Reg:
00594                 ni_660x_register = G01JointResetRegister;
00595                 break;
00596         case NITIO_G23_Joint_Reset_Reg:
00597                 ni_660x_register = G23JointResetRegister;
00598                 break;
00599         case NITIO_G01_Joint_Status1_Reg:
00600                 ni_660x_register = G01JointStatus1Register;
00601                 break;
00602         case NITIO_G23_Joint_Status1_Reg:
00603                 ni_660x_register = G23JointStatus1Register;
00604                 break;
00605         case NITIO_G01_Joint_Status2_Reg:
00606                 ni_660x_register = G01JointStatus2Register;
00607                 break;
00608         case NITIO_G23_Joint_Status2_Reg:
00609                 ni_660x_register = G23JointStatus2Register;
00610                 break;
00611         case NITIO_G0_Counting_Mode_Reg:
00612                 ni_660x_register = G0CountingModeRegister;
00613                 break;
00614         case NITIO_G1_Counting_Mode_Reg:
00615                 ni_660x_register = G1CountingModeRegister;
00616                 break;
00617         case NITIO_G2_Counting_Mode_Reg:
00618                 ni_660x_register = G2CountingModeRegister;
00619                 break;
00620         case NITIO_G3_Counting_Mode_Reg:
00621                 ni_660x_register = G3CountingModeRegister;
00622                 break;
00623         case NITIO_G0_Second_Gate_Reg:
00624                 ni_660x_register = G0SecondGateRegister;
00625                 break;
00626         case NITIO_G1_Second_Gate_Reg:
00627                 ni_660x_register = G1SecondGateRegister;
00628                 break;
00629         case NITIO_G2_Second_Gate_Reg:
00630                 ni_660x_register = G2SecondGateRegister;
00631                 break;
00632         case NITIO_G3_Second_Gate_Reg:
00633                 ni_660x_register = G3SecondGateRegister;
00634                 break;
00635         case NITIO_G0_DMA_Config_Reg:
00636                 ni_660x_register = G0DMAConfigRegister;
00637                 break;
00638         case NITIO_G0_DMA_Status_Reg:
00639                 ni_660x_register = G0DMAStatusRegister;
00640                 break;
00641         case NITIO_G1_DMA_Config_Reg:
00642                 ni_660x_register = G1DMAConfigRegister;
00643                 break;
00644         case NITIO_G1_DMA_Status_Reg:
00645                 ni_660x_register = G1DMAStatusRegister;
00646                 break;
00647         case NITIO_G2_DMA_Config_Reg:
00648                 ni_660x_register = G2DMAConfigRegister;
00649                 break;
00650         case NITIO_G2_DMA_Status_Reg:
00651                 ni_660x_register = G2DMAStatusRegister;
00652                 break;
00653         case NITIO_G3_DMA_Config_Reg:
00654                 ni_660x_register = G3DMAConfigRegister;
00655                 break;
00656         case NITIO_G3_DMA_Status_Reg:
00657                 ni_660x_register = G3DMAStatusRegister;
00658                 break;
00659         case NITIO_G0_Interrupt_Acknowledge_Reg:
00660                 ni_660x_register = G0InterruptAcknowledge;
00661                 break;
00662         case NITIO_G1_Interrupt_Acknowledge_Reg:
00663                 ni_660x_register = G1InterruptAcknowledge;
00664                 break;
00665         case NITIO_G2_Interrupt_Acknowledge_Reg:
00666                 ni_660x_register = G2InterruptAcknowledge;
00667                 break;
00668         case NITIO_G3_Interrupt_Acknowledge_Reg:
00669                 ni_660x_register = G3InterruptAcknowledge;
00670                 break;
00671         case NITIO_G0_Status_Reg:
00672                 ni_660x_register = G0StatusRegister;
00673                 break;
00674         case NITIO_G1_Status_Reg:
00675                 ni_660x_register = G0StatusRegister;
00676                 break;
00677         case NITIO_G2_Status_Reg:
00678                 ni_660x_register = G0StatusRegister;
00679                 break;
00680         case NITIO_G3_Status_Reg:
00681                 ni_660x_register = G0StatusRegister;
00682                 break;
00683         case NITIO_G0_Interrupt_Enable_Reg:
00684                 ni_660x_register = G0InterruptEnable;
00685                 break;
00686         case NITIO_G1_Interrupt_Enable_Reg:
00687                 ni_660x_register = G1InterruptEnable;
00688                 break;
00689         case NITIO_G2_Interrupt_Enable_Reg:
00690                 ni_660x_register = G2InterruptEnable;
00691                 break;
00692         case NITIO_G3_Interrupt_Enable_Reg:
00693                 ni_660x_register = G3InterruptEnable;
00694                 break;
00695         default:
00696                 rt_printk("%s: unhandled register 0x%x in switch.\n",
00697                         __FUNCTION__, reg);
00698                 BUG();
00699                 return 0;
00700                 break;
00701         }
00702         return ni_660x_register;
00703 }
00704 
00705 static inline void ni_660x_write_register(comedi_device * dev,
00706         unsigned chip_index, unsigned bits, NI_660x_Register reg)
00707 {
00708         void *const write_address =
00709                 private(dev)->mite->daq_io_addr + GPCT_OFFSET[chip_index] +
00710                 registerData[reg].offset;
00711 
00712         switch (registerData[reg].size) {
00713         case DATA_2B:
00714                 writew(bits, write_address);
00715                 break;
00716         case DATA_4B:
00717                 writel(bits, write_address);
00718                 break;
00719         default:
00720                 rt_printk("%s: %s: bug! unhandled case (reg=0x%x) in switch.\n",
00721                         __FILE__, __FUNCTION__, reg);
00722                 BUG();
00723                 break;
00724         }
00725 }
00726 
00727 static inline unsigned ni_660x_read_register(comedi_device * dev,
00728         unsigned chip_index, NI_660x_Register reg)
00729 {
00730         void *const read_address =
00731                 private(dev)->mite->daq_io_addr + GPCT_OFFSET[chip_index] +
00732                 registerData[reg].offset;
00733 
00734         switch (registerData[reg].size) {
00735         case DATA_2B:
00736                 return readw(read_address);
00737                 break;
00738         case DATA_4B:
00739                 return readl(read_address);
00740                 break;
00741         default:
00742                 rt_printk("%s: %s: bug! unhandled case (reg=0x%x) in switch.\n",
00743                         __FILE__, __FUNCTION__, reg);
00744                 BUG();
00745                 break;
00746         }
00747         return 0;
00748 }
00749 
00750 static void ni_gpct_write_register(struct ni_gpct *counter, unsigned bits,
00751         enum ni_gpct_register reg)
00752 {
00753         comedi_device *dev = counter->counter_dev->dev;
00754         NI_660x_Register ni_660x_register = ni_gpct_to_660x_register(reg);
00755         ni_660x_write_register(dev, counter->chip_index, bits,
00756                 ni_660x_register);
00757 }
00758 
00759 static unsigned ni_gpct_read_register(struct ni_gpct *counter,
00760         enum ni_gpct_register reg)
00761 {
00762         comedi_device *dev = counter->counter_dev->dev;
00763         NI_660x_Register ni_660x_register = ni_gpct_to_660x_register(reg);
00764         return ni_660x_read_register(dev, counter->chip_index,
00765                 ni_660x_register);
00766 }
00767 
00768 static inline struct mite_dma_descriptor_ring *mite_ring(ni_660x_private * priv,
00769         struct ni_gpct *counter)
00770 {
00771         return priv->mite_rings[counter->chip_index][counter->counter_index];
00772 }
00773 
00774 static inline void ni_660x_set_dma_channel(comedi_device * dev,
00775         unsigned mite_channel, struct ni_gpct *counter)
00776 {
00777         unsigned long flags;
00778         comedi_spin_lock_irqsave(&private(dev)->soft_reg_copy_lock, flags);
00779         private(dev)->dma_configuration_soft_copies[counter->chip_index] &=
00780                 ~dma_select_mask(mite_channel);
00781         private(dev)->dma_configuration_soft_copies[counter->chip_index] |=
00782                 dma_select_bits(mite_channel,
00783                 dma_selection_counter(counter->counter_index));
00784         ni_660x_write_register(dev, counter->chip_index,
00785                 private(dev)->dma_configuration_soft_copies[counter->
00786                         chip_index] | dma_reset_bit(mite_channel),
00787                 DMAConfigRegister);
00788         mmiowb();
00789         comedi_spin_unlock_irqrestore(&private(dev)->soft_reg_copy_lock, flags);
00790 }
00791 
00792 static inline void ni_660x_unset_dma_channel(comedi_device * dev,
00793         unsigned mite_channel, struct ni_gpct *counter)
00794 {
00795         unsigned long flags;
00796         comedi_spin_lock_irqsave(&private(dev)->soft_reg_copy_lock, flags);
00797         private(dev)->dma_configuration_soft_copies[counter->chip_index] &=
00798                 ~dma_select_mask(mite_channel);
00799         private(dev)->dma_configuration_soft_copies[counter->chip_index] |=
00800                 dma_select_bits(mite_channel, dma_selection_none);
00801         ni_660x_write_register(dev, counter->chip_index,
00802                 private(dev)->dma_configuration_soft_copies[counter->
00803                         chip_index], DMAConfigRegister);
00804         mmiowb();
00805         comedi_spin_unlock_irqrestore(&private(dev)->soft_reg_copy_lock, flags);
00806 }
00807 
00808 static int ni_660x_request_mite_channel(comedi_device * dev,
00809         struct ni_gpct *counter, enum comedi_io_direction direction)
00810 {
00811         unsigned long flags;
00812         struct mite_channel *mite_chan;
00813 
00814         comedi_spin_lock_irqsave(&private(dev)->mite_channel_lock, flags);
00815         BUG_ON(counter->mite_chan);
00816         mite_chan =
00817                 mite_request_channel(private(dev)->mite, mite_ring(private(dev),
00818                         counter));
00819         if (mite_chan == NULL) {
00820                 comedi_spin_unlock_irqrestore(&private(dev)->mite_channel_lock,
00821                         flags);
00822                 comedi_error(dev,
00823                         "failed to reserve mite dma channel for counter.");
00824                 return -EBUSY;
00825         }
00826         mite_chan->dir = direction;
00827         ni_tio_set_mite_channel(counter, mite_chan);
00828         ni_660x_set_dma_channel(dev, mite_chan->channel, counter);
00829         comedi_spin_unlock_irqrestore(&private(dev)->mite_channel_lock, flags);
00830         return 0;
00831 }
00832 
00833 void ni_660x_release_mite_channel(comedi_device * dev, struct ni_gpct *counter)
00834 {
00835         unsigned long flags;
00836 
00837         comedi_spin_lock_irqsave(&private(dev)->mite_channel_lock, flags);
00838         if (counter->mite_chan) {
00839                 struct mite_channel *mite_chan = counter->mite_chan;
00840 
00841                 ni_660x_unset_dma_channel(dev, mite_chan->channel, counter);
00842                 ni_tio_set_mite_channel(counter, NULL);
00843                 mite_release_channel(mite_chan);
00844         }
00845         comedi_spin_unlock_irqrestore(&private(dev)->mite_channel_lock, flags);
00846 }
00847 
00848 static int ni_660x_cmd(comedi_device * dev, comedi_subdevice * s)
00849 {
00850         int retval;
00851 
00852         struct ni_gpct *counter = subdev_to_counter(s);
00853 //      const comedi_cmd *cmd = &s->async->cmd;
00854 
00855         retval = ni_660x_request_mite_channel(dev, counter, COMEDI_INPUT);
00856         if (retval) {
00857                 comedi_error(dev,
00858                         "no dma channel available for use by counter");
00859                 return retval;
00860         }
00861         ni_tio_acknowledge_and_confirm(counter, NULL, NULL, NULL, NULL);
00862         retval = ni_tio_cmd(counter, s->async);
00863 
00864         return retval;
00865 }
00866 
00867 static int ni_660x_cmdtest(comedi_device * dev, comedi_subdevice * s,
00868         comedi_cmd * cmd)
00869 {
00870         struct ni_gpct *counter = subdev_to_counter(s);
00871 
00872         return ni_tio_cmdtest(counter, cmd);
00873 }
00874 
00875 static int ni_660x_cancel(comedi_device * dev, comedi_subdevice * s)
00876 {
00877         struct ni_gpct *counter = subdev_to_counter(s);
00878         int retval;
00879 
00880         retval = ni_tio_cancel(counter);
00881         ni_660x_release_mite_channel(dev, counter);
00882         return retval;
00883 }
00884 
00885 static void set_tio_counterswap(comedi_device * dev, int chipset)
00886 {
00887         /* See P. 3.5 of the Register-Level Programming manual.  The
00888            CounterSwap bit has to be set on the second chip, otherwise
00889            it will try to use the same pins as the first chip.
00890          */
00891         if (chipset)
00892                 ni_660x_write_register(dev, chipset, CounterSwap,
00893                         ClockConfigRegister);
00894         else
00895                 ni_660x_write_register(dev, chipset, 0, ClockConfigRegister);
00896 }
00897 
00898 static void ni_660x_handle_gpct_interrupt(comedi_device * dev,
00899         comedi_subdevice * s)
00900 {
00901         ni_tio_handle_interrupt(subdev_to_counter(s), s);
00902         if (s->async->events) {
00903                 if (s->async->
00904                         events & (COMEDI_CB_EOA | COMEDI_CB_ERROR |
00905                                 COMEDI_CB_OVERFLOW)) {
00906                         ni_660x_cancel(dev, s);
00907                 }
00908                 comedi_event(dev, s);
00909         }
00910 }
00911 
00912 static irqreturn_t ni_660x_interrupt(int irq, void *d PT_REGS_ARG)
00913 {
00914         comedi_device *dev = d;
00915         comedi_subdevice *s;
00916         unsigned i;
00917         unsigned long flags;
00918 
00919         if (dev->attached == 0)
00920                 return IRQ_NONE;
00921         // lock to avoid race with comedi_poll
00922         comedi_spin_lock_irqsave(&private(dev)->interrupt_lock, flags);
00923         smp_mb();
00924         for (i = 0; i < ni_660x_num_counters(dev); ++i) {
00925                 s = dev->subdevices + NI_660X_GPCT_SUBDEV(i);
00926                 ni_660x_handle_gpct_interrupt(dev, s);
00927         }
00928         comedi_spin_unlock_irqrestore(&private(dev)->interrupt_lock, flags);
00929         return IRQ_HANDLED;
00930 }
00931 
00932 static int ni_660x_input_poll(comedi_device * dev, comedi_subdevice * s)
00933 {
00934         unsigned long flags;
00935         // lock to avoid race with comedi_poll
00936         comedi_spin_lock_irqsave(&private(dev)->interrupt_lock, flags);
00937         mite_sync_input_dma(subdev_to_counter(s)->mite_chan, s->async);
00938         comedi_spin_unlock_irqrestore(&private(dev)->interrupt_lock, flags);
00939         return comedi_buf_read_n_available(s->async);
00940 }
00941 
00942 static int ni_660x_buf_change(comedi_device * dev, comedi_subdevice * s,
00943         unsigned long new_size)
00944 {
00945         int ret;
00946 
00947         ret = mite_buf_change(mite_ring(private(dev), subdev_to_counter(s)),
00948                 s->async);
00949         if (ret < 0)
00950                 return ret;
00951 
00952         return 0;
00953 }
00954 
00955 static int ni_660x_allocate_private(comedi_device * dev)
00956 {
00957         int retval;
00958         unsigned i;
00959 
00960         if ((retval = alloc_private(dev, sizeof(ni_660x_private))) < 0)
00961                 return retval;
00962         spin_lock_init(&private(dev)->mite_channel_lock);
00963         spin_lock_init(&private(dev)->interrupt_lock);
00964         spin_lock_init(&private(dev)->soft_reg_copy_lock);
00965         for (i = 0; i < NUM_PFI_CHANNELS; ++i) {
00966                 private(dev)->pfi_output_selects[i] = pfi_output_select_counter;
00967         }
00968         return 0;
00969 }
00970 
00971 static int ni_660x_alloc_mite_rings(comedi_device * dev)
00972 {
00973         unsigned i;
00974         unsigned j;
00975 
00976         for (i = 0; i < board(dev)->n_chips; ++i) {
00977                 for (j = 0; j < counters_per_chip; ++j) {
00978                         private(dev)->mite_rings[i][j] =
00979                                 mite_alloc_ring(private(dev)->mite);
00980                         if (private(dev)->mite_rings[i][j] == NULL) {
00981                                 return -ENOMEM;
00982                         }
00983                 }
00984         }
00985         return 0;
00986 }
00987 
00988 static void ni_660x_free_mite_rings(comedi_device * dev)
00989 {
00990         unsigned i;
00991         unsigned j;
00992 
00993         for (i = 0; i < board(dev)->n_chips; ++i) {
00994                 for (j = 0; j < counters_per_chip; ++j) {
00995                         mite_free_ring(private(dev)->mite_rings[i][j]);
00996                 }
00997         }
00998 }
00999 
01000 static int ni_660x_attach(comedi_device * dev, comedi_devconfig * it)
01001 {
01002         comedi_subdevice *s;
01003         int ret;
01004         unsigned i;
01005         unsigned global_interrupt_config_bits;
01006 
01007         printk("comedi%d: ni_660x: ", dev->minor);
01008 
01009         ret = ni_660x_allocate_private(dev);
01010         if (ret < 0)
01011                 return ret;
01012         ret = ni_660x_find_device(dev, it->options[0], it->options[1]);
01013         if (ret < 0)
01014                 return ret;
01015 
01016         dev->board_name = board(dev)->name;
01017 
01018         ret = mite_setup2(private(dev)->mite, 1);
01019         if (ret < 0) {
01020                 printk("error setting up mite\n");
01021                 return ret;
01022         }
01023         comedi_set_hw_dev(dev, &private(dev)->mite->pcidev->dev);
01024         ret = ni_660x_alloc_mite_rings(dev);
01025         if (ret < 0)
01026                 return ret;
01027 
01028         printk(" %s ", dev->board_name);
01029 
01030         dev->n_subdevices = 2 + NI_660X_MAX_NUM_COUNTERS;
01031 
01032         if (alloc_subdevices(dev, dev->n_subdevices) < 0)
01033                 return -ENOMEM;
01034 
01035         s = dev->subdevices + 0;
01036         /* Old GENERAL-PURPOSE COUNTER/TIME (GPCT) subdevice, no longer used */
01037         s->type = COMEDI_SUBD_UNUSED;
01038 
01039         s = dev->subdevices + NI_660X_DIO_SUBDEV;
01040         /* DIGITAL I/O SUBDEVICE */
01041         s->type = COMEDI_SUBD_DIO;
01042         s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
01043         s->n_chan = NUM_PFI_CHANNELS;
01044         s->maxdata = 1;
01045         s->range_table = &range_digital;
01046         s->insn_bits = ni_660x_dio_insn_bits;
01047         s->insn_config = ni_660x_dio_insn_config;
01048         s->io_bits = 0;         /* all bits default to input */
01049         // we use the ioconfig registers to control dio direction, so zero output enables in stc dio control reg
01050         ni_660x_write_register(dev, 0, 0, STCDIOControl);
01051 
01052         private(dev)->counter_dev = ni_gpct_device_construct(dev,
01053                 &ni_gpct_write_register, &ni_gpct_read_register,
01054                 ni_gpct_variant_660x, ni_660x_num_counters(dev));
01055         if (private(dev)->counter_dev == NULL)
01056                 return -ENOMEM;
01057         for (i = 0; i < NI_660X_MAX_NUM_COUNTERS; ++i) {
01058                 s = dev->subdevices + NI_660X_GPCT_SUBDEV(i);
01059                 if (i < ni_660x_num_counters(dev)) {
01060                         s->type = COMEDI_SUBD_COUNTER;
01061                         s->subdev_flags =
01062                                 SDF_READABLE | SDF_WRITABLE | SDF_LSAMPL |
01063                                 SDF_CMD_READ /* | SDF_CMD_WRITE */ ;
01064                         s->n_chan = 3;
01065                         s->maxdata = 0xffffffff;
01066                         s->insn_read = ni_660x_GPCT_rinsn;
01067                         s->insn_write = ni_660x_GPCT_winsn;
01068                         s->insn_config = ni_660x_GPCT_insn_config;
01069                         s->do_cmd = &ni_660x_cmd;
01070                         s->len_chanlist = 1;
01071                         s->do_cmdtest = &ni_660x_cmdtest;
01072                         s->cancel = &ni_660x_cancel;
01073                         s->poll = &ni_660x_input_poll;
01074                         s->async_dma_dir = DMA_BIDIRECTIONAL;
01075                         s->buf_change = &ni_660x_buf_change;
01076                         s->private = &private(dev)->counter_dev->counters[i];
01077 
01078                         private(dev)->counter_dev->counters[i].chip_index =
01079                                 i / counters_per_chip;
01080                         private(dev)->counter_dev->counters[i].counter_index =
01081                                 i % counters_per_chip;
01082                 } else {
01083                         s->type = COMEDI_SUBD_UNUSED;
01084                 }
01085         }
01086         for (i = 0; i < board(dev)->n_chips; ++i) {
01087                 init_tio_chip(dev, i);
01088         }
01089         for (i = 0; i < ni_660x_num_counters(dev); ++i) {
01090                 ni_tio_init_counter(&private(dev)->counter_dev->counters[i]);
01091         }
01092         for (i = 0; i < NUM_PFI_CHANNELS; ++i) {
01093                 if (i < min_counter_pfi_chan)
01094                         ni_660x_set_pfi_routing(dev, i, pfi_output_select_do);
01095                 else
01096                         ni_660x_set_pfi_routing(dev, i,
01097                                 pfi_output_select_counter);
01098                 ni_660x_select_pfi_output(dev, i, pfi_output_select_high_Z);
01099         }
01100         /* to be safe, set counterswap bits on tio chips after all the counter
01101            outputs have been set to high impedance mode */
01102         for (i = 0; i < board(dev)->n_chips; ++i) {
01103                 set_tio_counterswap(dev, i);
01104         }
01105         if ((ret = comedi_request_irq(mite_irq(private(dev)->mite),
01106                                 &ni_660x_interrupt, IRQF_SHARED, "ni_660x",
01107                                 dev)) < 0) {
01108                 printk(" irq not available\n");
01109                 return ret;
01110         }
01111         dev->irq = mite_irq(private(dev)->mite);
01112         global_interrupt_config_bits = Global_Int_Enable_Bit;
01113         if (board(dev)->n_chips > 1)
01114                 global_interrupt_config_bits |= Cascade_Int_Enable_Bit;
01115         ni_660x_write_register(dev, 0, global_interrupt_config_bits,
01116                 GlobalInterruptConfigRegister);
01117         printk("attached\n");
01118         return 0;
01119 }
01120 
01121 static int ni_660x_detach(comedi_device * dev)
01122 {
01123         printk("comedi%d: ni_660x: remove\n", dev->minor);
01124 
01125         /* Free irq */
01126         if (dev->irq)
01127                 comedi_free_irq(dev->irq, dev);
01128 
01129         if (dev->private) {
01130                 if (private(dev)->counter_dev)
01131                         ni_gpct_device_destroy(private(dev)->counter_dev);
01132                 if (private(dev)->mite) {
01133                         ni_660x_free_mite_rings(dev);
01134                         mite_unsetup(private(dev)->mite);
01135                 }
01136         }
01137         return 0;
01138 }
01139 
01140 static int
01141 ni_660x_GPCT_rinsn(comedi_device * dev, comedi_subdevice * s,
01142         comedi_insn * insn, lsampl_t * data)
01143 {
01144         return ni_tio_rinsn(subdev_to_counter(s), insn, data);
01145 }
01146 
01147 static void init_tio_chip(comedi_device * dev, int chipset)
01148 {
01149         unsigned i;
01150 
01151         // init dma configuration register
01152         private(dev)->dma_configuration_soft_copies[chipset] = 0;
01153         for (i = 0; i < MAX_DMA_CHANNEL; ++i) {
01154                 private(dev)->dma_configuration_soft_copies[chipset] |=
01155                         dma_select_bits(i,
01156                         dma_selection_none) & dma_select_mask(i);
01157         }
01158         ni_660x_write_register(dev, chipset,
01159                 private(dev)->dma_configuration_soft_copies[chipset],
01160                 DMAConfigRegister);
01161         for(i = 0; i < NUM_PFI_CHANNELS; ++i)
01162         {
01163                 ni_660x_write_register(dev, chipset, 0, IOConfigReg(i));
01164         }
01165 }
01166 
01167 static int
01168 ni_660x_GPCT_insn_config(comedi_device * dev, comedi_subdevice * s,
01169         comedi_insn * insn, lsampl_t * data)
01170 {
01171         return ni_tio_insn_config(subdev_to_counter(s), insn, data);
01172 }
01173 
01174 static int ni_660x_GPCT_winsn(comedi_device * dev,
01175         comedi_subdevice * s, comedi_insn * insn, lsampl_t * data)
01176 {
01177         return ni_tio_winsn(subdev_to_counter(s), insn, data);
01178 }
01179 
01180 static int ni_660x_find_device(comedi_device * dev, int bus, int slot)
01181 {
01182         struct mite_struct *mite;
01183         int i;
01184 
01185         for (mite = mite_devices; mite; mite = mite->next) {
01186                 if (mite->used)
01187                         continue;
01188                 if (bus || slot) {
01189                         if (bus != mite->pcidev->bus->number ||
01190                                 slot != PCI_SLOT(mite->pcidev->devfn))
01191                                 continue;
01192                 }
01193 
01194                 for (i = 0; i < n_ni_660x_boards; i++) {
01195                         if (mite_device_id(mite) == ni_660x_boards[i].dev_id) {
01196                                 dev->board_ptr = ni_660x_boards + i;
01197                                 private(dev)->mite = mite;
01198                                 return 0;
01199                         }
01200                 }
01201         }
01202         printk("no device found\n");
01203         mite_list_devices();
01204         return -EIO;
01205 }
01206 
01207 static int ni_660x_dio_insn_bits(comedi_device * dev,
01208         comedi_subdevice * s, comedi_insn * insn, lsampl_t * data)
01209 {
01210         unsigned base_bitfield_channel = CR_CHAN(insn->chanspec);
01211 
01212         // Check if we have to write some bits
01213         if (data[0]) {
01214                 s->state &= ~(data[0] << base_bitfield_channel);
01215                 s->state |= (data[0] & data[1]) << base_bitfield_channel;
01216                 /* Write out the new digital output lines */
01217                 ni_660x_write_register(dev, 0, s->state, DIO32Output);
01218         }
01219         /* on return, data[1] contains the value of the digital
01220          * input and output lines. */
01221         data[1] =
01222                 (ni_660x_read_register(dev, 0,
01223                         DIO32Input) >> base_bitfield_channel);
01224         return 2;
01225 }
01226 
01227 static void ni_660x_select_pfi_output(comedi_device * dev, unsigned pfi_channel,
01228         unsigned output_select)
01229 {
01230         static const unsigned counter_4_7_first_pfi = 8;
01231         static const unsigned counter_4_7_last_pfi = 23;
01232         unsigned active_chipset = 0;
01233         unsigned idle_chipset = 0;
01234         unsigned active_bits;
01235         unsigned idle_bits;
01236 
01237         if(board(dev)->n_chips > 1) {
01238                 if(output_select == pfi_output_select_counter &&
01239                         pfi_channel >= counter_4_7_first_pfi &&
01240                         pfi_channel <= counter_4_7_last_pfi) {
01241                         active_chipset = 1;
01242                         idle_chipset = 0;
01243                 }else {
01244                         active_chipset = 0;
01245                         idle_chipset = 1;
01246                 }
01247         }
01248 
01249         if(idle_chipset != active_chipset) {
01250                 idle_bits = ni_660x_read_register(dev, idle_chipset, IOConfigReg(pfi_channel));
01251                 idle_bits &= ~pfi_output_select_mask(pfi_channel);
01252                 idle_bits |= pfi_output_select_bits(pfi_channel, pfi_output_select_high_Z);
01253                 ni_660x_write_register(dev, idle_chipset, idle_bits, IOConfigReg(pfi_channel));
01254         }
01255 
01256         active_bits = ni_660x_read_register(dev, active_chipset, IOConfigReg(pfi_channel));
01257         active_bits &= ~pfi_output_select_mask(pfi_channel);
01258         active_bits |= pfi_output_select_bits(pfi_channel, output_select);
01259         ni_660x_write_register(dev, active_chipset, active_bits, IOConfigReg(pfi_channel));
01260 }
01261 
01262 static int ni_660x_set_pfi_routing(comedi_device * dev, unsigned chan,
01263         unsigned source)
01264 {
01265         if (source > num_pfi_output_selects)
01266                 return -EINVAL;
01267         if (source == pfi_output_select_high_Z)
01268                 return -EINVAL;
01269         if (chan < min_counter_pfi_chan) {
01270                 if (source == pfi_output_select_counter)
01271                         return -EINVAL;
01272         } else if (chan > max_dio_pfi_chan) {
01273                 if (source == pfi_output_select_do)
01274                         return -EINVAL;
01275         }
01276         BUG_ON(chan >= NUM_PFI_CHANNELS);
01277 
01278         private(dev)->pfi_output_selects[chan] = source;
01279         if (private(dev)->pfi_direction_bits & (((uint64_t) 1) << chan))
01280                 ni_660x_select_pfi_output(dev, chan,
01281                         private(dev)->pfi_output_selects[chan]);
01282         return 0;
01283 }
01284 
01285 static unsigned ni_660x_get_pfi_routing(comedi_device * dev, unsigned chan)
01286 {
01287         BUG_ON(chan >= NUM_PFI_CHANNELS);
01288         return private(dev)->pfi_output_selects[chan];
01289 }
01290 
01291 static void ni660x_config_filter(comedi_device * dev, unsigned pfi_channel,
01292         enum ni_gpct_filter_select filter)
01293 {
01294         unsigned bits = ni_660x_read_register(dev, 0, IOConfigReg(pfi_channel));
01295         bits &= ~pfi_input_select_mask(pfi_channel);
01296         bits |= pfi_input_select_bits(pfi_channel, filter);
01297         ni_660x_write_register(dev, 0, bits, IOConfigReg(pfi_channel));
01298 }
01299 
01300 static int ni_660x_dio_insn_config(comedi_device * dev,
01301         comedi_subdevice * s, comedi_insn * insn, lsampl_t * data)
01302 {
01303         int chan = CR_CHAN(insn->chanspec);
01304 
01305         /* The input or output configuration of each digital line is
01306          * configured by a special insn_config instruction.  chanspec
01307          * contains the channel to be changed, and data[0] contains the
01308          * value COMEDI_INPUT or COMEDI_OUTPUT. */
01309 
01310         switch (data[0]) {
01311         case INSN_CONFIG_DIO_OUTPUT:
01312                 private(dev)->pfi_direction_bits |= ((uint64_t) 1) << chan;
01313                 ni_660x_select_pfi_output(dev, chan,
01314                         private(dev)->pfi_output_selects[chan]);
01315                 break;
01316         case INSN_CONFIG_DIO_INPUT:
01317                 private(dev)->pfi_direction_bits &= ~(((uint64_t) 1) << chan);
01318                 ni_660x_select_pfi_output(dev, chan, pfi_output_select_high_Z);
01319                 break;
01320         case INSN_CONFIG_DIO_QUERY:
01321                 data[1] =
01322                         (private(dev)->
01323                         pfi_direction_bits & (((uint64_t) 1) << chan)) ?
01324                         COMEDI_OUTPUT : COMEDI_INPUT;
01325                 return 0;
01326         case INSN_CONFIG_SET_ROUTING:
01327                 return ni_660x_set_pfi_routing(dev, chan, data[1]);
01328                 break;
01329         case INSN_CONFIG_GET_ROUTING:
01330                 data[1] = ni_660x_get_pfi_routing(dev, chan);
01331                 break;
01332         case INSN_CONFIG_FILTER:
01333                 ni660x_config_filter(dev, chan, data[1]);
01334                 break;
01335         default:
01336                 return -EINVAL;
01337                 break;
01338         };
01339         return 0;
01340 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines