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

📄 pcl726.c

📁 最新rtlinux内核源码
💻 C
字号:
/*    comedi/drivers/pcl726.c    hardware driver for Advantech cards:     card:   PCL-726, PCL-727, PCL-728     driver: pcl726,  pcl727,  pcl728    and for ADLink cards:     card:   ACL-6126, ACL-6128     driver: acl6126,  acl6128	           COMEDI - Linux Control and Measurement Device Interface    Copyright (C) 1998 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: pcl726.oDescription: Advantech PCL-726 & compatiblesAuthor: dsStatus: untestedDevices: [Advantech] PCL-726 (pcl726), PCL-727 (pcl727), PCL-728 (pcl728),  [ADLink] ACL-6126 (acl6126), ACL-6128 (acl6128)Interrupts are not supported.    Options for PCL-726:     [0] - IO Base     [2]...[7] - D/A output range for channel 1-6:                0: 0-5V, 1: 0-10V, 2: +/-5V, 3: +/-10V, 	       4: 4-20mA, 5: unknown (external reference)	           Options for PCL-727:     [0] - IO Base     [2]...[13] - D/A output range for channel 1-12:                0: 0-5V, 1: 0-10V, 2: +/-5V, 	       3: 4-20mA	           Options for PCL-728 and ACL-6128:     [0] - IO Base     [2], [3] - D/A output range for channel 1 and 2:                0: 0-5V, 1: 0-10V, 2: +/-5V, 3: +/-10V, 	       4: 4-20mA, 5: 0-20mA	           Options for ACL-6126:     [0] - IO Base     [1] - IRQ (0=disable, 3, 5, 6, 7, 9, 10, 11, 12, 15) (currently ignored)     [2]...[7] - D/A output range for channel 1-6:                0: 0-5V, 1: 0-10V, 2: +/-5V, 3: +/-10V, 	       4: 4-20mA*//*    Thanks to Circuit Specialists for having programming info (!) on    their web page.  (http://www.cir.com/)*/#include <linux/comedidev.h>#include <linux/ioport.h>#undef ACL6126_IRQ	/* no interrupt support (yet) */#define PCL726_SIZE 16#define PCL727_SIZE 32#define PCL728_SIZE 8#define PCL726_DAC0_HI 0#define PCL726_DAC0_LO 1#define PCL726_DO_HI 12#define PCL726_DO_LO 13#define PCL726_DI_HI 14#define PCL726_DI_LO 15#define PCL727_DO_HI 24#define PCL727_DO_LO 25#define PCL727_DI_HI  0#define PCL727_DI_LO  1static comedi_lrange range_4_20mA={ 1, {RANGE_mA(4,20)}};static comedi_lrange range_0_20mA={ 1, {RANGE_mA(0,20)}};static comedi_lrange *rangelist_726[]={	&range_unipolar5, &range_unipolar10, 	&range_bipolar5,  &range_bipolar10,	&range_4_20mA,    &range_unknown};static comedi_lrange *rangelist_727[]={	&range_unipolar5, &range_unipolar10, 	&range_bipolar5,  	&range_4_20mA};static comedi_lrange *rangelist_728[]={	&range_unipolar5, &range_unipolar10, 	&range_bipolar5,  &range_bipolar10,	&range_4_20mA,    &range_0_20mA};static int pcl726_attach(comedi_device *dev,comedi_devconfig *it);static int pcl726_detach(comedi_device *dev);typedef struct {	char 		*name;		// driver name	int 		n_aochan;	// num of D/A chans	int		num_of_ranges;	// num of ranges	unsigned int 	IRQbits;	// allowed interrupts	int 		io_range;	// len of IO space	char		have_dio;	// 1=card have DI/DO ports	int		di_hi;		// ports for DI/DO operations	int		di_lo;	int		do_hi;	int		do_lo;	comedi_lrange	**range_type_list;// list of supported ranges} boardtype;static boardtype boardtypes[] ={	{"pcl726",   6, 6, 0x0000, PCL726_SIZE, 1, 	 PCL726_DI_HI, PCL726_DI_LO, PCL726_DO_HI, PCL726_DO_LO, 	 &rangelist_726[0], },	{"pcl727",  12, 4, 0x0000, PCL727_SIZE, 1, 	 PCL727_DI_HI, PCL727_DI_LO, PCL727_DO_HI, PCL727_DO_LO, 	 &rangelist_727[0], },	{"pcl728",   2, 6, 0x0000, PCL728_SIZE, 0, 	 0, 0, 0, 0, 	 &rangelist_728[0], },	{"acl6126",  6, 5, 0x96e8, PCL726_SIZE, 1,	 PCL726_DI_HI, PCL726_DI_LO, PCL726_DO_HI, PCL726_DO_LO, 	 &rangelist_726[0], },	{"acl6128",  2, 6, 0x0000, PCL728_SIZE, 0,	 0, 0, 0, 0,	 &rangelist_728[0], },};#define n_boardtypes (sizeof(boardtypes)/sizeof(boardtype))#define this_board ((boardtype *)dev->board_ptr)static comedi_driver driver_pcl726={	driver_name:	"pcl726",	module:		THIS_MODULE,	attach:		pcl726_attach,	detach:		pcl726_detach,	board_name:	boardtypes,	num_names:	n_boardtypes,	offset:		sizeof(boardtype),};COMEDI_INITCLEANUP(driver_pcl726);typedef struct{	int bipolar[12];	comedi_lrange *rangelist[12];	lsampl_t ao_readback[12];}pcl726_private;#define devpriv ((pcl726_private *)dev->private)static int pcl726_ao_insn(comedi_device *dev,comedi_subdevice *s,	comedi_insn *insn,lsampl_t *data){	int hi,lo;	int n;	int chan=CR_CHAN(insn->chanspec);	for(n=0;n<insn->n;n++){		lo=data[n]&0xff;		hi=(data[n]>>8)&0xf;		if(devpriv->bipolar[chan])hi^=0x8;		/*		 * the programming info did not say which order		 * to write bytes.  switch the order of the next		 * two lines if you get glitches.		 */		outb(hi,dev->iobase+PCL726_DAC0_HI + 2*chan);		outb(lo,dev->iobase+PCL726_DAC0_LO + 2*chan);		devpriv->ao_readback[chan]=data[n];	}		return n;}static int pcl726_ao_insn_read(comedi_device *dev,comedi_subdevice *s,	comedi_insn *insn,lsampl_t *data){	int chan=CR_CHAN(insn->chanspec);	int n;	for(n=0;n<insn->n;n++){		data[n]=devpriv->ao_readback[chan];	}	return n;}static int pcl726_di_insn_bits(comedi_device *dev,comedi_subdevice *s,	comedi_insn *insn,lsampl_t *data){	if(insn->n!=2)return -EINVAL;		data[1]=inb(dev->iobase+this_board->di_lo)|		(inb(dev->iobase+this_board->di_hi)<<8);		return 2;}static int pcl726_do_insn_bits(comedi_device *dev,comedi_subdevice *s,	comedi_insn *insn,lsampl_t *data){	if(insn->n!=2)return -EINVAL;		if(data[0]){		s->state &= ~data[0];		s->state |= data[0]&data[1];	}	if(data[1]&0x00ff)		outb(s->state&0xff,dev->iobase+this_board->do_lo);	if(data[1]&0xff00)		outb((s->state>>8),dev->iobase+this_board->do_hi);	data[1] = s->state;			return 2;}static int pcl726_attach(comedi_device *dev,comedi_devconfig *it){	comedi_subdevice *s;        int iobase,iorange;	int ret,i;	        iobase=it->options[0];        iorange=this_board->io_range;	printk("comedi%d: pcl726: board=%s, 0x%03x ",dev->minor,this_board->name,iobase);	if(check_region(iobase,iorange)<0){		printk("I/O port conflict\n");		return -EIO;	}	        request_region(iobase, iorange, "pcl726");        dev->iobase=iobase;    	dev->board_name = this_board->name;	if((ret=alloc_private(dev,sizeof(pcl726_private)))<0)		return -ENOMEM;	for (i=0; i<12; i++) {		devpriv->bipolar[i]=0;		devpriv->rangelist[i]=&range_unknown;	}#ifdef ACL6126_IRQ        irq=0;        if (boardtypes[board].IRQbits!=0) { /* board support IRQ */		irq=it->options[1];		devpriv->first_chan=2;		if (irq>0)  {/* we want to use IRQ */		        if (((1<<irq)&boardtypes[board].IRQbits)==0) {				rt_printk(", IRQ %d is out of allowed range, DISABLING IT",irq);				irq=0; /* Bad IRQ */			} else { 				if (comedi_request_irq(irq, interrupt_pcl818, 0, "pcl726", dev)) {					rt_printk(", unable to allocate IRQ %d, DISABLING IT", irq);					irq=0; /* Can't use IRQ */				} else {					rt_printk(", irq=%d", irq);				}    			}  		}	}        dev->irq = irq;#endif		printk("\n");	if((ret=alloc_subdevices(dev, 3))<0)		return ret;	s=dev->subdevices+0;	/* ao */	s->type=COMEDI_SUBD_AO;	s->subdev_flags=SDF_WRITABLE|SDF_GROUND;	s->n_chan=this_board->n_aochan;	s->maxdata=0xfff;	s->len_chanlist=1;	s->insn_write=pcl726_ao_insn;	s->insn_read=pcl726_ao_insn_read;	s->range_table_list = devpriv->rangelist;	for (i=0; i<this_board->n_aochan; i++) {		int j;		j = it->options[2+1];		if ((j<0)||(j>=this_board->num_of_ranges)) {			printk("Invalid range for channel %d! Must be 0<=%d<%d\n",				i,j,this_board->num_of_ranges-1);			j=0;		}		devpriv->rangelist[i]=this_board->range_type_list[j];		if (devpriv->rangelist[i]->range[0].min==-devpriv->rangelist[i]->range[0].max)			devpriv->bipolar[i]=1;	/* bipolar range */	}	s=dev->subdevices+1;	/* di */	if (!this_board->have_dio){		s->type = COMEDI_SUBD_UNUSED;	}else{		s->type=COMEDI_SUBD_DI;		s->subdev_flags=SDF_READABLE|SDF_GROUND;		s->n_chan=16;		s->maxdata=1;		s->len_chanlist=1;		s->insn_bits=pcl726_di_insn_bits;		s->range_table=&range_digital;	}	s=dev->subdevices+2;	/* do */	if (!this_board->have_dio){		s->type = COMEDI_SUBD_UNUSED;	}else{		s->type=COMEDI_SUBD_DO;		s->subdev_flags=SDF_WRITABLE|SDF_GROUND;		s->n_chan=16;		s->maxdata=1;		s->len_chanlist=1;		s->insn_bits=pcl726_do_insn_bits;		s->range_table=&range_digital;	}	return 0;}static int pcl726_detach(comedi_device *dev){//	printk("comedi%d: pcl726: remove\n",dev->minor);	#ifdef ACL6126_IRQ	if(dev->irq){		comedi_free_irq(dev->irq,dev);	}#endif	if(dev->iobase)		release_region(dev->iobase,this_board->io_range);	return 0;}

⌨️ 快捷键说明

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