new drivers
authorDavid Schleef <ds@schleef.org>
Thu, 13 Jul 2000 00:35:48 +0000 (00:35 +0000)
committerDavid Schleef <ds@schleef.org>
Thu, 13 Jul 2000 00:35:48 +0000 (00:35 +0000)
comedi/drivers/das08-new.c [new file with mode: 0644]
comedi/drivers/das16-new.c [new file with mode: 0644]

diff --git a/comedi/drivers/das08-new.c b/comedi/drivers/das08-new.c
new file mode 100644 (file)
index 0000000..9a3fb7f
--- /dev/null
@@ -0,0 +1,624 @@
+/*
+    comedi/drivers/das.c
+    DAS08 driver
+
+    COMEDI - Linux Control and Measurement Device Interface
+    Copyright (C) 2000 David A. Schleef <ds@stm.lbl.gov>
+
+    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.
+
+*/
+
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <comedi_module.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <asm/io.h>
+#include <linux/malloc.h>
+#include <linux/delay.h>
+#include <8255.h>
+
+
+#define DAS08_SIZE 16
+
+/*
+    cio-das08.pdf
+
+  "das08"
+
+  0    a/d bits 0-3            start 8 bit
+  1    a/d bits 4-11           start 12 bit
+  2    eoc, ip1-3, irq, mux    op1-4, inte, mux
+  3    unused                  unused
+  4567 8254
+  89ab 8255
+
+  requires hard-wiring for async ai
+
+*/
+
+#define DAS08_LSB              0
+#define DAS08_MSB              1
+#define DAS08_TRIG_12BIT       1
+#define DAS08_STATUS           2
+#define          DAS08_EOC                     (1<<7)
+#define   DAS08_IRQ                    (1<<3)
+#define   DAS08_IP(x)                  (((x)>>4)&0x7)
+#define DAS08_CONTROL          2
+#define          DAS08_MUX(x)                  ((x)<<0)
+#define   DAS08_INTE                   (1<<3)
+#define   DAS08_OP(x)                  ((x)<<4)
+
+/*
+    cio-das08jr.pdf
+
+  "das08/jr-ao"
+
+  0    a/d bits 0-3            unused
+  1    a/d bits 4-11           start 12 bit
+  2    eoc, mux                mux
+  3    di                      do
+  4    unused                  ao0_lsb
+  5    unused                  ao0_msb
+  6    unused                  ao1_lsb
+  7    unused                  ao1_msb
+
+*/
+
+#define DAS08JR_DIO            3
+#define DAS08JR_AO_LSB(x)      ((x)?6:4)
+#define DAS08JR_AO_MSB(x)      ((x)?7:5)
+
+/*
+    cio-das08_aox.pdf
+
+  "das08-aoh"
+  "das08-aol"
+  "das08-aom"
+
+  0    a/d bits 0-3            start 8 bit
+  1    a/d bits 4-11           start 12 bit
+  2    eoc, ip1-3, irq, mux    op1-4, inte, mux
+  3    mux, gain status        gain control
+  4567 8254
+  8    unused                  ao0_lsb
+  9    unused                  ao0_msb
+  a    unused                  ao1_lsb
+  b    unused                  ao1_msb
+  89ab 
+  cdef 8255
+*/
+
+#define DAS08AO_GAIN_CONTROL   3
+#define DAS08AO_GAIN_STATUS    3
+
+#define DAS08AO_AO_LSB(x)      ((x)?0xa:8)
+#define DAS08AO_AO_MSB(x)      ((x)?0xb:9)
+#define DAS08AO_AO_UPDATE      8
+
+/* gainlist same as _pgx_ below */
+
+/*
+    cio-das08pgx.pdf
+
+    "das08pgx"
+
+  0    a/d bits 0-3            start 8 bit
+  1    a/d bits 4-11           start 12 bit
+  2    eoc, ip1-3, irq, mux    op1-4, inte, mux
+  3    mux, gain status        gain control
+  4567 8254
+
+*/
+
+static int das08_ai_rinsn(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn);
+static int das08_di_rbits(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn);
+static int das08_do_wbits(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn);
+static int das08jr_di_rbits(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn);
+static int das08jr_do_wbits(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn);
+static int das08jr_ao_winsn(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn);
+static int das08ao_ao_winsn(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn);
+
+static comedi_lrange range_das08_pgl = { 9, {
+       BIP_RANGE(10),
+       BIP_RANGE(5),
+       BIP_RANGE(2.5),
+       BIP_RANGE(1.25),
+       BIP_RANGE(0.625),
+       UNI_RANGE(10),
+       UNI_RANGE(5),
+       UNI_RANGE(2.5),
+       UNI_RANGE(1.25)
+}};
+static comedi_lrange range_das08_pgh = { 12, {
+       BIP_RANGE(10),
+       BIP_RANGE(5),
+       BIP_RANGE(1),
+       BIP_RANGE(0.5),
+       BIP_RANGE(0.1),
+       BIP_RANGE(0.05),
+       BIP_RANGE(0.01),
+       BIP_RANGE(0.005),
+       UNI_RANGE(10),
+       UNI_RANGE(1),
+       UNI_RANGE(0.1),
+       UNI_RANGE(0.01),
+}};
+static comedi_lrange range_das08_pgm = { 9, {
+       BIP_RANGE(10),
+       BIP_RANGE(5),
+       BIP_RANGE(0.5),
+       BIP_RANGE(0.05),
+       BIP_RANGE(0.01),
+       UNI_RANGE(10),
+       UNI_RANGE(1),
+       UNI_RANGE(0.1),
+       UNI_RANGE(0.01)
+}};
+
+enum { das08_pg_none, das08_pgh, das08_pgl, das08_pgm };
+
+static comedi_lrange *das08_ai_lranges[]={
+       &range_bipolar10, /* XXX guess */
+       &range_das08_pgh,
+       &range_das08_pgl,
+       &range_das08_pgm,
+};
+
+static int das08_pgh_gainlist[] = { 8, 0, 10, 2, 12, 4, 14, 6, 1, 3, 5, 7 };
+static int das08_pgl_gainlist[] = { 8, 0, 2, 4, 6, 1, 3, 5, 7 };
+static int das08_pgm_gainlist[] = { 8, 0, 10, 12, 14, 9, 11, 13, 15 };
+
+static int *das08_gainlists[] = {
+       NULL,
+       das08_pgh_gainlist,
+       das08_pgl_gainlist,
+       das08_pgm_gainlist,
+};
+
+struct das08_board_struct{
+       char            *name;
+       void            *ai;
+       unsigned int    ai_nbits;
+       unsigned int    ai_pg;
+       void            *ao;
+       unsigned int    ao_nbits;
+       void            *di;
+       void            *do_;
+       unsigned int    i8255_offset;
+       unsigned int    i8254_offset;
+};
+static struct das08_board_struct das08_boards[]={
+       {
+       name:           "das08",                // cio-das08.pdf
+       ai:             das08_ai_rinsn,
+       ai_nbits:       12,
+       ai_pg:          das08_pg_none,
+       ao:             NULL,
+       ao_nbits:       12,
+       di:             das08_di_rbits,
+       do_:            das08_do_wbits,
+       i8255_offset:   8,
+       i8254_offset:   4,
+       },
+       {
+       name:           "das08-pgm",            // cio-das08pgx.pdf
+       ai:             das08_ai_rinsn,
+       ai_nbits:       12,
+       ai_pg:          das08_pgm,
+       ao:             NULL,
+       di:             das08_di_rbits,
+       do_:            das08_do_wbits,
+       i8255_offset:   0,
+       i8254_offset:   0x04,
+       },
+       {
+       name:           "das08-pgh",            // cio-das08pgx.pdf
+       ai:             das08_ai_rinsn,
+       ai_nbits:       12,
+       ai_pg:          das08_pgh,
+       ao:             NULL,
+       di:             das08_di_rbits,
+       do_:            das08_do_wbits,
+       i8255_offset:   0,
+       i8254_offset:   0x04,
+       },
+       {
+       name:           "das08-pgl",            // cio-das08pgx.pdf
+       ai:             das08_ai_rinsn,
+       ai_nbits:       12,
+       ai_pg:          das08_pgl,
+       ao:             NULL,
+       di:             das08_di_rbits,
+       do_:            das08_do_wbits,
+       i8255_offset:   0,
+       i8254_offset:   0x04,
+       },
+       {
+       name:           "das08-aoh",            // cio-das08_aox.pdf
+       ai:             das08_ai_rinsn,
+       ai_nbits:       12,
+       ai_pg:          das08_pgh,
+       ao:             das08ao_ao_winsn,       // 8
+       ao_nbits:       12,
+       di:             das08_di_rbits,
+       do_:            das08_do_wbits,
+       i8255_offset:   0x0c,
+       i8254_offset:   0x04,
+       },
+       {
+       name:           "das08-aol",            // cio-das08_aox.pdf
+       ai:             das08_ai_rinsn,
+       ai_nbits:       12,
+       ai_pg:          das08_pgl,
+       ao:             das08ao_ao_winsn,       // 8
+       ao_nbits:       12,
+       di:             das08_di_rbits,
+       do_:            das08_do_wbits,
+       i8255_offset:   0x0c,
+       i8254_offset:   0x04,
+       },
+       {
+       name:           "das08-aom",            // cio-das08_aox.pdf
+       ai:             das08_ai_rinsn,
+       ai_nbits:       12,
+       ai_pg:          das08_pgm,
+       ao:             das08ao_ao_winsn,       // 8
+       ao_nbits:       12,
+       di:             das08_di_rbits,
+       do_:            das08_do_wbits,
+       i8255_offset:   0x0c,
+       i8254_offset:   0x04,
+       },
+       {
+       name:           "das08/jr-ao",          // cio-das08-jr-ao.pdf
+       ai:             das08_ai_rinsn,
+       ai_nbits:       12,
+       ai_pg:          das08_pg_none,
+       ao:             das08jr_ao_winsn,
+       ao_nbits:       12,
+       di:             das08jr_di_rbits,
+       do_:            das08jr_do_wbits,
+       i8255_offset:   0,
+       i8254_offset:   0,
+       },
+       {
+       name:           "das08jr-16-ao",        // cio-das08jr-16-ao.pdf
+       ai:             das08_ai_rinsn,
+       ai_nbits:       16,
+       ai_pg:          das08_pg_none,
+       ao:             das08jr_ao_winsn,
+       ao_nbits:       16,
+       di:             das08jr_di_rbits,
+       do_:            das08jr_do_wbits,
+       i8255_offset:   0,
+       i8254_offset:   0x04,
+       },
+#if 0
+       {
+       name:           "das08/f",
+       },
+       {
+       name:           "das08jr",
+       },
+       {
+       name:           "das08jr/16",
+       },
+       {
+       name:           "das48-pga",            // cio-das48-pga.pdf
+       },
+       {
+       name:           "das08-pga-g2",         // a KM board
+       },
+#endif
+};
+static int n_boardtypes = sizeof(das08_boards)/sizeof(das08_boards[0]);
+
+
+struct das08_private_struct{
+       unsigned int    do_bits;
+       unsigned int    *pg_gainlist;
+};
+
+#define devpriv ((struct das08_private_struct *)dev->private)
+#define thisboard ((struct das08_board_struct *)dev->board)
+
+#define TIMEOUT 1000
+
+static int das08_ai_rinsn(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn)
+{
+       int i,n;
+       int chan;
+       int range;
+       int lsb,msb;
+
+       chan = CR_CHAN(insn->chanspec);
+       range = CR_RANGE(insn->chanspec);
+
+       /* clear crap */
+       inb(dev->iobase+DAS08_LSB);
+       inb(dev->iobase+DAS08_MSB);
+
+       /* set multiplexer */
+       outb_p(DAS08_MUX(chan) | devpriv->do_bits,dev->iobase+DAS08_CONTROL);
+       
+       if(thisboard->ai_pg!=das08_pg_none){
+               /* set gain/range */
+               range = CR_RANGE(insn->chanspec);
+               outb_p(devpriv->pg_gainlist[range],dev->iobase+DAS08AO_GAIN_CONTROL);
+       }
+
+       /* How long should we wait for MUX to settle? */
+       //udelay(5);
+
+       for(n=0;n<insn->n;n++){
+               /* trigger conversion */
+               outb_p(0,dev->iobase+DAS08_TRIG_12BIT);
+
+               for(i=0;i<TIMEOUT;i++){
+                       if(!(inb(DAS08_STATUS)&DAS08_EOC))
+                               break;
+               }
+               if(i==TIMEOUT){
+                       rt_printk("das08: timeout\n");
+                       return -ETIME;
+               }
+               msb = inb(dev->iobase + DAS08_MSB);
+               lsb = inb(dev->iobase + DAS08_LSB);
+               if(thisboard->ai_nbits==12){
+                       insn->data[n] = (lsb>>4) | (msb << 4);
+               }else{
+                       insn->data[n] = lsb | (msb << 8);
+               }
+       }
+
+       return n;
+}
+
+static int das08_di_rbits(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn)
+{
+       insn->data[0]=DAS08_IP(inb(dev->iobase+DAS08_STATUS));
+
+       return 1;
+}
+
+static int das08_do_wbits(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn)
+{
+       /* XXX race with ai */
+
+       devpriv->do_bits = DAS08_OP(insn->data[0]);
+
+       outb(devpriv->do_bits,dev->iobase+DAS08_CONTROL);
+
+       return 1;
+}
+
+static int das08jr_di_rbits(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn)
+{
+       insn->data[0]=inb(dev->iobase+DAS08JR_DIO);
+
+       return 1;
+}
+
+static int das08jr_do_wbits(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn)
+{
+       outb(insn->data[0],dev->iobase+DAS08JR_DIO);
+
+       return 1;
+}
+
+static int das08jr_ao_winsn(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn)
+{
+       int n;
+       int lsb,msb;
+       int chan;
+
+       lsb=insn->data[0]&0xff;
+       msb=(insn->data[0]>>8)&0xf;
+
+       chan=CR_CHAN(insn->chanspec);
+
+       for(n=0;n<insn->n;n++){
+#if 0
+               outb(lsb,dev->iobase+devpriv->ao_offset_lsb[chan]);
+               outb(msb,dev->iobase+devpriv->ao_offset_msb[chan]);
+#else
+               outb(lsb,dev->iobase+DAS08JR_AO_LSB(chan));
+               outb(msb,dev->iobase+DAS08JR_AO_MSB(chan));
+#endif
+
+               /* load DACs */
+               inb(dev->iobase+DAS08JR_DIO);
+
+               /* XXX */
+               break;
+       }
+
+       return n;
+}
+
+/*
+ *
+ * The -aox boards have the DACs at a different offset and use
+ * a different method to force an update.
+ *
+ */
+static int das08ao_ao_winsn(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn)
+{
+       int n;
+       int lsb,msb;
+       int chan;
+
+       lsb=insn->data[0]&0xff;
+       msb=(insn->data[0]>>8)&0xf;
+
+       chan=CR_CHAN(insn->chanspec);
+
+       for(n=0;n<insn->n;n++){
+#if 0
+               outb(lsb,dev->iobase+devpriv->ao_offset_lsb[chan]);
+               outb(msb,dev->iobase+devpriv->ao_offset_msb[chan]);
+#else
+               outb(lsb,dev->iobase+DAS08AO_AO_LSB(chan));
+               outb(msb,dev->iobase+DAS08AO_AO_MSB(chan));
+#endif
+
+               /* load DACs */
+               inb(dev->iobase+DAS08AO_AO_UPDATE);
+
+               /* XXX */
+               break;
+       }
+
+       return n;
+}
+
+static int das08_attach(comedi_device *dev,comedi_devconfig *it);
+static int das08_detach(comedi_device *dev);
+static int das08_recognize(char *name);
+
+comedi_driver driver_das08={
+       driver_name:    "das08",
+       module:         THIS_MODULE,
+       attach:         das08_attach,
+       detach:         das08_detach,
+       recognize:      das08_recognize,
+};
+
+static int das08_attach(comedi_device *dev,comedi_devconfig *it)
+{
+       comedi_subdevice *s;
+       int ret;
+
+       dev->iobase=it->options[0];
+       printk("comedi%d: das08: )x%04x",dev->minor,dev->iobase);
+       if(check_region(dev->iobase,DAS08_SIZE)<0){
+               printk(" I/O port conflict\n");
+               return -EIO;
+       }
+
+       dev->board_name="das08";
+       dev->board_ptr=das08_boards+dev->board;
+       dev->iosize=DAS08_SIZE;
+
+       dev->n_subdevices=5;
+       if((ret=alloc_subdevices(dev))<0)
+               return ret;
+       if((ret=alloc_private(dev,sizeof(struct das08_private_struct)))<0)
+               return ret;
+
+       request_region(dev->iobase,DAS08_SIZE,"das08");
+
+       s=dev->subdevices+0;
+       /* ai */
+       if(thisboard->ai){
+               s->type=COMEDI_SUBD_AI;
+               s->subdev_flags = SDF_READABLE;
+               s->n_chan = 8;
+               s->maxdata = (1<<thisboard->ai_nbits)-1;
+               s->range_table = das08_ai_lranges[thisboard->ai_pg];
+               s->insn_read = thisboard->ai;
+               devpriv->pg_gainlist = das08_gainlists[thisboard->ai_pg];
+       }else{
+               s->type=COMEDI_SUBD_UNUSED;
+       }
+
+       s=dev->subdevices+1;
+       /* ao */
+       if(thisboard->ao){
+               s->type=COMEDI_SUBD_AO;
+               s->subdev_flags = SDF_WRITEABLE;
+               s->n_chan = 2;
+               s->maxdata = (1<<thisboard->ao_nbits)-1;
+               s->range_table = &range_unknown; /* XXX */
+               s->insn_write = thisboard->ao;
+       }else{
+               s->type=COMEDI_SUBD_UNUSED;
+       }
+
+       s=dev->subdevices+2;
+       /* di */
+       if(thisboard->di){
+               s->type=COMEDI_SUBD_DI;
+               s->subdev_flags = SDF_READABLE;
+               s->n_chan = (thisboard->di==das08_di_rbits)?3:8;
+               s->maxdata = 1;
+               s->range_table = &range_digital;
+               s->insn_read = thisboard->di; /* XXX */
+       }else{
+               s->type=COMEDI_SUBD_UNUSED;
+       }
+
+       s=dev->subdevices+3;
+       /* do */
+       if(thisboard->do_){
+               s->type=COMEDI_SUBD_DO;
+               s->subdev_flags = SDF_WRITEABLE;
+               s->n_chan = (thisboard->do_==das08_do_wbits)?4:8;
+               s->maxdata = 1;
+               s->range_table = &range_digital;
+               s->insn_write = thisboard->do_; /* XXX */
+       }else{
+               s->type=COMEDI_SUBD_UNUSED;
+       }
+
+       s=dev->subdevices+4;
+       /* 8255 */
+       if(thisboard->i8255_offset!=0){
+               subdev_8255_init(dev,s,NULL,(void *)(dev->iobase+
+                       thisboard->i8255_offset));
+       }else{
+               s->type=COMEDI_SUBD_UNUSED;
+       }
+
+       return 0;
+}
+
+static int das08_detach(comedi_device *dev)
+{
+       printk(KERN_INFO "comedi%d: das08: remove\n",dev->minor);
+
+       release_region(dev->iobase,DAS08_SIZE);
+
+       return 0;
+}
+
+static int das08_recognize(char *name)
+{
+       int i;
+
+       for(i=0;i<n_boardtypes;i++){
+               if(!strcmp(das08_boards[i].name,name))return i;
+       }
+
+       return -1;
+}
+
+#ifdef MODULE
+int init_module(void)
+{
+       comedi_driver_register(&driver_das08);
+
+       return 0;
+}
+
+void cleanup_module(void)
+{
+       comedi_driver_unregister(&driver_das08);
+}
+#endif
+
diff --git a/comedi/drivers/das16-new.c b/comedi/drivers/das16-new.c
new file mode 100644 (file)
index 0000000..bc5f45c
--- /dev/null
@@ -0,0 +1,490 @@
+/*
+    comedi/drivers/das16.c
+    DAS16 driver
+
+    COMEDI - Linux Control and Measurement Device Interface
+    Copyright (C) 2000 David A. Schleef <ds@stm.lbl.gov>
+
+    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.
+
+*/
+
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <comedi_module.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <asm/io.h>
+#include <linux/malloc.h>
+#include <linux/delay.h>
+#include <8255.h>
+
+
+/*
+    cio-das16.pdf
+
+    "das16"
+    "das16/f"
+
+  0    a/d bits 0-3            start 12 bit
+  1    a/d bits 4-11           unused
+  2    mux read                mux set
+  3    di 4 bit                do 4 bit
+  4    unused                  ao0_lsb
+  5    unused                  ao0_msb
+  6    unused                  ao1_lsb
+  7    unused                  ao1_msb
+  8    status eoc uni/bip      interrupt reset
+  9    dma, int, trig ctrl     set dma, int
+  a    pacer control           unused
+  b    reserved                reserved
+  cdef 8254
+  0123 8255
+
+*/
+
+/*
+    cio-das16jr.pdf
+
+    "das16jr"
+
+  0    a/d bits 0-3            start 12 bit
+  1    a/d bits 4-11           unused
+  2    mux read                mux set
+  3    di 4 bit                do 4 bit
+  4567 unused                  unused
+  8    status eoc uni/bip      interrupt reset
+  9    dma, int, trig ctrl     set dma, int
+  a    pacer control           unused
+  b    gain status             gain control
+  cdef 8254
+
+*/
+
+/*
+    cio-das160x-1x.pdf
+
+    "das1601/12"
+    "das1602/12"
+    "das1602/16"
+
+  0    a/d bits 0-3            start 12 bit
+  1    a/d bits 4-11           unused
+  2    mux read                mux set
+  3    di 4 bit                do 4 bit
+  4    unused                  ao0_lsb
+  5    unused                  ao0_msb
+  6    unused                  ao1_lsb
+  7    unused                  ao1_msb
+  8    status eoc uni/bip      interrupt reset
+  9    dma, int, trig ctrl     set dma, int
+  a    pacer control           unused
+  b    gain status             gain control
+  cdef 8254
+  400  8255
+  404  unused                  conversion enable
+  405  unused                  burst enable
+  406  unused                  das1600 enable
+  407  status
+
+*/
+
+#define DAS16_TRIG             0
+#define DAS16_AI_LSB           0
+#define DAS16_AI_MSB           1
+#define DAS16_MUX              2
+#define DAS16_DIO              3
+#define DAS16_AO_LSB(x)        ((x)?6:4)
+#define DAS16_AO_MSB(x)        ((x)?7:5)
+#define DAS16_STATUS           8
+#define   DAS16_EOC                    (1<<7)
+#define   DAS16_UB                     (1<<6)
+#define   DAS16_MUXbit                 (1<<5)
+#define   DAS16_INT                    (1<<4)
+#define   DAS16_INT                    (1<<4)
+#define DAS16_CONTROL          9
+#define   DAS16_INTE                   (1<<7)
+#define   DAS16_IRQ(x)                 ((x)<<4)
+#define   DAS16_DMA                    (1<<2)
+#define   DAS16_TS(x)                  ((x)<<0)
+#define DAS16_PACER            0x0a
+#define   DAS16_CTR0                   (1<<1)
+#define   DAS16_TRIG0                  (1<<0)
+#define DAS16_GAIN             0x0b
+
+#define DAS1600_CONV           0x404
+#define DAS1600_BURST          0x405
+#define   DAS1600_BURST_VAL            0x40
+#define DAS1600_ENABLE         0x406
+#define   DAS1600_ENABLE_VAL           0x40
+#define DAS1600_BURST_STATUS   0x407
+#define   DAS1600_BME                  (1<<7)
+#define   DAS1600_ME                   (1<<6)
+#define   DAS1600_CD                   (1<<5)
+#define   DAS1600_WS                   (1<<1)
+#define   DAS1600_CLK                  (1<<0)
+
+
+static int das16jr_gainlist[] = { 8, 0, 1, 2, 3, 4, 5, 6, 7 };
+static int das1600_gainlist[] = { 0, 1, 2, 3 };
+
+static int das16_ao_winsn(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn);
+static int das16_do_wbits(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn);
+static int das16_di_rbits(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn);
+static int das16_ai_rinsn(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn);
+static int das08jr16_ao_winsn(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn);
+
+
+
+struct das_board_struct{
+       char            *name;
+       void            *ai;
+       unsigned int    ai_nbits;
+       void            *ao;
+       unsigned int    ao_nbits;
+       void            *di;
+       void            *do_;
+       unsigned int ai_type;
+
+       unsigned int i8255_offset;
+       unsigned int i8254_offset;
+};
+static struct das_board_struct boards[]={
+       {
+       name:           "das16",        // cio-das16.pdf
+       ai:             das16_ai_rinsn,
+       ai_nbits:       12,
+       ao:             das16_ao_winsn,
+       ao_nbits:       12,
+       di:             das16_di_rbits,
+       do_:            das16_do_wbits,
+       i8255_offset:   0x10,
+       i8254_offset:   0x0c,
+       },
+       {
+       name:           "das16/jr",     // cio-das16jr.pdf
+       ai:             das16_ai_rinsn,
+       ai_nbits:       12,
+       ao:             NULL,
+       ao_nbits:       12,
+       di:             das16_di_rbits,
+       do_:            das16_do_wbits,
+       i8255_offset:   0,
+       i8254_offset:   0x0c,
+       },
+       {
+       name:           "das1401/12",   // cio-das1400_series.pdf
+       ai:             das16_ai_rinsn,
+       ai_nbits:       12,
+       ao:             NULL,
+       ao_nbits:       12,
+       di:             das16_di_rbits,
+       do_:            das16_do_wbits,
+       i8255_offset:   0,
+       i8254_offset:   0x0c,
+       },
+       {
+       name:           "das1402/12",   // cio-das1400_series.pdf
+       ai:             das16_ai_rinsn,
+       ai_nbits:       12,
+       ao:             NULL,
+       ao_nbits:       12,
+       di:             das16_di_rbits,
+       do_:            das16_do_wbits,
+       i8255_offset:   0,
+       i8254_offset:   0x0c,
+       },
+       {
+       name:           "das1402/16",   // cio-das1400_series.pdf
+       ai:             das16_ai_rinsn,
+       ai_nbits:       16,
+       ao:             NULL,
+       ao_nbits:       12,
+       di:             das16_di_rbits,
+       do_:            das16_do_wbits,
+       i8255_offset:   0,
+       i8254_offset:   0x0c,
+       },
+       {
+       name:           "das1601/12",   // cio-das160x-1x.pdf
+       ai:             das16_ai_rinsn,
+       ai_nbits:       12,
+       ao:             das16_ao_winsn,
+       ao_nbits:       12,
+       di:             das16_di_rbits,
+       do_:            das16_do_wbits,
+       i8255_offset:   0x400,
+       i8254_offset:   0x0c,
+       },
+       {
+       name:           "das1602/12",   // cio-das160x-1x.pdf
+       ai:             das16_ai_rinsn,
+       ai_nbits:       12,
+       ao:             das16_ao_winsn,
+       ao_nbits:       12,
+       di:             das16_di_rbits,
+       do_:            das16_do_wbits,
+       i8255_offset:   0x400,
+       i8254_offset:   0x0c,
+       },
+       {
+       name:           "das1602/16",   // cio-das160x-1x.pdf
+       ai:             das16_ai_rinsn,
+       ai_nbits:       16,
+       ao:             das16_ao_winsn,
+       ao_nbits:       12,
+       di:             das16_di_rbits,
+       do_:            das16_do_wbits,
+       i8255_offset:   0x400,
+       i8254_offset:   0x0c,
+       },
+       {
+       name:           "das16/330",    // ?
+       ai:             das16_ai_rinsn,
+       ai_nbits:       12,
+       ao:             das16_ao_winsn,
+       ao_nbits:       12,
+       di:             das16_di_rbits,
+       do_:            das16_do_wbits,
+       i8255_offset:   0,
+       i8254_offset:   0x0c,
+       },
+       {
+       name:           "das16/330i",   // ?
+       },
+       {
+       name:           "das16/f",      // das16.pdf
+       // faster version of das16
+       },
+       {
+       name:           "das16/jr/ctr5", // ?
+       },
+       {
+       name:           "das16/n1",     // cio-das-m1-16.pdf ?
+       },
+       {
+       name:           "das1601/12-p5",//
+       },
+       {
+       name:           "das1602/12-p5",//
+       },
+};
+
+#define TIMEOUT 1000
+
+static comedi_lrange range_das1x01_bip = { 4, {
+       BIP_RANGE( 10 ),
+       BIP_RANGE( 1 ),
+       BIP_RANGE( 0.1 ),
+       BIP_RANGE( 0.01 ),
+}};
+static comedi_lrange range_das1x01_unip = { 4, {
+       UNI_RANGE( 10 ),
+       UNI_RANGE( 1 ),
+       UNI_RANGE( 0.1 ),
+       UNI_RANGE( 0.01 ),
+}};
+static comedi_lrange range_das1x02_bip = { 4, {
+       BIP_RANGE( 10 ),
+       BIP_RANGE( 5 ),
+       BIP_RANGE( 2.5 ),
+       BIP_RANGE( 1.25 ),
+}};
+static comedi_lrange range_das1x02_unip = { 4, {
+       UNI_RANGE( 10 ),
+       UNI_RANGE( 5 ),
+       UNI_RANGE( 2.5 ),
+       UNI_RANGE( 1.25 ),
+}};
+static comedi_lrange range_das16jr = { 9, {
+       // also used by 16/330
+       BIP_RANGE( 10 ),
+       BIP_RANGE( 5 ),
+       BIP_RANGE( 2.5 ),
+       BIP_RANGE( 1.25 ),
+       BIP_RANGE( 0.625 ),
+       UNI_RANGE( 10 ),
+       UNI_RANGE( 5 ),
+       UNI_RANGE( 2.5 ),
+       UNIP_RANGE( 1.25 ),
+}};
+
+
+static int das08jr16_ao_winsn(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn)
+{
+       int n;
+       int lsb,msb;
+       int chan;
+
+       lsb=insn->data[0]&0xff;
+       msb=(insn->data[0]>>8)&0xff;
+
+       chan=CR_CHAN(insn->chanspec);
+
+       for(n=0;n<insn->n;n++){
+#if 0
+               outb(lsb,dev->iobase+devpriv->ao_offset_lsb[chan]);
+               outb(msb,dev->iobase+devpriv->ao_offset_msb[chan]);
+#else
+               outb(lsb,dev->iobase+DAS08AO_AO_LSB(chan));
+               outb(msb,dev->iobase+DAS08AO_AO_MSB(chan));
+#endif
+
+               /* load DACs */
+               inb(dev->iobase+DAS08AO_UPDATE);
+
+               /* XXX */
+               break;
+       }
+
+       return n;
+}
+
+static int das16_ai_rinsn(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn)
+{
+       int i,n;
+
+       /* clear crap */
+       inb(dev->iobase+DAS16_LSB);
+       inb(dev->iobase+DAS16_MSB);
+
+       /* set multiplexer */
+       outb_p(chan,dev->iobase+DAS16_MUX);
+       
+       /* set gain */
+       if(board->have_pg){
+               range = CR_RANGE(insn->chanspec);
+               outb(das16_gainlist[range],dev->iobase+DAS16_GAIN);
+       }
+
+       /* How long should we wait for MUX to settle? */
+       //udelay(5);
+
+       for(n=0;n<insn->n;n++){
+               /* trigger conversion */
+               outb_p(0,dev->iobase+DAS16_TRIG);
+
+               for(i=0;i<TIMEOUT;i++){
+                       if(!(inb(DAS16_STATUS)&DAS16_EOC))
+                               break;
+               }
+               if(i==TIMEOUT){
+                       rt_printk("das08: timeout\n");
+                       return -ETIME;
+               }
+               msb = inb(dev->iobase + DAS16_MSB);
+               lsb = inb(dev->iobase + DAS16_LSB);
+               if(board->ai_nbits==12){
+                       insn->data[n] = (lsb>>4) | (msb << 4);
+               }else{
+                       insn->data[n] = lsb | (msb << 8);
+               }
+       }
+
+       return n;
+}
+
+static void das16_init(comedi_device *dev)
+{
+       outb(DAS16_IRQ(dev->irq),dev->iobase+DAS16_CONTROL);
+       outb(0,DAS16_PACER);
+
+}
+
+static int das16_di_rbits(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn)
+{
+       insn->data[0]=inb(dev->iobase+DAS08JR_DIO)&0xf;
+
+       return 1;
+}
+
+static int das16_do_wbits(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn)
+{
+       outb(insn->data[0],dev->iobase+DAS08JR_DIO);
+
+       return 1;
+}
+
+static int das16_ao_winsn(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn)
+{
+       int n;
+       int lsb,msb;
+       int chan;
+
+       if(board->ao_nbits==12){
+               lsb=(insn->data[0]<<4)&0xff;
+               msb=(insn->data[0]>>4)&0xff;
+       }else{
+               lsb=insn->data[0]&0xff;
+               msb=(insn->data[0]>>8)&0xff;
+       }
+
+       chan=CR_CHAN(insn->chanspec);
+
+       for(n=0;n<insn->n;n++){
+#if 0
+               outb(lsb,dev->iobase+devpriv->ao_offset_lsb[chan]);
+               outb(msb,dev->iobase+devpriv->ao_offset_msb[chan]);
+#else
+               outb(lsb,dev->iobase+DAS16_AO_LSB(chan));
+               outb(msb,dev->iobase+DAS16_AO_MSB(chan));
+#endif
+               /* XXX */
+               break;
+       }
+
+       return n;
+}
+
+static void das1600_init(comedi_device *dev)
+{
+       int status, extstatus;
+
+       status = inb(dev->iobase + DAS16_STATUS);
+       extstatus = inb(dev->iobase + DAS1600_BURST_STATUS);
+
+       if((extstatus & 0xfc)==0x10){
+               /* probably a 1600 board */
+       }
+
+       if((extstatus & DAS1600_CLK)){
+               /* clock is 10 Mhz */
+       }else{
+               /* clock is 1 Mhz */
+       }
+
+       outb(DAS1600_ENABLE_VAL,dev->iobase+DAS1600_ENABLE);
+
+       if((status & DAS16_UB)){
+               /* unipolar */
+       }else{
+               /* bipolar */
+       }
+
+       if((status & DAS16_MUX)){
+               /* single ended */
+       }else{
+               /* differential */
+       }
+
+       printk("4 bit: 0x%02x\n",inb(dev->iobase + DAS16_DIO));
+       /* 0x80: das16 */
+       /* 0x00: das16jr, das16/330 */
+       /* 0xc0: das1600, das1400 */
+
+}
+
+