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

📄 cb_pcidas64.c

📁 rtlinux-3.2-pre3.tar.bz2 rtlinux3.2-pre3的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
/*    cb_pcidas64.c    This is a driver for the ComputerBoards/MeasurementComputing PCI-DAS    64xx, 60xx, and 4020 cards.    Author:  Frank Mori Hess <fmhess@users.sourceforge.net>    Copyright (C) 2001, 2002 Frank Mori Hess    Thanks also go to the following people:    Steve Rosenbluth, for providing the source code for    his pci-das6402 driver, and source code for working QNX pci-6402    drivers by Greg Laird and Mariusz Bogacz.  None of the code was    used directly here, but it was useful as an additional source of    documentation on how to program the boards.    John Sims, for much testing and feedback on pcidas-4020 support.    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_pcidas64.oDescription: Driver for the ComputerBoards/MeasurementComputing   PCI-DAS64xx, 60XX, and 4020 series with the PLX 9080 PCI controller.Author: Frank Mori Hess <fmhess@users.sourceforge.net>Status: works, but no streaming analog output yetUpdated: 2002-07-18Devices: [Measurement Computing] PCI-DAS6402/16 (cb_pcidas64),  PCI-DAS6402/12, PCI-DAS64/M1/16, PCI-DAS64/M2/16,  PCI-DAS64/M3/16, PCI-DAS6402/16/JR, PCI-DAS64/M1/16/JR,  PCI-DAS64/M2/16/JR, PCI-DAS64/M3/16/JR, PCI-DAS64/M1/14,  PCI-DAS64/M2/14, PCI-DAS64/M3/14, PCI-DAS6023, PCI-DAS6025, PCI-DAS6030,  PCI-DAS6031, PCI-DAS6032, PCI-DAS6033, PCI-DAS6034,  PCI-DAS6035, PCI-DAS6036, PCI-DAS6040, PCI-DAS6052,  PCI-DAS6070, PCI-DAS6071, PCI-DAS4020/12Configuration options:   [0] - PCI bus of device (optional)   [1] - PCI slot of device (optional)These boards may be autocalibrated with the comedi_calibrate utility.To select the bnc trigger input on the 4020 (instead of the dio input),specify channel 1000 in the chanspec.Feel free to send and success/failure reports to Frank Hess.Some devices are not identified because the PCI device IDs are not yetknown. If you have such a board, contact Frank Hess and the ID can beeasily added.*//*TODO:	command support for ao	user counter subdevice	there are a number of boards this driver will support when they are		fully released, but does not yet since the pci device id numbers		are not yet available.	support prescaled 100khz clock for slow pacing (not available on 6000 series?)*/#include <linux/comedidev.h>#include <linux/delay.h>#include <linux/pci.h>#include "8253.h"#include "8255.h"#include "plx9080.h"#include "comedi_fc.h"#undef PCIDAS64_DEBUG	// disable debugging code//#define PCIDAS64_DEBUG	// enable debugging code#ifdef PCIDAS64_DEBUG#define DEBUG_PRINT(format, args...)  rt_printk(format , ## args )#else#define DEBUG_PRINT(format, args...)#endif#define TIMER_BASE 25	// 40MHz master clock#define PRESCALED_TIMER_BASE	10000	// 100kHz 'prescaled' clock for slow aquisition, maybe I'll support this someday#define DMA_BUFFER_SIZE 0x1000/* maximum number of dma transfers we will chain together into a ring * (and the maximum number of dma buffers we maintain) */#define DMA_RING_COUNT 64// arbitrary channel number used to select bnc trigger inputstatic const int bnc_trigger_channel_4020 = 1000;/* PCI-DAS64xxx base addresses */// indices of base address regionsenum base_address_regions{	PLX9080_BADDRINDEX = 0,	MAIN_BADDRINDEX = 2,	DIO_COUNTER_BADDRINDEX = 3,};// priv(dev)->main_iobase registersenum write_only_registers{	INTR_ENABLE_REG = 0x0,	// interrupt enable register	HW_CONFIG_REG = 0x2,	// hardware config register	DAQ_SYNC_REG = 0xc,	DAQ_ATRIG_LOW_4020_REG = 0xc,	ADC_CONTROL0_REG = 0x10,	// adc control register 0	ADC_CONTROL1_REG = 0x12,	// adc control register 1	CALIBRATION_REG = 0x14,	ADC_SAMPLE_INTERVAL_LOWER_REG = 0x16,	// lower 16 bits of sample interval counter	ADC_SAMPLE_INTERVAL_UPPER_REG = 0x18,	// upper 8 bits of sample interval counter	ADC_DELAY_INTERVAL_LOWER_REG = 0x1a,	// lower 16 bits of delay interval counter	ADC_DELAY_INTERVAL_UPPER_REG = 0x1c,	// upper 8 bits of delay interval counter	ADC_COUNT_LOWER_REG = 0x1e,	// lower 16 bits of hardware conversion/scan counter	ADC_COUNT_UPPER_REG = 0x20,	// upper 8 bits of hardware conversion/scan counter	ADC_START_REG = 0x22,	// software trigger to start aquisition	ADC_CONVERT_REG = 0x24,	// initiates single conversion	ADC_QUEUE_CLEAR_REG = 0x26,	// clears adc queue	ADC_QUEUE_LOAD_REG = 0x28,	// loads adc queue	ADC_BUFFER_CLEAR_REG = 0x2a,	ADC_QUEUE_HIGH_REG = 0x2c,	// high channel for internal queue, use adc_chan_bits() inline above	DAC_CONTROL0_REG = 0x50,	// dac control register 0	DAC_CONTROL1_REG = 0x52,	// dac control register 0	DAC_BUFFER_CLEAR_REG = 0x66,	// clear dac buffer};static inline unsigned int dac_convert_reg( unsigned int channel ){	return 0x70 + ( 2 * ( channel & 0x1 ) );}static inline unsigned int dac_lsb_4020_reg( unsigned int channel ){	return 0x70 + ( 4 * ( channel & 0x1 ) );}static inline unsigned int dac_msb_4020_reg( unsigned int channel ){	return 0x72 + ( 4 * ( channel & 0x1 ) );}enum read_only_registers{	HW_STATUS_REG = 0x0,	// hardware status register, reading this apparently clears pending interrupts as well	PIPE1_READ_REG = 0x4,	ADC_READ_PNTR_REG = 0x8,	LOWER_XFER_REG = 0x10,	ADC_WRITE_PNTR_REG = 0xc,	PREPOST_REG = 0x14,};enum read_write_registers{	I8255_4020_REG = 0x48,	// 8255 offset, for 4020 only	ADC_QUEUE_FIFO_REG = 0x100,	// external channel/gain queue, uses same bits as ADC_QUEUE_LOAD_REG	ADC_FIFO_REG = 0x200,	// adc data fifo};// priv(dev)->dio_counter_iobase registersenum dio_counter_registers{	DIO_8255_OFFSET = 0x0,	DO_REG = 0x20,	DI_REG = 0x28,	DIO_DIRECTION_60XX_REG = 0x40,	DIO_DATA_60XX_REG = 0x48,};// bit definitions for write-only registersenum intr_enable_contents{	ADC_INTR_SRC_MASK = 0x3,	// bits that set adc interrupt source	ADC_INTR_QFULL_BITS = 0x0,	// interrupt fifo quater full	ADC_INTR_EOC_BITS = 0x1,	// interrupt end of conversion	ADC_INTR_EOSCAN_BITS = 0x2,	// interrupt end of scan	ADC_INTR_EOSEQ_BITS = 0x3,	// interrupt end of sequence (probably wont use this it's pretty fancy)	EN_ADC_INTR_SRC_BIT = 0x4,	// enable adc interrupt source	EN_ADC_DONE_INTR_BIT = 0x8,	// enable adc aquisition done interrupt	EN_DAC_INTR_SRC_BIT = 0x40,	// enable dac interrupt source	EN_ADC_ACTIVE_INTR_BIT = 0x200,	// enable adc active interrupt	EN_ADC_STOP_INTR_BIT = 0x400,	// enable adc stop trigger interrupt	EN_DAC_ACTIVE_INTR_BIT = 0x800,	// enable dac active interrupt	EN_DAC_UNDERRUN_BIT = 0x4000,	// enable dac underrun status bit	EN_ADC_OVERRUN_BIT = 0x8000,	// enable adc overrun status bit};enum hw_config_contents{	MASTER_CLOCK_4020_MASK = 0x3,	// bits that specify master clock source for 4020	INTERNAL_CLOCK_4020_BITS = 0x1,	// use 40 MHz internal master clock for 4020	BNC_CLOCK_4020_BITS = 0x2,	// use BNC input for master clock	EXT_CLOCK_4020_BITS = 0x3,	// use dio input for master clock	EXT_QUEUE_BIT = 0x200,	// use external channel/gain queue (more versatile than internal queue)	SLOW_DAC_BIT = 0x400,	// use 225 nanosec strobe when loading dac instead of 50 nanosec	HW_CONFIG_DUMMY_BITS = 0x2000,	// bit with unknown function yet given as default value in pci-das64 manual	DMA_CH_SELECT_BIT = 0x8000,	// bit selects channels 1/0 for analog input/output, otherwise 0/1	FIFO_SIZE_REG = 0x4,	// allows adjustment of fifo sizes, we will always use maximum	DAC_FIFO_SIZE_MASK = 0xff00,	// bits that set dac fifo size	DAC_FIFO_BITS = 0xf000,};enum daq_atrig_low_4020_contents{	EXT_AGATE_BNC_BIT = 0x8000,	// use trig/ext clk bnc input for analog gate signal	EXT_STOP_TRIG_BNC_BIT = 0x4000,	// use trig/ext clk bnc input for external stop trigger signal	EXT_START_TRIG_BNC_BIT = 0x2000,	// use trig/ext clk bnc input for external start trigger signal};static inline uint16_t analog_trig_low_threshold_bits( uint16_t threshold ){	return threshold & 0xfff;}enum adc_control0_contents{	ADC_GATE_SRC_MASK = 0x3,	// bits that select gate	ADC_SOFT_GATE_BITS = 0x1,	// software gate	ADC_EXT_GATE_BITS = 0x2,	// external digital gate	ADC_ANALOG_GATE_BITS = 0x3,	// analog level gate	ADC_GATE_LEVEL_BIT = 0x4,	// level-sensitive gate (for digital)	ADC_GATE_POLARITY_BIT = 0x8,	// gate active low	ADC_START_TRIG_SOFT_BITS = 0x10,	ADC_START_TRIG_EXT_BITS = 0x20,	ADC_START_TRIG_ANALOG_BITS = 0x30,	ADC_START_TRIG_MASK = 0x30,	ADC_START_TRIG_FALLING_BIT = 0x40,	// trig 1 uses falling edge	ADC_EXT_CONV_FALLING_BIT = 0x800,	// external pacing uses falling edge	ADC_SAMPLE_COUNTER_EN_BIT = 0x1000,	// enable hardware scan counter	ADC_DMA_DISABLE_BIT = 0x4000,	// disables dma	ADC_ENABLE_BIT = 0x8000,	// master adc enable};enum adc_control1_contents{	ADC_QUEUE_CONFIG_BIT = 0x1,	// should be set for boards with > 16 channels	CONVERT_POLARITY_BIT = 0x10,	EOC_POLARITY_BIT = 0x20,	SW_GATE_BIT = 0x40,	// software gate of adc	ADC_DITHER_BIT = 0x200,	// turn on extra noise for dithering	RETRIGGER_BIT = 0x800,	ADC_LO_CHANNEL_4020_MASK = 0x300,	ADC_HI_CHANNEL_4020_MASK = 0xc00,	TWO_CHANNEL_4020_BITS = 0x1000, // two channel mode for 4020	FOUR_CHANNEL_4020_BITS = 0x2000,	// four channel mode for 4020	CHANNEL_MODE_4020_MASK = 0x3000,	ADC_MODE_MASK = 0xf000,};static inline uint16_t adc_lo_chan_4020_bits( unsigned int channel ){	return ( channel & 0x3 ) << 8;};static inline uint16_t adc_hi_chan_4020_bits( unsigned int channel ){	return ( channel & 0x3 ) << 10;};static inline uint16_t adc_mode_bits( unsigned int mode ){	return ( mode & 0xf ) << 12;};enum calibration_contents{	SELECT_8800_BIT = 0x1,	SELECT_8402_64XX_BIT = 0x2,	SELECT_1590_60XX_BIT = 0x2,	CAL_EN_64XX_BIT = 0x40,	// calibration enable for 64xx series	SERIAL_DATA_IN_BIT = 0x80,	SERIAL_CLOCK_BIT = 0x100,	CAL_EN_60XX_BIT = 0x200,	// calibration enable for 60xx series	CAL_GAIN_BIT = 0x800,};/* calibration sources for 6025 are: *  0 : ground *  1 : 10V *  2 : 5V *  3 : 0.5V *  4 : 0.05V *  5 : ground *  6 : dac channel 0 *  7 : dac channel 1 */static inline uint16_t adc_src_bits( unsigned int source ){	return ( source & 0xf ) << 3;};static inline uint16_t adc_convert_chan_4020_bits( unsigned int channel ){	return ( channel & 0x3 ) << 8;};enum adc_queue_load_contents{	UNIP_BIT = 0x800,	// unipolar/bipolar bit	ADC_SE_DIFF_BIT = 0x1000,	// single-ended/ differential bit	ADC_COMMON_BIT = 0x2000,	// non-referenced single-ended (common-mode input)	QUEUE_EOSEQ_BIT = 0x4000,	// queue end of sequence	QUEUE_EOSCAN_BIT = 0x8000,	// queue end of scan};static inline uint16_t adc_chan_bits( unsigned int channel ){	return channel & 0x3f;};enum dac_control0_contents{	DAC_ENABLE_BIT = 0x8000,	// dac controller enable bit};enum dac_control1_contents{	DAC_OUTPUT_ENABLE_BIT = 0x80,	// dac output enable bit};// bit definitions for read-only registersenum hw_status_contents{	DAC_UNDERRUN_BIT = 0x1,	ADC_OVERRUN_BIT = 0x2,	DAC_ACTIVE_BIT = 0x4,	ADC_ACTIVE_BIT = 0x8,	DAC_INTR_PENDING_BIT = 0x10,	ADC_INTR_PENDING_BIT = 0x20,	DAC_DONE_BIT = 0x40,	ADC_DONE_BIT = 0x80,	EXT_INTR_PENDING_BIT = 0x100,	ADC_STOP_BIT = 0x200,};static inline uint16_t pipe_full_bits( uint16_t hw_status_bits ){	return ( hw_status_bits >> 10) & 0x3;};static inline unsigned int dma_chain_flag_bits( uint16_t prepost_bits ){	return ( prepost_bits >> 6 ) & 0x3;}static inline unsigned int adc_upper_read_ptr_code( uint16_t prepost_bits ){	return ( prepost_bits >> 12 ) & 0x3;}static inline unsigned int adc_upper_write_ptr_code( uint16_t prepost_bits ){	return ( prepost_bits >> 14 ) & 0x3;}// I2C addresses for 4020enum i2c_addresses{	RANGE_CAL_I2C_ADDR = 0x20,	CALDAC0_I2C_ADDR = 0xc,	CALDAC1_I2C_ADDR = 0xd,};enum range_cal_i2c_contents{	ADC_SRC_4020_MASK = 0x70,	// bits that set what source the adc converter measures	BNC_TRIG_THRESHOLD_0V_BIT = 0x80,	// make bnc trig/ext clock threshold 0V instead of 2.5V};static inline uint8_t adc_src_4020_bits( unsigned int source ){	return ( source << 4 ) & ADC_SRC_4020_MASK;};static inline uint8_t attenuate_bit( unsigned int channel ){	// attenuate channel (+-5V input range)	return 1 << ( channel & 0x3 );};// analog input ranges for 64xx boardsstatic comedi_lrange ai_ranges_64xx ={	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)	}};/* analog input ranges for 60xx boards */static comedi_lrange ai_ranges_60xx ={	4,	{		BIP_RANGE(10),		BIP_RANGE(5),		BIP_RANGE(0.5),		BIP_RANGE(0.05),	}};/* analog input ranges for 6030, etc boards */static comedi_lrange ai_ranges_6030 ={	14,	{		BIP_RANGE(10),		BIP_RANGE(5),		BIP_RANGE(2),		BIP_RANGE(1),		BIP_RANGE(0.5),		BIP_RANGE(0.2),		BIP_RANGE(0.1),		UNI_RANGE(10),		UNI_RANGE(5),		UNI_RANGE(2),		UNI_RANGE(1),		UNI_RANGE(0.5),		UNI_RANGE(0.2),		UNI_RANGE(0.1),	}};/* analog input ranges for 6052, etc boards */static comedi_lrange ai_ranges_6052 ={	15,	{		BIP_RANGE(10),		BIP_RANGE(5),		BIP_RANGE(2.5),		BIP_RANGE(1),		BIP_RANGE(0.5),		BIP_RANGE(0.25),		BIP_RANGE(0.1),		BIP_RANGE(0.05),		UNI_RANGE(10),		UNI_RANGE(5),		UNI_RANGE(2),		UNI_RANGE(1),		UNI_RANGE(0.5),		UNI_RANGE(0.2),		UNI_RANGE(0.1),	}};

⌨️ 快捷键说明

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