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

📄 ni_pcidio.c

📁 最新rtlinux内核源码
💻 C
📖 第 1 页 / 共 2 页
字号:
			async->events |= COMEDI_CB_EOA;			writeb(0x00,dev->iobase+Master_DMA_And_Interrupt_Control);		}#if 0		else{			printk("ni_pcidio: unknown interrupt\n");			async->events |= COMEDI_CB_ERROR|COMEDI_CB_EOA;			writeb(0x00,dev->iobase+Master_DMA_And_Interrupt_Control);		}#endif		flags = readb(dev->iobase+Group_1_Flags);		status = readb(dev->iobase+Interrupt_And_Window_Status);		//DPRINTK("loop end: IntEn=0x%02x,flags=0x%02x,status=0x%02x\n",		//	IntEn,flags,status);		//ni_pcidio_print_flags(flags);		//ni_pcidio_print_status(status);	}out:	comedi_event(dev,s,async->events);	    #if unused	if(!tag){		writeb(0x03,dev->iobase+Master_DMA_And_Interrupt_Control);	}#endif}#ifdef DEBUG_FLAGSstatic char *flags_strings[] = {	"TransferReady", "CountExpired", "2", "3",	"4", "Waited", "PrimaryTC", "SecondaryTC",};static void ni_pcidio_print_flags(unsigned int flags){	int i;	printk("group_1_flags:");	for(i=7;i>=0;i--){		if(flags&(1<<i)){			printk(" %s",flags_strings[i]);		}	}	printk("\n");}static char *status_strings[] = {	"DataLeft1", "Reserved1", "Req1", "StopTrig1",	"DataLeft2", "Reserved2", "Req2", "StopTrig2",};static void ni_pcidio_print_status(unsigned int flags){	int i;	printk("group_status:");	for(i=7;i>=0;i--){		if(flags&(1<<i)){			printk(" %s",status_strings[i]);		}	}	printk("\n");}#endif#ifdef unusedstatic void debug_int(comedi_device *dev){	int a,b;	static int n_int = 0;	struct timeval tv;	do_gettimeofday(&tv);	a=readb(dev->iobase+Group_Status);	b=readb(dev->iobase+Group_1_Flags);	if(n_int < 10){		DPRINTK("status 0x%02x flags 0x%02x time %06d\n",a,b,(int)tv.tv_usec);	}	while(b&1){		writew(0xff,dev->iobase+Group_1_FIFO);		b=readb(dev->iobase+Group_1_Flags);	}	b=readb(dev->iobase+Group_1_Flags);	if(n_int < 10){		DPRINTK("new status 0x%02x\n",b);		n_int++;	}}#endifstatic int ni_pcidio_insn_config(comedi_device *dev,comedi_subdevice *s,	comedi_insn *insn,lsampl_t *data){	if(insn->n!=1)return -EINVAL;	switch(data[0]){	case COMEDI_OUTPUT:		s->io_bits |= 1<<CR_CHAN(insn->chanspec);		break;	case COMEDI_INPUT:		s->io_bits &= ~(1<<CR_CHAN(insn->chanspec));		break;	default:		return -EINVAL;	}	writel(s->io_bits,dev->iobase+Port_Pin_Directions(0));	return 1;}static int ni_pcidio_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]);		writel(s->state,dev->iobase+Port_IO(0));	}	data[1] = readl(dev->iobase+Port_IO(0));	return 2;}static int ni_pcidio_cmdtest(comedi_device *dev,comedi_subdevice *s,	comedi_cmd *cmd){	int err=0;	int tmp;	/* step 1: make sure trigger sources are trivially valid */	tmp=cmd->start_src;	cmd->start_src &= TRIG_NOW|TRIG_INT;	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_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;	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->start_src!=TRIG_NOW &&	   cmd->start_src!=TRIG_INT)err++;	if(cmd->scan_begin_src!=TRIG_TIMER &&	   cmd->scan_begin_src!=TRIG_EXT)err++;	if(err)return 2;	/* step 3: make sure arguments are trivially compatible */	if(cmd->start_arg!=0){		/* same for both TRIG_INT and TRIG_NOW */		cmd->start_arg=0;		err++;	}#define MAX_SPEED	(TIMER_BASE)	/* in nanoseconds */	if(cmd->scan_begin_src==TRIG_TIMER){		if(cmd->scan_begin_arg<MAX_SPEED){			cmd->scan_begin_arg=MAX_SPEED;			err++;		}		/* no minumum speed */	}else{		/* TRIG_EXT */		/* should be level/edge, hi/lo specification here */		if(cmd->scan_begin_arg!=0){			cmd->scan_begin_arg=0;			err++;		}	}	if(cmd->convert_arg!=0){		cmd->convert_arg = 0;		err++;	}	if(cmd->scan_end_arg!=cmd->chanlist_len){		cmd->scan_end_arg=cmd->chanlist_len;		err++;	}	if(cmd->stop_src==TRIG_COUNT){		/* no limit */	}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;		ni_pcidio_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 ni_pcidio_ns_to_timer(int *nanosec, int round_mode){	int divider, base;	base = TIMER_BASE;	switch(round_mode){	case TRIG_ROUND_NEAREST:	default:		divider = (*nanosec + base/2)/base;		break;	case TRIG_ROUND_DOWN:		divider = (*nanosec)/base;		break;	case TRIG_ROUND_UP:		divider = (*nanosec + base - 1)/base;		break;	}	*nanosec = base * divider;	return divider;}static int ni_pcidio_cmd(comedi_device *dev,comedi_subdevice *s){	comedi_cmd *cmd = &s->async->cmd;	/* XXX configure ports for input*/	writel(0x0000,dev->iobase+Port_Pin_Directions(0));	if(0){		/* enable fifos A B C D */		writeb(0x0f,dev->iobase+Data_Path);		/* set transfer width a 32 bits*/		writeb(TransferWidth(0) | TransferLength(0),			dev->iobase+Transfer_Size_Control);	}else{		writeb(0x03,dev->iobase+Data_Path);		writeb(TransferWidth(3) | TransferLength(0),			dev->iobase+Transfer_Size_Control);	}	/* protocol configuration */	if(cmd->scan_begin_src == TRIG_TIMER){		/* page 4-5, "input with internal REQs" */		writeb(  0 ,dev->iobase+OpMode);		writeb(0x00,dev->iobase+ClockReg);		writeb(  1 ,dev->iobase+Sequence);		writeb(0x04,dev->iobase+ReqReg);		writeb(  4 ,dev->iobase+BlockMode);		writeb(  3 ,dev->iobase+LinePolarities);		writeb(0xc0,dev->iobase+AckSer);		writel(ni_pcidio_ns_to_timer(&cmd->scan_begin_arg,			TRIG_ROUND_NEAREST),dev->iobase+StartDelay);		writeb(  1 ,dev->iobase+ReqDelay);		writeb(  1 ,dev->iobase+ReqNotDelay);		writeb(  1 ,dev->iobase+AckDelay);		writeb(0x0b,dev->iobase+AckNotDelay);		writeb(0x01,dev->iobase+Data1Delay);		/* manual, page 4-5: ClockSpeed comment is incorrectly listed	 	* on DAQOptions */		writew(0   ,dev->iobase+ClockSpeed);		writeb(0   ,dev->iobase+DAQOptions);	}else{		/* TRIG_EXT */		/* page 4-5, "input with external REQs" */		writeb(  0 ,dev->iobase+OpMode);		writeb(0x00,dev->iobase+ClockReg);		writeb(  0 ,dev->iobase+Sequence);		writeb(0x00,dev->iobase+ReqReg);		writeb(  4 ,dev->iobase+BlockMode);		writeb(  0 ,dev->iobase+LinePolarities);		writeb(0x00,dev->iobase+AckSer);		writel(  1 ,dev->iobase+StartDelay);		writeb(  1 ,dev->iobase+ReqDelay);		writeb(  1 ,dev->iobase+ReqNotDelay);		writeb(  1 ,dev->iobase+AckDelay);		writeb(0x0C,dev->iobase+AckNotDelay);		writeb(0x10,dev->iobase+Data1Delay);		writew(  0 ,dev->iobase+ClockSpeed);		writeb(0x60,dev->iobase+DAQOptions);	}	if(cmd->stop_src == TRIG_COUNT){		writel(cmd->stop_arg,dev->iobase+Transfer_Count);	}else{		/* XXX */	}#ifdef USE_DMA	writeb(0x05,dev->iobase+DMA_Line_Control);	writeb(0x30,dev->iobase+Group_1_First_Clear);	setup_mite_dma(dev,s);#else	writeb(0x00,dev->iobase+DMA_Line_Control);#endif  	/* clear and enable interrupts */	writeb(0xff,dev->iobase+Group_1_First_Clear);	//writeb(ClearExpired,dev->iobase+Group_1_Second_Clear);	writeb(IntEn,dev->iobase+Interrupt_Control);	writeb(0x03,dev->iobase+Master_DMA_And_Interrupt_Control);	if(cmd->start_src == TRIG_NOW){		/* start */		writeb(Numbered | RunMode(7),dev->iobase+OpMode);		s->async->inttrig = NULL;	}else{		/* TRIG_INT */		s->async->inttrig = ni_pcidio_inttrig;	}	DPRINTK("ni_pcidio: command started\n");	return 0;}static void setup_mite_dma(comedi_device *dev,comedi_subdevice *s){	struct mite_struct *mite = devpriv->mite;	struct mite_channel *mite_chan = &mite->channels[ DI_DMA_CHAN ];	mite_chan->current_link = 0;	mite_chan->dir = COMEDI_INPUT;	mite_prep_dma(mite, DI_DMA_CHAN, 16, 16);	mite_dma_arm(mite, DI_DMA_CHAN);}static int ni_pcidio_inttrig(comedi_device *dev, comedi_subdevice *s,	unsigned int trignum){	if(trignum!=0)return -EINVAL;	writeb(Numbered | RunMode(7),dev->iobase+OpMode);	s->async->inttrig = NULL;	return 1;}static int ni_pcidio_cancel(comedi_device *dev, comedi_subdevice *s){	writeb(0x00,dev->iobase+Master_DMA_And_Interrupt_Control);	return 0;}static int ni_pcidio_change(comedi_device *dev, comedi_subdevice *s,	unsigned long new_size){	int ret;	ret = mite_buf_change(devpriv->mite, DI_DMA_CHAN, s->async, new_size);	if(ret<0)return ret;	memset(s->async->prealloc_buf, 0xaa, s->async->prealloc_bufsz);	return 0;}static int nidio_attach(comedi_device *dev,comedi_devconfig *it){	comedi_subdevice *s;	int i;	int ret;	int n_subdevices;	printk("comedi%d: nidio:",dev->minor);	if((ret=alloc_private(dev,sizeof(nidio96_private)))<0)		return ret;	ret=nidio_find_device(dev,it->options[0],it->options[1]);	if(ret<0)return ret;	ret = mite_setup(devpriv->mite);	if(ret < 0)	{		printk("error setting up mite\n");		return ret;	}	dev->iobase = mite_iobase(devpriv->mite);	dev->board_name=this_board->name;	dev->irq=mite_irq(devpriv->mite);	printk(" %s",dev->board_name);	if(!this_board->is_diodaq){		n_subdevices=this_board->n_8255;	}else{		n_subdevices=1;	}	if((ret=alloc_subdevices(dev, n_subdevices))<0)		return ret;	if(!this_board->is_diodaq){		for(i=0;i<this_board->n_8255;i++){			subdev_8255_init(dev,dev->subdevices+i,				nidio96_8255_cb,(unsigned long)(dev->iobase+NIDIO_8255_BASE(i)));		}	}else{		printk(" rev=%d",readb(dev->iobase+Chip_Version));		s=dev->subdevices+0;		dev->read_subdev = s;		s->type=COMEDI_SUBD_DIO;		s->subdev_flags=SDF_READABLE|SDF_WRITABLE;		s->n_chan=32;		s->range_table=&range_digital;		s->maxdata=1;		s->insn_config = ni_pcidio_insn_config;		s->insn_bits = ni_pcidio_insn_bits;		s->do_cmd = ni_pcidio_cmd;		s->do_cmdtest = ni_pcidio_cmdtest;		s->cancel = ni_pcidio_cancel;		s->len_chanlist=32;		/* XXX */		s->buf_change = ni_pcidio_change;		writel(0,dev->iobase+Port_IO(0));		writel(0,dev->iobase+Port_Pin_Directions(0));		writel(0,dev->iobase+Port_Pin_Mask(0));		/* disable interrupts on board */		writeb(0x00,dev->iobase+Master_DMA_And_Interrupt_Control);		ret=comedi_request_irq(dev->irq,nidio_interrupt,SA_SHIRQ,"ni_pcidio",dev);		if(ret<0){			dev->irq=0;			printk(" irq not available");		}	}	printk("\n");	return 0;}static int nidio_detach(comedi_device *dev){	int i;	if(this_board && !this_board->is_diodaq){		for(i=0;i<this_board->n_8255;i++){			subdev_8255_cleanup(dev,dev->subdevices+i);		}	}	if(dev->irq)		comedi_free_irq(dev->irq,dev);	if(devpriv && devpriv->mite)		mite_unsetup(devpriv->mite);	return 0;}static int nidio_find_device(comedi_device *dev,int bus,int slot){	struct mite_struct *mite;	int i;		for(mite=mite_devices;mite;mite=mite->next){		if(mite->used)continue;		if(bus || slot){			if(bus!=mite->pcidev->bus->number ||			   slot!=PCI_SLOT(mite->pcidev->devfn))				continue;		}		for(i=0;i<n_nidio_boards;i++){			if(mite_device_id(mite)==nidio_boards[i].dev_id){				dev->board_ptr=nidio_boards+i;				devpriv->mite=mite;				return 0;			}		}	}	printk("no device found\n");	mite_list_devices();	return -EIO;}

⌨️ 快捷键说明

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