2 * Device Driver for DataTranslation DT2801
7 Description: Data Translation DT2801 series and DT01-EZ
10 Devices: [Data Translation] DT2801 (dt2801), DT2801-A, DT2801/5716A,
11 DT2805, DT2805/5716A, DT2808, DT2818, DT2809, DT01-EZ
13 This driver can autoprobe the type of board.
15 Configuration options:
16 [0] - I/O port base address
18 [2] - A/D reference 0=differential, 1=single-ended
28 [5] - D/A 1 range (same choices)
31 #include <linux/comedidev.h>
32 #include <linux/delay.h>
33 #include <linux/ioport.h>
36 #define DT2801_TIMEOUT 1000
39 /* Hardware Configuration */
40 /* ====================== */
42 #define DT2801_MAX_DMA_SIZE (64 * 1024)
45 #define DT2801_IOSIZE 2
48 /* define's & typedef's */
49 /* ====================== */
52 #define DT_C_RESET 0x0
53 #define DT_C_CLEAR_ERR 0x1
54 #define DT_C_READ_ERRREG 0x2
55 #define DT_C_SET_CLOCK 0x3
60 #define DT_C_SET_DIGIN 0x4
61 #define DT_C_SET_DIGOUT 0x5
62 #define DT_C_READ_DIG 0x6
63 #define DT_C_WRITE_DIG 0x7
65 #define DT_C_WRITE_DAIM 0x8
66 #define DT_C_SET_DA 0x9
67 #define DT_C_WRITE_DA 0xa
69 #define DT_C_READ_ADIM 0xc
70 #define DT_C_SET_AD 0xd
71 #define DT_C_READ_AD 0xe
73 /* Command modifiers (only used with read/write), EXTTRIG can be
74 used with some other commands.
76 #define DT_MOD_DMA (1<<4)
77 #define DT_MOD_CONT (1<<5)
78 #define DT_MOD_EXTCLK (1<<6)
79 #define DT_MOD_EXTTRIG (1<<7)
81 /* Bits in status register */
82 #define DT_S_DATA_OUT_READY (1<<0)
83 #define DT_S_DATA_IN_FULL (1<<1)
84 #define DT_S_READY (1<<2)
85 #define DT_S_COMMAND (1<<3)
86 #define DT_S_COMPOSITE_ERROR (1<<7)
91 #define DT2801_STATUS 1
94 static int dt2801_attach(comedi_device *dev,comedi_devconfig *it);
95 static int dt2801_detach(comedi_device *dev);
96 static comedi_driver driver_dt2801={
97 driver_name: "dt2801",
99 attach: dt2801_attach,
100 detach: dt2801_detach,
102 COMEDI_INITCLEANUP(driver_dt2801);
105 // ignore 'defined but not used' warning
106 static const comedi_lrange range_dt2801_ai_pgh_bipolar={ 4, {
110 RANGE( -1.25, 1.25 ),
113 static const comedi_lrange range_dt2801_ai_pgl_bipolar={ 4, {
117 RANGE( -0.02, 0.02 ),
120 // ignore 'defined but not used' warning
121 static const comedi_lrange range_dt2801_ai_pgh_unipolar={ 4, {
128 static const comedi_lrange range_dt2801_ai_pgl_unipolar={ 4, {
145 /* Typeid's for the different boards of the DT2801-series
146 (taken from the test-software, that comes with the board)
148 static const boardtype_t boardtypes[] =
169 name: "dt2801/5716a",
187 name: "dt2805/5716a",
223 #define n_boardtypes ((sizeof(boardtypes))/(sizeof(boardtypes[0])))
224 #define boardtype (*(const boardtype_t *)dev->board_ptr)
228 const comedi_lrange *dac_range_types[2];
229 lsampl_t ao_readback[2];
231 #define devpriv ((dt2801_private *)dev->private)
233 static int dt2801_ai_insn_read(comedi_device *dev,comedi_subdevice *s,
234 comedi_insn *insn,lsampl_t *data);
235 static int dt2801_ao_insn_read(comedi_device *dev,comedi_subdevice *s,
236 comedi_insn *insn,lsampl_t *data);
237 static int dt2801_ao_insn_write(comedi_device *dev,comedi_subdevice *s,
238 comedi_insn *insn,lsampl_t *data);
239 static int dt2801_dio_insn_bits(comedi_device *dev,comedi_subdevice *s,
240 comedi_insn *insn,lsampl_t *data);
241 static int dt2801_dio_insn_config(comedi_device *dev,comedi_subdevice *s,
242 comedi_insn *insn,lsampl_t *data);
244 /* These are the low-level routines:
245 writecommand: write a command to the board
246 writedata: write data byte
247 readdata: read data byte
250 /* Only checks DataOutReady-flag, not the Ready-flag as it is done
251 in the examples of the manual. I don't see why this should be
253 static int dt2801_readdata(comedi_device *dev, int* data)
256 int timeout = DT2801_TIMEOUT;
259 stat = inb_p(dev->iobase+DT2801_STATUS);
260 if (stat & (DT_S_COMPOSITE_ERROR | DT_S_READY)) {
263 if(stat & DT_S_DATA_OUT_READY){
264 *data = inb_p(dev->iobase+DT2801_DATA);
273 static int dt2801_readdata2(comedi_device *dev, int *data)
278 ret=dt2801_readdata(dev, &lb);
280 ret=dt2801_readdata(dev, &hb);
287 static int dt2801_writedata(comedi_device *dev, unsigned int data)
290 int timeout = DT2801_TIMEOUT;
293 stat = inb_p(dev->iobase+DT2801_STATUS);
295 if (stat & DT_S_COMPOSITE_ERROR) {
298 if (!(stat & DT_S_DATA_IN_FULL)) {
299 outb_p(data & 0xff, dev->iobase+DT2801_DATA);
303 if(stat & DT_S_READY){
304 printk("dt2801: ready flag set (bad!) in dt2801_writedata()\n");
313 static int dt2801_writedata2(comedi_device *dev, unsigned int data)
317 ret=dt2801_writedata(dev, data & 0xff);
319 ret=dt2801_writedata(dev, (data >> 8) );
325 static int dt2801_wait_for_ready(comedi_device *dev)
327 int timeout = DT2801_TIMEOUT;
330 stat = inb_p(dev->iobase+DT2801_STATUS);
331 if(stat & DT_S_READY){
335 stat = inb_p(dev->iobase+DT2801_STATUS);
337 if (stat & DT_S_COMPOSITE_ERROR) {
340 if(stat & DT_S_READY){
348 static int dt2801_writecmd(comedi_device * dev, int command)
352 dt2801_wait_for_ready(dev);
354 stat = inb_p(dev->iobase+DT2801_STATUS);
355 if (stat & DT_S_COMPOSITE_ERROR) {
356 printk("dt2801: composite-error in dt2801_writecmd(), ignoring\n");
358 if (!(stat & DT_S_READY)) {
359 printk("dt2801: !ready in dt2801_writecmd(), ignoring\n");
361 outb_p(command, dev->iobase+DT2801_CMD);
367 static int dt2801_reset(comedi_device *dev)
373 DPRINTK("dt2801: resetting board...\n");
374 DPRINTK("fingerprint: 0x%02x 0x%02x\n",inb_p(dev->iobase),inb_p(dev->iobase+1));
376 /* pull random data from data port */
377 inb_p(dev->iobase+DT2801_DATA);
378 inb_p(dev->iobase+DT2801_DATA);
379 inb_p(dev->iobase+DT2801_DATA);
380 inb_p(dev->iobase+DT2801_DATA);
382 DPRINTK("dt2801: stop\n");
383 //dt2801_writecmd(dev,DT_C_STOP);
384 outb_p(DT_C_STOP, dev->iobase+DT2801_CMD);
386 //dt2801_wait_for_ready(dev);
390 stat = inb_p(dev->iobase+DT2801_STATUS);
391 if(stat & DT_S_READY)break;
394 printk("dt2801: timeout 1 status=0x%02x\n",stat);
397 //printk("dt2801: reading dummy\n");
398 //dt2801_readdata(dev,&board_code);
400 DPRINTK("dt2801: reset\n");
401 outb_p(DT_C_RESET, dev->iobase+DT2801_CMD);
402 //dt2801_writecmd(dev,DT_C_RESET);
407 stat = inb_p(dev->iobase+DT2801_STATUS);
408 if(stat & DT_S_READY)break;
411 printk("dt2801: timeout 2 status=0x%02x\n",stat);
414 DPRINTK("dt2801: reading code\n");
415 dt2801_readdata(dev,&board_code);
417 DPRINTK("dt2801: ok. code=0x%02x\n",board_code);
422 static int probe_number_of_ai_chans(comedi_device *dev)
428 for(n_chans=0;n_chans<16;n_chans++){
429 stat = dt2801_writecmd(dev, DT_C_READ_ADIM);
430 dt2801_writedata(dev, 0);
431 dt2801_writedata(dev, n_chans);
432 stat = dt2801_readdata2(dev, &data);
444 static const comedi_lrange *dac_range_table[]={
452 static const comedi_lrange *dac_range_lkup(int opt)
454 if(opt<0 || opt>5)return &range_unknown;
455 return dac_range_table[opt];
458 static const comedi_lrange *ai_range_lkup(int type,int opt)
463 &range_dt2801_ai_pgl_unipolar:
464 &range_dt2801_ai_pgl_bipolar;
470 return &range_unipolar5;
472 return &range_unknown;
481 [2] - a/d 0=differential, 1=single-ended
482 [3] - a/d range 0=[-10,10], 1=[0,10]
483 [4] - dac0 range 0=[-10,10], 1=[-5,5], 2=[-2.5,2.5] 3=[0,10], 4=[0,5]
484 [5] - dac1 range 0=[-10,10], 1=[-5,5], 2=[-2.5,2.5] 3=[0,10], 4=[0,5]
486 static int dt2801_attach(comedi_device *dev,comedi_devconfig *it)
489 unsigned long iobase;
494 iobase=it->options[0];
495 if(!request_region(iobase, DT2801_IOSIZE, "dt2801")){
496 comedi_error(dev,"I/O port conflict");
501 /* do some checking */
503 board_code=dt2801_reset(dev);
505 /* heh. if it didn't work, try it again. */
506 if(!board_code)board_code=dt2801_reset(dev);
508 for(type=0;type<n_boardtypes;type++){
509 if(boardtypes[type].boardcode==board_code)
512 printk("dt2801: unrecognized board code=0x%02x, contact author\n",board_code);
516 dev->board_ptr = boardtypes+type;
517 printk("dt2801: %s at port 0x%lx",boardtype.name,iobase);
519 n_ai_chans=probe_number_of_ai_chans(dev);
520 printk(" (ai channels = %d)",n_ai_chans);
522 if((ret=alloc_subdevices(dev, 4))<0)
525 if((ret=alloc_private(dev,sizeof(dt2801_private)))<0)
528 dev->board_name = boardtype.name;
532 s->type=COMEDI_SUBD_AI;
533 s->subdev_flags=SDF_READABLE|SDF_GROUND;
535 s->n_chan=n_ai_chans;
537 if(it->options[2])s->n_chan=boardtype.ad_chan;
538 else s->n_chan=boardtype.ad_chan/2;
540 s->maxdata=(1<<boardtype.adbits)-1;
541 s->range_table=ai_range_lkup(boardtype.adrangetype,it->options[3]);
542 s->insn_read=dt2801_ai_insn_read;
546 s->type=COMEDI_SUBD_AO;
547 s->subdev_flags=SDF_WRITABLE;
549 s->maxdata=(1<<boardtype.dabits)-1;
550 s->range_table_list=devpriv->dac_range_types;
551 devpriv->dac_range_types[0]=dac_range_lkup(it->options[4]);
552 devpriv->dac_range_types[1]=dac_range_lkup(it->options[5]);
553 s->insn_read=dt2801_ao_insn_read;
554 s->insn_write=dt2801_ao_insn_write;
557 /* 1st digital subdevice */
558 s->type=COMEDI_SUBD_DIO;
559 s->subdev_flags=SDF_READABLE|SDF_WRITABLE;
562 s->range_table=&range_digital;
563 s->insn_bits=dt2801_dio_insn_bits;
564 s->insn_config=dt2801_dio_insn_config;
567 /* 2nd digital subdevice */
568 s->type=COMEDI_SUBD_DIO;
569 s->subdev_flags=SDF_READABLE|SDF_WRITABLE;
572 s->range_table=&range_digital;
573 s->insn_bits=dt2801_dio_insn_bits;
574 s->insn_config=dt2801_dio_insn_config;
583 static int dt2801_detach(comedi_device *dev)
586 release_region(dev->iobase,DT2801_IOSIZE);
591 static int dt2801_error(comedi_device *dev,int stat)
595 printk("dt2801: timeout\n");
597 printk("dt2801: error %d\n",stat);
601 printk("dt2801: error status 0x%02x, resetting...\n",stat);
609 static int dt2801_ai_insn_read(comedi_device *dev,comedi_subdevice *s,
610 comedi_insn *insn,lsampl_t *data)
616 for(i=0;i<insn->n;i++){
617 stat = dt2801_writecmd(dev, DT_C_READ_ADIM);
618 dt2801_writedata(dev, CR_RANGE(insn->chanspec));
619 dt2801_writedata(dev, CR_CHAN(insn->chanspec));
620 stat = dt2801_readdata2(dev, &d);
622 if (stat != 0) return dt2801_error(dev,stat);
630 static int dt2801_ao_insn_read(comedi_device *dev,comedi_subdevice *s,
631 comedi_insn *insn,lsampl_t *data)
633 data[0]=devpriv->ao_readback[CR_CHAN(insn->chanspec)];
638 static int dt2801_ao_insn_write(comedi_device *dev,comedi_subdevice *s,
639 comedi_insn *insn,lsampl_t *data)
641 dt2801_writecmd(dev, DT_C_WRITE_DAIM);
642 dt2801_writedata(dev, CR_CHAN(insn->chanspec));
643 dt2801_writedata2(dev, data[0]);
645 devpriv->ao_readback[CR_CHAN(insn->chanspec)]=data[0];
650 static int dt2801_dio_insn_bits(comedi_device *dev,comedi_subdevice *s,
651 comedi_insn *insn,lsampl_t *data)
655 if(s==dev->subdevices+4)which=1;
657 if(insn->n!=2)return -EINVAL;
659 s->state &= ~data[0];
660 s->state |= (data[0]&data[1]);
661 dt2801_writecmd(dev, DT_C_WRITE_DIG);
662 dt2801_writedata(dev, which);
663 dt2801_writedata(dev, s->state);
665 dt2801_writecmd(dev, DT_C_READ_DIG);
666 dt2801_writedata(dev, which);
667 dt2801_readdata(dev, data+1);
672 static int dt2801_dio_insn_config(comedi_device *dev,comedi_subdevice *s,
673 comedi_insn *insn,lsampl_t *data)
677 if(s==dev->subdevices+4)which=1;
682 dt2801_writecmd(dev, DT_C_SET_DIGOUT);
685 dt2801_writecmd(dev, DT_C_SET_DIGIN);
687 dt2801_writedata(dev, which);