📄 das6402.c
字号:
/* Some comments on the code.. - it shouldn't be necessary to use outb_p(). - ignoreirq creates a race condition. It needs to be fixed. *//* An experimental driver for Computerboards' DAS6402 I/O card Copyright (C) 1999 Oystein Svendsen <svendsen@pvv.org> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *//*Driver: das6402.oDescription: Keithley Metrabyte DAS6402 (& compatibles)Author: Oystein Svendsen <svendsen@pvv.org>Status: bitrottenDevices: [Keithley Metrabyte] DAS6402 (das6402)This driver has suffered bitrot.*/#include <linux/comedidev.h>#include <linux/ioport.h>#define DAS6402_SIZE 16#define N_WORDS 3000*64#define STOP 0#define START 1#define SCANL 0x3f00#define BYTE unsigned char#define WORD unsigned short/*----- register 8 ----*/#define CLRINT 0x01#define CLRXTR 0x02#define CLRXIN 0x04#define EXTEND 0x10#define ARMED 0x20 /* enable conting of post sample conv */#define POSTMODE 0x40#define MHZ 0x80 /* 10 MHz clock *//*---------------------*//*----- register 9 ----*/#define IRQ (0x04 << 4) /* these two are */#define IRQV 10 /* dependent on each other */#define CONVSRC 0x03 /* trig src is Intarnal pacer */#define BURSTEN 0x04 /* enable burst */#define XINTE 0x08 /* use external int. trig */#define INTE 0x80 /* enable analog interrupts *//*---------------------*//*----- register 10 ---*/#define TGEN 0x01 /* Use pin DI1 for externl trigging? */#define TGSEL 0x02 /* Use edge triggering */#define TGPOL 0x04 /* active edge is falling */#define PRETRIG 0x08 /* pretrig *//*---------------------*//*----- register 11 ---*/#define EOB 0x0c#define FIFOHFULL 0x08#define GAIN 0x01#define FIFONEPTY 0x04#define MODE 0x10#define SEM 0x20#define BIP 0x40/*---------------------*/#define M0 0x00#define M2 0x04#define C0 0x00#define C1 0x40#define C2 0x80#define RWLH 0x30 static int das6402_attach(comedi_device *dev,comedi_devconfig *it);static int das6402_detach(comedi_device *dev);static comedi_driver driver_das6402={ driver_name: "das6402", module: THIS_MODULE, attach: das6402_attach, detach: das6402_detach,};COMEDI_INITCLEANUP(driver_das6402);typedef struct{ int ai_bytes_to_read; int das6402_ignoreirq;}das6402_private;#define devpriv ((das6402_private *)dev->private)static void das6402_ai_fifo_dregs(comedi_device *dev,comedi_subdevice *s);static void das6402_setcounter(comedi_device *dev){ BYTE p; unsigned short ctrlwrd; /* set up counter0 first, mode 0 */ p=M0|C0|RWLH; outb_p(p,dev->iobase+15); ctrlwrd=2000; p=(BYTE) (0xff & ctrlwrd); outb_p(p,dev->iobase+12); p=(BYTE) (0xff & (ctrlwrd >> 8)); outb_p(p,dev->iobase+12); /* set up counter1, mode 2 */ p=M2|C1|RWLH; outb_p(p,dev->iobase+15); ctrlwrd=10; p=(BYTE) (0xff & ctrlwrd); outb_p(p,dev->iobase+13); p=(BYTE) (0xff & (ctrlwrd >> 8)); outb_p(p,dev->iobase+13); /* set up counter1, mode 2 */ p=M2|C2|RWLH; outb_p(p,dev->iobase+15); ctrlwrd=1000; p=(BYTE) (0xff & ctrlwrd); outb_p(p,dev->iobase+14); p=(BYTE) (0xff & (ctrlwrd >> 8)); outb_p(p,dev->iobase+14);}static void intr_handler(int irq,void *d,struct pt_regs *regs){ comedi_device *dev=d; comedi_subdevice *s=dev->subdevices; if (devpriv->das6402_ignoreirq){ printk("das6402: BUG: spurious interrupt\n"); return; }#ifdef DEBUG printk("das6402: interrupt! das6402_irqcount=%i\n",devpriv->das6402_irqcount); printk("das6402: iobase+2=%i\n",inw_p(dev->iobase+2));#endif das6402_ai_fifo_dregs(dev,s); if(s->async->buf_write_count >= devpriv->ai_bytes_to_read){ outw_p(SCANL,dev->iobase+2); /* clears the fifo */ outb(0x07,dev->iobase+8); /* clears all flip-flops */#ifdef DEBUG printk("das6402: Got %i samples\n\n",devpriv->das6402_wordsread-diff);#endif s->async->events |= COMEDI_CB_EOA; comedi_event(dev,s,s->async->events); } outb(0x01,dev->iobase+8); /* clear only the interrupt flip-flop */ comedi_event(dev,s,s->async->events);}#if 0static void das6402_ai_fifo_read(comedi_device *dev,sampl_t *data,int n){ int i; for(i=0;i<n;i++)data[i]=inw(dev->iobase);}#endifstatic void das6402_ai_fifo_dregs(comedi_device *dev,comedi_subdevice *s){ while(1){ if(!(inb(dev->iobase+8)&0x01)) return; comedi_buf_put( s->async, inw(dev->iobase) ); }}static int das6402_ai_cancel(comedi_device *dev,comedi_subdevice *s){ /* * This function should reset the board from whatever condition it * is in (i.e., acquiring data), to a non-active state. */ devpriv->das6402_ignoreirq=1;#ifdef DEBUG printk("das6402: Stopping acquisition\n");#endif devpriv->das6402_ignoreirq=1; outb_p(0x02,dev->iobase+10); /* disable external trigging */ outw_p(SCANL,dev->iobase+2); /* resets the card fifo */ outb_p(0,dev->iobase+9); /* disables interrupts */ outw_p(SCANL,dev->iobase+2); return 0;}#ifdef unusedstatic int das6402_ai_mode2(comedi_device *dev,comedi_subdevice *s,comedi_trig *it){ devpriv->das6402_ignoreirq=1;#ifdef DEBUG printk("das6402: Starting acquisition\n");#endif outb_p(0x03,dev->iobase+10); /* enable external trigging */ outw_p(SCANL,dev->iobase+2); /* resets the card fifo */ outb_p(IRQ|CONVSRC|BURSTEN|INTE,dev->iobase+9); devpriv->ai_bytes_to_read=it->n*sizeof(sampl_t); /* um... ignoreirq is a nasty race condition */ devpriv->das6402_ignoreirq=0; outw_p(SCANL,dev->iobase+2); return 0;}#endifstatic int board_init(comedi_device *dev){ BYTE b; devpriv->das6402_ignoreirq=1; outb(0x07,dev->iobase+8); /* register 11 */ outb_p(MODE,dev->iobase+11); b=BIP|SEM|MODE|GAIN|FIFOHFULL; outb_p(b, dev->iobase+11); /* register 8 */ outb_p(EXTEND,dev->iobase+8); b=EXTEND|MHZ; outb_p(b,dev->iobase+8); b= MHZ|CLRINT|CLRXTR|CLRXIN; outb_p(b,dev->iobase+8); /* register 9 */ b=IRQ|CONVSRC|BURSTEN|INTE; outb_p(b,dev->iobase+9); /* register 10 */ b=TGSEL|TGEN; outb_p(b,dev->iobase+10); b=0x07; outb_p(b,dev->iobase+8); das6402_setcounter(dev); outw_p(SCANL,dev->iobase+2); /* reset card fifo */ devpriv->das6402_ignoreirq=0; return 0;}static int das6402_detach(comedi_device *dev){ if(dev->irq)comedi_free_irq(dev->irq,dev); if(dev->iobase)release_region(dev->iobase,DAS6402_SIZE); return 0;}static int das6402_attach(comedi_device *dev,comedi_devconfig *it){ int irq; int iobase; int ret; comedi_subdevice *s; dev->board_name="das6402"; iobase=it->options[0]; if(iobase==0)iobase=0x300; printk("comedi%d: das6402: 0x%04x",dev->minor,iobase); if(check_region(iobase,DAS6402_SIZE)<0){ printk(" I/O port conflict\n"); return -EIO; } request_region(iobase,DAS6402_SIZE,"das6402"); dev->iobase=iobase; /* should do a probe here */ irq=it->options[0]; printk(" ( irq = %d )", irq); ret=comedi_request_irq(irq, intr_handler, 0, "das6402", dev); if(ret<0){ printk("irq conflict\n"); return ret; } dev->irq=irq; if((ret=alloc_private(dev,sizeof(das6402_private)))<0) return ret; if((ret=alloc_subdevices(dev, 1))<0) return ret; /* ai subdevice */ s=dev->subdevices+0; s->type=COMEDI_SUBD_AI; s->subdev_flags=SDF_READABLE|SDF_GROUND; s->n_chan=8; //s->trig[2]=das6402_ai_mode2; s->cancel=das6402_ai_cancel; s->maxdata=(1<<12)-1; s->len_chanlist=16; /* ? */ s->range_table = &range_unknown; board_init(dev); return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -