📄 dt3000.c
字号:
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; dt3k_ns_to_timer(100,&cmd->scan_begin_arg, cmd->flags&TRIG_ROUND_MASK); if(tmp!=cmd->scan_begin_arg)err++; }else{ /* not supported */ } if(cmd->convert_src==TRIG_TIMER){ tmp=cmd->convert_arg; dt3k_ns_to_timer(50,&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++; } }else{ /* not supported */ } if(err)return 4; return 0;}static int dt3k_ns_to_timer(unsigned int timer_base, unsigned int *nanosec, unsigned int round_mode){ int divider, base, prescale; /* This function needs improvment */ /* Don't know if divider==0 works. */ for(prescale=0;prescale<16;prescale++){ base = timer_base * (prescale+1); 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; break; } if(divider<65536){ *nanosec = divider*base; return (prescale<<16)|(divider); } } prescale = 15; base = timer_base * (1<<prescale); divider = 65535; *nanosec = divider*base; return (prescale<<16)|(divider);}static int dt3k_ai_cmd(comedi_device *dev,comedi_subdevice *s){ comedi_cmd *cmd = &s->async->cmd; int i; unsigned int chan,range,aref; unsigned int divider; unsigned int tscandiv; int ret; unsigned int mode;printk("dt3k_ai_cmd:\n"); for(i=0;i<cmd->chanlist_len;i++){ chan=CR_CHAN(cmd->chanlist[i]); range=CR_RANGE(cmd->chanlist[i]); writew((range<<6)|chan,dev->iobase+DPR_ADC_buffer+i); } aref=CR_AREF(cmd->chanlist[0]); writew(cmd->scan_end_arg,dev->iobase+DPR_Params(0));printk("param[0]=0x%04x\n",cmd->scan_end_arg); if(cmd->convert_src==TRIG_TIMER){ divider = dt3k_ns_to_timer(50,&cmd->convert_arg, cmd->flags&TRIG_ROUND_MASK); writew((divider>>16),dev->iobase+DPR_Params(1));printk("param[1]=0x%04x\n",divider>>16); writew((divider&0xffff),dev->iobase+DPR_Params(2));printk("param[2]=0x%04x\n",divider&0xffff); }else{ /* not supported */ } if(cmd->scan_begin_src==TRIG_TIMER){ tscandiv = dt3k_ns_to_timer(100,&cmd->scan_begin_arg, cmd->flags&TRIG_ROUND_MASK); writew((tscandiv>>16),dev->iobase+DPR_Params(3));printk("param[3]=0x%04x\n",tscandiv>>16); writew((tscandiv&0xffff),dev->iobase+DPR_Params(4));printk("param[4]=0x%04x\n",tscandiv&0xffff); }else{ /* not supported */ } mode = DT3000_AD_RETRIG_INTERNAL | 0 | 0; writew(mode,dev->iobase+DPR_Params(5));printk("param[5]=0x%04x\n",mode); writew(aref==AREF_DIFF,dev->iobase+DPR_Params(6));printk("param[6]=0x%04x\n",aref==AREF_DIFF); writew(AI_FIFO_DEPTH/2,dev->iobase+DPR_Params(7));printk("param[7]=0x%04x\n",AI_FIFO_DEPTH/2); writew(SUBS_AI,dev->iobase+DPR_SubSys); ret = dt3k_send_cmd(dev,CMD_CONFIG); writew(DT3000_ADFULL | DT3000_ADSWERR | DT3000_ADHWERR, dev->iobase + DPR_Int_Mask);debug_n_ints = 0; writew(SUBS_AI,dev->iobase+DPR_SubSys); ret = dt3k_send_cmd(dev,CMD_START); return 0;}static int dt3k_ai_cancel(comedi_device *dev,comedi_subdevice *s){ int ret; writew(SUBS_AI,dev->iobase+DPR_SubSys); ret = dt3k_send_cmd(dev,CMD_STOP); writew(0, dev->iobase + DPR_Int_Mask); return 0;}static int dt3k_ai_insn(comedi_device *dev,comedi_subdevice *s, comedi_insn *insn,lsampl_t *data){ int i; unsigned int chan,gain,aref; chan=CR_CHAN(insn->chanspec); gain=CR_RANGE(insn->chanspec); /* XXX docs don't explain how to select aref */ aref=CR_AREF(insn->chanspec); for(i=0;i<insn->n;i++){ data[i]=dt3k_readsingle(dev,SUBS_AI,chan,gain); } return i;}static int dt3k_ao_insn(comedi_device *dev,comedi_subdevice *s, comedi_insn *insn,lsampl_t *data){ int i; unsigned int chan; chan=CR_CHAN(insn->chanspec); for(i=0;i<insn->n;i++){ dt3k_writesingle(dev,SUBS_AO,chan,data[i]); devpriv->ao_readback[chan]=data[i]; } return i;}static int dt3k_ao_insn_read(comedi_device *dev,comedi_subdevice *s, comedi_insn *insn,lsampl_t *data){ int i; unsigned int chan; chan=CR_CHAN(insn->chanspec); for(i=0;i<insn->n;i++){ data[i]=devpriv->ao_readback[chan]; } return i;}static void dt3k_dio_config(comedi_device *dev,int bits){ /* XXX */ writew(SUBS_DOUT,dev->iobase+DPR_SubSys); writew(bits,dev->iobase+DPR_Params(0));#if 0 /* don't know */ writew(0,dev->iobase+DPR_Params(1)); writew(0,dev->iobase+DPR_Params(2));#endif dt3k_send_cmd(dev,CMD_CONFIG);}static int dt3k_dio_insn_config(comedi_device *dev,comedi_subdevice *s, comedi_insn *insn,lsampl_t *data){ int mask; if(insn->n!=1)return -EINVAL; mask=(CR_CHAN(insn->chanspec)<4)?0x0f:0xf0; if(data[0]==COMEDI_OUTPUT)s->io_bits|=mask; else s->io_bits&=~mask; mask=(s->io_bits&0x01)|((s->io_bits&0x10)>>3); dt3k_dio_config(dev,mask); return 1;}static int dt3k_dio_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[1]&data[0]; dt3k_writesingle(dev,SUBS_DOUT,0,s->state); } data[1]=dt3k_readsingle(dev,SUBS_DIN,0,0); return 2;}static int dt3k_mem_insn_read(comedi_device *dev,comedi_subdevice *s, comedi_insn *insn,lsampl_t *data){ unsigned int addr=CR_CHAN(insn->chanspec); int i; for(i=0;i<insn->n;i++){ writew(SUBS_MEM,dev->iobase+DPR_SubSys); writew(addr,dev->iobase+DPR_Params(0)); writew(1,dev->iobase+DPR_Params(1)); dt3k_send_cmd(dev,CMD_READCODE); data[i]=readw(dev->iobase+DPR_Params(2)); } return i;}static int dt_pci_probe(comedi_device *dev);static int dt3000_attach(comedi_device *dev,comedi_devconfig *it){ comedi_subdevice *s; int ret=0; printk("dt3000:"); if(!pci_present()){ printk(" no PCI bus\n"); return -EINVAL; } if((ret=alloc_private(dev,sizeof(dt3k_private)))<0) return ret; ret=dt_pci_probe(dev); if(ret<0)return ret; if(ret==0){ printk(" no DT board found\n"); return -ENODEV; } dev->board_name = this_board->name; if(comedi_request_irq(devpriv->pci_dev->irq, dt3k_interrupt, SA_SHIRQ, "dt3000", dev)){ printk(" unable to allocate IRQ %d\n", devpriv->pci_dev->irq); return -EINVAL; } dev->irq = devpriv->pci_dev->irq; if( (ret = alloc_subdevices(dev, 4)) <0) return ret; s=dev->subdevices; dev->read_subdev = s; /* ai subdevice */ s->type=COMEDI_SUBD_AI; s->subdev_flags=SDF_READABLE|SDF_GROUND|SDF_DIFF; s->n_chan=this_board->adchan; s->insn_read=dt3k_ai_insn; s->maxdata=(1<<this_board->adbits)-1; s->len_chanlist=512; s->range_table=&range_dt3000_ai; /* XXX */ s->do_cmd = dt3k_ai_cmd; s->do_cmdtest = dt3k_ai_cmdtest; s->cancel = dt3k_ai_cancel; s++; /* ao subsystem */ s->type=COMEDI_SUBD_AO; s->subdev_flags=SDF_WRITABLE; s->n_chan=2; s->insn_read=dt3k_ao_insn_read; s->insn_write=dt3k_ao_insn; s->maxdata=(1<<this_board->dabits)-1; s->len_chanlist=1; s->range_table=&range_bipolar10; s++; /* dio subsystem */ s->type=COMEDI_SUBD_DIO; s->subdev_flags=SDF_READABLE|SDF_WRITABLE; s->n_chan=8; s->insn_config=dt3k_dio_insn_config; s->insn_bits=dt3k_dio_insn_bits; s->maxdata=1; s->len_chanlist=8; s->range_table=&range_digital; s++; /* mem subsystem */ s->type=COMEDI_SUBD_MEMORY; s->subdev_flags=SDF_READABLE; s->n_chan=0x1000; s->insn_read=dt3k_mem_insn_read; s->maxdata=0xff; s->len_chanlist=1; s->range_table=&range_unknown;#if 0 s++; /* proc subsystem */ s->type=COMEDI_SUBD_PROC;#endif return 0;}static int dt3000_detach(comedi_device *dev){ if(dev->irq)comedi_free_irq(dev->irq,dev); /* XXX */ return 0;}static struct pci_dev *dt_pci_find_device(struct pci_dev *from,int *board);static int setup_pci(comedi_device *dev);static int dt_pci_probe(comedi_device *dev){ int board; devpriv->pci_dev=dt_pci_find_device(NULL,&board); dev->board_ptr=dt3k_boardtypes+board; if(!devpriv->pci_dev) return 0; setup_pci(dev); return 1;}static int setup_pci(comedi_device *dev){ unsigned long offset; u32 addr; int ret; ret = pci_enable_device(devpriv->pci_dev); if(ret<0)return ret; addr=pci_resource_start(devpriv->pci_dev,0); devpriv->phys_addr=addr; offset = devpriv->phys_addr & ~PAGE_MASK; devpriv->io_addr = ioremap(devpriv->phys_addr & PAGE_MASK, DT3000_SIZE + offset ) + offset;#if DEBUG printk("0x%08lx mapped to %p, ",devpriv->phys_addr,devpriv->io_addr);#endif dev->iobase = (int)devpriv->io_addr; return 0;}#if LINUX_VERSION_CODE < 0x020300static struct pci_dev *dt_pci_find_device(struct pci_dev *from,int *board){ int i; if(!from){ from=pci_devices; }else{ from=from->next; } while(from){ if(from->vendor == PCI_VENDOR_ID_DT){ for(i=0;i<n_dt3k_boards;i++){ if(from->device == dt3k_boardtypes[i].device_id){ *board=i; return from; } } printk("unknown Data Translation PCI device found with device_id=0x%04x\n",from->device); } from=from->next; } *board=-1; return from;}#elsestatic struct pci_dev *dt_pci_find_device(struct pci_dev *from,int *board){ int i; if(!from){ from=(struct pci_dev *)(pci_devices.next); }else{ from=(struct pci_dev *)(from->global_list.next); } while(from){ if(from->vendor == PCI_VENDOR_ID_DT){ for(i=0;i<n_dt3k_boards;i++){ if(from->device == dt3k_boardtypes[i].device_id){ *board=i; return from; } } printk("unknown Data Translation PCI device found with device_id=0x%04x\n",from->device); } from=(struct pci_dev *)(from->global_list.next); } *board=-1; return from;}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -