📄 rtd520.c
字号:
/* Set burst start source select (write only) */#define RtdBurstStartSource(dev,v) \ writel (v, devpriv->las0+LAS0_BURST_START)/* Set Pacer start source select (write only) */#define RtdPacerStartSource(dev,v) \ writel (v, devpriv->las0+LAS0_PACER_START)/* Set Pacer stop source select (write only) */#define RtdPacerStopSource(dev,v) \ writel (v, devpriv->las0+LAS0_PACER_STOP)/* Set Pacer clock source select (write only) 0=external 1=internal */#define RtdPacerClockSource(dev,v) \ writel ((v > 0) ? 1 : 0, devpriv->las0+LAS0_PACER_SELECT)/* Set sample counter source select (write only) */#define RtdAdcSampleCounterSource(dev,v) \ writel (v, devpriv->las0+LAS0_ADC_SCNT_SRC)/* Set Pacer trigger mode select (write only) 0=single cycle, 1=repeat */#define RtdPacerTriggerMode(dev,v) \ writel ((v > 0) ? 1 : 0, devpriv->las0+LAS0_PACER_REPEAT)/* Set About counter stop enable (write only) */#define RtdAboutStopEnable(dev,v) \ writel ((v > 0) ? 1 : 0, devpriv->las0+LAS0_ACNT_STOP_ENABLE)/* Set external trigger polarity (write only) 0=positive edge, 1=negative */#define RtdTriggerPolarity(dev,v) \ writel ((v > 0) ? 1 : 0, devpriv->las0+LAS0_ETRG_POLARITY)/* Start single ADC conversion */#define RtdAdcStart(dev) \ writew (0, devpriv->las0+LAS0_ADC)/* Read one ADC data value (12bit (with sign extend) as 16bit) *//* Note: matches what DMA would get. Actual value >> 3 */#define RtdAdcFifoGet(dev) \ readw (devpriv->las1+LAS1_ADC_FIFO)/* Read two ADC data values (DOESNT WORK) */#define RtdAdcFifoGet2(dev) \ readl (devpriv->las1+LAS1_ADC_FIFO)/* FIFO status */#define RtdFifoStatus(dev) \ readl (devpriv->las0+LAS0_ADC)/* pacer start/stop read=start, write=stop*/#define RtdPacerStart(dev) \ readl (devpriv->las0+LAS0_PACER)#define RtdPacerStop(dev) \ writel (0, devpriv->las0+LAS0_PACER)/* Interrupt status */#define RtdInterruptStatus(dev) \ readw (devpriv->las0+LAS0_IT)/* Interrupt mask */#define RtdInterruptMask(dev,v) \ writew ((devpriv->intMask = (v)),devpriv->las0+LAS0_IT)/* Interrupt status clear (only bits set in mask) */#define RtdInterruptClear(dev) \ readw (devpriv->las0+LAS0_CLEAR)/* Interrupt clear mask */#define RtdInterruptClearMask(dev,v) \ writew ((devpriv->intClearMask = (v)), devpriv->las0+LAS0_CLEAR)/* Interrupt overrun status */#define RtdInterruptOverrunStatus(dev) \ readl (devpriv->las0+LAS0_OVERRUN)/* Interrupt overrun clear */#define RtdInterruptOverrunClear(dev) \ writel (0, devpriv->las0+LAS0_OVERRUN)/* Pacer counter, 24bit */#define RtdPacerCount(dev) \ readl (devpriv->las0+LAS0_PCLK)#define RtdPacerCounter(dev,v) \ writel ((v) & 0xffffff,devpriv->las0+LAS0_PCLK)/* Burst counter, 10bit */#define RtdBurstCount(dev) \ readl (devpriv->las0+LAS0_BCLK)#define RtdBurstCounter(dev,v) \ writel ((v) & 0x3ff,devpriv->las0+LAS0_BCLK)/* Delay counter, 16bit */#define RtdDelayCount(dev) \ readl (devpriv->las0+LAS0_DCLK)#define RtdDelayCounter(dev,v) \ writel ((v) & 0xffff, devpriv->las0+LAS0_DCLK)/* About counter, 16bit */#define RtdAboutCount(dev) \ readl (devpriv->las0+LAS0_ACNT)#define RtdAboutCounter(dev,v) \ writel ((v) & 0xffff, devpriv->las0+LAS0_ACNT)/* ADC sample counter, 10bit */#define RtdAdcSampleCount(dev) \ readl (devpriv->las0+LAS0_ADC_SCNT)#define RtdAdcSampleCounter(dev,v) \ writel ((v) & 0x3ff, devpriv->las0+LAS0_ADC_SCNT)/* User Timer/Counter (8254) */#define RtdUtcCounterGet(dev,n) \ readb (devpriv->las0 \ + ((n <= 0) ? LAS0_UTC0 : ((1 == n) ? LAS0_UTC1 : LAS0_UTC2)))#define RtdUtcCounterPut(dev,n,v) \ writeb ((v) & 0xff, devpriv->las0 \ + ((n <= 0) ? LAS0_UTC0 : ((1 == n) ? LAS0_UTC1 : LAS0_UTC2)))/* Set UTC (8254) control byte */#define RtdUtcCtrlPut(dev,n,v) \ writeb (devpriv->utcCtrl[(n) & 3] = (((n) & 3) << 6) | ((v) & 0x3f), \ devpriv->las0 + LAS0_UTC_CTRL)/* Set UTCn clock source (write only) */#define RtdUtcClockSource(dev,n,v) \ writew (v, devpriv->las0 \ + ((n <= 0) ? LAS0_UTC0_CLOCK : \ ((1 == n) ? LAS0_UTC1_CLOCK : LAS0_UTC2_CLOCK)))/* Set UTCn gate source (write only) */#define RtdUtcGateSource(dev,n,v) \ writew (v, devpriv->las0 \ + ((n <= 0) ? LAS0_UTC0_GATE : \ ((1 == n) ? LAS0_UTC1_GATE : LAS0_UTC2_GATE)))/* User output N source select (write only) */#define RtdUsrOutSource(dev,n,v) \ writel (v,devpriv->las0+((n <= 0) ? LAS0_UOUT0_SELECT : LAS0_UOUT1_SELECT))/* Digital IO */#define RtdDio0Read(dev) \ (readw (devpriv->las0+LAS0_DIO0) & 0xff)#define RtdDio0Write(dev,v) \ writew ((v) & 0xff, devpriv->las0+LAS0_DIO0)#define RtdDio1Read(dev) \ (readw (devpriv->las0+LAS0_DIO1) & 0xff)#define RtdDio1Write(dev,v) \ writew ((v) & 0xff, devpriv->las0+LAS0_DIO1)#define RtdDioStatusRead(dev) \ (readw (devpriv->las0+LAS0_DIO_STATUS) & 0xff)#define RtdDioStatusWrite(dev,v) \ writew ((devpriv->dioStatus = (v)), devpriv->las0+LAS0_DIO_STATUS)#define RtdDio0CtrlRead(dev) \ (readw (devpriv->las0+LAS0_DIO0_CTRL) & 0xff)#define RtdDio0CtrlWrite(dev,v) \ writew ((v) & 0xff, devpriv->las0+LAS0_DIO0_CTRL)/* Digital to Analog converter *//* Write one data value (sign + 12bit + marker bits) *//* Note: matches what DMA would put. Actual value << 3 */#define RtdDacFifoPut(dev,n,v) \ writew ((v), devpriv->las1 +(((n) == 0) ? LAS1_DAC1_FIFO : LAS1_DAC2_FIFO))/* Start single DAC conversion */#define RtdDacUpdate(dev,n) \ writew (0, devpriv->las0 +(((n) == 0) ? LAS0_DAC1 : LAS0_DAC2))/* Start single DAC conversion on both DACs */#define RtdDacBothUpdate(dev) \ writew (0, devpriv->las0+LAS0_DAC)/* Set DAC output type and range */#define RtdDacRange(dev,n,v) \ writew ((v) & 7, devpriv->las0 \ +(((n) == 0) ? LAS0_DAC1_CTRL : LAS0_DAC2_CTRL))/* Reset DAC FIFO */#define RtdDacClearFifo(dev,n) \ writel (0, devpriv->las0+(((n) == 0) ? LAS0_DAC1_RESET : LAS0_DAC2_RESET))/* Set source for DMA 0 (write only, shadow?) */#define RtdDma0Source(dev,n) \ writel ((n) & 0xf, devpriv->las0+LAS0_DMA0_SRC)/* Set source for DMA 1 (write only, shadow?) */#define RtdDma1Source(dev,n) \ writel ((n) & 0xf, devpriv->las0+LAS0_DMA1_SRC)/* Reset board state for DMA 0 */#define RtdDma0Reset(dev) \ writel (0, devpriv->las0+LAS0_DMA0_RESET)/* Reset board state for DMA 1 */#define RtdDma1Reset(dev) \ writel (0, devpriv->las0+LAS0_DMA1_SRC)/* PLX9080 interrupt mask and status */#define RtdPlxInterruptRead(dev) \ readl (devpriv->lcfg+LCFG_ITCSR)#define RtdPlxInterruptWrite(dev,v) \ writel (v, devpriv->lcfg+LCFG_ITCSR)/* Set mode for DMA 0 */#define RtdDma0Mode(dev,m) \ writel ((m), devpriv->lcfg+LCFG_DMAMODE0)/* Set PCI address for DMA 0 */#define RtdDma0PciAddr(dev,a) \ writel ((a), devpriv->lcfg+LCFG_DMAPADR0)/* Set local address for DMA 0 */#define RtdDma0LocalAddr(dev,a) \ writel ((a), devpriv->lcfg+LCFG_DMALADR0)/* Set byte count for DMA 0 */#define RtdDma0Count(dev,c) \ writel ((c), devpriv->lcfg+LCFG_DMASIZ0)/* Set next descriptor for DMA 0 */#define RtdDma0Next(dev,a) \ writel ((a), devpriv->lcfg+LCFG_DMADPR0)/* Set mode for DMA 1 */#define RtdDma1Mode(dev,m) \ writel ((m), devpriv->lcfg+LCFG_DMAMODE1)/* Set PCI address for DMA 1 */#define RtdDma1PciAddr(dev,a) \ writel ((a), devpriv->lcfg+LCFG_DMAADR1)/* Set local address for DMA 1 */#define RtdDma1LocalAddr(dev,a) \ writel ((a), devpriv->lcfg+LCFG_DMALADR1)/* Set byte count for DMA 1 */#define RtdDma1Count(dev,c) \ writel ((c), devpriv->lcfg+LCFG_DMASIZ1)/* Set next descriptor for DMA 1 */#define RtdDma1Next(dev,a) \ writel ((a), devpriv->lcfg+LCFG_DMADPR1)/* Set control for DMA 0 (write only, shadow?) */#define RtdDma0Control(dev,n) \ writeb (devpriv->dma0Control = (n), devpriv->lcfg+LCFG_DMACSR0)/* Get status for DMA 0 */#define RtdDma0Status(dev) \ readb (devpriv->lcfg+LCFG_DMACSR0)/* Set control for DMA 1 (write only, shadow?) */#define RtdDma1Control(dev,n) \ writeb (devpriv->dma1Control = (n), devpriv->lcfg+LCFG_DMACSR1)/* Get status for DMA 1 */#define RtdDma1Status(dev) \ readb (devpriv->lcfg+LCFG_DMACSR1)/* * The comedi_driver structure tells the Comedi core module * which functions to call to configure/deconfigure (attac/detach) * the board, and also about the kernel module that contains * the device code. */static int rtd_attach (comedi_device *dev, comedi_devconfig *it);static int rtd_detach (comedi_device *dev);static comedi_driver rtd520Driver={ driver_name: "rtd520", module: THIS_MODULE, attach: rtd_attach, detach: rtd_detach, board_name: rtd520Boards, offset: sizeof(rtdBoard), num_names: sizeof(rtd520Boards) / sizeof(rtdBoard),};static int rtd_ai_rinsn (comedi_device *dev, comedi_subdevice *s, comedi_insn *insn, lsampl_t *data);static int rtd_ao_winsn (comedi_device *dev, comedi_subdevice *s, comedi_insn *insn, lsampl_t *data);static int rtd_ao_rinsn (comedi_device *dev, comedi_subdevice *s, comedi_insn *insn, lsampl_t *data);static int rtd_dio_insn_bits (comedi_device *dev, comedi_subdevice *s, comedi_insn *insn, lsampl_t *data);static int rtd_dio_insn_config (comedi_device *dev, comedi_subdevice *s, comedi_insn *insn, lsampl_t *data);static int rtd_ai_cmdtest (comedi_device *dev,comedi_subdevice *s, comedi_cmd *cmd);static int rtd_ai_cmd ( comedi_device *dev, comedi_subdevice *s);static int rtd_ai_cancel ( comedi_device *dev, comedi_subdevice *s);//static int rtd_ai_poll (comedi_device *dev,comedi_subdevice *s);static int rtd_ns_to_timer (unsigned int *ns, int roundMode);static void rtd_interrupt ( int irq, void *d, struct pt_regs *regs);/* * Attach is called by the Comedi core to configure the driver * for a particular board. If you specified a board_name array * in the driver structure, dev->board_ptr contains that * address. */static int rtd_attach ( comedi_device *dev, comedi_devconfig *it) /* board name and options flags */{ comedi_subdevice *s; struct pci_dev* pcidev; int ret; unsigned long physLas0; /* configuation */ unsigned long physLas1; /* data area */ unsigned long physLcfg; /* PLX9080 */#ifdef USE_DMA int index;#endif printk ("comedi%d: rtd520 attaching.\n", dev->minor);#if defined (CONFIG_COMEDI_DEBUG) && defined (USE_DMA) /* You can set this a load time: modprobe comedi comedi_debug=1 */ if (0 == comedi_debug) /* force DMA debug printks */ comedi_debug = 1;#endif /* * Allocate the private structure area. alloc_private() is a * convenient macro defined in comedidev.h. */ if (alloc_private (dev, sizeof(rtdPrivate))<0) return -ENOMEM; /* * Probe the device to determine what device in the series it is. */ pci_for_each_dev (pcidev) { if (pcidev->vendor == PCI_VENDOR_ID_RTD) { if (it->options[0] || it->options[1]) { if (pcidev->bus->number == it->options[0] && PCI_SLOT(pcidev->devfn) == it->options[1]) { DPRINTK("rtd520: found bus=%d slot=%d\n", it->options[0], it->options[1]); break; /* found it */ } } else { /* specific board/slot not specified */ break; /* found one */ } } } if (!pcidev) { if (it->options[0] && it->options[1]) { printk ("No RTD card at bus=%d slot=%d.\n", it->options[0], it->options[1]); } else { printk ("No RTD card found.\n"); } return -EIO; } if (pcidev->device != thisboard->device_id) { printk ("Found an RTD card, but not the supported type (%x).\n", pcidev->device); return -EIO; } devpriv->pci_dev = pcidev; dev->board_name = thisboard->name; if((ret=pci_enable_device(pcidev))<0){ return ret; } /* * Initialize base addresses */ /* Get the physical address from PCI config */ physLas0 = pci_resource_start(devpriv->pci_dev, LAS0_PCIINDEX); physLas1 = pci_resource_start(devpriv->pci_dev, LAS1_PCIINDEX); physLcfg = pci_resource_start(devpriv->pci_dev, LCFG_PCIINDEX); /* Now have the kernel map this into memory */ /* ASSUME page aligned */ devpriv->las0 = ioremap_nocache(physLas0, LAS0_PCISIZE); devpriv->las1 = ioremap_nocache(physLas1, LAS1_PCISIZE); devpriv->lcfg = ioremap_nocache(physLcfg, LCFG_PCISIZE); DPRINTK ("%s: LAS0=%lx, LAS1=%lx, CFG=%lx.\n", dev->board_name, physLas0, physLas1, physLcfg); { /* The RTD driver does this */ unsigned char pci_latency; u16 revision; /*uint32_t epld_version;*/ pci_read_config_word(devpriv->pci_dev, PCI_REVISION_ID, &revision); DPRINTK("%s: PCI revision %d.\n", dev->board_name, revision); pci_read_config_byte(devpriv->pci_dev, PCI_LATENCY_TIMER, &pci_latency); if (pci_latency < 32) { printk ("%s: PCI latency changed from %d to %d\n", dev->board_name, pci_latency, 32); pci_write_config_byte(devpriv->pci_dev, PCI_LATENCY_TIMER, 32); } else { DPRINTK ("rtd520: PCI latency = %d\n", pci_latency); } /* Undocumented EPLD version (doesnt match RTD driver results) */ /*DPRINTK ("rtd520: Reading epld from %p\n", devpriv->las0+0); epld_version = readl (devpriv->las0+0); if ((epld_version & 0xF0) >> 4 == 0x0F) { DPRINTK("rtd520: pre-v8 EPLD. (%x)\n", epld_version); } else { DPRINTK("rtd520: EPLD version %x.\n", epld_version >> 4); }*/ } /* Show board configuration */ /* It is critical that the FIFO length matches the board. Otherwise, data transfers and DMA will either read 0s or overwrite memory! It is possible to probe for FIFO size. */ printk ("%s: ( fifoLen=%d )" , dev->board_name, thisboard->fifoLen); /* * Allocate the subdevice structures. alloc_subdevice() is a * convenient macro defined in comedidev.h.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -