📄 ni_mio_common.c
字号:
}static int ni_ao_insn_read(comedi_device *dev,comedi_subdevice *s, comedi_insn *insn,lsampl_t *data){ data[0] = devpriv->ao[CR_CHAN(insn->chanspec)]; return 1;}static int ni_ao_insn_write(comedi_device *dev,comedi_subdevice *s, comedi_insn *insn,lsampl_t *data){ unsigned int chan = CR_CHAN(insn->chanspec); unsigned int invert; invert = ni_ao_config_chanlist(dev,s,&insn->chanspec,1); devpriv->ao[chan] = data[0]; ni_writew(data[0] ^ invert,(chan)? DAC1_Direct_Data : DAC0_Direct_Data); return 1;}static int ni_ao_insn_write_671x(comedi_device *dev,comedi_subdevice *s, comedi_insn *insn,lsampl_t *data){ unsigned int chan = CR_CHAN(insn->chanspec); unsigned int invert; ao_win_out(1 << chan, AO_Immediate_671x); invert = 1 << (boardtype.aobits - 1); if( boardtype.reg_611x == 0 ) ni_ao_config_chanlist(dev,s,&insn->chanspec,1); devpriv->ao[chan] = data[0]; ao_win_out(data[0] ^ invert, DACx_Direct_Data_671x(chan)); return 1;}static int ni_ao_inttrig(comedi_device *dev,comedi_subdevice *s, unsigned int trignum){ int ret; int bits; if(trignum!=0)return -EINVAL; win_out(devpriv->ao_mode3|AO_Not_An_UPDATE,AO_Mode_3_Register); win_out(devpriv->ao_mode3,AO_Mode_3_Register); /* wait for DACs to be loaded */ comedi_udelay(100); win_out(devpriv->ao_cmd1|AO_UI_Arm|AO_UC_Arm|AO_BC_Arm|AO_DAC1_Update_Mode|AO_DAC0_Update_Mode, AO_Command_1_Register); bits = AO_Error_Interrupt_Enable;#ifdef PCIDMA win_out(0, DAC_FIFO_Clear); // offset load doesn't seem to be necessary //ao_win_out( 0x6, AO_FIFO_Offset_Load_611x ); ni_ao_setup_MITE_dma(dev, &s->async->cmd); ret = ni_ao_wait_for_dma_load(dev); if(ret < 0) return ret; ni_set_bits(dev, Interrupt_B_Enable_Register, AO_FIFO_Interrupt_Enable, 0);#else ret = ni_ao_prep_fifo(dev,s); if(ret==0)return -EPIPE; bits |= AO_FIFO_Interrupt_Enable;#endif ni_set_bits(dev, Interrupt_B_Enable_Register, bits, 1); win_out(devpriv->ao_cmd2|AO_START1_Pulse,AO_Command_2_Register); s->async->inttrig=NULL; return 0;}static int ni_ao_cmd(comedi_device *dev,comedi_subdevice *s){ comedi_cmd *cmd = &s->async->cmd; int trigvar; int bits; trigvar = ni_ns_to_timer(&cmd->scan_begin_arg,TRIG_ROUND_NEAREST); win_out(AO_Configuration_Start,Joint_Reset_Register); win_out(AO_Disarm,AO_Command_1_Register); ni_ao_config_chanlist(dev,s,cmd->chanlist,cmd->chanlist_len); if(cmd->stop_src==TRIG_NONE){ devpriv->ao_mode1|=AO_Continuous; devpriv->ao_mode1&=~AO_Trigger_Once; }else{ devpriv->ao_mode1&=~AO_Continuous; devpriv->ao_mode1|=AO_Trigger_Once; } win_out(devpriv->ao_mode1,AO_Mode_1_Register); devpriv->ao_trigger_select&=~(AO_START1_Polarity|AO_START1_Select(-1)); devpriv->ao_trigger_select|=AO_START1_Edge|AO_START1_Sync; win_out(devpriv->ao_trigger_select,AO_Trigger_Select_Register); devpriv->ao_mode3&=~AO_Trigger_Length; win_out(devpriv->ao_mode3,AO_Mode_3_Register); win_out(devpriv->ao_mode1,AO_Mode_1_Register); devpriv->ao_mode2&=~AO_BC_Initial_Load_Source; win_out(devpriv->ao_mode2,AO_Mode_2_Register); if(cmd->stop_src==TRIG_NONE){ win_out2(0xffffff,AO_BC_Load_A_Register); }else{ win_out2(0,AO_BC_Load_A_Register); } win_out(AO_BC_Load,AO_Command_1_Register); devpriv->ao_mode2&=~AO_UC_Initial_Load_Source; win_out(devpriv->ao_mode2,AO_Mode_2_Register); switch(cmd->stop_src){ case TRIG_COUNT: win_out2(cmd->stop_arg,AO_UC_Load_A_Register); win_out(AO_UC_Load,AO_Command_1_Register); win_out2(cmd->stop_arg - 1,AO_UC_Load_A_Register); break; case TRIG_NONE: win_out2(0xffffff,AO_UC_Load_A_Register); win_out(AO_UC_Load,AO_Command_1_Register); win_out2(0xffffff,AO_UC_Load_A_Register); break; default: win_out2(0,AO_UC_Load_A_Register); win_out(AO_UC_Load,AO_Command_1_Register); win_out2(cmd->stop_arg,AO_UC_Load_A_Register); } devpriv->ao_cmd2&=~AO_BC_Gate_Enable; win_out(devpriv->ao_cmd2,AO_Command_2_Register); devpriv->ao_mode1&=~(AO_UI_Source_Select(0x1f)|AO_UI_Source_Polarity); win_out(devpriv->ao_mode1,AO_Mode_1_Register); devpriv->ao_mode2&=~(AO_UI_Reload_Mode(3)|AO_UI_Initial_Load_Source); win_out(devpriv->ao_mode2,AO_Mode_2_Register); win_out2(1,AO_UI_Load_A_Register); win_out(AO_UI_Load,AO_Command_1_Register); win_out2(trigvar,AO_UI_Load_A_Register); if( boardtype.ao_671x == 0 ){ if(cmd->scan_end_arg>1){ devpriv->ao_mode1|=AO_Multiple_Channels; win_out(AO_Number_Of_Channels(cmd->scan_end_arg-1)| AO_UPDATE_Output_Select(1), AO_Output_Control_Register); }else{ devpriv->ao_mode1&=~AO_Multiple_Channels; win_out(AO_Number_Of_Channels(CR_CHAN(cmd->chanlist[0]))| AO_UPDATE_Output_Select(1), AO_Output_Control_Register); } win_out(devpriv->ao_mode1,AO_Mode_1_Register); } win_out(AO_DAC0_Update_Mode|AO_DAC1_Update_Mode,AO_Command_1_Register); devpriv->ao_mode3|=AO_Stop_On_Overrun_Error; win_out(devpriv->ao_mode3,AO_Mode_3_Register); devpriv->ao_mode2 &= AO_FIFO_Mode_Mask;#ifdef PCIDMA devpriv->ao_mode2 |= AO_FIFO_Mode_HF_to_F;#else devpriv->ao_mode2 |= AO_FIFO_Mode_HF;#endif devpriv->ao_mode2 &= ~AO_FIFO_Retransmit_Enable; win_out(devpriv->ao_mode2,AO_Mode_2_Register); bits = AO_BC_Source_Select | AO_UPDATE_Pulse_Width | AO_TMRDACWR_Pulse_Width; if( boardtype.ao_fifo_depth ) bits |= AO_FIFO_Enable; win_out(bits, AO_Personal_Register); // enable sending of ao dma requests win_out(AO_AOFREQ_Enable, AO_Start_Select_Register); win_out(AO_Configuration_End,Joint_Reset_Register); if(cmd->stop_src==TRIG_COUNT) { win_out(AO_BC_TC_Interrupt_Ack,Interrupt_B_Ack_Register); ni_set_bits(dev, Interrupt_B_Enable_Register, AO_BC_TC_Interrupt_Enable, 1); } s->async->inttrig=ni_ao_inttrig; return 0;}static int ni_ao_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_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 */ 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++; }#if 0 /* XXX need ao_speed */ if(cmd->scan_begin_arg<boardtype.ao_speed){ cmd->scan_begin_arg=boardtype.ao_speed; err++; }#endif if(cmd->scan_begin_arg>TIMER_BASE*0xffffff){ /* XXX check */ cmd->scan_begin_arg=TIMER_BASE*0xffffff; 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){ /* XXX check */ 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 */ tmp = cmd->scan_begin_arg; ni_ns_to_timer(&cmd->scan_begin_arg,cmd->flags&TRIG_ROUND_MASK); if(tmp!=cmd->scan_begin_arg)err++; if(err)return 4; /* step 5: fix up chanlist */ if(cmd->chanlist_len != cmd->scan_end_arg){ cmd->chanlist_len = cmd->scan_end_arg; err++; } if(err)return 5; return 0;}static int ni_ao_reset(comedi_device *dev,comedi_subdevice *s){ //devpriv->ao0p=0x0000; //ni_writew(devpriv->ao0p,AO_Configuration); //devpriv->ao1p=AO_Channel(1); //ni_writew(devpriv->ao1p,AO_Configuration);#ifdef PCIDMA mite_dma_disarm(devpriv->mite, AO_DMA_CHAN); writel(CHOR_DMARESET | CHOR_FRESET, devpriv->mite->mite_io_addr + MITE_CHOR + CHAN_OFFSET(AO_DMA_CHAN));#endif win_out(AO_Configuration_Start,Joint_Reset_Register); win_out(AO_Disarm,AO_Command_1_Register); ni_set_bits(dev,Interrupt_B_Enable_Register,~0,0); win_out(0x0010,AO_Personal_Register); win_out(0x3f98,Interrupt_B_Ack_Register); win_out(AO_BC_Source_Select | AO_UPDATE_Pulse_Width | AO_TMRDACWR_Pulse_Width, AO_Personal_Register); win_out(0,AO_Output_Control_Register); win_out(0,AO_Start_Select_Register); devpriv->ao_cmd1=0; win_out(devpriv->ao_cmd1,AO_Command_1_Register); devpriv->ao_cmd2=0; devpriv->ao_mode1=0; devpriv->ao_mode2=0; devpriv->ao_mode3=0; devpriv->ao_trigger_select=0; if(boardtype.ao_671x){ ao_win_out(0x3, AO_Immediate_671x); ao_win_out(CLEAR_WG, AO_Misc_611x); } return 0;}static int ni_dio_insn_config(comedi_device *dev,comedi_subdevice *s, comedi_insn *insn,lsampl_t *data){#ifdef DEBUG_DIO printk("ni_dio_insn_config() chan=%d io=%d\n", CR_CHAN(insn->chanspec),data[0]);#endif 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; } devpriv->dio_control &= ~DIO_Pins_Dir_Mask; devpriv->dio_control |= DIO_Pins_Dir(s->io_bits); win_out(devpriv->dio_control,DIO_Control_Register); return 1;}static int ni_dio_insn_bits(comedi_device *dev,comedi_subdevice *s, comedi_insn *insn,lsampl_t *data){#ifdef DEBUG_DIO printk("ni_dio_insn_bits() mask=0x%x bits=0x%x\n",data[0],data[1]);#endif if(insn->n!=2)return -EINVAL; if(data[0]){ s->state &= ~data[0]; s->state |= (data[0]&data[1]); devpriv->dio_output &= ~DIO_Parallel_Data_Mask; devpriv->dio_output |= DIO_Parallel_Data_Out(s->state); win_out(devpriv->dio_output,DIO_Output_Register); } data[1] = win_in(DIO_Parallel_Input_Register); return 2;}static void mio_common_detach(comedi_device *dev){ if(dev->subdevices && boardtype.has_8255) subdev_8255_cleanup(dev,dev->subdevices+3);}static int ni_E_init(comedi_device *dev,comedi_devconfig *it){ comedi_subdevice *s; int bits; if(alloc_subdevices(dev, 8)<0) return -ENOMEM; /* analog input subdevice */ s=dev->subdevices+0; dev->read_subdev=s; if(boardtype.n_adchan){ s->type=COMEDI_SUBD_AI; s->subdev_flags=SDF_READABLE|SDF_DIFF; if( boardtype.reg_611x == 0 ) s->subdev_flags |= SDF_GROUND | SDF_COMMON | SDF_OTHER; s->subdev_flags|=SDF_DITHER; s->n_chan=boardtype.n_adchan; s->len_chanlist=512; s->maxdata=(1<<boardtype.adbits)-1; s->range_table=ni_range_lkup[boardtype.gainlkup]; s->insn_read=ni_ai_insn_read; s->insn_config=ni_ai_insn_config; s->do_cmdtest=ni_ai_cmdtest; s->do_cmd=ni_ai_cmd; s->cancel=ni_ai_reset; s->poll=ni_ai_poll; s->munge=ni_ai_munge; }else{ s->type=COMEDI_SUBD_UNUSED; } /* analog output subdevice */ s=dev->subdevices+1; if(boardtype.n_aochan){ dev->write_subdev=s; s->type=COMEDI_SUBD_AO; s->subdev_flags=SDF_WRITABLE|SDF_DEGLITCH|SDF_GROUND; s->n_chan=boardtype.n_aochan; s->maxdata=(1<<boardtype.aobits)-1; if(boardtype.ao_unipolar){ s->range_table=&range_ni_E_ao_ext; /* XXX wrong for some boards */ }else{ s->range_table=&range_bipolar10; } s->insn_read=ni_ao_insn_read; if(boardtype.ao_671x){ s->insn_write=ni_ao_insn_write_671x; }else{ s->insn_write=ni_ao_insn_write; } if(boardtype.ao_fifo_depth){ s->do_cmd=ni_ao_cmd; s->do_cmdtest=ni_ao_cmdtest; s->len_chanlist = 2; } s->cancel=ni_ao_reset; s->munge=ni_ao_munge; }else{ s->type=COMEDI_SUBD_UNUSED; } /* digital i/o subdevice */ s=dev->subdevices+2; s->type=COMEDI_SUBD_DIO; s->subdev_flags=SDF_WRITABLE|SDF_READABLE; s->n_chan=8; s->maxdata=1; s->range_table=&range_digital; s->io_bits=0; /* all bits input */ s->insn_bits=ni_dio_insn_bits; s->insn_config=ni_dio_insn_config; /* dio setup */ devpriv->dio_control = DIO_Pins_Dir(s->io_bits); win_out(devpriv->dio_control,DIO_Control_Register); /* 8255 device */ s=dev->subdevices+3; if(boardtype.has_8255){ subdev_8255_init(dev,s,ni_8255_callback,(unsigned long)dev); }else{ s->type=COMEDI_SUBD_UNUSED; } /* general purpose counter/timer device */ s=dev->subdevices+4; s->type=COMEDI_SUBD_COUNTER; s->subdev_flags=SDF_READABLE|SDF_WRITABLE; s->insn_read= ni_gpct_insn_read; s->insn_write= ni_gpct_insn_write; s->insn_config=ni_gpct_insn_config; s->n_chan=2; s->maxdata=1; devpriv->an_trig_etc_reg = 0; GPCT_Reset(dev,0); GPCT_Reset(dev,1); /* calibration subdevice -- ai and ao */ s=dev->subdevices+5; s->type=COMEDI_SUBD_CALIB; s->subdev_flags=SDF_WRITABLE|SDF_INTERNAL; s->insn_read=ni_calib_insn_read; s->insn_write=ni_calib_insn_write; caldac_setup(dev,s); /* EEPROM */ s=dev->subdevices+6; s->type=COMEDI_SUBD_MEMORY; s->subdev_flags=SDF_READABLE|SDF_INTERNAL; s->n_chan=512; s->maxdata=0xff; s->insn_read=ni_eeprom_insn_re
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -