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

📄 cb_pcidas.c

📁 rtlinux-3.2-pre3.tar.bz2 rtlinux3.2-pre3的源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
/*    cb_pcidas.c    Developed by Ivan Martinez and Frank Mori Hess, with valuable help from    David Schleef and the rest of the Comedi developers comunity.    Copyright (C) 2001-2003 Ivan Martinez <imr@oersted.dtu.dk>    Copyright (C) 2001,2002 Frank Mori Hess <fmhess@users.sourceforge.net>    COMEDI - Linux Control and Measurement Device Interface    Copyright (C) 1997-8 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: cb_pcidas.oDescription: Driver for the ComputerBoards/MeasurementComputing cards  of the PCI-DAS series with the AMCC S5933 PCI controller.Author: Ivan Martinez <imr@oersted.dtu.dk>,  Frank Mori Hess <fmhess@users.sourceforge.net>Updated: 2003-3-11Devices: [Measurement Computing] PCI-DAS1602/16 (cb_pcidas),  PCI-DAS1602/16jr, PCI-DAS1602/12, PCI-DAS1200, PCI-DAS1200jr,  PCI-DAS1000, PCI-DAS1001, PCI_DAS1002Status:  There are many reports of the driver being used with most of the  supported cards. Despite no detailed log is maintained, it can  be said that the driver is quite tested and stable.  The boards may be autocalibrated using the comedi_calibrate  utility.	Configuration options:  [0] - PCI bus of device (optional)  [1] - PCI slot of device (optional)  If bus/slot is not specified, the first supported  PCI device found will be used.For commands, the scanned channels must be consecutive(i.e. 4-5-6-7, 2-3-4,...), and must all have the samerange and aref.*//*TODO:analog triggering on 1602 series*/#include <linux/comedidev.h>#include <linux/delay.h>#include <linux/pci.h>#include "8253.h"#include "8255.h"#include "amcc_s5933.h"#include "comedi_fc.h"#undef CB_PCIDAS_DEBUG	// disable debugging code//#define CB_PCIDAS_DEBUG	// enable debugging code// PCI vendor number of ComputerBoards/MeasurementComputing#define PCI_VENDOR_ID_CB	0x1307#define TIMER_BASE 100	// 10MHz master clock#define AI_BUFFER_SIZE 1024	// maximum fifo size of any supported board#define AO_BUFFER_SIZE 1024	// maximum fifo size of any supported board#define NUM_CHANNELS_8800 8#define NUM_CHANNELS_7376 1#define NUM_CHANNELS_8402 2#define NUM_CHANNELS_DAC08 1/* PCI-DAS base addresses */// indices of base address regions#define S5933_BADRINDEX 0#define CONT_STAT_BADRINDEX 1#define ADC_FIFO_BADRINDEX 2#define PACER_BADRINDEX 3#define AO_BADRINDEX 4// sizes of io regions#define CONT_STAT_SIZE 10#define ADC_FIFO_SIZE 4#define PACER_SIZE 12#define AO_SIZE 4/* Control/Status registers */#define INT_ADCFIFO	0	// INTERRUPT / ADC FIFO register#define   INT_EOS 0x1	// interrupt end of scan#define   INT_FHF 0x2	// interrupt fifo half full#define   INT_FNE 0x3	// interrupt fifo not empty#define   INT_MASK 0x3	// mask of interrupt select bits#define   INTE 0x4	// interrupt enable#define   DAHFIE 0x8	// dac half full interrupt enable#define   EOAIE	0x10	// end of aquisition interrupt enable#define   DAHFI	0x20	// dac half full read status / write interrupt clear#define   EOAI 0x40	// read end of acq. interrupt status / write clear#define   INT 0x80	// read interrupt status / write clear#define   EOBI 0x200	// read end of burst interrupt status#define   ADHFI 0x400	// read half-full interrupt status#define   ADNEI 0x800	// read fifo not empty interrupt latch status#define   ADNE 0x1000	// read, fifo not empty (realtime, not latched) status#define   DAEMIE	0x1000	// write, dac empty interrupt enable#define   LADFUL 0x2000	// read fifo overflow / write clear#define   DAEMI 0x4000	// dac fifo empty interrupt status / write clear#define ADCMUX_CONT	2	// ADC CHANNEL MUX AND CONTROL register#define   BEGIN_SCAN(x)	((x) & 0xf)#define   END_SCAN(x)	(((x) & 0xf) << 4)#define   GAIN_BITS(x)	(((x) & 0x3) << 8)#define   UNIP	0x800	// Analog front-end unipolar for range#define   SE	0x400	// Inputs in single-ended mode#define   PACER_MASK	0x3000	// pacer source bits#define   PACER_INT 0x1000	// internal pacer#define   PACER_EXT_FALL	0x2000	// external falling edge#define   PACER_EXT_RISE	0x3000	// external rising edge#define   EOC	0x4000	// adc not busy#define TRIG_CONTSTAT 4 // TRIGGER CONTROL/STATUS register#define   SW_TRIGGER 0x1	// software start trigger#define   EXT_TRIGGER 0x2	// external start trigger#define   ANALOG_TRIGGER 0x3	// external analog trigger#define   TRIGGER_MASK	0x3	// mask of bits that determine start trigger#define   TGEN	0x10	// enable external start trigger#define   BURSTE 0x20	// burst mode enable#define   XTRCL	0x80	// clear external trigger#define CALIBRATION_REG	6	// CALIBRATION register#define   SELECT_8800_BIT	0x100	// select 8800 caldac#define   SELECT_TRIMPOT_BIT	0x200	// select ad7376 trim pot#define   SELECT_DAC08_BIT	0x400	// select dac08 caldac#define   CAL_SRC_BITS(x)	(((x) & 0x7) << 11)#define   CAL_EN_BIT	0x4000	// read calibration source instead of analog input channel 0#define   SERIAL_DATA_IN_BIT	0x8000	// serial data stream going to 8800 and 7376#define DAC_CSR	0x8	// dac control and status registerenum dac_csr_bits{	DACEN = 0x2,	// dac enable	DAC_MODE_UPDATE_BOTH = 0x80,	// update both dacs when dac0 is written};static inline unsigned int DAC_RANGE( unsigned int channel, unsigned int range){	return ( range & 0x3 ) << ( 8 + 2 * ( channel & 0x1 ) );}static inline unsigned int DAC_RANGE_MASK( unsigned int channel ){	return 0x3 << ( 8 + 2 * ( channel & 0x1 ) );};// bits for 1602 series onlyenum dac_csr_bits_1602{	DAC_EMPTY = 0x1,	// dac fifo empty, read, write clear	DAC_START = 0x4,	// start/arm dac fifo operations	DAC_PACER_MASK = 0x18,	// bits that set dac pacer source	DAC_PACER_INT = 0x8,	// dac internal pacing	DAC_PACER_EXT_FALL = 0x10,	// dac external pacing, falling edge	DAC_PACER_EXT_RISE = 0x18,	// dac external pacing, rising edge};static inline unsigned int DAC_CHAN_EN( unsigned int channel ){	return 1 << ( 5 + ( channel & 0x1 ) );	// enable channel 0 or 1};/* analog input fifo */#define ADCDATA	0	// ADC DATA register#define ADCFIFOCLR	2	// ADC FIFO CLEAR// pacer, counter, dio registers#define ADC8254 0#define DIO_8255 4#define DAC8254 8// analog output registers for 100x, 1200 seriesstatic inline unsigned int DAC_DATA_REG( unsigned int channel ){	return 2 * ( channel & 0x1 );}/* analog output registers for 1602 series*/#define DACDATA	0	// DAC DATA register#define DACFIFOCLR	2	// DAC FIFO CLEAR// bit in hexadecimal representation of range index that indicates unipolar input range#define IS_UNIPOLAR 0x4// analog input ranges for most boardsstatic comedi_lrange cb_pcidas_ranges ={	8,	{		BIP_RANGE(10),		BIP_RANGE(5),		BIP_RANGE(2.5),		BIP_RANGE(1.25),		UNI_RANGE(10),		UNI_RANGE(5),		UNI_RANGE(2.5),		UNI_RANGE(1.25)	}};// pci-das1001 input rangesstatic comedi_lrange cb_pcidas_alt_ranges ={	8,	{		BIP_RANGE(10),		BIP_RANGE(1),		BIP_RANGE(0.1),		BIP_RANGE(0.01),		UNI_RANGE(10),		UNI_RANGE(1),		UNI_RANGE(0.1),		UNI_RANGE(0.01)	}};// analog output rangesstatic comedi_lrange cb_pcidas_ao_ranges ={	4,	{		BIP_RANGE(5),		BIP_RANGE(10),		UNI_RANGE(5),		UNI_RANGE(10),	}};enum trimpot_model{	AD7376,	AD8402,};typedef struct cb_pcidas_board_struct{	char *name;	unsigned short device_id;	int ai_se_chans;	// Inputs in single-ended mode	int ai_diff_chans;	// Inputs in differential mode	int ai_bits;	// analog input resolution	int ai_speed;	// fastest conversion period in ns	int ao_nchan;	// number of analog out channels	int has_ao_fifo;	// analog output has fifo	int ao_scan_speed;	// analog output speed for 1602 series (for a scan, not conversion)	int fifo_size;	// number of samples fifo can hold	comedi_lrange *ranges;	enum trimpot_model trimpot;	unsigned has_dac08 : 1;} cb_pcidas_board;static cb_pcidas_board cb_pcidas_boards[] ={	{		name:		"pci-das1602/16",		device_id:	0x1,		ai_se_chans:	16,		ai_diff_chans:	8,		ai_bits:	16,		ai_speed:	5000,		ao_nchan: 2,		has_ao_fifo:	1,		ao_scan_speed:	10000,		fifo_size:	512,		ranges:	&cb_pcidas_ranges,		trimpot:	AD8402,		has_dac08:	1,	},	{		name:		"pci-das1200",		device_id:	0xF,		ai_se_chans:	16,		ai_diff_chans:	8,		ai_bits:	12,		ai_speed:	3200,		ao_nchan: 2,		has_ao_fifo:	0,		fifo_size:	1024,		ranges:	&cb_pcidas_ranges,		trimpot: AD7376,		has_dac08:	0,	},	{		name:		"pci-das1602/12",		device_id:	0x10,		ai_se_chans:	16,		ai_diff_chans:	8,		ai_bits:	12,		ai_speed:	3200,		ao_nchan: 2,		has_ao_fifo:	1,		ao_scan_speed:	4000,		fifo_size:	1024,		ranges:	&cb_pcidas_ranges,		trimpot: AD7376,		has_dac08:	0,	},	{		name:		"pci-das1200/jr",		device_id:	0x19,		ai_se_chans:	16,		ai_diff_chans:	8,		ai_bits:	12,		ai_speed:	3200,		ao_nchan: 0,		has_ao_fifo:	0,		fifo_size:	1024,		ranges:	&cb_pcidas_ranges,		trimpot: AD7376,		has_dac08:	0,	},	{		name:		"pci-das1602/16/jr",		device_id:	0x1C,		ai_se_chans:	16,		ai_diff_chans:	8,		ai_bits:	16,		ai_speed: 5000,		ao_nchan: 0,		has_ao_fifo:	0,		fifo_size:	512,		ranges:	&cb_pcidas_ranges,		trimpot: AD8402,		has_dac08:	1,	},	{		name:		"pci-das1000",		device_id:	0x4C,		ai_se_chans:	16,		ai_diff_chans:	8,		ai_bits:	12,		ai_speed:	4000,		ao_nchan: 0,		has_ao_fifo:	0,		fifo_size:	1024,		ranges:	&cb_pcidas_ranges,		trimpot: AD7376,		has_dac08:	0,	},	{		name:		"pci-das1001",		device_id:	0x1a,		ai_se_chans:	16,		ai_diff_chans:	8,		ai_bits:	12,		ai_speed:	6800,		ao_nchan: 2,		has_ao_fifo:	0,		fifo_size:	1024,		ranges:	&cb_pcidas_alt_ranges,		trimpot: AD7376,		has_dac08:	0,	},	{		name:		"pci-das1002",		device_id:	0x1b,		ai_se_chans:	16,		ai_diff_chans:	8,		ai_bits:	12,		ai_speed:	6800,		ao_nchan: 2,		has_ao_fifo:	0,		fifo_size:	1024,		ranges:	&cb_pcidas_ranges,		trimpot: AD7376,		has_dac08:	0,	},};// Number of boards in cb_pcidas_boards#define N_BOARDS	(sizeof(cb_pcidas_boards) / sizeof(cb_pcidas_board))static struct pci_device_id cb_pcidas_pci_table[] __devinitdata = {	{ PCI_VENDOR_ID_CB, 0x0001, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },	{ PCI_VENDOR_ID_CB, 0x000f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },	{ PCI_VENDOR_ID_CB, 0x0010, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },	{ PCI_VENDOR_ID_CB, 0x0019, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },	{ PCI_VENDOR_ID_CB, 0x001c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },	{ PCI_VENDOR_ID_CB, 0x004c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },	{ PCI_VENDOR_ID_CB, 0x001a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },	{ PCI_VENDOR_ID_CB, 0x001b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },	{ 0 }};MODULE_DEVICE_TABLE(pci, cb_pcidas_pci_table);/* * Useful for shorthand access to the particular board structure */#define thisboard ((cb_pcidas_board *)dev->board_ptr)/* this structure is for data unique to this hardware driver.  If   several hardware drivers keep similar information in this structure,   feel free to suggest moving the variable to the comedi_device struct.  */typedef struct{	/* would be useful for a PCI device */	struct pci_dev *pci_dev;	// base addresses	unsigned int s5933_config;	unsigned int control_status;	unsigned int adc_fifo;	unsigned int pacer_counter_dio;	unsigned int ao_registers;	// divisors of master clock for analog input pacing	unsigned int divisor1;	unsigned int divisor2;	volatile unsigned int count;	// number of analog input samples remaining	volatile unsigned int adc_fifo_bits;	// bits to write to interupt/adcfifo register	volatile unsigned int s5933_intcsr_bits;	// bits to write to amcc s5933 interrupt control/status register	volatile unsigned int ao_control_bits;	// bits to write to ao control and status register	sampl_t ai_buffer[ AI_BUFFER_SIZE ];	sampl_t ao_buffer[ AO_BUFFER_SIZE ];	// divisors of master clock for analog output pacing	unsigned int ao_divisor1;	unsigned int ao_divisor2;	volatile unsigned int ao_count;	// number of analog output samples remaining	int ao_value[2];	// remember what the analog outputs are set to, to allow readback	unsigned int caldac_value[ NUM_CHANNELS_8800 ];	// for readback of caldac	unsigned int trimpot_value[ NUM_CHANNELS_8402 ];	// for readback of trimpot	unsigned int dac08_value;	unsigned int calibration_source;} cb_pcidas_private;/* * most drivers define the following macro to make it easy to * access the private structure. */#define devpriv ((cb_pcidas_private *)dev->private)/* * The comedi_driver structure tells the Comedi core module * which functions to call to configure/deconfigure (attach/detach) * the board, and also about the kernel module that contains * the device code. */static int cb_pcidas_attach(comedi_device *dev,comedi_devconfig *it);static int cb_pcidas_detach(comedi_device *dev);static comedi_driver driver_cb_pcidas={	driver_name:	"cb_pcidas",	module:		THIS_MODULE,	attach:		cb_pcidas_attach,	detach:		cb_pcidas_detach,};static int cb_pcidas_ai_rinsn(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data);static int ai_config_insn(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data);static int cb_pcidas_ao_nofifo_winsn(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data);static int cb_pcidas_ao_fifo_winsn(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data);static int cb_pcidas_ao_readback_insn(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data);

⌨️ 快捷键说明

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