⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rtd520.c

📁 rtlinux-3.2-pre3.tar.bz2 rtlinux3.2-pre3的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
/*    comedi/drivers/rtd520.c    Comedi driver for Real Time Devices (RTD) PCI4520/DM7520        COMEDI - Linux Control and Measurement Device Interface    Copyright (C) 2001 David A. Schleef <ds@schleef.org>    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.    This program is distributed in the hope that it will be useful,    but WITHOUT ANY WARRANTY; without even the implied warranty of    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the    GNU General Public License for more details.    You should have received a copy of the GNU General Public License    along with this program; if not, write to the Free Software    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.*//*Driver: rtd520.oDescription: Real Time Devices PCI4520/DM7520Author: Dan ChristianDevices: [Real Time Devices] DM7520HR-1 (DM7520), DM7520HR-8 (DM7520-8),  PCI4520 (PCI4520), PCI4520-8 (PCI4520-8)Status: Works.  Only tested on DM7520-8.  Not SMP safe.Configuration options:  [0] - PCI bus of device (optional)          If bus/slot is not specified, the first available PCI          device will be used.  [1] - PCI slot of device (optional)*//*    Created by Dan Christian, NASA Ames Research Center.    The PCI4520 is a PCI card.  The DM7520 is a PC/104-plus card.    Both have:    8/16 12 bit ADC with FIFO and channel gain table    8 bits high speed digital out (for external MUX) (or 8 in or 8 out)    8 bits high speed digital in with FIFO and interrupt on change (or 8 IO)    2 12 bit DACs with FIFOs    2 bits output    2 bits input    bus mastering DMA    timers: ADC sample, pacer, burst, about, delay, DA1, DA2    sample counter    3 user timer/counters (8254)    external interrupt    The DM7520 has slightly fewer features (fewer gain steps).    These boards can support external multiplexors and multi-board    synchronization, but this driver doesn't support that.    Board docs: http://www.rtdusa.com/PC104/DM/analog%20IO/dm7520.htm    Data sheet: http://www.rtdusa.com/pdf/dm7520.pdf    Example source: http://www.rtdusa.com/examples/dm/dm7520.zip    Call them and ask for the register level manual.    PCI chip: http://www.plxtech.com/products/toolbox/9080.htm    Notes:    This board is memory mapped.  There is some IO stuff, but it isn't needed.    I use a pretty loose naming style within the driver (rtd_blah).    All externally visible names should be rtd520_blah.    I use camelCase for structures (and inside them).    I may also use upper CamelCase for function names (old habit).    This board is somewhat related to the RTD PCI4400 board.    I borrowed heavily from the ni_mio_common, ni_atmio16d, mite, and    das1800, since they have the best documented code.  Driver    cb_pcidas64.c uses the same DMA controller.    As far as I can tell, the About interrupt doesnt work if Sample is    also enabled.  It turns out that About really isn't needed, since    we always count down samples read.    There was some timer/counter code, but it didn't follow the right API.*//*  driver status:  Analog-In supports instruction and command mode.    With DMA, you can sample at 1.15Mhz with 70% idle on a 400Mhz K6-2  (single channel, 64K read buffer).  I get random system lockups when  using DMA with ALI-15xx based systems.  I haven't been able to test  any other chipsets.  The lockups happen soon after the start of an  acquistion, not in the middle of a long run.  Without DMA, you can do 620Khz sampling with 20% idle on a 400Mhz K6-2  (with a 256K read buffer).    Digital-IO and Analog-Out only support instruction mode.*/#include <linux/comedidev.h>#include <linux/delay.h>#include <linux/pci.h>/*======================================================================  Driver specific stuff (tunable)======================================================================*//* Enable this to test the new DMA support. You may get hard lock ups *//*#define USE_DMA*//* We really only need 2 buffers.  More than that means being much   smarter about knowing which ones are full. */#define DMA_CHAIN_COUNT 2	/* max DMA segments/buffers in a ring (min 2)*//* Target period for periodic transfers.  This sets the user read latency. *//* Note: There are certain rates where we give this up and transfer 1/2 FIFO *//* If this is too low, efficiency is poor */#define TRANS_TARGET_PERIOD 10000000	/* 10 ms (in nanoseconds) *//* Set a practical limit on how long a list to support (affects memory use) *//* The board support a channel list up to the FIFO length (1K or 8K) */#define RTD_MAX_CHANLIST	128	/* max channel list that we allow *//* tuning for ai/ao instruction done polling */#ifdef FAST_SPIN#define WAIT_QUIETLY	/* as nothing, spin on done bit */#define RTD_ADC_TIMEOUT	66000		/* 2 msec at 33mhz bus rate */#define RTD_DAC_TIMEOUT	66000#define RTD_DMA_TIMEOUT	33000		/* 1 msec */#else/* by delaying, power and electrical noise are reduced somewhat */#define WAIT_QUIETLY	comedi_udelay (1)#define RTD_ADC_TIMEOUT	2000		/* in usec */#define RTD_DAC_TIMEOUT	2000		/* in usec */#define RTD_DMA_TIMEOUT	1000		/* in usec */#endif/*======================================================================  Board specific stuff======================================================================*//* registers  */#define PCI_VENDOR_ID_RTD	0x1435/*  The board has three memory windows: las0, las1, and lcfg (the PCI chip)  Las1 has the data and can be burst DMAed 32bits at a time.*/#define LCFG_PCIINDEX	0/* PCI region 1 is a 256 byte IO space mapping.  Use??? */#define LAS0_PCIINDEX	2		/* PCI memory resources */#define LAS1_PCIINDEX	3#define LCFG_PCISIZE	0x100#define LAS0_PCISIZE	0x200#define LAS1_PCISIZE	0x10#define RTD_CLOCK_RATE	8000000		/* 8Mhz onboard clock */#define RTD_CLOCK_BASE	125		/* clock period in ns *//* Note: these speed are slower than the spec, but fit the counter resolution*/#define RTD_MAX_SPEED	1625		/* when sampling, in nanoseconds *//* max speed if we don't have to wait for settling */#define RTD_MAX_SPEED_1	875		/* if single channel, in nanoseconds */#define RTD_MIN_SPEED	2097151875	/* (24bit counter) in nanoseconds *//* min speed when only 1 channel (no burst counter) */#define RTD_MIN_SPEED_1	5000000		/* 200Hz, in nanoseconds */#include "rtd520.h"#include "plx9080.h"/* Setup continuous ring of 1/2 FIFO transfers.  See RTD manual p91 */#define DMA_MODE_BITS (\		       PLX_LOCAL_BUS_16_WIDE_BITS \		       | PLX_DMA_EN_READYIN_BIT \		       | PLX_DMA_LOCAL_BURST_EN_BIT \		       | PLX_EN_CHAIN_BIT \		       | PLX_DMA_INTR_PCI_BIT \		       | PLX_LOCAL_ADDR_CONST_BIT \		       | PLX_DEMAND_MODE_BIT)#define DMA_TRANSFER_BITS (\/* descriptors in PCI memory*/ 	PLX_DESC_IN_PCI_BIT \/* interrupt at end of block */ | PLX_INTR_TERM_COUNT \/* from board to PCI */		| PLX_XFER_LOCAL_TO_PCI) /*======================================================================  Comedi specific stuff======================================================================*//*  The board has 3 input modes and the gains of 1,2,4,...32 (, 64, 128)*/static comedi_lrange rtd_ai_7520_range = { 18, {					/* +-5V input range gain steps */    BIP_RANGE(5.0),    BIP_RANGE(5.0/2),    BIP_RANGE(5.0/4),    BIP_RANGE(5.0/8),    BIP_RANGE(5.0/16),    BIP_RANGE(5.0/32),					/* +-10V input range gain steps */    BIP_RANGE(10.0),    BIP_RANGE(10.0/2),    BIP_RANGE(10.0/4),    BIP_RANGE(10.0/8),    BIP_RANGE(10.0/16),    BIP_RANGE(10.0/32),					/* +10V input range gain steps */    UNI_RANGE(10.0),    UNI_RANGE(10.0/2),    UNI_RANGE(10.0/4),    UNI_RANGE(10.0/8),    UNI_RANGE(10.0/16),    UNI_RANGE(10.0/32),}};/* PCI4520 has two more gains (6 more entries) */static comedi_lrange rtd_ai_4520_range = { 24, {					/* +-5V input range gain steps */    BIP_RANGE(5.0),    BIP_RANGE(5.0/2),    BIP_RANGE(5.0/4),    BIP_RANGE(5.0/8),    BIP_RANGE(5.0/16),    BIP_RANGE(5.0/32),    BIP_RANGE(5.0/64),    BIP_RANGE(5.0/128),					/* +-10V input range gain steps */    BIP_RANGE(10.0),    BIP_RANGE(10.0/2),    BIP_RANGE(10.0/4),    BIP_RANGE(10.0/8),    BIP_RANGE(10.0/16),    BIP_RANGE(10.0/32),    BIP_RANGE(10.0/64),    BIP_RANGE(10.0/128),					/* +10V input range gain steps */    UNI_RANGE(10.0),    UNI_RANGE(10.0/2),    UNI_RANGE(10.0/4),    UNI_RANGE(10.0/8),    UNI_RANGE(10.0/16),    UNI_RANGE(10.0/32),    UNI_RANGE(10.0/64),    UNI_RANGE(10.0/128),}};/* Table order matches range values */static comedi_lrange rtd_ao_range = { 4, {    RANGE(0, 5),    RANGE(0, 10),    RANGE(-5, 5),    RANGE(-10, 10),}};/*  Board descriptions */typedef struct rtdBoard_struct{    char	*name;			/* must be first */    int		device_id;    int		aiChans;    int		aiBits;    int		aiMaxGain;    int		fifoLen;    int		range10Start;		/* start of +-10V range */    int		rangeUniStart;		/* start of +10V range */} rtdBoard;static rtdBoard rtd520Boards[] = {    {	name:		"DM7520",	device_id:	0x7520,	aiChans:	16,	aiBits:		12,	aiMaxGain:	32,	fifoLen:	1024,	range10Start:	6,	rangeUniStart:	12,    },    {	name:		"DM7520-8",	device_id:	0x7520,	aiChans:	16,	aiBits:		12,	aiMaxGain:	32,	fifoLen:	8192,	range10Start:	6,	rangeUniStart:	12,    },    {	name:		"PCI4520",	device_id:	0x4520,	aiChans:	16,	aiBits:		12,	aiMaxGain:	128,	fifoLen:	1024,	range10Start:	8,	rangeUniStart:	16,    },    {	name:		"PCI4520-8",	device_id:	0x4520,	aiChans:	16,	aiBits:		12,	aiMaxGain:	128,	fifoLen:	8192,	range10Start:	8,	rangeUniStart:	16,    },};static struct pci_device_id rtd520_pci_table[] __devinitdata = {	{ PCI_VENDOR_ID_RTD, 0x7520, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },	{ PCI_VENDOR_ID_RTD, 0x4520, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },	{ 0 }};MODULE_DEVICE_TABLE(pci, rtd520_pci_table);/* * Useful for shorthand access to the particular board structure */#define thisboard ((rtdBoard *)dev->board_ptr)/*   This structure is for data unique to this hardware driver.   This is also unique for each board in the system.*/typedef struct{					/* memory mapped board structures */    void	*las0;    void	*las1;    void	*lcfg;    unsigned long	intCount;	/* interrupt count */    long		aiCount;	/* total transfer size (samples) */    int			transCount;	/* # to tranfer data. 0->1/2FIFO*/    int			flags;		/* flag event modes */					/* PCI device info */    struct pci_dev *pci_dev;    /* channel list info */    /* chanBipolar tracks whether a channel is bipolar (and needs +2048) */    unsigned char	chanBipolar[RTD_MAX_CHANLIST/8]; /* bit array */    /* read back data */    lsampl_t	aoValue[2];		/* Used for AO read back */    /* timer gate (when enabled) */    u8		utcGate[4];		/* 1 extra allows simple range check */    /* shadow registers affect other registers, but cant be read back */    /* The macros below update these on writes */    u16		intMask;		/* interrupt mask */    u16		intClearMask;		/* interrupt clear mask */    u8		utcCtrl[4];		/* crtl mode for 3 utc + read back */    u8		dioStatus;		/* could be read back (dio0Ctrl) */#ifdef USE_DMA    /* Always DMA 1/2 FIFO.  Buffer (dmaBuff?) is (at least) twice that size.       After transferring, interrupt processes 1/2 FIFO and passes to comedi */    s16		dma0Offset;		/* current processing offset (0, 1/2)*/    uint16_t *dma0Buff[DMA_CHAIN_COUNT];	/* DMA buffers (for ADC) */    dma_addr_t dma0BuffPhysAddr[DMA_CHAIN_COUNT]; /* physical addresses */    struct plx_dma_desc *dma0Chain;  /* DMA descriptor ring for dmaBuff*/    dma_addr_t dma0ChainPhysAddr; /* physical addresses */    /* shadow registers */    u8		dma0Control;    u8		dma1Control;#endif /* USE_DMA */} rtdPrivate;/* bit defines for "flags" */#define SEND_EOS	0x01		/* send End Of Scan events */#define DMA0_ACTIVE	0x02		/* DMA0 is active */#define DMA1_ACTIVE	0x04		/* DMA1 is active *//* Macros for accessing channel list bit array */#define CHAN_ARRAY_TEST(array,index) \	(((array)[(index)/8] >> ((index) & 0x7)) & 0x1)#define CHAN_ARRAY_SET(array,index) \	(((array)[(index)/8] |= 1 << ((index) & 0x7)))#define CHAN_ARRAY_CLEAR(array,index) \	(((array)[(index)/8] &= ~(1 << ((index) & 0x7))))/* * most drivers define the following macro to make it easy to * access the private structure. */#define devpriv ((rtdPrivate *)dev->private)/* Macros to access registers *//* Reset board */#define RtdResetBoard(dev) \    writel (0, devpriv->las0+LAS0_BOARD_RESET)/* Reset channel gain table read pointer */#define RtdResetCGT(dev) \    writel (0, devpriv->las0+LAS0_CGT_RESET)/* Reset channel gain table read and write pointers */#define RtdClearCGT(dev) \    writel (0, devpriv->las0+LAS0_CGT_CLEAR)/* Reset channel gain table read and write pointers */#define RtdEnableCGT(dev,v) \    writel ((v > 0) ? 1 : 0, devpriv->las0+LAS0_CGT_ENABLE)/* Write channel gain table entry */#define RtdWriteCGTable(dev,v) \    writel (v, devpriv->las0+LAS0_CGT_WRITE)/* Write Channel Gain Latch */#define RtdWriteCGLatch(dev,v) \    writel (v, devpriv->las0+LAS0_CGL_WRITE)/* Reset ADC FIFO */#define RtdAdcClearFifo(dev) \    writel (0, devpriv->las0+LAS0_ADC_FIFO_CLEAR)/* Set ADC start conversion source select (write only) */#define RtdAdcConversionSource(dev,v) \    writel (v, devpriv->las0+LAS0_ADC_CONVERSION)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -