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

📄 ni_labpc.c

📁 rtlinux-3.2-pre3.tar.bz2 rtlinux3.2-pre3的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
/*    ni_labpc.c driver for National Instruments Lab-PC series boards and compatibles    Copyright (C) 2001, 2002 Frank Mori Hess <fmhess@users.sourceforge.net>    PCMCIA crap at end of file is adapted from dummy_cs.c 1.31 2001/08/24 12:13:13    from the pcmcia package.    The initial developer of the pcmcia dummy_cs.c code is David A. Hinds    <dahinds@users.sourceforge.net>.  Portions created by David A. Hinds    are Copyright (C) 1999 David A. Hinds.  All Rights Reserved.    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: ni_labpc.oDescription: National Instruments Lab-PC (& compatibles)Author: Frank Mori Hess <fmhess@users.sourceforge.net>Devices: [National Instruments] DAQCard-1200 (daqcard-1200), Lab-PC-1200 (labpc-1200),  Lab-PC-1200AI (labpc-1200ai), Lab-PC+ (lab-pc+), PCI-1200 (pci-1200)Status: worksThanks go to Fredrik Lingvall for much testing and perseverance inhelping to debug daqcard-1200 support.Tested with lab-pc-1200.  For the older Lab-PC+, not all input rangesand analog references will work, the available ranges/arefs willdepend on how you have configured the jumpers on your board(see your owner's manual).The 1200 series boards have onboard calibration dacs for correctinganalog input/output offsets and gains.  The proper settings for thesecaldacs are stored on the board's eeprom.  To read the caldac valuesfrom the eeprom and store them into a file that can be then be used bycomedilib, use the comedi_calibrate program.Configuration options - ISA boards:  [0] - I/O port base address  [1] - IRQ (optional, required for timed or externally triggered conversions)  [2] - DMA channel (optional)Configuration options - PCI boards:  [0] - bus (optional)  [1] - slot (optional)Configuration options - PCMCIA boards:  noneThe Lab-pc+ and daqcard-1200 have quirky chanlist requirementswhen scanning multiple channels.  Multiple channel scansequence must start at highest channel, then decrement down tochannel 0.  The rest of the cards can scan down like lab-pc+ or scanup from channel zero.  Chanlists consisting of all one channelare also legal, and allow you to pace conversions in bursts.*//*NI manuals:341309a (labpc-1200 register manual)340988a (daqcard-1200)340914a (pci-1200)320502b (lab-pc+)*/#undef LABPC_DEBUG//#define LABPC_DEBUG	// enable debugging messages#include <linux/comedidev.h>#include <linux/delay.h>#include <asm/dma.h>#include "8253.h"#include "8255.h"#include "mite.h"#include "comedi_fc.h"#if defined(CONFIG_PCMCIA) || defined(CONFIG_PCMCIA_MODULE)#include <pcmcia/version.h>#include <pcmcia/cs_types.h>#include <pcmcia/cs.h>#include <pcmcia/cistpl.h>#include <pcmcia/cisreg.h>#include <pcmcia/ds.h>#include <pcmcia/bus_ops.h>/*   A linked list of "instances" of the dummy device.  Each actual   PCMCIA card corresponds to one device instance, and is described   by one dev_link_t structure (defined in ds.h).   You may not want to use a linked list for this -- for example, the   memory card driver uses an array of dev_link_t pointers, where minor   device numbers are used to derive the corresponding array index.*/static dev_link_t *pcmcia_dev_list = NULL;#endif // CONFIG_PCMCIA#define LABPC_SIZE           32	// size of io region used by board#define LABPC_TIMER_BASE            500	// 2 MHz master clock#define EEPROM_SIZE	256	// 256 byte eeprom#define NUM_AO_CHAN	2	// boards have two analog output channels/* Registers for the lab-pc+ *///write-only registers#define COMMAND1_REG	0x0#define   ADC_GAIN_MASK	(0x7 << 4)#define   ADC_CHAN_BITS(x)	((x) & 0x7)#define   ADC_SCAN_EN_BIT	0x80	// enables multi channel scans#define COMMAND2_REG	0x1#define   PRETRIG_BIT	0x1	// enable pretriggering (used in conjunction with SWTRIG)#define   HWTRIG_BIT	0x2	// enable paced conversions on external trigger#define   SWTRIG_BIT	0x4	// enable paced conversions#define   CASCADE_BIT	0x8	// use two cascaded counters for pacing#define   DAC_PACED_BIT(channel)	(0x40 << ((channel) & 0x1))#define COMMAND3_REG	0x2#define   DMA_EN_BIT	0x1	// enable dma transfers#define   DIO_INTR_EN_BIT	0x2	// enable interrupts for 8255#define   DMATC_INTR_EN_BIT	0x4	// enable dma terminal count interrupt#define   TIMER_INTR_EN_BIT	0x8	// enable timer interrupt#define   ERR_INTR_EN_BIT	0x10	// enable error interrupt#define   ADC_FNE_INTR_EN_BIT	0x20	// enable fifo not empty interrupt#define ADC_CONVERT_REG	0x3#define DAC_LSB_REG(channel)	(0x4 + 2 * ((channel) & 0x1))#define DAC_MSB_REG(channel)	(0x5 + 2 * ((channel) & 0x1))#define ADC_CLEAR_REG	0x8#define DMATC_CLEAR_REG	0xa#define TIMER_CLEAR_REG	0xc#define COMMAND6_REG	0xe	// 1200 boards only#define   ADC_COMMON_BIT	0x1	// select ground or common-mode reference#define   ADC_UNIP_BIT	0x2	// adc unipolar#define   DAC_UNIP_BIT(channel)	(0x4 << ((channel) & 0x1))	// dac unipolar#define   ADC_FHF_INTR_EN_BIT	0x20	// enable fifo half full interrupt#define   A1_INTR_EN_BIT	0x40	// enable interrupt on end of hardware count#define   ADC_SCAN_UP_BIT 0x80	// scan up from channel zero instead of down to zero#define COMMAND4_REG	0xf#define   INTERVAL_SCAN_EN_BIT	0x1	// enables 'interval' scanning#define   EXT_SCAN_EN_BIT	0x2	// enables external signal on counter b1 output to trigger scan#define   EXT_CONVERT_OUT_BIT	0x4	// chooses direction (output or input) for EXTCONV* line#define   ADC_DIFF_BIT	0x8	// chooses differential inputs for adc (in conjunction with board jumper)#define   EXT_CONVERT_DISABLE_BIT	0x10#define COMMAND5_REG	0x1c	// 1200 boards only, calibration stuff#define   EEPROM_WRITE_UNPROTECT_BIT	0x4// enable eeprom for write#define   DITHER_EN_BIT	0x8	// enable dithering#define   CALDAC_LOAD_BIT	0x10	// load calibration dac#define   SCLOCK_BIT	0x20	// serial clock - rising edge writes, falling edge reads#define   SDATA_BIT	0x40	// serial data bit for writing to eeprom or calibration dacs#define   EEPROM_EN_BIT	0x80	// enable eeprom for read/write#define INTERVAL_COUNT_REG	0x1e#define INTERVAL_LOAD_REG	0x1f#define   INTERVAL_LOAD_BITS	0x1// read-only registers#define STATUS1_REG	0x0#define   DATA_AVAIL_BIT	0x1	// data is available in fifo#define   OVERRUN_BIT	0x2	// overrun has occurred#define   OVERFLOW_BIT	0x4	// fifo overflow#define   TIMER_BIT	0x8	// timer interrupt has occured#define   DMATC_BIT	0x10	// dma terminal count has occured#define   EXT_TRIG_BIT	0x40	// external trigger has occured#define STATUS2_REG	0x1d	// 1200 boards only#define   EEPROM_OUT_BIT	0x1	// programmable eeprom serial output#define   A1_TC_BIT	0x2	// counter A1 terminal count#define   FNHF_BIT	0x4	// fifo not half full#define ADC_FIFO_REG	0xa#define DIO_BASE_REG	0x10#define COUNTER_A_BASE_REG	0x14#define COUNTER_A_CONTROL_REG	(COUNTER_A_BASE_REG + 0x3)#define   INIT_A0_BITS	0x14	// check modes put conversion pacer output in harmless state (a0 mode 2)#define   INIT_A1_BITS	0x70	// put hardware conversion counter output in harmless state (a1 mode 0)#define COUNTER_B_BASE_REG	0x18static int labpc_attach(comedi_device *dev,comedi_devconfig *it);static int labpc_detach(comedi_device *dev);static int labpc_cancel(comedi_device *dev, comedi_subdevice *s);static void labpc_interrupt(int irq, void *d, struct pt_regs *regs);static int labpc_drain_fifo(comedi_device *dev);static void labpc_drain_dma(comedi_device *dev);static void handle_isa_dma(comedi_device *dev);static void labpc_drain_dregs(comedi_device *dev);static int labpc_ai_cmdtest(comedi_device *dev,comedi_subdevice *s,comedi_cmd *cmd);static int labpc_ai_cmd(comedi_device *dev, comedi_subdevice *s);static int labpc_ai_rinsn(comedi_device *dev, comedi_subdevice *s, comedi_insn *insn, lsampl_t *data);static int labpc_ao_winsn(comedi_device *dev, comedi_subdevice *s, comedi_insn *insn, lsampl_t *data);static int labpc_ao_rinsn(comedi_device *dev, comedi_subdevice *s, comedi_insn *insn, lsampl_t *data);static int labpc_calib_read_insn(comedi_device *dev, comedi_subdevice *s, comedi_insn *insn, lsampl_t *data);static int labpc_calib_write_insn(comedi_device *dev, comedi_subdevice *s, comedi_insn *insn, lsampl_t *data);static int labpc_eeprom_read_insn(comedi_device *dev, comedi_subdevice *s, comedi_insn *insn, lsampl_t *data);static int labpc_eeprom_write_insn(comedi_device *dev, comedi_subdevice *s, comedi_insn *insn, lsampl_t *data);static unsigned int labpc_suggest_transfer_size(comedi_cmd cmd);static void labpc_adc_timing(comedi_device *dev, comedi_cmd *cmd);static struct mite_struct* labpc_find_device(int bus, int slot);static unsigned int labpc_inb(unsigned long address);static void labpc_outb(unsigned int byte, unsigned long address);static unsigned int labpc_readb(unsigned long address);static void labpc_writeb(unsigned int byte, unsigned long address);static int labpc_dio_mem_callback(int dir, int port, int data, unsigned long arg);static void labpc_serial_out(comedi_device *dev, unsigned int value, unsigned int num_bits);static unsigned int labpc_serial_in(comedi_device *dev);static unsigned int labpc_eeprom_read(comedi_device *dev, unsigned int address);static unsigned int labpc_eeprom_read_status(comedi_device *dev);static unsigned int labpc_eeprom_write(comedi_device *dev, unsigned int address, unsigned int value);static void write_caldac(comedi_device *dev, unsigned int channel, unsigned int value);enum labpc_bustype {isa_bustype, pci_bustype, pcmcia_bustype};enum labpc_register_layout {labpc_plus_layout, labpc_1200_layout};enum transfer_type {fifo_not_empty_transfer, fifo_half_full_transfer, isa_dma_transfer};enum scan_mode{	MODE_SINGLE_CHAN,	MODE_SINGLE_CHAN_INTERVAL,	MODE_MULT_CHAN_UP,	MODE_MULT_CHAN_DOWN,};typedef struct labpc_board_struct{	char *name;	int device_id;	// device id for pci and pcmcia boards	int ai_speed;	// maximum input speed in nanoseconds	enum labpc_bustype bustype;	// ISA/PCI/etc.	enum labpc_register_layout register_layout;	// 1200 has extra registers compared to pc+	int has_ao;	// has analog output true/false	// function pointers so we can use inb/outb or readb/writeb as appropriate	unsigned int (*read_byte)(unsigned long address);	void (*write_byte)(unsigned int byte, unsigned long address);	comedi_lrange *ai_range_table;	int *ai_range_code;	int *ai_range_is_unipolar;	unsigned ai_scan_up : 1;	// board can auto scan up in ai channels, not just down}labpc_board;//analog input ranges#define NUM_LABPC_PLUS_AI_RANGES 16// indicates unipolar rangesstatic int labpc_plus_is_unipolar[NUM_LABPC_PLUS_AI_RANGES] ={	0,	0,	0,	0,	0,	0,	0,	0,	1,	1,	1,	1,	1,	1,	1,	1,};// map range index to gain bitsstatic int labpc_plus_ai_gain_bits[NUM_LABPC_PLUS_AI_RANGES] ={	0x00,	0x10,	0x20,	0x30,	0x40,	0x50,	0x60,	0x70,	0x00,	0x10,	0x20,	0x30,	0x40,	0x50,	0x60,	0x70,};static comedi_lrange range_labpc_plus_ai = {	NUM_LABPC_PLUS_AI_RANGES,	{		BIP_RANGE(5),		BIP_RANGE(4),		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(8),		UNI_RANGE(5),		UNI_RANGE(2),		UNI_RANGE(1),		UNI_RANGE(0.5),		UNI_RANGE(0.2),		UNI_RANGE(0.1),	}};#define NUM_LABPC_1200_AI_RANGES 14// indicates unipolar rangesstatic int labpc_1200_is_unipolar[NUM_LABPC_1200_AI_RANGES] ={	0,	0,	0,	0,	0,	0,	0,	1,	1,	1,	1,	1,	1,	1,};// map range index to gain bitsstatic int labpc_1200_ai_gain_bits[NUM_LABPC_1200_AI_RANGES] ={	0x00,	0x20,	0x30,	0x40,	0x50,	0x60,	0x70,	0x00,	0x20,	0x30,	0x40,	0x50,	0x60,	0x70,};static comedi_lrange range_labpc_1200_ai = {	NUM_LABPC_1200_AI_RANGES,	{		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),	}};//analog output ranges#define AO_RANGE_IS_UNIPOLAR 0x1static comedi_lrange range_labpc_ao = {	2,	{		BIP_RANGE(5),		UNI_RANGE(10),	}};static labpc_board labpc_boards[] ={#if defined(CONFIG_PCMCIA) || defined(CONFIG_PCMCIA_MODULE)	{		name:	"daqcard-1200",		device_id:	0x103,	// 0x10b is manufacturer id, 0x103 is device id		ai_speed:	10000,		bustype:	pcmcia_bustype,		register_layout:	labpc_1200_layout,		has_ao:	1,		read_byte:	labpc_inb,		write_byte:	labpc_outb,		ai_range_table:	&range_labpc_1200_ai,		ai_range_code: labpc_1200_ai_gain_bits,		ai_range_is_unipolar: labpc_1200_is_unipolar,		ai_scan_up: 0,	},#endif // CONFIG_PCMCIA	{		name:	"lab-pc-1200",		ai_speed:	10000,		bustype:	isa_bustype,		register_layout:	labpc_1200_layout,		has_ao:	1,		read_byte:	labpc_inb,		write_byte:	labpc_outb,		ai_range_table:	&range_labpc_1200_ai,		ai_range_code: labpc_1200_ai_gain_bits,		ai_range_is_unipolar: labpc_1200_is_unipolar,		ai_scan_up: 1,	},	{		name:	"lab-pc-1200ai",		ai_speed:	10000,		bustype:	isa_bustype,		register_layout:	labpc_1200_layout,		has_ao:	0,		read_byte:	labpc_inb,		write_byte:	labpc_outb,		ai_range_table:	&range_labpc_1200_ai,		ai_range_code: labpc_1200_ai_gain_bits,		ai_range_is_unipolar: labpc_1200_is_unipolar,		ai_scan_up: 1,	},	{		name:	"lab-pc+",		ai_speed:	12000,		bustype:	isa_bustype,		register_layout:	labpc_plus_layout,

⌨️ 快捷键说明

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