changes
authorDavid Schleef <ds@schleef.org>
Sat, 15 Jul 2000 02:37:50 +0000 (02:37 +0000)
committerDavid Schleef <ds@schleef.org>
Sat, 15 Jul 2000 02:37:50 +0000 (02:37 +0000)
comedi/comedi_module.h
comedi/drivers/das08-new.c
comedi/drivers/das16-new.c

index c21064236aadf40876ef3b52dfb0b167044e3cf0..8c200f1dcd4d407a55a937bd301e4368dab25b46 100644 (file)
 #define COMEDI_VERSION "1.0.0"
 #endif
 
+#ifdef MODULE
+#define COMEDI_INITCLEANUP(x)                                          \
+       int init_module(void){comedi_driver_register(&(x));return 0;}   \
+       void cleanup_module(void){comedi_driver_unregister(&(x));}
+#else
+#define COMEDI_INITCLEANUP(x)
+#endif
 typedef struct comedi_device_struct comedi_device;
 typedef struct comedi_subdevice_struct comedi_subdevice;
 typedef struct comedi_driver_struct comedi_driver;
index 9a3fb7fc3533603c37c894a65f050c180d4e39a1..fa0140babaa29ccbe51db253fa8449544d6b965f 100644 (file)
@@ -505,15 +505,15 @@ static int das08_attach(comedi_device *dev,comedi_devconfig *it)
        int ret;
 
        dev->iobase=it->options[0];
-       printk("comedi%d: das08: )x%04x",dev->minor,dev->iobase);
+       printk("comedi%d: das08: 0x%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->board_ptr = das08_boards+dev->board;
+       dev->board_name = thisboard->name;
+       dev->iosize = DAS08_SIZE;
 
        dev->n_subdevices=5;
        if((ret=alloc_subdevices(dev))<0)
index bc5f45c9a2853cf51d9b38a821a321b94ecf2c74..3047a893f1c6eea29ccaa0410da92e11c21f445d 100644 (file)
@@ -33,6 +33,8 @@
 #include <8255.h>
 
 
+#define DAS16_SIZE 20
+
 /*
     cio-das16.pdf
 
 #define   DAS1600_CLK                  (1<<0)
 
 
+
+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 ),
+       UNI_RANGE( 1.25 ),
+}};
+
+
 static int das16jr_gainlist[] = { 8, 0, 1, 2, 3, 4, 5, 6, 7 };
 static int das1600_gainlist[] = { 0, 1, 2, 3 };
+enum {
+       das16_pg_none = 0,
+       das16_pg_16jr,
+       das16_pg_1601,
+       das16_pg_1602,
+};
+static int *das16_gainlists[] = {
+       NULL,
+       das16jr_gainlist,
+       das1600_gainlist,
+       das1600_gainlist,
+};
+static comedi_lrange *das16_ai_uni_lranges[]={
+       &range_bipolar10, /* XXX guess */
+       &range_das16jr,
+       &range_das1x01_unip,
+       &range_das1x02_unip,
+};
+static comedi_lrange *das16_ai_bip_lranges[]={
+       &range_unipolar10, /* XXX guess */
+       &range_das16jr,
+       &range_das1x01_bip,
+       &range_das1x02_bip,
+};
 
 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{
+struct das16_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 ai_type;
 
-       unsigned int i8255_offset;
-       unsigned int i8254_offset;
+       unsigned int    i8255_offset;
+       unsigned int    i8254_offset;
+
+       unsigned int    size;
+};
+enum{  /* must match following array */
+       das16_board_das16,
+       das16_board_das16f,
+       das16_board_das16jr,
+       das16_board_das1401_12,
+       das16_board_das1402_12,
+       das16_board_das1402_16,
+       das16_board_das1601_12,
+       das16_board_das1602_12,
+       das16_board_das1602_16,
+       das16_board_das16_330,
 };
