| /* |
| * Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module. |
| * |
| * ADDI-DATA GmbH |
| * Dieselstrasse 3 |
| * D-77833 Ottersweier |
| * Tel: +19(0)7223/9493-0 |
| * Fax: +49(0)7223/9493-92 |
| * http://www.addi-data-com |
| * info@addi-data.com |
| * |
| * This program is free software; you can redistribute it and/or modify it |
| * under the terms of the GNU General Public License as published by the Free |
| * Software Foundation; either version 2 of the License, or (at your option) |
| * any later version. |
| */ |
| |
| #include <linux/kernel.h> |
| #include <linux/module.h> |
| #include <linux/sched.h> |
| #include <linux/mm.h> |
| #include <linux/slab.h> |
| #include <linux/errno.h> |
| #include <linux/ioport.h> |
| #include <linux/delay.h> |
| #include <linux/interrupt.h> |
| #include <linux/timex.h> |
| #include <linux/timer.h> |
| #include <linux/pci.h> |
| #include <linux/io.h> |
| #include <linux/kmod.h> |
| #include <linux/uaccess.h> |
| #include "../../comedidev.h" |
| #include "addi_amcc_s5933.h" |
| |
| #define ERROR -1 |
| #define SUCCESS 1 |
| |
| /* variable type definition */ |
| typedef unsigned char BYTE, *PBYTE; |
| typedef short SHORT, *PSHORT; |
| typedef unsigned short USHORT, *PUSHORT; |
| typedef unsigned short WORD, *PWORD; |
| typedef int INT, *PINT;; |
| typedef unsigned int UINT, *PUINT; |
| typedef int LONG, *PLONG; /* 32-bit */ |
| typedef unsigned int ULONG, *PULONG; /* 32-bit */ |
| typedef unsigned int DWORD, *PDWORD; /* 32-bit */ |
| typedef unsigned long ULONG_PTR; |
| |
| typedef const struct comedi_lrange *PCRANGE; |
| |
| #define LOBYTE(W) (BYTE)((W) & 0xFF) |
| #define HIBYTE(W) (BYTE)(((W) >> 8) & 0xFF) |
| #define MAKEWORD(H, L) (USHORT)((L) | ((H) << 8)) |
| #define LOWORD(W) (USHORT)((W) & 0xFFFF) |
| #define HIWORD(W) (USHORT)(((W) >> 16) & 0xFFFF) |
| #define MAKEDWORD(H, L) (UINT)((L) | ((H) << 16)) |
| |
| #define ADDI_ENABLE 1 |
| #define ADDI_DISABLE 0 |
| #define APCI1710_SAVE_INTERRUPT 1 |
| |
| #define ADDIDATA_EEPROM 1 |
| #define ADDIDATA_NO_EEPROM 0 |
| #define ADDIDATA_93C76 "93C76" |
| #define ADDIDATA_S5920 "S5920" |
| #define ADDIDATA_S5933 "S5933" |
| #define ADDIDATA_9054 "9054" |
| |
| /* ADDIDATA Enable Disable */ |
| #define ADDIDATA_ENABLE 1 |
| #define ADDIDATA_DISABLE 0 |
| |
| /* Structures */ |
| |
| /* structure for the boardtype */ |
| typedef struct { |
| const char *pc_DriverName; // driver name |
| INT i_VendorId; //PCI vendor a device ID of card |
| INT i_DeviceId; |
| INT i_IorangeBase0; |
| INT i_IorangeBase1; |
| INT i_IorangeBase2; // base 2 range |
| INT i_IorangeBase3; // base 3 range |
| INT i_PCIEeprom; // eeprom present or not |
| char *pc_EepromChip; // type of chip |
| INT i_NbrAiChannel; // num of A/D chans |
| INT i_NbrAiChannelDiff; // num of A/D chans in diff mode |
| INT i_AiChannelList; // len of chanlist |
| INT i_NbrAoChannel; // num of D/A chans |
| INT i_AiMaxdata; // resolution of A/D |
| INT i_AoMaxdata; // resolution of D/A |
| PCRANGE pr_AiRangelist; // rangelist for A/D |
| PCRANGE pr_AoRangelist; // rangelist for D/A |
| |
| INT i_NbrDiChannel; // Number of DI channels |
| INT i_NbrDoChannel; // Number of DO channels |
| INT i_DoMaxdata; // data to set all chanels high |
| |
| INT i_NbrTTLChannel; // Number of TTL channels |
| PCRANGE pr_TTLRangelist; // rangelist for TTL |
| |
| INT i_Dma; // dma present or not |
| INT i_Timer; // timer subdevice present or not |
| BYTE b_AvailableConvertUnit; |
| UINT ui_MinAcquisitiontimeNs; // Minimum Acquisition in Nano secs |
| UINT ui_MinDelaytimeNs; // Minimum Delay in Nano secs |
| |
| /* interrupt and reset */ |
| void (*v_hwdrv_Interrupt)(int irq, void *d); |
| int (*i_hwdrv_Reset)(struct comedi_device *dev); |
| |
| /* Subdevice functions */ |
| |
| /* ANALOG INPUT */ |
| int (*i_hwdrv_InsnConfigAnalogInput)(struct comedi_device *dev, |
| struct comedi_subdevice *s, |
| struct comedi_insn *insn, |
| unsigned int *data); |
| int (*i_hwdrv_InsnReadAnalogInput)(struct comedi_device *dev, |
| struct comedi_subdevice *s, |
| struct comedi_insn *insn, |
| unsigned int *data); |
| int (*i_hwdrv_InsnWriteAnalogInput)(struct comedi_device *dev, |
| struct comedi_subdevice *s, |
| struct comedi_insn *insn, |
| unsigned int *data); |
| int (*i_hwdrv_InsnBitsAnalogInput)(struct comedi_device *dev, |
| struct comedi_subdevice *s, |
| struct comedi_insn *insn, |
| unsigned int *data); |
| int (*i_hwdrv_CommandTestAnalogInput)(struct comedi_device *dev, |
| struct comedi_subdevice *s, |
| struct comedi_cmd *cmd); |
| int (*i_hwdrv_CommandAnalogInput)(struct comedi_device *dev, |
| struct comedi_subdevice *s); |
| int (*i_hwdrv_CancelAnalogInput)(struct comedi_device *dev, |
| struct comedi_subdevice *s); |
| |
| /* Analog Output */ |
| int (*i_hwdrv_InsnConfigAnalogOutput)(struct comedi_device *dev, |
| struct comedi_subdevice *s, |
| struct comedi_insn *insn, |
| unsigned int *data); |
| int (*i_hwdrv_InsnWriteAnalogOutput)(struct comedi_device *dev, |
| struct comedi_subdevice *s, |
| struct comedi_insn *insn, |
| unsigned int *data); |
| int (*i_hwdrv_InsnBitsAnalogOutput)(struct comedi_device *dev, |
| struct comedi_subdevice *s, |
| struct comedi_insn *insn, |
| unsigned int *data); |
| |
| /* Digital Input */ |
| int (*i_hwdrv_InsnConfigDigitalInput) (struct comedi_device *dev, |
| struct comedi_subdevice *s, |
| struct comedi_insn *insn, |
| unsigned int *data); |
| int (*i_hwdrv_InsnReadDigitalInput) (struct comedi_device *dev, |
| struct comedi_subdevice *s, |
| struct comedi_insn *insn, |
| unsigned int *data); |
| int (*i_hwdrv_InsnWriteDigitalInput) (struct comedi_device *dev, |
| struct comedi_subdevice *s, |
| struct comedi_insn *insn, |
| unsigned int *data); |
| int (*i_hwdrv_InsnBitsDigitalInput) (struct comedi_device *dev, |
| struct comedi_subdevice *s, |
| struct comedi_insn *insn, |
| unsigned int *data); |
| |
| /* Digital Output */ |
| int (*i_hwdrv_InsnConfigDigitalOutput)(struct comedi_device *dev, |
| struct comedi_subdevice *s, |
| struct comedi_insn *insn, |
| unsigned int *data); |
| int (*i_hwdrv_InsnWriteDigitalOutput)(struct comedi_device *dev, |
| struct comedi_subdevice *s, |
| struct comedi_insn *insn, |
| unsigned int *data); |
| int (*i_hwdrv_InsnBitsDigitalOutput)(struct comedi_device *dev, |
| struct comedi_subdevice *s, |
| struct comedi_insn *insn, |
| unsigned int *data); |
| int (*i_hwdrv_InsnReadDigitalOutput)(struct comedi_device *dev, |
| struct comedi_subdevice *s, |
| struct comedi_insn *insn, |
| unsigned int *data); |
| |
| /* TIMER */ |
| int (*i_hwdrv_InsnConfigTimer)(struct comedi_device *dev, |
| struct comedi_subdevice *s, |
| struct comedi_insn *insn, unsigned int *data); |
| int (*i_hwdrv_InsnWriteTimer)(struct comedi_device *dev, |
| struct comedi_subdevice *s, struct comedi_insn *insn, |
| unsigned int *data); |
| int (*i_hwdrv_InsnReadTimer)(struct comedi_device *dev, struct comedi_subdevice *s, |
| struct comedi_insn *insn, unsigned int *data); |
| int (*i_hwdrv_InsnBitsTimer)(struct comedi_device *dev, struct comedi_subdevice *s, |
| struct comedi_insn *insn, unsigned int *data); |
| |
| /* TTL IO */ |
| int (*i_hwdr_ConfigInitTTLIO)(struct comedi_device *dev, |
| struct comedi_subdevice *s, struct comedi_insn *insn, |
| unsigned int *data); |
| int (*i_hwdr_ReadTTLIOBits)(struct comedi_device *dev, struct comedi_subdevice *s, |
| struct comedi_insn *insn, unsigned int *data); |
| int (*i_hwdr_ReadTTLIOAllPortValue)(struct comedi_device *dev, |
| struct comedi_subdevice *s, |
| struct comedi_insn *insn, |
| unsigned int *data); |
| int (*i_hwdr_WriteTTLIOChlOnOff)(struct comedi_device *dev, |
| struct comedi_subdevice *s, |
| struct comedi_insn *insn, unsigned int *data); |
| } boardtype; |
| |
| //MODULE INFO STRUCTURE |
| |
| typedef union { |
| /* Incremental counter infos */ |
| struct { |
| union { |
| struct { |
| BYTE b_ModeRegister1; |
| BYTE b_ModeRegister2; |
| BYTE b_ModeRegister3; |
| BYTE b_ModeRegister4; |
| } s_ByteModeRegister; |
| DWORD dw_ModeRegister1_2_3_4; |
| } s_ModeRegister; |
| |
| struct { |
| unsigned int b_IndexInit:1; |
| unsigned int b_CounterInit:1; |
| unsigned int b_ReferenceInit:1; |
| unsigned int b_IndexInterruptOccur:1; |
| unsigned int b_CompareLogicInit:1; |
| unsigned int b_FrequencyMeasurementInit:1; |
| unsigned int b_FrequencyMeasurementEnable:1; |
| } s_InitFlag; |
| |
| } s_SiemensCounterInfo; |
| |
| /* SSI infos */ |
| struct { |
| BYTE b_SSIProfile; |
| BYTE b_PositionTurnLength; |
| BYTE b_TurnCptLength; |
| BYTE b_SSIInit; |
| } s_SSICounterInfo; |
| |
| /* TTL I/O infos */ |
| struct { |
| BYTE b_TTLInit; |
| BYTE b_PortConfiguration[4]; |
| } s_TTLIOInfo; |
| |
| /* Digital I/O infos */ |
| struct { |
| BYTE b_DigitalInit; |
| BYTE b_ChannelAMode; |
| BYTE b_ChannelBMode; |
| BYTE b_OutputMemoryEnabled; |
| DWORD dw_OutputMemory; |
| } s_DigitalIOInfo; |
| |
| /*********************/ |
| /* 82X54 timer infos */ |
| /*********************/ |
| |
| struct { |
| struct { |
| BYTE b_82X54Init; |
| BYTE b_InputClockSelection; |
| BYTE b_InputClockLevel; |
| BYTE b_OutputLevel; |
| BYTE b_HardwareGateLevel; |
| DWORD dw_ConfigurationWord; |
| } s_82X54TimerInfo[3]; |
| BYTE b_InterruptMask; |
| } s_82X54ModuleInfo; |
| |
| /*********************/ |
| /* Chronometer infos */ |
| /*********************/ |
| |
| struct { |
| BYTE b_ChronoInit; |
| BYTE b_InterruptMask; |
| BYTE b_PCIInputClock; |
| BYTE b_TimingUnit; |
| BYTE b_CycleMode; |
| double d_TimingInterval; |
| DWORD dw_ConfigReg; |
| } s_ChronoModuleInfo; |
| |
| /***********************/ |
| /* Pulse encoder infos */ |
| /***********************/ |
| |
| struct { |
| struct { |
| BYTE b_PulseEncoderInit; |
| } s_PulseEncoderInfo[4]; |
| DWORD dw_SetRegister; |
| DWORD dw_ControlRegister; |
| DWORD dw_StatusRegister; |
| } s_PulseEncoderModuleInfo; |
| |
| /* Tor conter infos */ |
| struct { |
| struct { |
| BYTE b_TorCounterInit; |
| BYTE b_TimingUnit; |
| BYTE b_InterruptEnable; |
| double d_TimingInterval; |
| ULONG ul_RealTimingInterval; |
| } s_TorCounterInfo[2]; |
| BYTE b_PCIInputClock; |
| } s_TorCounterModuleInfo; |
| |
| /* PWM infos */ |
| struct { |
| struct { |
| BYTE b_PWMInit; |
| BYTE b_TimingUnit; |
| BYTE b_InterruptEnable; |
| double d_LowTiming; |
| double d_HighTiming; |
| ULONG ul_RealLowTiming; |
| ULONG ul_RealHighTiming; |
| } s_PWMInfo[2]; |
| BYTE b_ClockSelection; |
| } s_PWMModuleInfo; |
| |
| /* ETM infos */ |
| struct { |
| struct { |
| BYTE b_ETMEnable; |
| BYTE b_ETMInterrupt; |
| } s_ETMInfo[2]; |
| BYTE b_ETMInit; |
| BYTE b_TimingUnit; |
| BYTE b_ClockSelection; |
| double d_TimingInterval; |
| ULONG ul_Timing; |
| } s_ETMModuleInfo; |
| |
| /* CDA infos */ |
| struct { |
| BYTE b_CDAEnable; |
| BYTE b_CDAInterrupt; |
| BYTE b_CDAInit; |
| BYTE b_FctSelection; |
| BYTE b_CDAReadFIFOOverflow; |
| } s_CDAModuleInfo; |
| |
| } str_ModuleInfo; |
| |
| /* Private structure for the addi_apci3120 driver */ |
| typedef struct { |
| |
| INT iobase; |
| INT i_IobaseAmcc; // base+size for AMCC chip |
| INT i_IobaseAddon; //addon base address |
| INT i_IobaseReserved; |
| ULONG_PTR dw_AiBase; |
| struct pcilst_struct *amcc; // ptr too AMCC data |
| BYTE allocated; // we have blocked card |
| BYTE b_ValidDriver; // driver is ok |
| BYTE b_AiContinuous; // we do unlimited AI |
| BYTE b_AiInitialisation; |
| UINT ui_AiActualScan; //how many scans we finished |
| UINT ui_AiBufferPtr; // data buffer ptr in samples |
| UINT ui_AiNbrofChannels; // how many channels is measured |
| UINT ui_AiScanLength; // Length of actual scanlist |
| UINT ui_AiActualScanPosition; // position in actual scan |
| PUINT pui_AiChannelList; // actual chanlist |
| UINT ui_AiChannelList[32]; // actual chanlist |
| BYTE b_AiChannelConfiguration[32]; // actual chanlist |
| UINT ui_AiReadData[32]; |
| DWORD dw_AiInitialised; |
| UINT ui_AiTimer0; //Timer Constant for Timer0 |
| UINT ui_AiTimer1; //Timer constant for Timer1 |
| UINT ui_AiFlags; |
| UINT ui_AiDataLength; |
| short *AiData; // Pointer to sample data |
| UINT ui_AiNbrofScans; // number of scans to do |
| USHORT us_UseDma; // To use Dma or not |
| BYTE b_DmaDoubleBuffer; // we can use double buffering |
| UINT ui_DmaActualBuffer; // which buffer is used now |
| //*UPDATE-0.7.57->0.7.68 |
| //ULONG ul_DmaBufferVirtual[2];// pointers to begin of DMA buffer |
| short *ul_DmaBufferVirtual[2]; // pointers to begin of DMA buffer |
| ULONG ul_DmaBufferHw[2]; // hw address of DMA buff |
| UINT ui_DmaBufferSize[2]; // size of dma buffer in bytes |
| UINT ui_DmaBufferUsesize[2]; // which size we may now used for transfer |
| UINT ui_DmaBufferSamples[2]; // size in samples |
| UINT ui_DmaBufferPages[2]; // number of pages in buffer |
| BYTE b_DigitalOutputRegister; // Digital Output Register |
| BYTE b_OutputMemoryStatus; |
| BYTE b_AnalogInputChannelNbr; // Analog input channel Nbr |
| BYTE b_AnalogOutputChannelNbr; // Analog input Output Nbr |
| BYTE b_TimerSelectMode; // Contain data written at iobase + 0C |
| BYTE b_ModeSelectRegister; // Contain data written at iobase + 0E |
| USHORT us_OutputRegister; // Contain data written at iobase + 0 |
| BYTE b_InterruptState; |
| BYTE b_TimerInit; // Specify if InitTimerWatchdog was load |
| BYTE b_TimerStarted; // Specify if timer 2 is running or not |
| BYTE b_Timer2Mode; // Specify the timer 2 mode |
| BYTE b_Timer2Interrupt; //Timer2 interrupt enable or disable |
| BYTE b_AiCyclicAcquisition; // indicate cyclic acquisition |
| BYTE b_InterruptMode; // eoc eos or dma |
| BYTE b_EocEosInterrupt; // Enable disable eoc eos interrupt |
| UINT ui_EocEosConversionTime; |
| BYTE b_EocEosConversionTimeBase; |
| BYTE b_SingelDiff; |
| BYTE b_ExttrigEnable; /* To enable or disable external trigger */ |
| |
| /* Pointer to the current process */ |
| struct task_struct *tsk_Current; |
| boardtype *ps_BoardInfo; |
| |
| /* Hardware board infos for 1710 */ |
| struct { |
| UINT ui_Address; /* Board address */ |
| UINT ui_FlashAddress; |
| BYTE b_InterruptNbr; /* Board interrupt number */ |
| BYTE b_SlotNumber; /* PCI slot number */ |
| BYTE b_BoardVersion; |
| DWORD dw_MolduleConfiguration[4]; /* Module config */ |
| } s_BoardInfos; |
| |
| /* Interrupt infos */ |
| struct { |
| ULONG ul_InterruptOccur; /* 0 : No interrupt occur */ |
| /* > 0 : Interrupt occur */ |
| UINT ui_Read; /* Read FIFO */ |
| UINT ui_Write; /* Write FIFO */ |
| struct { |
| BYTE b_OldModuleMask; |
| ULONG ul_OldInterruptMask; /* Interrupt mask */ |
| ULONG ul_OldCounterLatchValue; /* Interrupt counter value */ |
| } s_FIFOInterruptParameters[APCI1710_SAVE_INTERRUPT]; |
| } s_InterruptParameters; |
| |
| str_ModuleInfo s_ModuleInfo[4]; |
| ULONG ul_TTLPortConfiguration[10]; |
| |
| } addi_private; |
| |
| static unsigned short pci_list_builded; /* set to 1 when list of card is known */ |
| |
| /* Function declarations */ |
| static int i_ADDI_Attach(struct comedi_device *dev, struct comedi_devconfig *it); |
| static int i_ADDI_Detach(struct comedi_device *dev); |
| static int i_ADDI_Reset(struct comedi_device *dev); |
| |
| static irqreturn_t v_ADDI_Interrupt(int irq, void *d PT_REGS_ARG); |
| static int i_ADDIDATA_InsnReadEeprom(struct comedi_device *dev, struct comedi_subdevice *s, |
| struct comedi_insn *insn, unsigned int *data); |