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

📄 skel.c

📁 rtlinux-3.2-pre3.tar.bz2 rtlinux3.2-pre3的源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
 * "instructions" read/write data in "one-shot" or "software-triggered" * mode. */static int skel_ai_rinsn(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data){	int n,i;	unsigned int d;	unsigned int status;	/* a typical programming sequence */	/* write channel to multiplexer */	//outw(chan,dev->iobase + SKEL_MUX);	/* don't wait for mux to settle */	/* convert n samples */	for(n=0;n<insn->n;n++){		/* trigger conversion */		//outw(0,dev->iobase + SKEL_CONVERT);#define TIMEOUT 100		/* wait for conversion to end */		for(i=0;i<TIMEOUT;i++){			status = 1;			//status = inb(dev->iobase + SKEL_STATUS);			if(status)break;		}		if(i==TIMEOUT){			/* rt_printk() should be used instead of printk()			 * whenever the code can be called from real-time. */			rt_printk("timeout\n");			return -ETIMEDOUT;		}		/* read data */		//d = inw(dev->iobase + SKEL_AI_DATA);		d = 0;		/* mangle the data as necessary */		d ^= 1<<(thisboard->ai_bits-1);		data[n] = d;	}	/* return the number of samples read/written */	return n;}static int skel_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++;		}	}else{		/* external trigger */		/* should be level/edge, hi/lo specification here */		/* should specify multiple external triggers */		if(cmd->scan_begin_arg>9){			cmd->scan_begin_arg=9;			err++;		}	}	if(cmd->convert_src==TRIG_TIMER){		if(cmd->convert_arg<MAX_SPEED){			cmd->convert_arg=MAX_SPEED;			err++;		}		if(cmd->convert_arg>MIN_SPEED){			cmd->convert_arg=MIN_SPEED;			err++;		}	}else{		/* external trigger */		/* see above */		if(cmd->convert_arg>9){			cmd->convert_arg=9;			err++;		}	}	if(cmd->scan_end_arg!=cmd->chanlist_len){		cmd->scan_end_arg=cmd->chanlist_len;		err++;	}	if(cmd->stop_src==TRIG_COUNT){		if(cmd->stop_arg>0x00ffffff){			cmd->stop_arg=0x00ffffff;			err++;		}	}else{		/* TRIG_NONE */		if(cmd->stop_arg!=0){			cmd->stop_arg=0;			err++;		}	}	if(err)return 3;	/* step 4: fix up any arguments */	if(cmd->scan_begin_src==TRIG_TIMER){		tmp=cmd->scan_begin_arg;		skel_ns_to_timer(&cmd->scan_begin_arg,cmd->flags&TRIG_ROUND_MASK);		if(tmp!=cmd->scan_begin_arg)err++;	}	if(cmd->convert_src==TRIG_TIMER){		tmp=cmd->convert_arg;		skel_ns_to_timer(&cmd->convert_arg,cmd->flags&TRIG_ROUND_MASK);		if(tmp!=cmd->convert_arg)err++;		if(cmd->scan_begin_src==TRIG_TIMER &&		  cmd->scan_begin_arg<cmd->convert_arg*cmd->scan_end_arg){			cmd->scan_begin_arg=cmd->convert_arg*cmd->scan_end_arg;			err++;		}	}	if(err)return 4;	return 0;}/* This function doesn't require a particular form, this is just * what happens to be used in some of the drivers.  It should * convert ns nanoseconds to a counter value suitable for programming * the device.  Also, it should adjust ns so that it cooresponds to * the actual time that the device will use. */static int skel_ns_to_timer(unsigned int *ns,int round){	/* trivial timer */	/* if your timing is done through two cascaded timers, the	 * i8253_cascade_ns_to_timer() function in 8253.h can be	 * very helpful.  There are also i8254_load() and i8254_mm_load()	 * which can be used to load values into the ubiquitous 8254 counters	 */	return *ns;}static int skel_ao_winsn(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data){	int i;	int chan = CR_CHAN(insn->chanspec);printk("skel_ao_winsn\n");	/* Writing a list of values to an AO channel is probably not	 * very useful, but that's how the interface is defined. */	for(i=0;i<insn->n;i++){		/* a typical programming sequence */		//outw(data[i],dev->iobase + SKEL_DA0 + chan);		devpriv->ao_readback[chan] = data[i];	}	/* return the number of samples read/written */	return i;}/* AO subdevices should have a read insn as well as a write insn. * Usually this means copying a value stored in devpriv. */static int skel_ao_rinsn(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data){	int i;	int chan = CR_CHAN(insn->chanspec);	for(i=0;i<insn->n;i++)		data[i] = devpriv->ao_readback[chan];	return i;}/* DIO devices are slightly special.  Although it is possible to * implement the insn_read/insn_write interface, it is much more * useful to applications if you implement the insn_bits interface. * This allows packed reading/writing of the DIO channels.  The * comedi core can convert between insn_bits and insn_read/write */static int skel_dio_insn_bits(comedi_device *dev,comedi_subdevice *s,	comedi_insn *insn,lsampl_t *data){	if(insn->n!=2)return -EINVAL;	/* The insn data is a mask in data[0] and the new data	 * in data[1], each channel cooresponding to a bit. */	if(data[0]){		s->state &= ~data[0];		s->state |= data[0]&data[1];		/* Write out the new digital output lines */		//outw(s->state,dev->iobase + SKEL_DIO);	}	/* on return, data[1] contains the value of the digital	 * input and output lines. */	//data[1]=inw(dev->iobase + SKEL_DIO);	/* or we could just return the software copy of the output values if	 * it was a purely digital output subdevice */	//data[1]=s->state;	return 2;}static int skel_dio_insn_config(comedi_device *dev,comedi_subdevice *s,	comedi_insn *insn,lsampl_t *data){	int chan=CR_CHAN(insn->chanspec);	if(insn->n!=1)return -EINVAL;	/* The input or output configuration of each digital line is	 * configured by a special insn_config instruction.  chanspec	 * contains the channel to be changed, and data[0] contains the	 * value COMEDI_INPUT or COMEDI_OUTPUT. */	if(data[0]==COMEDI_OUTPUT){		s->io_bits |= 1<<chan;	}else{		s->io_bits &= ~(1<<chan);	}	//outw(s->io_bits,dev->iobase + SKEL_DIO_CONFIG);	return 1;}/* * A convenient macro that defines init_module() and cleanup_module(), * as necessary. */COMEDI_INITCLEANUP(driver_skel);

⌨️ 快捷键说明

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