blob: 13621d47037b85e6adcf61f5d89d806e1b8ace93 [file] [log] [blame]
/*
* 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
#define LOBYTE(W) (unsigned char)((W) & 0xFF)
#define HIBYTE(W) (unsigned char)(((W) >> 8) & 0xFF)
#define MAKEWORD(H, L) (unsigned short)((L) | ((H) << 8))
#define LOWORD(W) (unsigned short)((W) & 0xFFFF)
#define HIWORD(W) (unsigned short)(((W) >> 16) & 0xFFFF)
#define MAKEDWORD(H, L) (unsigned int)((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 */
struct addi_board {
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 */
const struct comedi_lrange *pr_AiRangelist; /* rangelist for A/D */
const struct comedi_lrange *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 channels high */
int i_NbrTTLChannel; /* Number of TTL channels */
const struct comedi_lrange *pr_TTLRangelist; /* rangelist for TTL */
int i_Dma; /* dma present or not */
int i_Timer; /* timer subdevice present or not */
unsigned char b_AvailableConvertUnit;
unsigned int ui_MinAcquisitiontimeNs; /* Minimum Acquisition in Nano secs */
unsigned int 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);
};
/* MODULE INFO STRUCTURE */
union str_ModuleInfo {
/* Incremental counter infos */
struct {
union {
struct {
unsigned char b_ModeRegister1;
unsigned char b_ModeRegister2;
unsigned char b_ModeRegister3;
unsigned char b_ModeRegister4;
} s_ByteModeRegister;
unsigned int 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 {
unsigned char b_SSIProfile;
unsigned char b_PositionTurnLength;
unsigned char b_TurnCptLength;
unsigned char b_SSIInit;
} s_SSICounterInfo;
/* TTL I/O infos */
struct {
unsigned char b_TTLInit;
unsigned char b_PortConfiguration[4];
} s_TTLIOInfo;
/* Digital I/O infos */
struct {
unsigned char b_DigitalInit;
unsigned char b_ChannelAMode;
unsigned char b_ChannelBMode;
unsigned char b_OutputMemoryEnabled;
unsigned int dw_OutputMemory;
} s_DigitalIOInfo;
/*********************/
/* 82X54 timer infos */
/*********************/
struct {
struct {
unsigned char b_82X54Init;
unsigned char b_InputClockSelection;
unsigned char b_InputClockLevel;
unsigned char b_OutputLevel;
unsigned char b_HardwareGateLevel;
unsigned int dw_ConfigurationWord;
} s_82X54TimerInfo[3];
unsigned char b_InterruptMask;
} s_82X54ModuleInfo;
/*********************/
/* Chronometer infos */
/*********************/
struct {
unsigned char b_ChronoInit;
unsigned char b_InterruptMask;
unsigned char b_PCIInputClock;
unsigned char b_TimingUnit;
unsigned char b_CycleMode;
double d_TimingInterval;
unsigned int dw_ConfigReg;
} s_ChronoModuleInfo;
/***********************/
/* Pulse encoder infos */
/***********************/
struct {
struct {
unsigned char b_PulseEncoderInit;
} s_PulseEncoderInfo[4];
unsigned int dw_SetRegister;
unsigned int dw_ControlRegister;
unsigned int dw_StatusRegister;
} s_PulseEncoderModuleInfo;
/* Tor conter infos */
struct {
struct {
unsigned char b_TorCounterInit;
unsigned char b_TimingUnit;
unsigned char b_InterruptEnable;
double d_TimingInterval;
unsigned int ul_RealTimingInterval;
} s_TorCounterInfo[2];
unsigned char b_PCIInputClock;
} s_TorCounterModuleInfo;
/* PWM infos */
struct {
struct {
unsigned char b_PWMInit;
unsigned char b_TimingUnit;
unsigned char b_InterruptEnable;
double d_LowTiming;
double d_HighTiming;
unsigned int ul_RealLowTiming;
unsigned int ul_RealHighTiming;
} s_PWMInfo[2];
unsigned char b_ClockSelection;
} s_PWMModuleInfo;
/* ETM infos */
struct {
struct {
unsigned char b_ETMEnable;
unsigned char b_ETMInterrupt;
} s_ETMInfo[2];
unsigned char b_ETMInit;
unsigned char b_TimingUnit;
unsigned char b_ClockSelection;
double d_TimingInterval;
unsigned int ul_Timing;
} s_ETMModuleInfo;
/* CDA infos */
struct {
unsigned char b_CDAEnable;
unsigned char b_CDAInterrupt;
unsigned char b_CDAInit;
unsigned char b_FctSelection;
unsigned char b_CDAReadFIFOOverflow;
} s_CDAModuleInfo;
};
/* Private structure for the addi_apci3120 driver */
struct addi_private {
int iobase;
int i_IobaseAmcc; /* base+size for AMCC chip */
int i_IobaseAddon; /* addon base address */
int i_IobaseReserved;
void __iomem *dw_AiBase;
struct pcilst_struct *amcc; /* ptr too AMCC data */
unsigned char allocated; /* we have blocked card */
unsigned char b_ValidDriver; /* driver is ok */
unsigned char b_AiContinuous; /* we do unlimited AI */
unsigned char b_AiInitialisation;
unsigned int ui_AiActualScan; /* how many scans we finished */
unsigned int ui_AiBufferPtr; /* data buffer ptr in samples */
unsigned int ui_AiNbrofChannels; /* how many channels is measured */
unsigned int ui_AiScanLength; /* Length of actual scanlist */
unsigned int ui_AiActualScanPosition; /* position in actual scan */
unsigned int *pui_AiChannelList; /* actual chanlist */
unsigned int ui_AiChannelList[32]; /* actual chanlist */
unsigned char b_AiChannelConfiguration[32]; /* actual chanlist */
unsigned int ui_AiReadData[32];
unsigned int dw_AiInitialised;
unsigned int ui_AiTimer0; /* Timer Constant for Timer0 */
unsigned int ui_AiTimer1; /* Timer constant for Timer1 */
unsigned int ui_AiFlags;
unsigned int ui_AiDataLength;
short *AiData; /* Pointer to sample data */
unsigned int ui_AiNbrofScans; /* number of scans to do */
unsigned short us_UseDma; /* To use Dma or not */
unsigned char b_DmaDoubleBuffer; /* we can use double buffering */
unsigned int ui_DmaActualBuffer; /* which buffer is used now */
/* UPDATE-0.7.57->0.7.68 */
/* unsigned int ul_DmaBufferVirtual[2]; pointers to begin of DMA buffer */
short *ul_DmaBufferVirtual[2]; /* pointers to begin of DMA buffer */
unsigned int ul_DmaBufferHw[2]; /* hw address of DMA buff */
unsigned int ui_DmaBufferSize[2]; /* size of dma buffer in bytes */
unsigned int ui_DmaBufferUsesize[2]; /* which size we may now used for transfer */
unsigned int ui_DmaBufferSamples[2]; /* size in samples */
unsigned int ui_DmaBufferPages[2]; /* number of pages in buffer */
unsigned char b_DigitalOutputRegister; /* Digital Output Register */
unsigned char b_OutputMemoryStatus;
unsigned char b_AnalogInputChannelNbr; /* Analog input channel Nbr */
unsigned char b_AnalogOutputChannelNbr; /* Analog input Output Nbr */
unsigned char b_TimerSelectMode; /* Contain data written at iobase + 0C */
unsigned char b_ModeSelectRegister; /* Contain data written at iobase + 0E */
unsigned short us_OutputRegister; /* Contain data written at iobase + 0 */
unsigned char b_InterruptState;
unsigned char b_TimerInit; /* Specify if InitTimerWatchdog was load */
unsigned char b_TimerStarted; /* Specify if timer 2 is running or not */
unsigned char b_Timer2Mode; /* Specify the timer 2 mode */
unsigned char b_Timer2Interrupt; /* Timer2 interrupt enable or disable */
unsigned char b_AiCyclicAcquisition; /* indicate cyclic acquisition */
unsigned char b_InterruptMode; /* eoc eos or dma */
unsigned char b_EocEosInterrupt; /* Enable disable eoc eos interrupt */
unsigned int ui_EocEosConversionTime;
unsigned char b_EocEosConversionTimeBase;
unsigned char b_SingelDiff;
unsigned char b_ExttrigEnable; /* To enable or disable external trigger */
/* Pointer to the current process */
struct task_struct *tsk_Current;
struct addi_board *ps_BoardInfo;
/* Hardware board infos for 1710 */
struct {
unsigned int ui_Address; /* Board address */
unsigned int ui_FlashAddress;
unsigned char b_InterruptNbr; /* Board interrupt number */
unsigned char b_SlotNumber; /* PCI slot number */
unsigned char b_BoardVersion;
unsigned int dw_MolduleConfiguration[4]; /* Module config */
} s_BoardInfos;
/* Interrupt infos */
struct {
unsigned int ul_InterruptOccur; /* 0 : No interrupt occur */
/* > 0 : Interrupt occur */
unsigned int ui_Read; /* Read FIFO */
unsigned int ui_Write; /* Write FIFO */
struct {
unsigned char b_OldModuleMask;
unsigned int ul_OldInterruptMask; /* Interrupt mask */
unsigned int ul_OldCounterLatchValue; /* Interrupt counter value */
} s_FIFOInterruptParameters[APCI1710_SAVE_INTERRUPT];
} s_InterruptParameters;
union str_ModuleInfo s_ModuleInfo[4];
unsigned int ul_TTLPortConfiguration[10];
};
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);
static int i_ADDIDATA_InsnReadEeprom(struct comedi_device *dev, struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data);