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

📄 adv_pci1710.c

📁 最新rtlinux内核源码
💻 C
📖 第 1 页 / 共 3 页
字号:
		return 4;	}	/* step 5: complain about special chanlist considerations */	if (cmd->chanlist){		if (!check_channel_list(dev, s, cmd->chanlist,			cmd->chanlist_len)) return 5; // incorrect channels list	}	DPRINTK("adv_pci1710 EDBG: BGN: pci171x_ai_cmdtest(...) ret=0\n");	return 0;}/* ==============================================================================*/static int pci171x_ai_cmd(comedi_device *dev,comedi_subdevice *s){	comedi_cmd *cmd=&s->async->cmd;	DPRINTK("adv_pci1710 EDBG: BGN: pci171x_ai_cmd(...)\n");	devpriv->ai_n_chan=cmd->chanlist_len;	devpriv->ai_chanlist=cmd->chanlist;	devpriv->ai_flags=cmd->flags;	devpriv->ai_data_len=s->async->prealloc_bufsz;	devpriv->ai_data=s->async->prealloc_buf;	devpriv->ai_timer1=0;	devpriv->ai_timer2=0;	if (cmd->stop_src==TRIG_COUNT) { devpriv->ai_scans=cmd->stop_arg; }				else   { devpriv->ai_scans=0; }	if(cmd->scan_begin_src==TRIG_FOLLOW){ // mode 1, 2, 3		if (cmd->convert_src==TRIG_TIMER) { // mode 1 and 2			devpriv->ai_timer1=cmd->convert_arg;			return pci171x_ai_docmd_and_mode(cmd->start_src==TRIG_EXT?2:1,dev,s);		}		if (cmd->convert_src==TRIG_EXT) { // mode 3			return pci171x_ai_docmd_and_mode(3,dev,s);		}	}		return -1;}/*============================================================================== Check if channel list from user is builded correctly  If it's ok, then program scan/gain logic. This works for all cards.*/static int check_channel_list(comedi_device * dev, comedi_subdevice * s, unsigned int *chanlist, unsigned int n_chan){        unsigned int chansegment[32];          unsigned int i, nowmustbechan, seglen, segpos;    	DPRINTK("adv_pci1710 EDBG:  check_channel_list(...,%d)\n",n_chan);    /* correct channel and range number check itself comedi/range.c */	if (n_chan<1) {		comedi_error(dev,"range/channel list is empty!");		return 0;        }        if (n_chan > 1) {		chansegment[0]=chanlist[0]; // first channel is everytime ok		for (i=1, seglen=1; i<n_chan; i++, seglen++) { // build part of chanlist			// rt_printk("%d. %d %d\n",i,CR_CHAN(chanlist[i]),CR_RANGE(chanlist[i]));			if (chanlist[0]==chanlist[i]) break; // we detect loop, this must by finish			if (CR_CHAN(chanlist[i]) & 1) // odd channel cann't by differencial				if (CR_AREF(chanlist[i])==AREF_DIFF) {					comedi_error(dev,"Odd channel can't be differential input!\n");					return 0;				}			nowmustbechan=(CR_CHAN(chansegment[i-1])+1) % s->n_chan;			if (CR_AREF(chansegment[i-1])==AREF_DIFF) 				nowmustbechan=(nowmustbechan+1) % s->n_chan;			if (nowmustbechan!=CR_CHAN(chanlist[i])) { // channel list isn't continous :-(				rt_printk("channel list must be continous! chanlist[%i]=%d but must be %d or %d!\n",					    i,CR_CHAN(chanlist[i]),nowmustbechan,CR_CHAN(chanlist[0]) );				return 0;			}			chansegment[i]=chanlist[i]; // well, this is next correct channel in list		}		for (i=0, segpos=0; i<n_chan; i++) {  // check whole chanlist			//rt_printk("%d %d=%d %d\n",CR_CHAN(chansegment[i%seglen]),CR_RANGE(chansegment[i%seglen]),CR_CHAN(chanlist[i]),CR_RANGE(chanlist[i]));			if (chanlist[i]!=chansegment[i%seglen]) {				rt_printk("bad channel, reference or range number! chanlist[%i]=%d,%d,%d and not %d,%d,%d!\n",					    i,CR_CHAN(chansegment[i]),CR_RANGE(chansegment[i]),CR_AREF(chansegment[i]),CR_CHAN(chanlist[i%seglen]),CR_RANGE(chanlist[i%seglen]),CR_AREF(chansegment[i%seglen]));				return 0; // chan/gain list is strange			}		}	} else {		seglen=1;	}	return seglen;}	static void setup_channel_list(comedi_device * dev, comedi_subdevice * s, unsigned int *chanlist,	unsigned int n_chan, unsigned int seglen){	unsigned int i, range, chanprog;		DPRINTK("adv_pci1710 EDBG:  setup_channel_list(...,%d,%d)\n",n_chan,seglen);	devpriv->act_chanlist_len=seglen;	devpriv->act_chanlist_pos=0;	DPRINTK("SegLen: %d\n", seglen); 	for (i=0; i<seglen; i++) {  // store range list to card		chanprog=muxonechan[CR_CHAN(chanlist[i])];		outw(chanprog, dev->iobase+PCI171x_MUX); /* select channel */		range=this_board->rangecode_ai[CR_RANGE(chanlist[i])];		if (CR_AREF(chanlist[i])==AREF_DIFF) range|=0x0020;		outw(range, dev->iobase+PCI171x_RANGE); /* select gain */#ifdef PCI171x_PARANOIDCHECK		devpriv->act_chanlist[i]=(CR_CHAN(chanlist[i])<<12) & 0xf000;#endif		DPRINTK("GS: %2d. [%4x]=%4x %4x\n", i, chanprog, range, devpriv->act_chanlist[i]);	}	devpriv->ai_et_MuxVal =		CR_CHAN(chanlist[0]) | (CR_CHAN(chanlist[seglen-1]) << 8);	outw(devpriv->ai_et_MuxVal, dev->iobase+PCI171x_MUX); /* select channel interval to scan */	DPRINTK("MUX: %4x L%4x.H%4x\n", CR_CHAN(chanlist[0]) | (CR_CHAN(chanlist[seglen-1]) << 8), CR_CHAN(chanlist[0]), CR_CHAN(chanlist[seglen-1]));}/*==============================================================================*/static void start_pacer(comedi_device * dev, int mode, unsigned int divisor1, unsigned int divisor2) {	DPRINTK("adv_pci1710 EDBG: BGN: start_pacer(%d,%u,%u)\n",mode,divisor1,divisor2);        outw(0xb4, dev->iobase + PCI171x_CNTCTRL);        outw(0x74, dev->iobase + PCI171x_CNTCTRL);          if (mode==1) {		outw(divisor2 & 0xff, dev->iobase + PCI171x_CNT2);		outw((divisor2 >> 8) & 0xff, dev->iobase + PCI171x_CNT2);		outw(divisor1  & 0xff, dev->iobase + PCI171x_CNT1);		outw((divisor1 >> 8) & 0xff, dev->iobase + PCI171x_CNT1);        }	DPRINTK("adv_pci1710 EDBG: END: start_pacer(...)\n");}/* ==============================================================================*/static int pci171x_ai_cancel(comedi_device * dev, comedi_subdevice * s){	DPRINTK("adv_pci1710 EDBG: BGN: pci171x_ai_cancel(...)\n");	switch (this_board->cardtype) {	default:		devpriv->CntrlReg&=Control_CNT0;		devpriv->CntrlReg|=Control_SW;			outw(devpriv->CntrlReg, dev->iobase+PCI171x_CONTROL);	// reset any operations		start_pacer(dev,-1,0,0);		outb(0,dev->iobase + PCI171x_CLRFIFO);		outb(0,dev->iobase + PCI171x_CLRINT);		break;	}	 			devpriv->ai_do=0;        devpriv->ai_act_scan=0;        s->async->cur_chan=0;        devpriv->ai_buf_ptr=0;        devpriv->neverending_ai=0;	DPRINTK("adv_pci1710 EDBG: END: pci171x_ai_cancel(...)\n");	return 0;}/* ==============================================================================*/static int pci171x_reset(comedi_device *dev){	DPRINTK("adv_pci1710 EDBG: BGN: pci171x_reset(...)\n");	outw(0x30, dev->iobase + PCI171x_CNTCTRL);	devpriv->CntrlReg=Control_SW;	// Software trigger, CNT0=100kHz	outw(devpriv->CntrlReg, dev->iobase+PCI171x_CONTROL);	// reset any operations	outb(0, dev->iobase + PCI171x_CLRFIFO);		// clear FIFO	outb(0, dev->iobase + PCI171x_CLRINT);		// clear INT request	start_pacer(dev,-1,0,0);				// stop 8254	devpriv->da_ranges=0;	if (this_board->n_aochan) {		outb(devpriv->da_ranges, dev->iobase+PCI171x_DAREF); // set DACs to 0..5V		outw(0, dev->iobase+PCI171x_DA1);		// set DA outputs to 0V		devpriv->ao_data[0]=0x0000; 		if (this_board->n_aochan>1) {			outw(0, dev->iobase+PCI171x_DA2);			devpriv->ao_data[1]=0x0000;		}	}	outw(0, dev->iobase + PCI171x_DO);		// digital outputs to 0	outb(0, dev->iobase + PCI171x_CLRFIFO);		// clear FIFO	outb(0, dev->iobase + PCI171x_CLRINT);		// clear INT request		DPRINTK("adv_pci1710 EDBG: END: pci171x_reset(...)\n");	return 0;}/* ==============================================================================*/static int pci1720_reset(comedi_device *dev){	DPRINTK("adv_pci1710 EDBG: BGN: pci1720_reset(...)\n");	outb(Syncont_SC0, dev->iobase + PCI1720_SYNCONT); // set synchronous output mode	devpriv->da_ranges=0xAA;	outb(devpriv->da_ranges, dev->iobase + PCI1720_RANGE); // set all ranges to +/-5V 	outw(0x0800, dev->iobase + PCI1720_DA0);	// set outputs to 0V	outw(0x0800, dev->iobase + PCI1720_DA1);	outw(0x0800, dev->iobase + PCI1720_DA2);	outw(0x0800, dev->iobase + PCI1720_DA3);	outb(0, dev->iobase + PCI1720_SYNCOUT); // update outputs	devpriv->ao_data[0]=0x0800; devpriv->ao_data[1]=0x0800;	devpriv->ao_data[2]=0x0800; devpriv->ao_data[3]=0x0800;	DPRINTK("adv_pci1710 EDBG: END: pci1720_reset(...)\n");	return 0;}/* ==============================================================================*/static int pci1710_reset(comedi_device *dev){	DPRINTK("adv_pci1710 EDBG: BGN: pci1710_reset(...)\n");        switch (this_board->cardtype) {	case TYPE_PCI1720:		return pci1720_reset(dev);	default:		return pci171x_reset(dev);	}	DPRINTK("adv_pci1710 EDBG: END: pci1710_reset(...)\n");}/* ==============================================================================*/static int pci1710_attach(comedi_device *dev,comedi_devconfig *it){	comedi_subdevice *s;	int ret,subdev,n_subdevices;	unsigned short io_addr[5],master,irq;	struct pcilst_struct *card=NULL;        unsigned int iobase;	unsigned char pci_bus,pci_slot,pci_func;	if (!pci_list_builded) {		pci_card_list_init(PCI_VENDOR_ID_ADVANTECH,#ifdef PCI171X_EXTDEBUG						    1#else						    0#endif		);		pci_list_builded=1;	}	rt_printk("comedi%d: adv_pci1710: board=%s",dev->minor,this_board->name);	/* this call pci_enable_device() */	if ((card=select_and_alloc_pci_card(PCI_VENDOR_ID_ADVANTECH, this_board->device_id, it->options[0], it->options[1], 0))==NULL)		return -EIO;	if ((pci_card_data(card,&pci_bus,&pci_slot,&pci_func,	                    &io_addr[0],&irq,&master))<0) {		pci_card_free(card);		rt_printk(" - Can't get configuration data!\n");		return -EIO;	}	iobase=io_addr[2];	rt_printk(", b:s:f=%d:%d:%d, io=0x%4x",pci_bus,pci_slot,pci_func,iobase);        if (check_region(iobase, this_board->iorange) < 0) {		pci_card_free(card);		rt_printk("I/O port conflict\n");		return -EIO;        }        request_region(iobase, this_board->iorange, "Advantech PCI-1710");        dev->iobase=iobase;	dev->board_name = this_board->name;	if((ret=alloc_private(dev,sizeof(pci1710_private)))<0) {    		release_region(dev->iobase, this_board->iorange);		pci_card_free(card);		return -ENOMEM;	}        n_subdevices = 0;	if (this_board->n_aichan) n_subdevices++;	if (this_board->n_aochan) n_subdevices++;	if (this_board->n_dichan) n_subdevices++;	if (this_board->n_dochan) n_subdevices++;        if((ret=alloc_subdevices(dev, n_subdevices))<0) {    		release_region(dev->iobase, this_board->iorange);		pci_card_free(card);    		return ret;	}	if (this_board->have_irq) {		if (irq)  {			if (comedi_request_irq(irq, interrupt_service_pci1710, SA_SHIRQ, "Advantech PCI-1710", dev)) {				rt_printk(", unable to allocate IRQ %d, DISABLING IT", irq);				irq=0; /* Can't use IRQ */			} else {				rt_printk(", irq=%d", irq);			}    		} else {			rt_printk(", IRQ disabled");		}	} else {		irq=0;	}	        dev->irq = irq;	printk(".\n");	subdev=0;		if (this_board->n_aichan) {		s = dev->subdevices + subdev;		dev->read_subdev = s;		s->type = COMEDI_SUBD_AI;		s->subdev_flags = SDF_READABLE|SDF_COMMON|SDF_GROUND;		if (this_board->n_aichand) s->subdev_flags |= SDF_DIFF;		s->n_chan = this_board->n_aichan;		s->maxdata = this_board->ai_maxdata;		s->len_chanlist = this_board->n_aichan;		s->range_table = this_board->rangelist_ai;		s->cancel=pci171x_ai_cancel;		s->insn_read=pci171x_insn_read_ai;		if (irq) {			s->do_cmdtest=pci171x_ai_cmdtest;			s->do_cmd=pci171x_ai_cmd;		} 		devpriv->i8254_osc_base=100;	// 100ns=10MHz		subdev++;	}		if (this_board->n_aochan) {		s = dev->subdevices + subdev;		s->type = COMEDI_SUBD_AO;		s->subdev_flags = SDF_WRITABLE|SDF_GROUND|SDF_COMMON;		s->n_chan = this_board->n_aochan;		s->maxdata = this_board->ao_maxdata;		s->len_chanlist = this_board->n_aochan;		s->range_table = this_board->rangelist_ao;    		switch (this_board->cardtype) {		case TYPE_PCI1720:			s->insn_write=pci1720_insn_write_ao;			break;		default:			s->insn_write=pci171x_insn_write_ao;			break;		}		s->insn_read=pci171x_insn_read_ao;		subdev++;	}	if (this_board->n_dichan) {		s = dev->subdevices + subdev;		s->type = COMEDI_SUBD_DI;		s->subdev_flags = SDF_READABLE|SDF_GROUND|SDF_COMMON;		s->n_chan = this_board->n_dichan;		s->maxdata = 1;		s->len_chanlist = this_board->n_dichan;		s->range_table = &range_digital;		s->io_bits=0;		/* all bits input */		s->insn_bits=pci171x_insn_bits_di;		subdev++;	}	if (this_board->n_dochan) {		s = dev->subdevices + subdev;		s->type = COMEDI_SUBD_DO;		s->subdev_flags = SDF_WRITABLE|SDF_GROUND|SDF_COMMON;		s->n_chan = this_board->n_dochan;		s->maxdata = 1;		s->len_chanlist = this_board->n_dochan;		s->range_table = &range_digital;		s->io_bits=(1 << this_board->n_dochan)-1;	/* all bits output */		s->state=0;		s->insn_bits=pci171x_insn_bits_do;		subdev++;	}	// XXX There is unused counter 0 from onboard 82C54. Well, one user counter/timer?		devpriv->valid=1;	pci1710_reset(dev);	return 0;}/* ==============================================================================*/static int pci1710_detach(comedi_device *dev){		if (dev->private) 		if (devpriv->valid) pci1710_reset(dev);		if (dev->irq) comedi_free_irq(dev->irq,dev);	if (dev->iobase) release_region(dev->iobase,this_board->iorange);	if (pci_list_builded) {	    	pci_card_list_cleanup(PCI_VENDOR_ID_ADVANTECH);		pci_list_builded=0;	}	return 0;}/* ==============================================================================*/COMEDI_INITCLEANUP(driver_pci1710);/* ==============================================================================*/

⌨️ 快捷键说明

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