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

📄 ni_atmio16d.c

📁 rtlinux-3.2-pre3.tar.bz2 rtlinux3.2-pre3的源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/*   module/ni_atmio16d   hardware driver for National Instruments AT-MIO16D board   Copyright (C) 2000 Chris R. Baugher <baugher@enteract.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.   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_atmio16d.oDescription: National Instruments AT-MIO-16DAuthor: Chris R. Baugher <baugher@enteract.com>Status: unknownDevices: [National Instruments] AT-MIO-16 (atmio16), AT-MIO-16D (atmio16d)*//* * I must give credit here to Michal Dobes <dobes@tesnet.cz> who * wrote the driver for Advantec's pcl812 boards. I used the interrupt  * handling code from his driver as an example for this one. *  * Chris Baugher * 5/1/2000 *  */#include <linux/comedidev.h>#include <linux/ioport.h>#include "8255.h"/* Configuration and Status Registers */#define COM_REG_1	0x00	/* wo 16 */#define STAT_REG	0x00	/* ro 16 */#define COM_REG_2	0x02	/* wo 16 *//* Event Strobe Registers */#define START_CONVERT_REG	0x08	/* wo 16 */#define START_DAQ_REG		0x0A	/* wo 16 */#define AD_CLEAR_REG		0x0C	/* wo 16 */#define EXT_STROBE_REG		0x0E	/* wo 16 *//* Analog Output Registers */#define DAC0_REG		0x10	/* wo 16 */#define DAC1_REG		0x12	/* wo 16 */#define INT2CLR_REG		0x14	/* wo 16 *//* Analog Input Registers */#define MUX_CNTR_REG		0x04	/* wo 16 */#define MUX_GAIN_REG		0x06	/* wo 16 */#define AD_FIFO_REG		0x16	/* ro 16 */#define DMA_TC_INT_CLR_REG	0x16	/* wo 16 *//* AM9513A Counter/Timer Registers */#define AM9513A_DATA_REG	0x18	/* rw 16 */#define AM9513A_COM_REG		0x1A	/* wo 16 */#define AM9513A_STAT_REG	0x1A	/* ro 16 *//* MIO-16 Digital I/O Registers */#define MIO_16_DIG_IN_REG	0x1C	/* ro 16 */#define MIO_16_DIG_OUT_REG	0x1C	/* wo 16 *//* RTSI Switch Registers */#define RTSI_SW_SHIFT_REG	0x1E	/* wo 8 */#define RTSI_SW_STROBE_REG	0x1F	/* wo 8 *//* DIO-24 Registers */#define DIO_24_PORTA_REG	0x00	/* rw 8 */#define DIO_24_PORTB_REG	0x01	/* rw 8 */#define DIO_24_PORTC_REG	0x02	/* rw 8 */#define DIO_24_CNFG_REG		0x03	/* wo 8 *//* Command Register bits */#define COMREG1_2SCADC		0x0001#define COMREG1_1632CNT		0x0002#define COMREG1_SCANEN		0x0008#define COMREG1_DAQEN		0x0010#define COMREG1_DMAEN		0x0020#define COMREG1_CONVINTEN	0x0080#define COMREG2_SCN2		0x0010#define COMREG2_INTEN		0x0080#define COMREG2_DOUTEN0		0x0100#define COMREG2_DOUTEN1		0x0200/* Status Register bits */#define STAT_AD_OVERRUN		0x0100#define STAT_AD_OVERFLOW	0x0200#define STAT_AD_DAQPROG		0x0800#define STAT_AD_CONVAVAIL	0x2000#define STAT_AD_DAQSTOPINT	0x4000/* AM9513A Counter/Timer defines */#define CLOCK_1_MHZ		0x8B25#define CLOCK_100_KHZ	0x8C25#define CLOCK_10_KHZ	0x8D25#define CLOCK_1_KHZ		0x8E25#define CLOCK_100_HZ	0x8F25/* Other miscellaneous defines */#define ATMIO16D_SIZE	32	/* bus address range */#define devpriv ((atmio16d_private *)dev->private)#define ATMIO16D_TIMEOUT 10typedef struct{	char *name;	int has_8255;}atmio16_board_t;static atmio16_board_t atmio16_boards[]={	{	name:		"atmio16",	has_8255:	0,	},	{	name:		"atmio16d",	has_8255:	1,	},};#define n_atmio16_boards sizeof(atmio16_boards)/sizeof(atmio16_boards[0])#define boardtype ((atmio16_board_t *)dev->board_ptr)/* function prototypes */static int atmio16d_attach(comedi_device *dev,comedi_devconfig *it);static int atmio16d_detach(comedi_device *dev);static void atmio16d_interrupt(int irq, void *d, struct pt_regs *regs);static int atmio16d_ai_cmdtest(comedi_device *dev, comedi_subdevice *s, comedi_cmd *cmd);static int atmio16d_ai_cmd(comedi_device *dev, comedi_subdevice *s);static int atmio16d_ai_cancel(comedi_device *dev, comedi_subdevice *s);static void reset_counters(comedi_device *dev);static void reset_atmio16d(comedi_device *dev);/* main driver struct */static comedi_driver driver_atmio16d={	driver_name:    "atmio16",	module:     THIS_MODULE,	attach:     atmio16d_attach,	detach:     atmio16d_detach,	board_name:	atmio16_boards,	num_names:	n_atmio16_boards,	offset:		sizeof(atmio16_board_t),};COMEDI_INITCLEANUP(driver_atmio16d);/* range structs */static comedi_lrange range_atmio16d_ai_10_bipolar = { 4, {	BIP_RANGE( 10 ),	BIP_RANGE( 1 ),	BIP_RANGE( 0.1 ),	BIP_RANGE( 0.02 )} };static comedi_lrange range_atmio16d_ai_5_bipolar = { 4, {	BIP_RANGE( 5 ),	BIP_RANGE( 0.5 ),	BIP_RANGE( 0.05 ),	BIP_RANGE( 0.01 )} };static comedi_lrange range_atmio16d_ai_unipolar = { 4, {	UNI_RANGE( 10 ),	UNI_RANGE( 1 ),	UNI_RANGE( 0.1 ),	UNI_RANGE( 0.02 )} };/* private data struct */typedef struct {	enum { adc_diff, adc_singleended } adc_mux;	enum { adc_bipolar10, adc_bipolar5, adc_unipolar10 } adc_range;	enum { adc_2comp, adc_straight } adc_coding;	enum { dac_bipolar, dac_unipolar } dac0_range, dac1_range;	enum { dac_internal, dac_external } dac0_reference, dac1_reference;	enum { dac_2comp, dac_straight } dac0_coding, dac1_coding;	comedi_lrange *ao_range_type_list[2];	lsampl_t ao_readback[2];	unsigned int com_reg_1_state;	/* current state of command register 1 */	unsigned int com_reg_2_state;	/* current state of command register 2 */} atmio16d_private;static void reset_counters(comedi_device *dev){	/* Counter 2 */	outw(0xFFC2, dev->iobase+AM9513A_COM_REG);	outw(0xFF02, dev->iobase+AM9513A_COM_REG);	outw(0x4, dev->iobase+AM9513A_DATA_REG);	outw(0xFF0A, dev->iobase+AM9513A_COM_REG);	outw(0x3, dev->iobase+AM9513A_DATA_REG);	outw(0xFF42, dev->iobase+AM9513A_COM_REG);	outw(0xFF42, dev->iobase+AM9513A_COM_REG);	/* Counter 3 */	outw(0xFFC4, dev->iobase+AM9513A_COM_REG);	outw(0xFF03, dev->iobase+AM9513A_COM_REG);	outw(0x4, dev->iobase+AM9513A_DATA_REG);	outw(0xFF0B, dev->iobase+AM9513A_COM_REG);	outw(0x3, dev->iobase+AM9513A_DATA_REG);	outw(0xFF44, dev->iobase+AM9513A_COM_REG);	outw(0xFF44, dev->iobase+AM9513A_COM_REG);	/* Counter 4 */	outw(0xFFC8, dev->iobase+AM9513A_COM_REG);	outw(0xFF04, dev->iobase+AM9513A_COM_REG);	outw(0x4, dev->iobase+AM9513A_DATA_REG);	outw(0xFF0C, dev->iobase+AM9513A_COM_REG);	outw(0x3, dev->iobase+AM9513A_DATA_REG);	outw(0xFF48, dev->iobase+AM9513A_COM_REG);	outw(0xFF48, dev->iobase+AM9513A_COM_REG);	/* Counter 5 */	outw(0xFFD0, dev->iobase+AM9513A_COM_REG);	outw(0xFF05, dev->iobase+AM9513A_COM_REG);	outw(0x4, dev->iobase+AM9513A_DATA_REG);	outw(0xFF0D, dev->iobase+AM9513A_COM_REG);	outw(0x3, dev->iobase+AM9513A_DATA_REG);	outw(0xFF50, dev->iobase+AM9513A_COM_REG);	outw(0xFF50, dev->iobase+AM9513A_COM_REG);	outw(0, dev->iobase+AD_CLEAR_REG);}static void reset_atmio16d(comedi_device *dev){	int i;		/* now we need to initialize the board */	outw(0, dev->iobase+COM_REG_1);	outw(0, dev->iobase+COM_REG_2);	outw(0, dev->iobase+MUX_GAIN_REG);		/* init AM9513A timer */	outw(0xFFFF, dev->iobase+AM9513A_COM_REG);	outw(0xFFEF, dev->iobase+AM9513A_COM_REG);	outw(0xFF17, dev->iobase+AM9513A_COM_REG);	outw(0xF000, dev->iobase+AM9513A_DATA_REG);	for(i=1; i<=5; ++i) {		outw(0xFF00+i, dev->iobase+AM9513A_COM_REG);		outw(0x0004, dev->iobase+AM9513A_DATA_REG);		outw(0xFF08+i, dev->iobase+AM9513A_COM_REG);		outw(0x3, dev->iobase+AM9513A_DATA_REG);	}	outw(0xFF5F, dev->iobase+AM9513A_COM_REG);	/* timer init done */	outw(0, dev->iobase+AD_CLEAR_REG);	outw(0, dev->iobase+INT2CLR_REG);	/* select straight binary mode for Analog Input */	devpriv->com_reg_1_state |= 1;	outw(devpriv->com_reg_1_state, dev->iobase+COM_REG_1);	devpriv->adc_coding = adc_straight;	/* zero the analog outputs */	outw(2048, dev->iobase+DAC0_REG);	outw(2048, dev->iobase+DAC1_REG);}static void atmio16d_interrupt(int irq, void *d, struct pt_regs *regs){	comedi_device *dev = d;	comedi_subdevice *s = dev->subdevices + 0;	//	printk("atmio16d_interrupt!\n");	comedi_buf_put( s->async, inw(dev->iobase+AD_FIFO_REG) );	comedi_event(dev, s, s->async->events);}static int atmio16d_ai_cmdtest(comedi_device *dev, comedi_subdevice *s, comedi_cmd *cmd){	int err=0, tmp;#ifdef DEBUG1	printk("atmio16d_ai_cmdtest\n");#endif	/* make sure triggers are valid */	tmp=cmd->start_src;	cmd->start_src &= TRIG_NOW;	if(!cmd->start_src || tmp!=cmd->start_src)err++;	tmp=cmd->scan_begin_src;	cmd->scan_begin_src &= TRIG_FOLLOW|TRIG_TIMER;	if(!cmd->scan_begin_src || tmp!=cmd->scan_begin_src)err++;	tmp=cmd->convert_src;	cmd->convert_src &= TRIG_TIMER;	if(!cmd->convert_src || tmp!=cmd->convert_src)err++;	tmp=cmd->scan_end_src;	cmd->scan_end_src &= TRIG_COUNT;	if(!cmd->scan_end_src || tmp!=cmd->scan_end_src)err++;	tmp=cmd->stop_src;	cmd->stop_src &= TRIG_COUNT|TRIG_NONE;	if(!cmd->stop_src || tmp!=cmd->stop_src)err++;	if(err)return 1;	/* step 2: make sure trigger sources are unique and mutually compatible */	/* note that mutual compatiblity is not an issue here */	if(cmd->scan_begin_src!=TRIG_FOLLOW &&	   cmd->scan_begin_src!=TRIG_EXT &&	   cmd->scan_begin_src!=TRIG_TIMER)err++;	if(cmd->stop_src!=TRIG_COUNT &&	   cmd->stop_src!=TRIG_NONE)err++;	if(err)return 2;	/* step 3: make sure arguments are trivially compatible */	if(cmd->start_arg!=0){		cmd->start_arg=0;		err++;	}	if(cmd->scan_begin_src==TRIG_FOLLOW){		/* internal trigger */		if(cmd->scan_begin_arg!=0){			cmd->scan_begin_arg=0;			err++;		}	}else{#if 0		/* external trigger */		/* should be level/edge, hi/lo specification here */		if(cmd->scan_begin_arg!=0){			cmd->scan_begin_arg=0;			err++;		}#endif	}	if(cmd->convert_arg<10000){		cmd->convert_arg=10000;		err++;	}#if 0	if(cmd->convert_arg>SLOWEST_TIMER){		cmd->convert_arg=SLOWEST_TIMER;		err++;	}#endif	if(cmd->scan_end_arg!=cmd->chanlist_len){		cmd->scan_end_arg=cmd->chanlist_len;		err++;	}	if(cmd->stop_src==TRIG_COUNT){		/* any count is allowed */	}else{		/* TRIG_NONE */		if(cmd->stop_arg!=0){			cmd->stop_arg=0;			err++;		}	}	if(err)return 3;	return 0;}static int atmio16d_ai_cmd(comedi_device *dev, comedi_subdevice *s){	comedi_cmd *cmd = &s->async->cmd;	unsigned int timer, base_clock;	unsigned int sample_count, tmp, chan, gain;	int i;#ifdef DEBUG1	printk("atmio16d_ai_cmd\n");#endif	/* This is slowly becoming a working command interface. *	 * It is still uber-experimental */	reset_counters(dev);	s->async->cur_chan	= 0;		/* check if scanning multiple channels */	if(cmd->chanlist_len < 2) {		devpriv->com_reg_1_state &= ~COMREG1_SCANEN;		outw(devpriv->com_reg_1_state, dev->iobase+COM_REG_1);	} else {		devpriv->com_reg_1_state |= COMREG1_SCANEN;		devpriv->com_reg_2_state |= COMREG2_SCN2;		outw(devpriv->com_reg_1_state, dev->iobase+COM_REG_1);		outw(devpriv->com_reg_2_state, dev->iobase+COM_REG_2);	}	/* Setup the Mux-Gain Counter */	for(i=0; i < cmd->chanlist_len; ++i ) {		chan = CR_CHAN(cmd->chanlist[i]);		gain = CR_RANGE(cmd->chanlist[i]);		outw(i, dev->iobase+MUX_CNTR_REG);		tmp = chan|(gain<<6);		if( i == cmd->scan_end_arg-1 ) tmp |= 0x0010;	/* set LASTONE bit */		outw(tmp, dev->iobase+MUX_GAIN_REG);	}		/* Now program the sample interval timer */	/* Figure out which clock to use then get an	 * appropriate timer value */	if(cmd->convert_arg<65536000) {		base_clock = CLOCK_1_MHZ;		timer = cmd->convert_arg/1000;	} else if(cmd->convert_arg<655360000) {		base_clock = CLOCK_100_KHZ;		timer = cmd->convert_arg/10000;	} else if(cmd->convert_arg<=0xffffffff /* 6553600000 */ ) {		base_clock = CLOCK_10_KHZ;		timer = cmd->convert_arg/100000;	} else if(cmd->convert_arg<=0xffffffff /* 65536000000 */ ) {		base_clock = CLOCK_1_KHZ;		timer = cmd->convert_arg/1000000;	}	outw(0xFF03, dev->iobase+AM9513A_COM_REG);	outw(base_clock, dev->iobase+AM9513A_DATA_REG);	outw(0xFF0B, dev->iobase+AM9513A_COM_REG);	outw(0x2, dev->iobase+AM9513A_DATA_REG);	outw(0xFF44, dev->iobase+AM9513A_COM_REG);	outw(0xFFF3, dev->iobase+AM9513A_COM_REG);	outw(timer, dev->iobase+AM9513A_DATA_REG);	outw(0xFF24, dev->iobase+AM9513A_COM_REG);				/* Now figure out how many samples to get */	/* and program the sample counter */	sample_count = cmd->stop_arg*cmd->scan_end_arg;	outw(0xFF04, dev->iobase+AM9513A_COM_REG);

⌨️ 快捷键说明

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