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

📄 cb_das16_cs.c

📁 rtlinux-3.2-pre3.tar.bz2 rtlinux3.2-pre3的源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
/*    comedi/drivers/das16cs.c    Skeleton code for a Comedi driver    COMEDI - Linux Control and Measurement Device Interface    Copyright (C) 2000, 2001, 2002 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_das16_cs.oDescription: Computer Boards PC-CARD DAS16/16Devices: (ComputerBoards) PC-CARD DAS16/16 [cb_das16_cs], PC-CARD DAS16/16-AOAuthor: dsUpdated: Mon, 04 Nov 2002 20:04:21 -0800Status: experimental*/#include <linux/comedidev.h>#include <linux/delay.h>#include <linux/pci.h>#include <pcmcia/version.h>#include <pcmcia/cs_types.h>#include <pcmcia/cs.h>#include <pcmcia/cistpl.h>#include <pcmcia/ds.h>#include "8253.h"#define DAS16CS_SIZE			18#define DAS16CS_ADC_DATA		0#define DAS16CS_DIO_MUX			2#define DAS16CS_MISC1			4#define DAS16CS_MISC2			6#define DAS16CS_CTR0			8#define DAS16CS_CTR1			10#define DAS16CS_CTR2			12#define DAS16CS_CTR_CONTROL		14#define DAS16CS_DIO			16typedef struct das16cs_board_struct{	char *name;	int device_id;	int n_ao_chans;}das16cs_board;static das16cs_board das16cs_boards[] = {	{	device_id:	0x0000, /* unknown */	name:		"PC-CARD DAS16/16",	n_ao_chans:	0,	},	{	device_id:	0x0039,	name:		"PC-CARD DAS16/16-AO",	n_ao_chans:	2,	},};#define n_boards (sizeof(das16cs_boards)/sizeof(das16cs_boards[0]))#define thisboard ((das16cs_board *)dev->board_ptr)typedef struct{	dev_link_t *link;	lsampl_t ao_readback[2];	unsigned short status1;	unsigned short status2;}das16cs_private;#define devpriv ((das16cs_private *)dev->private)static int das16cs_attach(comedi_device *dev,comedi_devconfig *it);static int das16cs_detach(comedi_device *dev);static comedi_driver driver_das16cs={	driver_name:	"cb_das16_cs",	module:		THIS_MODULE,	attach:		das16cs_attach,	detach:		das16cs_detach,};static dev_link_t *dev_list = NULL;static comedi_lrange das16cs_ai_range = { 4, {	RANGE( -10, 10 ),	RANGE( -5, 5 ),	RANGE( -2.5, 2.5 ),	RANGE( -1.25, 1.25 ),}};static void das16cs_interrupt(int irq, void *d, struct pt_regs *regs);static int das16cs_ai_rinsn(comedi_device *dev,comedi_subdevice *s,	comedi_insn *insn,lsampl_t *data);static int das16cs_ai_cmd(comedi_device *dev,comedi_subdevice *s);static int das16cs_ai_cmdtest(comedi_device *dev,comedi_subdevice *s,	comedi_cmd *cmd);static int das16cs_ao_winsn(comedi_device *dev,comedi_subdevice *s,	comedi_insn *insn,lsampl_t *data);static int das16cs_ao_rinsn(comedi_device *dev,comedi_subdevice *s,	comedi_insn *insn,lsampl_t *data);static int das16cs_dio_insn_bits(comedi_device *dev,comedi_subdevice *s,	comedi_insn *insn,lsampl_t *data);static int das16cs_dio_insn_config(comedi_device *dev,comedi_subdevice *s,	comedi_insn *insn,lsampl_t *data);static int das16cs_timer_insn_read(comedi_device *dev,comedi_subdevice *s,	comedi_insn *insn,lsampl_t *data);static int das16cs_timer_insn_config(comedi_device *dev,comedi_subdevice *s,	comedi_insn *insn,lsampl_t *data);static int get_prodid(comedi_device *dev, dev_link_t *link){	client_handle_t handle = link->handle;	tuple_t tuple;	u_short buf[128];	int prodid = 0;	tuple.TupleData = (cisdata_t *) buf;	tuple.TupleOffset = 0;	tuple.TupleDataMax = 255;	tuple.DesiredTuple = CISTPL_MANFID;	tuple.Attributes = TUPLE_RETURN_COMMON;	if((CardServices(GetFirstTuple,handle, &tuple) == CS_SUCCESS) &&	   (CardServices(GetTupleData,handle,&tuple) == CS_SUCCESS)){		prodid = le16_to_cpu(buf[1]);	}	return prodid;}static das16cs_board *das16cs_probe(comedi_device *dev, dev_link_t *link){	int id;	int i;	id = get_prodid(dev,link);	for(i=0;i<n_boards;i++){		if(das16cs_boards[i].device_id==id){			return das16cs_boards + i;		}	}	printk("unknown board!\n");	return NULL;}static int das16cs_attach(comedi_device *dev,comedi_devconfig *it){	dev_link_t *link;	comedi_subdevice *s;	int ret;	int i;	printk("comedi%d: cb_das16_cs: ",dev->minor);		link = dev_list; /* XXX hack */	if(!link)return -EIO;	dev->iobase = link->io.BasePort1;	printk("I/O base=0x%04x ",dev->iobase);	printk("fingerprint:\n");	for(i=0;i<48;i+=2){		printk("%04x ",inw(dev->iobase + i));	}	printk("\n");	ret = comedi_request_irq(link->irq.AssignedIRQ, das16cs_interrupt,		SA_SHIRQ, "cb_das16_cs", dev);	if(ret<0){		return ret;	}	dev->irq = link->irq.AssignedIRQ;	printk("irq=%d ",dev->irq);	dev->board_ptr = das16cs_probe(dev, link);	if(!dev->board_ptr)return -EIO;	dev->board_name = thisboard->name;	if(alloc_private(dev,sizeof(das16cs_private))<0)		return -ENOMEM;	if(alloc_subdevices(dev, 4)<0)		return -ENOMEM;	s=dev->subdevices+0;	dev->read_subdev=s;	/* analog input subdevice */	s->type=COMEDI_SUBD_AI;	s->subdev_flags=SDF_READABLE|SDF_GROUND|SDF_DIFF;	s->n_chan=16;	s->maxdata=0xffff;	s->range_table=&das16cs_ai_range;	s->len_chanlist=16;	s->insn_read = das16cs_ai_rinsn;	s->do_cmd = das16cs_ai_cmd;	s->do_cmdtest = das16cs_ai_cmdtest;	s=dev->subdevices+1;	/* analog output subdevice */	if(thisboard->n_ao_chans){		s->type=COMEDI_SUBD_AO;		s->subdev_flags=SDF_WRITABLE;		s->n_chan=thisboard->n_ao_chans;		s->maxdata=0xffff;		s->range_table = &range_bipolar10;		s->insn_write = &das16cs_ao_winsn;		s->insn_read = &das16cs_ao_rinsn;	}	s=dev->subdevices+2;	/* digital i/o subdevice */	if(1){		s->type=COMEDI_SUBD_DIO;		s->subdev_flags=SDF_READABLE|SDF_WRITABLE;		s->n_chan=8;		s->maxdata=1;		s->range_table=&range_digital;		s->insn_bits = das16cs_dio_insn_bits;		s->insn_config = das16cs_dio_insn_config;	}else{		s->type = COMEDI_SUBD_UNUSED;	}		s=dev->subdevices+3;	/* timer subdevice */	if(0){		s->type=COMEDI_SUBD_TIMER;		s->subdev_flags=SDF_READABLE|SDF_WRITABLE;		s->n_chan=1;		s->maxdata=0xff;		s->range_table = &range_unknown;		s->insn_read = das16cs_timer_insn_read;		s->insn_config = das16cs_timer_insn_config;	}else{		s->type = COMEDI_SUBD_UNUSED;	}	printk("attached\n");	return 1;}static int das16cs_detach(comedi_device *dev){	printk("comedi%d: das16cs: remove\n",dev->minor);	if(dev->irq){		comedi_free_irq(dev->irq, dev);	}		return 0;}static void das16cs_interrupt(int irq, void *d, struct pt_regs *regs){	//comedi_device *dev = d;}/* * "instructions" read/write data in "one-shot" or "software-triggered" * mode. */static int das16cs_ai_rinsn(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data){	int i;	int to;	int aref;	int range;	int chan;	static int range_bits[] = { 0x800, 0x000, 0x100, 0x200 };	chan = CR_CHAN(insn->chanspec);	aref = CR_AREF(insn->chanspec);	range = CR_RANGE(insn->chanspec);	outw(chan, dev->iobase + 2);	devpriv->status1 &= ~0xf320;	devpriv->status1 |= (aref==AREF_DIFF)?0:0x0020;	outw(devpriv->status1, dev->iobase + 4);	devpriv->status2 &= ~0xff00;	devpriv->status2 |= range_bits[range];	outw(devpriv->status2, dev->iobase + 6);	for(i=0;i<insn->n;i++){		outw(0, dev->iobase);#define TIMEOUT 1000		for(to=0;to<TIMEOUT;to++){			if(inw(dev->iobase + 4) & 0x0080)break;		}		if(to==TIMEOUT){			printk("cb_das16_cs: ai timeout\n");			return -ETIME;		}		data[i] = (unsigned short)inw(dev->iobase + 0);	}	return i;}static int das16cs_ai_cmd(comedi_device *dev,comedi_subdevice *s){	return -EINVAL;}static int das16cs_ai_cmdtest(comedi_device *dev,comedi_subdevice *s,	comedi_cmd *cmd){	int err=0;	int tmp;	/* cmdtest tests a particular command to see if it is valid.	 * Using the cmdtest ioctl, a user can create a valid cmd	 * and then have it executes by the cmd ioctl.	 *	 * cmdtest returns 1,2,3,4 or 0, depending on which tests	 * the command passes. */	/* step 1: make sure trigger sources are trivially 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_TIMER|TRIG_EXT;	if(!cmd->scan_begin_src || tmp!=cmd->scan_begin_src)err++;	tmp=cmd->convert_src;	cmd->convert_src &= TRIG_TIMER|TRIG_EXT;	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_TIMER &&	   cmd->scan_begin_src!=TRIG_EXT)err++;	if(cmd->convert_src!=TRIG_TIMER &&	   cmd->convert_src!=TRIG_EXT)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++;	}#define MAX_SPEED	10000		/* in nanoseconds */#define MIN_SPEED	1000000000	/* in nanoseconds */	if(cmd->scan_begin_src==TRIG_TIMER){		if(cmd->scan_begin_arg<MAX_SPEED){			cmd->scan_begin_arg=MAX_SPEED;			err++;		}		if(cmd->scan_begin_arg>MIN_SPEED){			cmd->scan_begin_arg=MIN_SPEED;			err++;		}

⌨️ 快捷键说明

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