From ce07205618e2edcf9630a3d31acfc78d31648fae Mon Sep 17 00:00:00 2001 From: David Schleef Date: Sat, 15 Jul 2000 02:37:50 +0000 Subject: [PATCH] changes --- comedi/comedi_module.h | 7 + comedi/drivers/das08-new.c | 8 +- comedi/drivers/das16-new.c | 488 ++++++++++++++++++++++++++++--------- 3 files changed, 387 insertions(+), 116 deletions(-) diff --git a/comedi/comedi_module.h b/comedi/comedi_module.h index c2106423..8c200f1d 100644 --- a/comedi/comedi_module.h +++ b/comedi/comedi_module.h @@ -52,6 +52,13 @@ #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; diff --git a/comedi/drivers/das08-new.c b/comedi/drivers/das08-new.c index 9a3fb7fc..fa0140ba 100644 --- a/comedi/drivers/das08-new.c +++ b/comedi/drivers/das08-new.c @@ -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) diff --git a/comedi/drivers/das16-new.c b/comedi/drivers/das16-new.c index bc5f45c9..3047a893 100644 --- a/comedi/drivers/das16-new.c +++ b/comedi/drivers/das16-new.c @@ -33,6 +33,8 @@ #include <8255.h> +#define DAS16_SIZE 20 + /* cio-das16.pdf @@ -138,123 +140,227 @@ #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;nn;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<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<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); -- 2.26.2