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

📄 amplc_pci230.c

📁 rtlinux-3.2-pre3.tar.bz2 rtlinux3.2-pre3的源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
 * deallocated automatically by the core. */static int pci230_detach(comedi_device *dev){	printk("comedi%d: amplc_pci230: remove\n",dev->minor);	if(dev->subdevices && thisboard->have_dio)		subdev_8255_cleanup(dev,dev->subdevices + 2);	/* Clean up dio subdevice. */	if(dev->iobase)		release_region(dev->iobase,PCI230_IO2_SIZE);	if(dev->irq)		comedi_free_irq(dev->irq, dev);	if(devpriv){		if(devpriv->pci_iobase){			release_region(devpriv->pci_iobase, PCI230_IO1_SIZE);		}	}		return 0;}/* *  COMEDI_SUBD_AI instruction;  */  static int pci230_ai_rinsn(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data){	int n,i;	int chan, range, aref;	unsigned int status;	unsigned int adccon, adcen, adcg;	/* Unpack channel and range. */	chan = CR_CHAN(insn->chanspec);	range = CR_RANGE(insn->chanspec);	aref = CR_AREF(insn->chanspec);	/* If bit 2 of range unset, range is referring to bipolar element in range table */	adccon = PCI230_ADC_TRIG_SW | PCI230_ADC_FIFO_RESET;	devpriv->ai_bipolar = !PCI230_TEST_BIT(range, 2);	if (aref==AREF_DIFF) {		/* Differential. */		adcen = 3<<2*chan;		adccon |= PCI230_ADC_IM_DIF;			if (devpriv->ai_bipolar) {			adccon |= PCI230_ADC_IR_BIP;			adcg = range<<(2*chan-2*chan%2);		}		else {			adccon |= PCI230_ADC_IR_UNI;			adcg = ((range&(~4))+1)<<(2*chan-2*chan%2);		}	}	else {		/* Single ended. */		adcen = 1<<chan;		adccon |= PCI230_ADC_IM_SE;			if (devpriv->ai_bipolar) {			adccon |= PCI230_ADC_IR_BIP;			adcg = range<<(chan-chan%2);		}		else {			adccon |= PCI230_ADC_IR_UNI;			adcg = ((range&(~4))+1)<<(chan-chan%2);		}	}	/* Enable only this channel in the scan list - otherwise by default we'll get one sample from each channel. */	outw_p(adcen, dev->iobase + PCI230_ADCEN);	/* Set gain for channel. */	outw_p(adcg, dev->iobase + PCI230_ADCG);	/* Specify uni/bip, se/diff, s/w conversion, and reset FIFO (even though we're not using it - MEV says so). */	outw_p(adccon, dev->iobase + PCI230_ADCCON);	/* Convert n samples */	for(n=0;n<insn->n;n++){		/* trigger conversion */		outw_p(PCI230_ADC_CONV,dev->iobase + PCI230_ADCDATA);#define TIMEOUT 100		/* wait for conversion to end */		for(i=0;i<TIMEOUT;i++){			status = inw(dev->iobase + PCI230_ADCCON);			if(PCI230_TEST_BIT(status, PCI230_ADC_BUSY_BIT))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 */		data[n] = pci230_ai_read(dev);	}	/* return the number of samples read/written */	return n;}/* *  COMEDI_SUBD_AO instructions;  */  static int pci230_ao_winsn(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data){	int i;	int chan, range;		/* Unpack channel and range. */	chan = CR_CHAN(insn->chanspec);	range = CR_RANGE(insn->chanspec);	/* Set range - see analogue output range table; 0 => unipolar 10V, 1 => bipolar +/-10V range scale */	devpriv->ao_bipolar = PCI230_TEST_BIT(range, PCI230_DAC_BIP_BIT);	outw(range, dev->iobase + PCI230_DACCON);	/* 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++){		/* Store the value to be written to the DAC in our pci230_private struct before mangling it. */		devpriv->ao_readback[chan] = data[i];		/* Write value to DAC. */		pci230_ao_write(dev, data[i], chan);	}	/* 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 pci230_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;}/* *  COMEDI_SUBD_TIMER instructions;  *   *  insn_config allows user to start and stop counter/timer 2 (SK1 pin 21). *  Period specified in ns. * *  rinsn returns counter/timer's actual period in ns.   */static int pci230_ct_insn_config(comedi_device *dev,comedi_subdevice *s,	comedi_insn *insn,lsampl_t *data){	unsigned int ns;		if(insn->n!=1)return -EINVAL;	ns = data[0];	if (ns == 0) {		//Stop counter/timer 2.		pci230_cancel_ct2(dev);	}	else {		//Start conter/timer 2 with period ns.		pci230_z2_ct2(dev, &ns, TRIG_ROUND_MASK);	}	return 1;}static int pci230_ct_rinsn(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data){	if(insn->n!=1)return -EINVAL;		/* Return the actual period set in ns. */	data[0] = PCI230_TIMEBASE_10MHZ*devpriv->divisor1*devpriv->divisor2;	return 1;}static int pci230_ao_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.	 * "invalid source" returned by comedilib to user mode process 	 * if this fails. */	tmp=cmd->start_src;	cmd->start_src &= TRIG_INT;	if(!cmd->start_src || tmp!=cmd->start_src)err++;	tmp=cmd->scan_begin_src;	cmd->scan_begin_src &= TRIG_TIMER;	if(!cmd->scan_begin_src || tmp!=cmd->scan_begin_src)err++;	tmp=cmd->convert_src;	cmd->convert_src &= TRIG_NOW;	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	 * "source conflict" returned by comedilib to user mode process 	 * if this fails. */	if(cmd->stop_src!=TRIG_COUNT &&	   cmd->stop_src!=TRIG_NONE)err++;		if(err)return 2;	/* Step 3: make sure arguments are trivially compatible.	 * "invalid argument" returned by comedilib to user mode process 	 * if this fails. */	if(cmd->start_arg!=0){		cmd->start_arg=0;		err++;	}#define MAX_SPEED	3205		/* 3205ns => 312kHz */#define MIN_SPEED	4294967295u	/* 4294967295ns = 4.29s - Comedi limit due to unsigned int cmd.  Driver limit = 2^32 (2 cascaded 16bit counters) * 100ns (default 10MHz onboard clock) = 429s */	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++;		}	}	if(cmd->scan_end_arg!=cmd->chanlist_len){		cmd->scan_end_arg=cmd->chanlist_len;		err++;	}	if(cmd->stop_src==TRIG_NONE){		/* TRIG_NONE */		if(cmd->stop_arg!=0){			cmd->stop_arg=0;			err++;		}	}	if(err)return 3;	/* Step 4: fix up any arguments.	 * "argument conflict" returned by comedilib to user mode process 	 * if this fails. */	if(cmd->scan_begin_src==TRIG_TIMER){		tmp=cmd->scan_begin_arg;		pci230_ns_to_timer(&cmd->scan_begin_arg,cmd->flags&TRIG_ROUND_MASK);		if(tmp!=cmd->scan_begin_arg)err++;	}	if(err)return 4;	return 0;}static int pci230_ao_inttrig(comedi_device *dev,comedi_subdevice *s,		unsigned int trig_num){	if(trig_num != 0)		return -EINVAL;	/* Enable DAC interrupt. */	devpriv->ier |= PCI230_INT_ZCLK_CT1;	outb(devpriv->ier, devpriv->pci_iobase + PCI230_INT_SCE);	s->async->inttrig=NULL;	return 1;}static int pci230_ao_cmd(comedi_device *dev,comedi_subdevice *s){	int range;	/* Get the command. */	comedi_cmd *cmd=&s->async->cmd;	/* Calculate number of conversions required. */	if(cmd->stop_src == TRIG_COUNT) {		devpriv->ao_count = cmd->stop_arg * cmd->chanlist_len;		devpriv->ao_stop = 0;	}	else {		/* TRIG_NONE, user calls cancel. */		devpriv->ao_count = 0;		devpriv->ao_stop = 1;	}		/* Disable DAC interrupt. */	devpriv->ier &= ~PCI230_INT_ZCLK_CT1;	outb(devpriv->ier, devpriv->pci_iobase + PCI230_INT_SCE);	/* Set range - see analogue output range table; 0 => unipolar 10V, 1 => bipolar +/-10V range scale */	range = CR_RANGE(cmd->chanlist[0]);	devpriv->ao_bipolar = PCI230_TEST_BIT(range, PCI230_DAC_BIP_BIT);	outw(range, dev->iobase + PCI230_DACCON);	/* Set the counter timers to the specified sampling frequency.	 * TODO - when Comedi supports concurrent commands, this must be	 * changed; using ct0 and ct1 for DAC will screw up ADC pacer	 * which uses ct2 and ct0.  Change to only use ct1 for DAC?	 */	pci230_z2_ct1(dev, &cmd->scan_begin_arg, cmd->flags & TRIG_ROUND_MASK);	/* cmd->convert_arg is sampling period in ns */	s->async->inttrig=pci230_ao_inttrig;	return 0;}static int pci230_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.	 * "invalid source" returned by comedilib to user mode process 	 * if this fails. */	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;	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	 * "source conflict" returned by comedilib to user mode process 	 * if this fails. */	if(cmd->start_src!=TRIG_NOW)err++;	if(cmd->scan_begin_src!=TRIG_FOLLOW)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.	 * "invalid argument" returned by comedilib to user mode process 	 * if this fails. */	if(cmd->start_arg!=0){		cmd->start_arg=0;		err++;	}#define MAX_SPEED	3205		/* 3205ns => 312kHz max sampling - claimed max for single channel; should really be fn(nchans) */#define MIN_SPEED	4294967295u	/* 4294967295ns = 4.29s - Comedi limit due to unsigned int cmd.  Driver limit = 2^32 (2 cascaded 16bit counters) * 100ns (default 10MHz onboard clock) = 429s */	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 */		/* convert_arg == 0 => trigger on -ve edge. */		/* convert_arg == 1 => trigger on +ve edge. */		if(cmd->convert_arg>1){			cmd->convert_arg=1;			/* Default to trigger on +ve edge. */			err++;		}	}	if(cmd->scan_end_arg!=cmd->chanlist_len){		cmd->scan_end_arg=cmd->chanlist_len;		err++;	}	if(cmd->stop_src==TRIG_NONE){		/* TRIG_NONE */		if(cmd->stop_arg!=0){			cmd->stop_arg=0;			err++;		}	}	if(err)return 3;	/* Step 4: fix up any arguments.	 * "argument conflict" returned by comedilib to user mode process 	 * if this fails. */	if(cmd->convert_src==TRIG_TIMER){		tmp=cmd->convert_arg;		pci230_ns_to_timer(&cmd->convert_arg,cmd->flags&TRIG_ROUND_MASK);

⌨️ 快捷键说明

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