📄 daqboard2000.c
字号:
//comedi_udelay(2); } data[i] = fpga->acqResultsFIFO; fpga->acqControl = DAQBOARD2000_AdcPacerDisable; fpga->acqControl = DAQBOARD2000_SeqStopScanList; } return i;}static int daqboard2000_ao_insn_read(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;}static int daqboard2000_ao_insn_write(comedi_device *dev, comedi_subdevice *s, comedi_insn *insn, lsampl_t *data){ int i; int chan = CR_CHAN(insn->chanspec); daqboard2000_hw *fpga = devpriv->daq; int timeout; for(i=0;i<insn->n;i++){ /* * OK, since it works OK without enabling the DAC's, let's keep * it as simple as possible... */ //fpga->dacControl = (chan + 2) * 0x0010 | 0x0001; comedi_udelay(1000); fpga->dacSetting[chan] = data[i]; for (timeout = 0 ; timeout < 20 ; timeout++) { if ((fpga->dacControl & ((chan + 1) * 0x0010)) == 0) { break; } //comedi_udelay(2); } devpriv->ao_readback[chan] = data[i]; /* * Since we never enabled the DAC's, we don't need to disable it... * fpga->dacControl = (chan + 2) * 0x0010 | 0x0000; comedi_udelay(1000); */ } return i;}static void daqboard2000_resetLocalBus(comedi_device *dev){ printk("daqboard2000_resetLocalBus\n"); writel(DAQBOARD2000_SECRLocalBusHi, devpriv->plx + 0x6c); comedi_udelay(10000); writel(DAQBOARD2000_SECRLocalBusLo, devpriv->plx + 0x6c); comedi_udelay(10000);}static void daqboard2000_reloadPLX(comedi_device *dev){ printk("daqboard2000_reloadPLX\n"); writel(DAQBOARD2000_SECRReloadLo, devpriv->plx + 0x6c); comedi_udelay(10000); writel(DAQBOARD2000_SECRReloadHi, devpriv->plx + 0x6c); comedi_udelay(10000); writel(DAQBOARD2000_SECRReloadLo, devpriv->plx + 0x6c); comedi_udelay(10000);}static void daqboard2000_pulseProgPin(comedi_device *dev){ printk("daqboard2000_pulseProgPin 1\n"); writel(DAQBOARD2000_SECRProgPinHi, devpriv->plx + 0x6c); comedi_udelay(10000); writel(DAQBOARD2000_SECRProgPinLo, devpriv->plx + 0x6c); comedi_udelay(10000); /* Not in the original code, but I like symmetry... */}static int daqboard2000_pollCPLD(comedi_device *dev, int mask) { int result = 0; int i; int cpld; /* timeout after 50 tries -> 5ms */ for (i = 0 ; i < 50 ; i++) { cpld = readw(devpriv->daq + 0x1000); if ((cpld & mask) == mask){ result=1; break; } comedi_udelay(100); } comedi_udelay(5); return result;}static int daqboard2000_writeCPLD(comedi_device *dev, int data){ int result = 0; comedi_udelay(10); writew(data, devpriv->daq + 0x1000); if ((readw(devpriv->daq + 0x1000) & DAQBOARD2000_CPLD_INIT) == DAQBOARD2000_CPLD_INIT) { result = 1; } return result;}static int initialize_daqboard2000(comedi_device *dev, unsigned char *cpld_array,int len){ int result = -EIO; /* Read the serial EEPROM control register */ int secr; int retry; int i; /* Check to make sure the serial eeprom is present on the board */ secr = readl(devpriv->plx + 0x6c); if (!(secr & DAQBOARD2000_EEPROM_PRESENT)) {#ifdef DEBUG_EEPROM printk("no serial eeprom\n");#endif return -EIO; } for (retry = 0 ; retry < 3 ; retry++) {#ifdef DEBUG_EEPROM printk("Programming EEPROM try %x\n", retry);#endif daqboard2000_resetLocalBus(dev); daqboard2000_reloadPLX(dev); daqboard2000_pulseProgPin(dev); if(daqboard2000_pollCPLD(dev, DAQBOARD2000_CPLD_INIT)) { for (i = 0 ; i < len ; i++) { if (cpld_array[i] == 0xff && cpld_array[i+1] == 0x20) { #ifdef DEBUG_EEPROM printk("Preamble found at %d\n", i);#endif break; } } for ( ; i < len ; i += 2) { int data = (cpld_array[i]<<8) + cpld_array[i+1]; if (!daqboard2000_writeCPLD(dev, data)) { break; } } if (i >= len) {#ifdef DEBUG_EEPROM printk("Programmed\n");#endif daqboard2000_resetLocalBus(dev); daqboard2000_reloadPLX(dev); result = 0; break; } } } return result;}static void daqboard2000_adcStopDmaTransfer(comedi_device *dev){/* printk("Implement: daqboard2000_adcStopDmaTransfer\n");*/}static void daqboard2000_adcDisarm(comedi_device *dev){ daqboard2000_hw *fpga = devpriv->daq; /* Disable hardware triggers */ comedi_udelay(2); fpga->trigControl = DAQBOARD2000_TrigAnalog | DAQBOARD2000_TrigDisable; comedi_udelay(2); fpga->trigControl = DAQBOARD2000_TrigTTL | DAQBOARD2000_TrigDisable; /* Stop the scan list FIFO from loading the configuration pipe */ comedi_udelay(2); fpga->acqControl = DAQBOARD2000_SeqStopScanList; /* Stop the pacer clock */ comedi_udelay(2); fpga->acqControl = DAQBOARD2000_AdcPacerDisable; /* Stop the input dma (abort channel 1) */ daqboard2000_adcStopDmaTransfer(dev);}static void daqboard2000_activateReferenceDacs(comedi_device *dev){ daqboard2000_hw *fpga = devpriv->daq; int timeout; // Set the + reference dac value in the FPGA fpga->refDacs = 0x80 | DAQBOARD2000_PosRefDacSelect; for (timeout = 0 ; timeout < 20 ; timeout++) { if ((fpga->dacControl & DAQBOARD2000_RefBusy) == 0) { break; } comedi_udelay(2); }/* printk("DAQBOARD2000_PosRefDacSelect %d\n", timeout);*/ // Set the - reference dac value in the FPGA fpga->refDacs = 0x80 | DAQBOARD2000_NegRefDacSelect; for (timeout = 0 ; timeout < 20 ; timeout++) { if ((fpga->dacControl & DAQBOARD2000_RefBusy) == 0) { break; } comedi_udelay(2); }/* printk("DAQBOARD2000_NegRefDacSelect %d\n", timeout);*/}static void daqboard2000_initializeCtrs(comedi_device *dev){/* printk("Implement: daqboard2000_initializeCtrs\n");*/}static void daqboard2000_initializeTmrs(comedi_device *dev){/* printk("Implement: daqboard2000_initializeTmrs\n");*/}static void daqboard2000_dacDisarm(comedi_device *dev){/* printk("Implement: daqboard2000_dacDisarm\n");*/}static void daqboard2000_initializeAdc(comedi_device *dev){ daqboard2000_adcDisarm(dev); daqboard2000_activateReferenceDacs(dev); daqboard2000_initializeCtrs(dev); daqboard2000_initializeTmrs(dev);}static void daqboard2000_initializeDac(comedi_device *dev){ daqboard2000_dacDisarm(dev);}/*The test command, REMOVE!!:rmmod daqboard2000 ; rmmod comedi; make install ; modprobe daqboard2000; /usr/sbin/comedi_config /dev/comedi0 daqboard/2000 ; tail -40 /var/log/messages*/static int daqboard2000_8255_cb(int dir, int port, int data, unsigned long ioaddr){ int result = 0; if(dir){ writew(data,ioaddr+port*2); result = 0; }else{ result = readw(ioaddr+port*2); }/* printk("daqboard2000_8255_cb %x %d %d %2.2x -> %2.2x\n", arg, dir, port, data, result);*/ return result;}static int daqboard2000_attach(comedi_device *dev, comedi_devconfig *it){ int result = 0; comedi_subdevice *s; struct pci_dev *card = NULL; void *aux_data; unsigned int aux_len; printk("comedi%d: daqboard2000:", dev->minor); if(!pci_present()) { printk(" PCI bus not present!\n"); result = -EIO; goto out; } /* FIXME: we should handle multiple cards, have to make David decide how, so we will be consistent among all PCI card drivers... */ card = pci_find_device(0x1616, 0x0409, NULL); if (!card) { printk(" no daqboard2000 found\n"); result = -EIO; goto out; } if((result = pci_enable_device(card))<0){ goto out; } if (card->hdr_type == PCI_HEADER_TYPE_NORMAL) { u32 id; int i; pci_read_config_dword(card, PCI_SUBSYSTEM_VENDOR_ID, &id); for(i=0;i<n_boardtypes;i++){ if(boardtypes[i].id==id){ printk(" %s",boardtypes[i].name); dev->board_ptr=boardtypes+i; } } if(!dev->board_ptr){ printk(" unknown subsystem id %08x (pretend it is an ids2)",id); dev->board_ptr=boardtypes; } }else{ printk(" abnormal pci header type !?!?\n"); result=-EIO; goto out; } result = alloc_private(dev,sizeof(daqboard2000_private)); if(result<0)goto out; result = alloc_subdevices(dev, 3); if(result<0)goto out; devpriv->plx = ioremap(pci_resource_start(card,0), DAQBOARD2000_PLX_SIZE); devpriv->daq = ioremap(pci_resource_start(card,2), DAQBOARD2000_DAQ_SIZE); readl(devpriv->plx + 0x6c); /* u8 interrupt; Windows code does restore interrupts, but since we don't use them... pci_read_config_byte(card, PCI_INTERRUPT_LINE, &interrupt); printk("Interrupt before is: %x\n", interrupt); */ aux_data = (void *)it->options[COMEDI_DEVCONF_AUX_DATA]; aux_len = it->options[COMEDI_DEVCONF_AUX_DATA_LENGTH]; if(aux_data && aux_len){ result = initialize_daqboard2000(dev, aux_data, aux_len); }else{ printk("no FPGA initialization code, aborting\n"); result=-EIO; } if(result<0)goto out; daqboard2000_initializeAdc(dev); daqboard2000_initializeDac(dev); /* Windows code does restore interrupts, but since we don't use them... pci_read_config_byte(card, PCI_INTERRUPT_LINE, &interrupt); printk("Interrupt after is: %x\n", interrupt); */ dev->iobase = (int)devpriv->daq; dev->board_name = this_board->name; s = dev->subdevices + 0; /* ai subdevice */ s->type = COMEDI_SUBD_AI; s->subdev_flags = SDF_READABLE|SDF_GROUND; s->n_chan = 24; s->maxdata = 0xffff; s->insn_read = daqboard2000_ai_insn_read; s->range_table = &range_daqboard2000_ai; s = dev->subdevices + 1; /* ao subdevice */ s->type = COMEDI_SUBD_AO; s->subdev_flags = SDF_WRITABLE; s->n_chan = 2; s->maxdata = 0xffff; s->insn_read = daqboard2000_ao_insn_read; s->insn_write = daqboard2000_ao_insn_write; s->range_table = &range_daqboard2000_ao; s = dev->subdevices + 2; result = subdev_8255_init(dev,s,daqboard2000_8255_cb, (unsigned long)(dev->iobase+0x40)); printk("\n");out: return result;}static int daqboard2000_detach(comedi_device * dev){ printk("comedi%d: daqboard2000: remove\n", dev->minor); if(dev->subdevices) subdev_8255_cleanup(dev,dev->subdevices+2); if (devpriv && devpriv->daq) { iounmap(devpriv->daq); } if (devpriv && devpriv->plx) { iounmap(devpriv->plx); } if (dev->irq) { free_irq(dev->irq, dev); } return 0;}COMEDI_INITCLEANUP(driver_daqboard2000);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -