From: David Schleef Date: Fri, 21 Jul 2000 22:37:53 +0000 (+0000) Subject: updates from Michal Dobes X-Git-Tag: r0_7_47~4 X-Git-Url: http://git.tremily.us/?a=commitdiff_plain;h=197703e353a88fa1c9520df1592520e65d448060;p=comedi.git updates from Michal Dobes --- diff --git a/comedi/drivers/pcl726.c b/comedi/drivers/pcl726.c index 36f3c8a9..826727c3 100644 --- a/comedi/drivers/pcl726.c +++ b/comedi/drivers/pcl726.c @@ -1,11 +1,16 @@ /* module/pcl726.c - hardware driver for PC-LabCard PCL-726 and compatibles - ACL-6126 + hardware driver for Advantech cards: + card: PCL-726, PCL-727, PCL-728 + driver: pcl726, pcl727, pcl728 + and for ADLink cards: + card: ACL-6126, ACL-6128 + driver: acl6126, acl6128 + COMEDI - Linux Control and Measurement Device Interface Copyright (C) 1998 David A. Schleef - + 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 @@ -22,6 +27,33 @@ */ +/* + Options for PCL-726: + [0] - IO Base + [1]...[6] - D/A output range for channel 1-6: + 0: 0-5V, 1: 0-10V, 2: +/-5V, 3: +/-10V, + 4: 4-20mA, 5: unknow (external reference) + + Options for PCL-727: + [0] - IO Base + [1]...[12] - D/A output range for channel 1-12: + 0: 0-5V, 1: 0-10V, 2: +/-5V, + 3: 4-20mA + + Options for PCL-728 and ACL-6128: + [0] - IO Base + [1], [2] - D/A output range for channel 1 and 2: + 0: 0-5V, 1: 0-10V, 2: +/-5V, 3: +/-10V, + 4: 4-20mA, 5: 0-20mA + + Options for ACL-6126: + [0] - IO Base + [1] - IRQ (0=disable, 3, 5, 6, 7, 9, 10, 11, 12, 15) + [2]...[7] - D/A output range for channel 1-6: + 0: 0-5V, 1: 0-10V, 2: +/-5V, 3: +/-10V, + 4: 4-20mA + NOTE: IRQ operations isn't now supported. +*/ /* Thanks to Circuit Specialists for having programming info (!) on @@ -43,10 +75,12 @@ #include -#undef PCL726_IRQ /* no interrupt support (yet) */ +#undef ACL6126_IRQ /* no interrupt support (yet) */ #define PCL726_SIZE 16 +#define PCL727_SIZE 32 +#define PCL728_SIZE 8 #define PCL726_DAC0_HI 0 #define PCL726_DAC0_LO 1 @@ -56,19 +90,83 @@ #define PCL726_DI_HI 14 #define PCL726_DI_LO 15 +#define PCL727_DO_HI 24 +#define PCL727_DO_LO 25 +#define PCL727_DI_HI 0 +#define PCL727_DI_LO 1 + +#define RANGE_mA(a,b) {(a)*1e6,(b)*1e6,UNIT_mA} + +comedi_lrange range_4_20mA={ 1, {RANGE_mA(4,20)}}; +comedi_lrange range_0_20mA={ 1, {RANGE_mA(0,20)}}; + +static comedi_lrange *rangelist_726[]={ + &range_unipolar5, &range_unipolar10, + &range_bipolar5, &range_bipolar10, + &range_4_20mA, &range_unknown +}; + +static comedi_lrange *rangelist_727[]={ + &range_unipolar5, &range_unipolar10, + &range_bipolar5, + &range_4_20mA +}; + +static comedi_lrange *rangelist_728[]={ + &range_unipolar5, &range_unipolar10, + &range_bipolar5, &range_bipolar10, + &range_4_20mA, &range_0_20mA +}; static int pcl726_attach(comedi_device *dev,comedi_devconfig *it); static int pcl726_detach(comedi_device *dev); +static int pcl726_recognize(char *name); + comedi_driver driver_pcl726={ driver_name: "pcl726", module: THIS_MODULE, attach: pcl726_attach, detach: pcl726_detach, + recognize: pcl726_recognize, }; +typedef struct { + char *name; // driver name + int n_aochan; // num of D/A chans + int num_of_ranges; // num of ranges + unsigned int IRQbits; // allowed interrupts + int io_range; // len of IO space + char have_dio; // 1=card have DI/DO ports + int di_hi; // ports for DI/DO operations + int di_lo; + int do_hi; + int do_lo; + comedi_lrange **range_type_list;// list of supported ranges +} boardtype; + +static boardtype boardtypes[] = +{ + {"pcl726", 6, 6, 0x0000, PCL726_SIZE, 1, + PCL726_DI_HI, PCL726_DI_LO, PCL726_DO_HI, PCL726_DO_LO, + &rangelist_726[0], }, + {"pcl727", 12, 4, 0x0000, PCL727_SIZE, 1, + PCL727_DI_HI, PCL727_DI_LO, PCL727_DO_HI, PCL727_DO_LO, + &rangelist_727[0], }, + {"pcl728", 2, 6, 0x0000, PCL728_SIZE, 0, + 0, 0, 0, 0, + &rangelist_728[0], }, + {"acl6126", 6, 5, 0x96e8, PCL726_SIZE, 1, + PCL726_DI_HI, PCL726_DI_LO, PCL726_DO_HI, PCL726_DO_LO, + &rangelist_726[0], }, + {"acl6128", 2, 6, 0x0000, PCL728_SIZE, 0, + 0, 0, 0, 0, + &rangelist_728[0], }, +}; +#define n_boardtypes (sizeof(boardtypes)/sizeof(boardtype)) typedef struct{ - int bipolar[6]; + int bipolar[12]; + comedi_lrange *rangelist[12]; }pcl726_private; #define devpriv ((pcl726_private *)dev->private) @@ -95,8 +193,8 @@ static int pcl726_di(comedi_device *dev,comedi_subdevice *s,comedi_trig *it) { unsigned int bits; - bits=inb(dev->iobase+PCL726_DI_LO)| - (inb(dev->iobase+PCL726_DI_HI)<<8); + bits=inb(dev->iobase+boardtypes[dev->board].di_lo)| + (inb(dev->iobase+boardtypes[dev->board].di_hi)<<8); return di_unpack(bits,it); } @@ -105,8 +203,8 @@ static int pcl726_do(comedi_device *dev,comedi_subdevice *s,comedi_trig *it) { do_pack(&s->state,it); - outb(s->state&0xff,dev->iobase+PCL726_DO_LO); - outb((s->state>>8),dev->iobase+PCL726_DO_HI); + outb(s->state&0xff,dev->iobase+boardtypes[dev->board].do_lo); + outb((s->state>>8),dev->iobase+boardtypes[dev->board].do_hi); return it->n_chan; } @@ -114,83 +212,124 @@ static int pcl726_do(comedi_device *dev,comedi_subdevice *s,comedi_trig *it) static int pcl726_attach(comedi_device *dev,comedi_devconfig *it) { comedi_subdevice *s; - int ret; + int board,iobase,iorange; + int ret,i,fstch; - dev->iobase=it->options[0]; - printk("comedi%d: pcl726: 0x%04x ",dev->minor,dev->iobase); - if(check_region(dev->iobase,PCL726_SIZE)<0){ + board=dev->board; + + iobase=it->options[0]; + iorange=boardtypes[board].io_range; + printk("comedi%d: pcl726: board=%s, 0x%03x ",dev->minor,boardtypes[board].name,iobase); + if(check_region(iobase,iorange)<0){ printk("I/O port conflict\n"); return -EIO; } - dev->board_name="pcl726"; - -#ifdef PCL726_IRQ - irq=dev->options[1]; - if(!is_b)irq=0; - if(irq<0 || irq==1 || irq>7){ - printk("irq out of range\n"); - return -EIO; + request_region(iobase, iorange, "pcl726"); + dev->iobase=iobase; + dev->iosize=iorange; + + dev->board_name = boardtypes[board].name; + + if((ret=alloc_private(dev,sizeof(pcl726_private)))<0) + return -ENOMEM; + + for (i=0; i<12; i++) { + devpriv->bipolar[i]=0; + devpriv->rangelist[i]=&range_unknown; } - if(irq){ - if(request_irq(irq,pcl726_interrupt,SA_INTERRUPT,"pcl726",dev)){ - printk("unable to allocate irq %d\n",irq); - irq=0; - }else{ - printk("( irq = %d )\n",irq); + +#ifdef ACL6126_IRQ + irq=0; + if (boardtypes[board].IRQbits!=0) { /* board support IRQ */ + irq=it->options[1]; + devpriv->first_chan=2; + if (irq>0) {/* we want to use IRQ */ + if (((1<irq=irq; + + dev->irq = irq; #endif - request_region(dev->iobase,PCL726_SIZE,"pcl726"); - dev->iosize=PCL726_SIZE; - - if((ret=alloc_private(dev,sizeof(pcl726_private)))<0) - return -ENOMEM; + printk("\n"); - dev->n_subdevices=3; + dev->n_subdevices=1; + if (boardtypes[board].have_dio) + dev->n_subdevices=3; + if((ret=alloc_subdevices(dev))<0) return ret; s=dev->subdevices+0; /* ao */ s->type=COMEDI_SUBD_AO; - s->subdev_flags=SDF_WRITEABLE; - s->n_chan=6; + s->subdev_flags=SDF_WRITEABLE|SDF_GROUND; + s->n_chan=boardtypes[board].n_aochan; s->maxdata=0xfff; + s->len_chanlist=1; s->trig[0]=pcl726_ao; - s->range_table=&range_unknown; /* XXX */ + /*s->range_table=&range_unknown;*/ /* XXX */ + s->range_table_list = devpriv->rangelist; + fstch=1; + if (board==3) fstch=2; + for (i=0; ioptions[fstch+i]<0)||(it->options[fstch+i]>=boardtypes[board].num_of_ranges)) { + printk("Invalid range for channel %d! Must be 0<=%d<%d\n",i+1,it->options[fstch+i],boardtypes[board].num_of_ranges-1); + it->options[fstch+i]=0; + } + devpriv->rangelist[i]=boardtypes[board].range_type_list[it->options[fstch+i]]; + if (devpriv->rangelist[i]->range[0].min==-devpriv->rangelist[i]->range[0].max) + devpriv->bipolar[i]=1; /* bipolar range */ + } + + if (dev->n_subdevices<2) { + return 0; + } s=dev->subdevices+1; /* di */ s->type=COMEDI_SUBD_DI; - s->subdev_flags=SDF_READABLE; + s->subdev_flags=SDF_READABLE|SDF_GROUND; s->n_chan=16; s->maxdata=1; + s->len_chanlist=1; s->trig[0]=pcl726_di; s->range_table=&range_digital; + if (dev->n_subdevices<3) { + return 0; + } + s=dev->subdevices+2; /* do */ s->type=COMEDI_SUBD_DO; - s->subdev_flags=SDF_WRITEABLE; + s->subdev_flags=SDF_WRITEABLE|SDF_GROUND; s->n_chan=16; s->maxdata=1; + s->len_chanlist=1; s->trig[0]=pcl726_do; s->range_table=&range_digital; - printk("\n"); - return 0; } static int pcl726_detach(comedi_device *dev) { - printk("comedi%d: pcl726: remove\n",dev->minor); +// printk("comedi%d: pcl726: remove\n",dev->minor); -#ifdef PCL726_IRQ +#ifdef ACL6126_IRQ if(dev->irq){ free_irq(dev->irq,dev); } @@ -201,18 +340,20 @@ static int pcl726_detach(comedi_device *dev) return 0; } +static int pcl726_recognize(char *name) +{ + int i; + for (i = 0; i < n_boardtypes; i++) { + if (!strcmp(boardtypes[i].name, name)) { + return i; + } + } -#ifdef MODULE -int init_module(void) -{ - comedi_driver_register(&driver_pcl726); - - return 0; + return -1; } -void cleanup_module(void) -{ - comedi_driver_unregister(&driver_pcl726); -} -#endif + + +COMEDI_INITCLEANUP(driver_pcl726); +