-static struct das_board_struct boards[]={
+static struct das16_board_struct das16_boards[]={
        {
        name:           "das16",        // cio-das16.pdf
        ai:             das16_ai_rinsn,
        ai_nbits:       12,
+       ai_pg:          das16_pg_none,
+       ao:             das16_ao_winsn,
+       ao_nbits:       12,
+       di:             das16_di_rbits,
+       do_:            das16_do_wbits,
+       i8255_offset:   0x10,
+       i8254_offset:   0x0c,
+       size:           0x14,
+       },
+       {
+       name:           "das16/f",      // das16.pdf
+       ai:             das16_ai_rinsn,
+       ai_nbits:       12,
+       ai_pg:          das16_pg_none,
        ao:             das16_ao_winsn,
        ao_nbits:       12,
        di:             das16_di_rbits,
        do_:            das16_do_wbits,
        i8255_offset:   0x10,
        i8254_offset:   0x0c,
+       size:           0x14,
        },
        {
        name:           "das16/jr",     // cio-das16jr.pdf
        ai:             das16_ai_rinsn,
        ai_nbits:       12,
+       ai_pg:          das16_pg_16jr,
        ao:             NULL,
        ao_nbits:       12,
        di:             das16_di_rbits,
        do_:            das16_do_wbits,
        i8255_offset:   0,
        i8254_offset:   0x0c,
+       size:           0x10,
        },
        {
        name:           "das1401/12",   // cio-das1400_series.pdf
        ai:             das16_ai_rinsn,
        ai_nbits:       12,
+       ai_pg:          das16_pg_1601,
        ao:             NULL,
        ao_nbits:       12,
        di:             das16_di_rbits,
        do_:            das16_do_wbits,
        i8255_offset:   0,
        i8254_offset:   0x0c,
+       size:           0x408,
        },
        {
        name:           "das1402/12",   // cio-das1400_series.pdf
        ai:             das16_ai_rinsn,
        ai_nbits:       12,
+       ai_pg:          das16_pg_1602,
        ao:             NULL,
        ao_nbits:       12,
        di:             das16_di_rbits,
        do_:            das16_do_wbits,
        i8255_offset:   0,
        i8254_offset:   0x0c,
+       size:           0x408,
        },
        {
        name:           "das1402/16",   // cio-das1400_series.pdf
        ai:             das16_ai_rinsn,
        ai_nbits:       16,
+       ai_pg:          das16_pg_1602,
        ao:             NULL,
        ao_nbits:       12,
        di:             das16_di_rbits,
        do_:            das16_do_wbits,
        i8255_offset:   0,
        i8254_offset:   0x0c,
+       size:           0x408,
        },
        {
        name:           "das1601/12",   // cio-das160x-1x.pdf
        ai:             das16_ai_rinsn,
        ai_nbits:       12,
+       ai_pg:          das16_pg_1601,
        ao:             das16_ao_winsn,
        ao_nbits:       12,
        di:             das16_di_rbits,
        do_:            das16_do_wbits,
        i8255_offset:   0x400,
        i8254_offset:   0x0c,
+       size:           0x408,
        },
        {
        name:           "das1602/12",   // cio-das160x-1x.pdf
        ai:             das16_ai_rinsn,
        ai_nbits:       12,
+       ai_pg:          das16_pg_1602,
        ao:             das16_ao_winsn,
        ao_nbits:       12,
        di:             das16_di_rbits,
        do_:            das16_do_wbits,
        i8255_offset:   0x400,
        i8254_offset:   0x0c,
+       size:           0x408,
        },
        {
        name:           "das1602/16",   // cio-das160x-1x.pdf
        ai:             das16_ai_rinsn,
        ai_nbits:       16,
+       ai_pg:          das16_pg_1602,
        ao:             das16_ao_winsn,
        ao_nbits:       12,
        di:             das16_di_rbits,
        do_:            das16_do_wbits,
        i8255_offset:   0x400,
        i8254_offset:   0x0c,
+       size:           0x408,
        },
        {
        name:           "das16/330",    // ?
        ai:             das16_ai_rinsn,
        ai_nbits:       12,
+       ai_pg:          das16_pg_16jr,
        ao:             das16_ao_winsn,
        ao_nbits:       12,
        di:             das16_di_rbits,
@@ -262,14 +368,11 @@ static struct das_board_struct boards[]={
        i8255_offset:   0,
        i8254_offset:   0x0c,
        },
+#if 0
        {
        name:           "das16/330i",   // ?
        },
        {
-       name:           "das16/f",      // das16.pdf
-       // faster version of das16
-       },
-       {
        name:           "das16/jr/ctr5", // ?
        },
        {
@@ -281,93 +384,51 @@ static struct das_board_struct boards[]={
        {
        name:           "das1602/12-p5",//
        },
+#endif
 };
 
-#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;
+static int das16_attach(comedi_device *dev,comedi_devconfig *it);
+static int das16_detach(comedi_device *dev);
+comedi_driver driver_das16={
+       driver_name:    "das16",
+       module:         THIS_MODULE,
+       attach:         das16_attach,
+       detach:         das16_detach,
+};
 
-       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
+#define TIMEOUT 1000
 
-               /* load DACs */
-               inb(dev->iobase+DAS08AO_UPDATE);
 
-               /* XXX */
-               break;
-       }
+struct das16_private_struct {
+       unsigned int    ai_unipolar;
+       unsigned int    ai_singleended;
+       unsigned int    clockbase;
+};
+#define devpriv ((struct das16_private_struct *)(dev->private))
+#define thisboard ((struct das16_board_struct *)(dev->board_ptr))
 
-       return n;
-}
 
 static int das16_ai_rinsn(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn)
 {
        int i,n;
+       int range;
+       int chan;
+       int msb,lsb;
 
        /* clear crap */
-       inb(dev->iobase+DAS16_LSB);
-       inb(dev->iobase+DAS16_MSB);
+       inb(dev->iobase+DAS16_AI_LSB);
+       inb(dev->iobase+DAS16_AI_MSB);
 
        /* set multiplexer */
+       chan = CR_CHAN(insn->chanspec);
        outb_p(chan,dev->iobase+DAS16_MUX);
        
        /* set gain */
-       if(board->have_pg){
+       if(thisboard->ai_pg != das16_pg_none){
                range = CR_RANGE(insn->chanspec);
-               outb(das16_gainlist[range],dev->iobase+DAS16_GAIN);
+               outb((das16_gainlists[thisboard->ai_pg])[range],
+                       dev->iobase+DAS16_GAIN);
        }
 
        /* How long should we wait for MUX to settle? */
@@ -382,12 +443,12 @@ static int das16_ai_rinsn(comedi_device *dev,comedi_subdevice *s,comedi_insn *in
                                break;
                }
                if(i==TIMEOUT){
-                       rt_printk("das08: timeout\n");
+                       rt_printk("das16: timeout\n");
                        return -ETIME;
                }
-               msb = inb(dev->iobase + DAS16_MSB);
-               lsb = inb(dev->iobase + DAS16_LSB);
-               if(board->ai_nbits==12){
+               msb = inb(dev->iobase + DAS16_AI_MSB);
+               lsb = inb(dev->iobase + DAS16_AI_LSB);
+               if(thisboard->ai_nbits==12){
                        insn->data[n] = (lsb>>4) | (msb << 4);
                }else{
                        insn->data[n] = lsb | (msb << 8);
@@ -397,23 +458,16 @@ static int das16_ai_rinsn(comedi_device *dev,comedi_subdevice *s,comedi_insn *in
        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;
+       insn->data[0]=inb(dev->iobase+DAS16_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);
+       outb(insn->data[0],dev->iobase+DAS16_DIO);
 
        return 1;
 }
@@ -424,7 +478,7 @@ static int das16_ao_winsn(comedi_device *dev,comedi_subdevice *s,comedi_insn *in
        int lsb,msb;
        int chan;
 
-       if(board->ao_nbits==12){
+       if(thisboard->ao_nbits==12){
                lsb=(insn->data[0]<<4)&0xff;
                msb=(insn->data[0]>>4)&0xff;
        }else{
@@ -449,42 +503,252 @@ static int das16_ao_winsn(comedi_device *dev,comedi_subdevice *s,comedi_insn *in
        return n;
 }
 
-static void das1600_init(comedi_device *dev)
+
+
+
+static void das16_init(comedi_device *dev)
+{
+       outb(DAS16_IRQ(dev->irq),dev->iobase+DAS16_CONTROL);
+       outb(0,DAS16_PACER);
+
+}
+
+static int detect_ao(comedi_device *dev)
 {
-       int status, extstatus;
+       int in_aa;
+       int in_55;
+
+       outb(0xaa,dev->iobase+DAS16_AO_LSB(0));
+       in_aa = inb(dev->iobase+DAS16_AO_LSB(0));
+
+       outb(0x55,dev->iobase+DAS16_AO_LSB(0));
+       in_55 = inb(dev->iobase+DAS16_AO_LSB(0));
+
+       printk("detect_ao: 0xaa -> 0x%02x, 0x55 -> 0x%02x\n",in_aa,in_55);
+
+       if((in_aa == 0xaa) && (in_55 == 0x55)){
+               printk("possibly 16 bit ao?\n");
+       }
+
+       if(((in_aa & 0xf0) == 0xa0) && ((in_55 & 0xf0) == 0x50)){
+               printk("ao test positive\n");
+               return 1;
+       }
+
+       printk("ao test negative\n");
+
+       return 0;
+}
+
+static int das16_probe(comedi_device *dev)
+{
+       int status;
+       int burststatus;
+       int diobits;
+
+       /* status is available on all boards */
 
        status = inb(dev->iobase + DAS16_STATUS);
-       extstatus = inb(dev->iobase + DAS1600_BURST_STATUS);
 
-       if((extstatus & 0xfc)==0x10){
-               /* probably a 1600 board */
+       if((status & DAS16_UB)){
+               devpriv->ai_unipolar = 1;
+       }else{
+               devpriv->ai_unipolar = 0;
        }
 
-       if((extstatus & DAS1600_CLK)){
-               /* clock is 10 Mhz */
+       if((status & DAS16_MUX)){
+               devpriv->ai_singleended = 1;
        }else{
-               /* clock is 1 Mhz */
+               devpriv->ai_singleended = 0;
+       }
+
+       /* diobits indicates boards */
+
+       diobits = inb(dev->iobase + DAS16_DIO) & 0xf0;
+
+printk("diobits 0x%02x",diobits);
+       switch(diobits){
+       case 0x80:
+               printk(" das16 or das16/f");
+               /* only difference is speed, so not an issue yet */
+               return das16_board_das16;
+       case 0x00:
+               printk(" das16jr or das16/330");
+               /* the 330 has ao, 16jr does not */
+
+               /* we can write the low 4 bits without updating DAC */
+               if(detect_ao(dev)){
+                       return das16_board_das16_330;
+               }else{
+                       return das16_board_das16jr;
+               }
+
+               break;
+       default:
+               printk(" unknown board");
+               return -1;
+       case 0xc0:
+               printk(" das1600 or das1400");
+               break;
+       }
+
+       /* burststatus is available on 1600, 1400 */
+
+       burststatus = inb(dev->iobase + DAS1600_BURST_STATUS);
+
+       if((burststatus & 0xfc)==0x10){
+               /* true for 1400, 1600 */
+       }
+
+       if((burststatus & DAS1600_CLK)){
+               devpriv->clockbase = 100;
+       }else{
+               devpriv->clockbase = 1000;
        }
 
        outb(DAS1600_ENABLE_VAL,dev->iobase+DAS1600_ENABLE);
 
-       if((status & DAS16_UB)){
-               /* unipolar */
+       if(detect_ao(dev)){
+               printk("das1600 series\n");
+               return das16_board_das1601_12;
        }else{
-               /* bipolar */
+               printk("das1400 series\n");
+               return das16_board_das1401_12;
        }
 
-       if((status & DAS16_MUX)){
-               /* single ended */
+}
+
+
+/*
+ *
+ * Options list:
+ *   0  I/O base
+ *   1  IRQ
+ */
+
+static int das16_attach(comedi_device *dev, comedi_devconfig *it)
+{
+       comedi_subdevice *s;
+       int ret;
+
+       dev->iobase = it->options[0];
+
+       printk("comedi%d: das16:",dev->minor);
+
+       dev->board_ptr = das16_boards + dev->board;
+       dev->board_name = thisboard->name;
+
+       if(thisboard->size<0x400){
+               printk(" 0x%04x-0x%04x",
+                       dev->iobase,dev->iobase+thisboard->size);
+               if(check_region(dev->iobase,thisboard->size)<0){
+                       printk(" I/O port conflict\n");
+                       return -EIO;
+               }
        }else{
-               /* differential */
+               printk(" 0x%04x-0x%04x 0x%04x-0x%04x",
+                       dev->iobase,dev->iobase+0x0f,
+                       dev->iobase+0x400,dev->iobase+(thisboard->size&0x3ff));
+               if(check_region(dev->iobase,0x10)<0 ||
+                  check_region(dev->iobase+0x400,thisboard->size&0x3ff)<0){
+                       printk(" I/O port conflict\n");
+                       return -EIO;
+               }
        }
 
-       printk("4 bit: 0x%02x\n",inb(dev->iobase + DAS16_DIO));
-       /* 0x80: das16 */
-       /* 0x00: das16jr, das16/330 */
-       /* 0xc0: das1600, das1400 */
+       dev->n_subdevices = 5;
+       if((ret=alloc_subdevices(dev))<0)
+               return ret;
+       if((ret=alloc_private(dev,sizeof(struct das16_private_struct)))<0)
+               return ret;
+
+       if(thisboard->size<0x400){
+               request_region(dev->iobase,thisboard->size,"das16");
+       }else{
+               request_region(dev->iobase,0x10,"das16");
+               request_region(dev->iobase,thisboard->size&0x3ff,"das16");
+       }
+
+       s=dev->subdevices+0;
+       /* ai */
+       if(thisboard->ai){
+               s->type = COMEDI_SUBD_AI;
+               s->subdev_flags = SDF_READABLE;
+               if(devpriv->ai_singleended){
+                       s->n_chan = 16;
+                       s->subdev_flags |= SDF_GROUND;  /* XXX ? */
+               }else{
+                       s->n_chan = 8;
+                       s->subdev_flags |= SDF_DIFF;
+               }
+               s->maxdata = (1<<thisboard->ai_nbits)-1;
+               if(devpriv->ai_unipolar){
+                       s->range_table = das16_ai_uni_lranges[thisboard->ai_pg];
+               }else{
+                       s->range_table = das16_ai_bip_lranges[thisboard->ai_pg];
+               }
+               s->insn_read = thisboard->ai;
+       }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 = 4;
+               s->maxdata = 1;
+               s->range_table = &range_digital;
+               s->insn_read = thisboard->di;
+       }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 = 4;
+               s->maxdata = 1;
+               s->range_table = &range_digital;
+               s->insn_write = thisboard->do_;
+       }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 das16_detach(comedi_device *dev)
+{
 
+       return 0;
 }
 
+COMEDI_INITCLEANUP(driver_das16);