From: David Schleef Date: Sun, 27 Feb 2000 01:39:02 +0000 (+0000) Subject: modularized PCI20k modules, general cleanup X-Git-Tag: r0_7_40~20 X-Git-Url: http://git.tremily.us/?a=commitdiff_plain;h=d3f55de3869beef315a3e2d78485c30c26f15cc6;p=comedi.git modularized PCI20k modules, general cleanup --- diff --git a/comedi/drivers/ii_pci20kc.c b/comedi/drivers/ii_pci20kc.c index ebc8cdbb..7d7f9901 100644 --- a/comedi/drivers/ii_pci20kc.c +++ b/comedi/drivers/ii_pci20kc.c @@ -44,90 +44,100 @@ #include /* printk() */ #include /* error codes */ -#include /* readb() ... */ -#include /* copy_to/from_user */ +#include /* readb() ... */ #define PCI20000_ID 0x1d #define PCI20341_ID 0x77 #define PCI20006_ID 0xe3 +#define PCI20xxx_EMPTY_ID 0 + #define PCI20000_OFFSET 0x100 #define PCI20000_MODULES 3 -#define PCI20341_OPTION 0x00 + #define PCI20000_DI_PORT 0 /* only ONE di-port is supported */ #define PCI20000_DO_PORT 1 /* only ONE do-port is supported */ +#define PCI20000_DIO_0 0x80 +#define PCI20000_DIO_1 0x81 +#define PCI20000_DIO_2 0xc0 +#define PCI20000_DIO_3 0xc1 + +#define PCI20341_OPTION 0x00 #define PCI20341_REPMODE 0x00 /* single shot mode */ #define PCI20341_PACER 0x00 /* Hardware Pacer disabled */ #define PCI20341_CHAN_NR 2 /* number of input channels */ -#define CHANNEL_READ 0x01 -#define CHANNEL_WRITE 0x01 -typedef struct { - unsigned int ai_mod_pos; /* block address of ai module */ - unsigned int ao_mod_pos; /* block address of ao module */ - comedi_lrange *ao_range_list[2]; /* range of channels of ao module */ - int dio_port[PCI20000_MODULES+1]; /* port address */ - int timebase; /* timebase ai module */ - int settling_time; /* settling time ai module */ - int ai_gain; /* analog input gain */ - }pci20xxx_private; - +typedef union { + int iobase; + struct { + int iobase; + comedi_lrange *ao_range_list[2]; /* range of channels of ao module */ + }pci20006; + struct { + int iobase; + int timebase; + int settling_time; + int ai_gain; + }pci20341; +} pci20xxx_subdev_private; + +typedef struct { + pci20xxx_subdev_private subdev_private[PCI20000_MODULES]; +} pci20xxx_private; + #define devpriv ((pci20xxx_private *)dev->private) #define CHAN (CR_CHAN(it->chanlist[0])) -static int pci20xxx_attach(comedi_device *dev, comedi_devconfig *it); -static int pci20xxx_detach(comedi_device *dev); -static int pci20xxx_recognize(char *name); - -comedi_driver driver_pci20xxx={ - driver_name: "pci20xxx", - module: &__this_module, - attach: pci20xxx_attach, - detach: pci20xxx_detach, - recognize: pci20xxx_recognize, - }; - -static int pci20xxx_ai_mode0(comedi_device *dev, comedi_subdevice *s, comedi_trig *it); -static int pci20xxx_ao(comedi_device *dev, comedi_subdevice *s, comedi_trig *it); -static int pci20xxx_di(comedi_device *dev, comedi_subdevice *s, comedi_trig *it); -static int pci20xxx_do(comedi_device *dev, comedi_subdevice *s, comedi_trig *it); - -static int pci20xxx_init(comedi_device *dev); -static int pci20xxx_ai_init(comedi_device *dev); -static int pci20xxx_di_init(comedi_device *dev); -static int pci20xxx_do_init(comedi_device *dev); - -static int pci20xxx_recognize(char *name) - { - if(!strcmp("pci20xxx",name)) - return 0; - return -1; - } +static int pci20xxx_attach(comedi_device * dev, comedi_devconfig * it); +static int pci20xxx_detach(comedi_device * dev); + +comedi_driver driver_pci20xxx = { + driver_name:"pci20xxx", + module:&__this_module, + attach:pci20xxx_attach, + detach:pci20xxx_detach, +}; + +static int pci20006_init(comedi_device * dev,comedi_subdevice *s, + int opt0,int opt1); +static int pci20341_init(comedi_device * dev,comedi_subdevice *s, + int opt0,int opt1); +static int pci20xxx_dio_init(comedi_device * dev,comedi_subdevice *s); /* options[0] Board base address options[1] IRQ - options[2] Analog input gain configuration + options[2] first option for module 1 + options[3] second option for module 1 + options[4] first option for module 2 + options[5] second option for module 2 + options[6] first option for module 3 + options[7] second option for module 3 + + options for PCI-20341M: + first Analog input gain configuration 1 10 100 200 - options[3] Analog output channel 0 range configuration + + options for PCI-20006M: + first Analog output channel 0 range configuration 0 == bipolar 10 (-10V -- +10V) 1 == unipolar 10V (0V -- +10V) 2 == bipolar 5V (-5V -- +5V) - options[4] Analog output channel 1 range configuration + second Analog output channel 1 range configuration 0 == bipolar 10 (-10V -- +10V) 1 == unipolar 10V (0V -- +10V) 2 == bipolar 5V (-5V -- +5V) */ static int pci20xxx_attach(comedi_device * dev, comedi_devconfig * it) - { +{ unsigned char i; int ret; - int isthere = 0; + int id; comedi_subdevice *s; dev->n_subdevices = 4; @@ -137,338 +147,419 @@ static int pci20xxx_attach(comedi_device * dev, comedi_devconfig * it) return ret; dev->iobase = it->options[0]; - - /* Check PCI-20001 C-2A Carrier Board ID */ - if((readb(dev->iobase) & PCI20000_ID) != PCI20000_ID) - { - printk("comedi%d: \n", dev->minor); - printk("PCI-20001 C-2A Carrier Board at base=0x%05x not found !\n", dev->iobase); - return -EINVAL; - } + dev->board_name = "pci20kc"; - /* looking for input module PCI-20341 M-1A*/ - for (i=1; i <= PCI20000_MODULES; i++) - { - if ( readb(dev->iobase+i*PCI20000_OFFSET) == PCI20341_ID) - { - devpriv->ai_mod_pos = dev->iobase + i*PCI20000_OFFSET; - printk("comedi%d: module PCI-20341 opened!\n", dev->minor); - isthere = 1; - } - } - if (!isthere) - { - printk("comedi%d: module PCI-20341 not found!\n", dev->minor); + /* Check PCI-20001 C-2A Carrier Board ID */ + if ((readb(dev->iobase) & PCI20000_ID) != PCI20000_ID) { + printk("comedi%d: ii_pci20kc", dev->minor); + printk(" PCI-20001 C-2A Carrier Board at base=0x%05x not found !\n", dev->iobase); return -EINVAL; - } + } + printk("comedi%d: pci20xxx: base=0x%05x\n", dev->minor, dev->iobase); - /* look for output module PCI-20006 M-2 */ - for (i=1; i<= PCI20000_MODULES; i++) - { - if ( readb(dev->iobase+i*PCI20000_OFFSET) == PCI20006_ID) - { - devpriv->ao_mod_pos = dev->iobase + i*PCI20000_OFFSET; - printk("comedi%d: module PCI-20006 opened!\n", dev->minor); - isthere = 1; - } - } - if (!isthere) - { - printk("comedi%d: module PCI-20006 not found!\n", dev->minor); - return -EINVAL; + for (i = 0; i < PCI20000_MODULES; i++) { + s = dev->subdevices + i; + id = readb(dev->iobase + (i+1) * PCI20000_OFFSET); + s->private = devpriv->subdev_private + i; + switch(id){ + case PCI20006_ID: + pci20006_init(dev,s,it->options[2*i+2],it->options[2*i+3]); + break; + case PCI20341_ID: + pci20341_init(dev,s,it->options[2*i+2],it->options[2*i+3]); + break; + default: + printk("ii_pci20kc: unknown module code 0x%02x in slot %d: module disabled\n", + id,i); + /* fall through */ + case PCI20xxx_EMPTY_ID: + s->type = COMEDI_SUBD_UNUSED; + break; } + } +//devpriv->ai_mod_pos = dev->iobase + i * PCI20000_OFFSET; + /* initialize pci20xxx_private */ + pci20xxx_dio_init(dev,dev->subdevices + PCI20000_MODULES); - printk("comedi%d: pci20xxx: base=0x%05x\n", dev->minor, dev->iobase); + return 1; +} - dev->board_name = "pci20xxx"; +static int pci20xxx_detach(comedi_device * dev) +{ + printk("comedi%d: pci20xxx: remove\n", dev->minor); - /* initialize pci20xxx_private */ - pci20xxx_init(dev); + return 0; +} - /* options handling */ - switch (it->options[2]) /* gain */ - { - case 1: devpriv->ai_gain = 0; /* gain 1 */ - devpriv->timebase = 0x00; /* timebase ai-module */ - devpriv->settling_time = 0x58; /* settling time ai-modlue */ - break; - case 10: devpriv->ai_gain = 1; /* gain 10 */ - devpriv->timebase = 0x00; /* timebase ai-module */ - devpriv->settling_time = 0x58; /* settling time ai-modlue */ - break; - case 100: devpriv->ai_gain = 2; /* gain 100 */ - devpriv->timebase = 0x00; /* timebase ai-module */ - devpriv->settling_time = 0x93; /* settling time ai-modlue */ - break; - case 200: devpriv->ai_gain = 3; /* gain 200 */ - devpriv->timebase = 0x04; /* timebase ai-module */ - devpriv->settling_time = 0x99; /* settling time ai-modlue */ - break; - default: devpriv->ai_gain = 0; /* gain 1 */ - devpriv->timebase = 0x00; /* timebase ai-module */ - devpriv->settling_time = 0x58; /* settling time ai-modlue */ - printk("comedi%d: ai default gain = 1 !\n", dev->minor); - break; - } - switch (it->options[3]) - { - case 0: devpriv->ao_range_list[0] = &range_bipolar10; break; - case 1: devpriv->ao_range_list[0] = &range_unipolar10; break; - case 2: devpriv->ao_range_list[0] = &range_bipolar5; break; - default: devpriv->ao_range_list[0] = &range_bipolar10; break; - } - switch (it->options[4]) - { - case 0: devpriv->ao_range_list[1] = &range_bipolar10; break; - case 1: devpriv->ao_range_list[1] = &range_unipolar10; break; - case 2: devpriv->ao_range_list[1] = &range_bipolar5; break; - default: devpriv->ao_range_list[1] = &range_bipolar10; break; - } - - /* initialize the analog subdevices */ - /* ai subdevice */ - s = dev->subdevices + 0; - s->type = COMEDI_SUBD_AI; - s->subdev_flags = SDF_READABLE; - s->n_chan = 4; - s->trig[0] = pci20xxx_ai_mode0; - s->maxdata = 0xffff; - s->range_table = &range_bipolar5; - pci20xxx_ai_init(dev); +/* pci20006m */ + +static int pci20006_ao(comedi_device * dev, comedi_subdevice * s, comedi_trig * it); + +comedi_lrange *pci20006_range_list[] = { + &range_bipolar10, + &range_unipolar10, + &range_bipolar5, + &range_unipolar5 +}; + +static int pci20006_init(comedi_device * dev,comedi_subdevice *s, + int opt0,int opt1) +{ + pci20xxx_subdev_private *sdp = s->private; + + if(opt0<0 || opt0>=3)opt0=0; + if(opt1<0 || opt1>=3)opt1=0; - /* ao subdevice */ - s = dev->subdevices + 1; + sdp->pci20006.ao_range_list[0] = pci20006_range_list[opt0]; + sdp->pci20006.ao_range_list[1] = pci20006_range_list[opt1]; + + /* ao subdevice */ s->type = COMEDI_SUBD_AO; s->subdev_flags = SDF_WRITEABLE; s->n_chan = 2; - s->trig[0] = pci20xxx_ao; + s->trig[0] = pci20006_ao; s->maxdata = 0xffff; - s->range_table_list = devpriv->ao_range_list; + s->range_table_list = sdp->pci20006.ao_range_list; - /* di subdevice */ - s = dev->subdevices + 2; - s->type = COMEDI_SUBD_DI; - s->subdev_flags = SDF_READABLE; - s->n_chan = 8; /* every bit of a port is one channel */ - s->trig[0] = pci20xxx_di; - s->maxdata = 1; - s->range_table = &range_digital; - pci20xxx_di_init(dev); + return 0; +} - /* do subdevice */ - s = dev->subdevices + 3; - s->type = COMEDI_SUBD_DO; - s->subdev_flags = SDF_WRITEABLE; - s->n_chan = 8; /* every bit of a port is one channel */ - s->trig[0] = pci20xxx_do; - s->maxdata = 1; - s->state = 0; - s->range_table = &range_digital; - pci20xxx_do_init(dev); +static int pci20006_ao(comedi_device * dev, comedi_subdevice * s, comedi_trig * it) +{ + pci20xxx_subdev_private *sdp = s->private; + int hi, lo; - return 1; + lo = (it->data[0] & 0xff); + hi = ((it->data[0] >> 8) & 0xff); + + switch (CHAN) { + case 0: + writeb(lo, sdp->iobase + 0x0d); + writeb(hi, sdp->iobase + 0x0d + 1); + writeb(0x00, sdp->iobase + 0x0b); + break; + case 1: + writeb(lo, sdp->iobase + 0x15); + writeb(hi, sdp->iobase + 0x15 + 1); + writeb(0x00, sdp->iobase + 0x13); + break; + default: + printk(" comedi%d: pci20xxx: ao channel Error!\n", dev->minor); + return -EINVAL; } + return 1; +} + +/* PCI20341M */ + +static int pci20341_mode0(comedi_device * dev, comedi_subdevice * s, + comedi_trig * it); + +static int pci20341_timebase[] = { 0x00, 0x00, 0x00, 0x04 }; +static int pci20341_settling_time[] = { 0x58, 0x58, 0x93, 0x99 }; + +#ifdef SOFTWARE_SELECT_GAIN +/* use this if you want to set the AI gain in the mode0 function */ +static comedi_lrange pci20341_range = { 4, { + BIP_RANGE(5), + BIP_RANGE(0.5), + BIP_RANGE(0.05), + BIP_RANGE(0.025), +}}; +#else +static comedi_lrange range_bipolar0_5 = { 1, { BIP_RANGE(0.5) }}; +static comedi_lrange range_bipolar0_05 = { 1, { BIP_RANGE(0.05) }}; +static comedi_lrange range_bipolar0_025 = { 1, { BIP_RANGE(0.025) }}; + +static comedi_lrange *pci20341_ranges[] = { + &range_bipolar5, + &range_bipolar0_5, + &range_bipolar0_05, + &range_bipolar0_025, +}; +#endif + +static int pci20341_init(comedi_device * dev,comedi_subdevice *s, + int opt0,int opt1) +{ + pci20xxx_subdev_private *sdp = s->private; + int option = PCI20341_OPTION; /* depends on gain, trigger, repetition mode */ -static int pci20xxx_detach(comedi_device * dev) - { - printk("comedi%d: pci20xxx: remove\n", dev->minor); + /* options handling */ + if(opt0<0 || opt0>3)opt0=0; + sdp->pci20341.timebase = pci20341_timebase[opt0]; + sdp->pci20341.settling_time = pci20341_settling_time[opt0]; + + /* ai subdevice */ + s->type = COMEDI_SUBD_AI; + s->subdev_flags = SDF_READABLE; + s->n_chan = 4; + s->trig[0] = pci20341_mode0; + s->maxdata = 0xffff; + s->range_table = pci20341_ranges[opt0]; + + option = sdp->pci20341.timebase | PCI20341_REPMODE; + + writeb(0x04, sdp->iobase + 0x10); /* initialize Module */ + writeb(PCI20341_PACER, sdp->iobase + 0x01); /* set Pacer */ + writeb(option, sdp->iobase + 0x11); /* option register */ + writeb(sdp->pci20341.settling_time, sdp->iobase + 0x15); /* settling time counter */ + /* trigger not implemented */ + /* Burst mode disabled, only one channel is read */ + writeb(1, sdp->iobase + 0x13); /* write number of input channels */ return 0; +} + +static int pci20341_mode0(comedi_device * dev, comedi_subdevice * s, comedi_trig * it) +{ + pci20xxx_subdev_private *sdp = s->private; + int i = 0, j = 0; + int lo, hi; + + writeb((0x24 | (sdp->pci20341.ai_gain << 3) | CHAN), sdp->iobase + 0x80); + writeb(0x00, sdp->iobase + 0x1b); /* reset settling time counter and trigger delay counter */ + writeb(0x00, sdp->iobase + 0x19); + + i = readb(sdp->iobase + 0x04); /* generate Pacer */ + + /* data polling isn't the niciest way to get the data, I know, + * but there are only 6 cycles (mean) and it is easier than + * the whole interrupt stuff + */ + while ((i < 0x80) && j < 100) { /* poll Interrupt Flag */ + j++; + i = readb(sdp->iobase + 0x12); + } + if (j >= 100) { + printk("comedi%d: pci20xxx: AI interrupt polling exit !\n", dev->minor); + return -EINVAL; } + lo = readb(sdp->iobase + 0x02); + hi = readb(sdp->iobase + 0x03); + + it->data[0] = lo + 0x100 * hi; + + return 1; +} + +/* native DIO */ + +static void pci20xxx_dio_config(comedi_device * dev,comedi_subdevice *s); +static void pci20xxx_do(comedi_device * dev,comedi_subdevice *s); +static unsigned int pci20xxx_di(comedi_device * dev,comedi_subdevice *s); +static int pci20xxx_dio(comedi_device *dev,comedi_subdevice *s,comedi_trig *it); /* initialize pci20xxx_private */ -static int pci20xxx_init(comedi_device *dev) - { - devpriv->dio_port[0] = 0x80; - devpriv->dio_port[1] = 0x81; - devpriv->dio_port[2] = 0xc0; - devpriv->dio_port[3] = 0xc1; +static int pci20xxx_dio_init(comedi_device * dev,comedi_subdevice *s) +{ - return 0; - } + s->type = COMEDI_SUBD_DIO; + s->subdev_flags = SDF_READABLE | SDF_WRITEABLE; + s->n_chan = 32; + s->trig[0] = pci20xxx_dio; + s->maxdata = 1; + s->len_chanlist = 32; + s->range_table = &range_digital; + s->io_bits = 0; + /* XXX digital I/O lines default to input on board reset. */ + pci20xxx_dio_config(dev,s); -/* initialize digital output */ -static int pci20xxx_do_init(comedi_device *dev) - { - unsigned char port; + return 0; +} + +static int pci20xxx_dio(comedi_device *dev,comedi_subdevice *s,comedi_trig *it) +{ + int mask,data_in; + int i; + + if(it->flags & TRIG_CONFIG){ + int bits; + + for(i=0;in_chan;i++){ + mask = 1<chanlist[i]); + if(mask&0x000000ff){ + bits = 0x000000ff; + }else if(mask & 0x0000ff00){ + bits = 0x0000ff00; + }else if(mask & 0x00ff0000){ + bits = 0x00ff0000; + }else { + bits = 0xff000000; + } + if(it->data[i]){ + s->io_bits |= bits; + }else{ + s->io_bits &= ~bits; + } + } + pci20xxx_dio_config(dev,s); + }else{ + if(it->flags&TRIG_WRITE){ + do_pack(&s->state,it); - /* only ONE do port supported: port1 ! */ - switch (PCI20000_DO_PORT) - { - case 0: port = readb(dev->iobase + 0x83); - writeb( (port & 0x82)| 0x80, dev->iobase + 0x83); /* port direction */ - writeb( 0xff, dev->iobase + devpriv->dio_port[PCI20000_DO_PORT]); /* write 0xff to port */ - port = readb(dev->iobase + 0x82); - writeb( (port & 0xfe)| 0x04, dev->iobase + 0x82); /* enable port */ - break; - case 1: port = readb(dev->iobase + 0x83); - writeb( (port & 0x90)| 0x80, dev->iobase + 0x83); - writeb( 0xff, dev->iobase + devpriv->dio_port[PCI20000_DO_PORT]); - port = readb(dev->iobase + 0x82); - writeb( (port & 0xfd)| 0x08, dev->iobase + 0x82); - break; - case 2: port = readb(dev->iobase + 0xc3); - writeb( (port & 0x82)| 0x80, dev->iobase + 0xc3); - writeb( 0xff, dev->iobase + devpriv->dio_port[PCI20000_DO_PORT]); - port = readb(dev->iobase + 0x82); - writeb( (port & 0xef)| 0x40, dev->iobase + 0x82); - break; - case 3: port = readb(dev->iobase + 0xc3); - writeb( (port & 0x90)| 0x80, dev->iobase + 0xc3); - writeb( 0xff, dev->iobase + devpriv->dio_port[PCI20000_DO_PORT]); - port = readb(dev->iobase + 0x82); - writeb( (port & 0xdf)| 0x80, dev->iobase + 0x82); - break; - default: printk("comedi%d: wrong DO-port in pci20xxx_do_init()", dev->minor); - return -EINVAL; + pci20xxx_do(dev,s); + }else{ + data_in = pci20xxx_di(dev,s); + + di_unpack(data_in,it); } - writeb( 0xff, dev->iobase + devpriv->dio_port[PCI20000_DO_PORT]); - - return 0; } -/* initialize digital input */ -static int pci20xxx_di_init(comedi_device *dev) - { - unsigned char port; + return it->n_chan; +} - /* only ONE di port supported: port0 ! */ - switch (PCI20000_DI_PORT) - { - case 0: port = readb(dev->iobase + 0x83); - writeb( port|0x90, dev->iobase + 0x83); - port = readb(dev->iobase + 0x82); - writeb( port & 0xfa, dev->iobase + 0x82); - break; - case 1: port = readb(dev->iobase + 0x83); - writeb( port|0x82, dev->iobase + 0x83); - port = readb(dev->iobase + 0x82); - writeb( port & 0xf5, dev->iobase + 0x82); - break; - case 2: port = readb(dev->iobase + 0xc3); - writeb( port|0x90, dev->iobase + 0xc3); - port = readb(dev->iobase + 0x82); - writeb( port & 0xaf, dev->iobase + 0x82); - break; - case 3: port = readb(dev->iobase + 0xc3); - writeb( port|0x82, dev->iobase + 0xc3); - port = readb(dev->iobase + 0x82); - writeb( port & 0x5f, dev->iobase + 0x82); - break; - default: printk("comedi%d: wrong DI-port in pci20xxx_di_init()", dev->minor); - return -EINVAL; - } +static void pci20xxx_dio_config(comedi_device * dev,comedi_subdevice *s) +{ + /* XXX it is not clear from the d[oi]_init functions how to + configure a group of bits for input or output */ - return 0; + if(s->io_bits & 0x000000ff ){ + /* output */ + }else{ + /* input */ } + if(s->io_bits & 0x0000ff00 ){ -/* initialize analog input */ -static int pci20xxx_ai_init(comedi_device *dev) - { - int option = PCI20341_OPTION; /* depends on gain, trigger, repetition mode */ - - option = devpriv->timebase | PCI20341_REPMODE; - - writeb( 0x04, devpriv->ai_mod_pos + 0x10); /* initialize Module */ - writeb( PCI20341_PACER, devpriv->ai_mod_pos + 0x01); /* set Pacer */ - writeb( option, devpriv->ai_mod_pos + 0x11); /* option register */ - writeb( devpriv->settling_time, devpriv->ai_mod_pos + 0x15); /* settling time counter */ - /* trigger not implemented */ - /* Burst mode disabled, only one channel is read */ - writeb( CHANNEL_READ, devpriv->ai_mod_pos + 0x13); /* write number of input channels */ + }else{ - return 0; } + if(s->io_bits & 0x00ff0000 ){ + + }else{ -static int pci20xxx_ao(comedi_device *dev, comedi_subdevice *s, comedi_trig *it) - { - int hi, lo; - - lo = (it->data[0] & 0xff); - hi = ((it->data[0] >>8) & 0xff); - - switch (CHAN) - { - case 0: writeb( lo, devpriv->ao_mod_pos + 0x0d); - writeb( hi, devpriv->ao_mod_pos + 0x0d + 1); - writeb( 0x00, devpriv->ao_mod_pos + 0x0b); - break; - case 1: writeb( lo, devpriv->ao_mod_pos + 0x15); - writeb( hi, devpriv->ao_mod_pos + 0x15 + 1); - writeb( 0x00, devpriv->ao_mod_pos + 0x13); - break; - default: printk(" comedi%d: pci20xxx: ao channel Error!\n", dev->minor); - return -EINVAL; - } - return CHANNEL_WRITE; /* return value == number of written datas */ } + if(s->io_bits & 0xff000000 ){ -static int pci20xxx_do(comedi_device *dev, comedi_subdevice *s, comedi_trig *it) - { - do_pack(&s->state, it); + }else{ - writeb(s->state, dev->iobase + devpriv->dio_port[PCI20000_DO_PORT]); + } +} - return it->n_chan; +#if 0 +/* initialize digital output */ +static int pci20xxx_do_init(comedi_device * dev) +{ + unsigned char port; + + /* only ONE do port supported: port1 ! */ + switch (PCI20000_DO_PORT) { + case 0: + port = readb(dev->iobase + 0x83); + writeb((port & 0x82) | 0x80, dev->iobase + 0x83); /* port direction */ + writeb(0xff, dev->iobase + devpriv->dio_port[PCI20000_DO_PORT]); /* write 0xff to port */ + port = readb(dev->iobase + 0x82); + writeb((port & 0xfe) | 0x04, dev->iobase + 0x82); /* enable port */ + break; + case 1: + port = readb(dev->iobase + 0x83); + writeb((port & 0x90) | 0x80, dev->iobase + 0x83); + writeb(0xff, dev->iobase + devpriv->dio_port[PCI20000_DO_PORT]); + port = readb(dev->iobase + 0x82); + writeb((port & 0xfd) | 0x08, dev->iobase + 0x82); + break; + case 2: + port = readb(dev->iobase + 0xc3); + writeb((port & 0x82) | 0x80, dev->iobase + 0xc3); + writeb(0xff, dev->iobase + devpriv->dio_port[PCI20000_DO_PORT]); + port = readb(dev->iobase + 0x82); + writeb((port & 0xef) | 0x40, dev->iobase + 0x82); + break; + case 3: + port = readb(dev->iobase + 0xc3); + writeb((port & 0x90) | 0x80, dev->iobase + 0xc3); + writeb(0xff, dev->iobase + devpriv->dio_port[PCI20000_DO_PORT]); + port = readb(dev->iobase + 0x82); + writeb((port & 0xdf) | 0x80, dev->iobase + 0x82); + break; + default: + printk("comedi%d: wrong DO-port in pci20xxx_do_init()", dev->minor); + return -EINVAL; } + writeb(0xff, dev->iobase + devpriv->dio_port[PCI20000_DO_PORT]); -static int pci20xxx_ai_mode0(comedi_device *dev, comedi_subdevice *s, comedi_trig *it) - { - int i=0, - j=0; - int lo, hi; - writeb( (0x24|(devpriv->ai_gain<<3)|CHAN), devpriv->ai_mod_pos + 0x80); - writeb( 0x00, devpriv->ai_mod_pos + 0x1b); /* reset settling time counter and trigger delay counter */ - writeb( 0x00, devpriv->ai_mod_pos + 0x19); + return 0; +} - i = readb( devpriv->ai_mod_pos + 0x04); /* generate Pacer */ +/* initialize digital input */ +static int pci20xxx_di_init(comedi_device * dev) +{ + unsigned char port; - /* data polling isn't the niciest way to get the data, I know, - * but there are only 6 cycles (mean) and it is easier than - * the whole interrupt stuff - */ - while ( (i<0x80) && j<100) /* poll Interrupt Flag */ - { - j++; - i = readb(devpriv->ai_mod_pos + 0x12); - } - if (j>=100) - { - printk("comedi%d: pci20xxx: AI interrupt polling exit !\n", dev->minor); + /* only ONE di port supported: port0 ! */ + switch (PCI20000_DI_PORT) { + case 0: + port = readb(dev->iobase + 0x83); + writeb(port | 0x90, dev->iobase + 0x83); + port = readb(dev->iobase + 0x82); + writeb(port & 0xfa, dev->iobase + 0x82); + break; + case 1: + port = readb(dev->iobase + 0x83); + writeb(port | 0x82, dev->iobase + 0x83); + port = readb(dev->iobase + 0x82); + writeb(port & 0xf5, dev->iobase + 0x82); + break; + case 2: + port = readb(dev->iobase + 0xc3); + writeb(port | 0x90, dev->iobase + 0xc3); + port = readb(dev->iobase + 0x82); + writeb(port & 0xaf, dev->iobase + 0x82); + break; + case 3: + port = readb(dev->iobase + 0xc3); + writeb(port | 0x82, dev->iobase + 0xc3); + port = readb(dev->iobase + 0x82); + writeb(port & 0x5f, dev->iobase + 0x82); + break; + default: + printk("comedi%d: wrong DI-port in pci20xxx_di_init()", dev->minor); return -EINVAL; - } - lo = readb(devpriv->ai_mod_pos + 0x02); - hi = readb(devpriv->ai_mod_pos + 0x03); - - it->data[0] = lo + 0x100 * hi; - - return CHANNEL_READ; /* return value == number of read datas !!*/ - } + } -static int pci20xxx_di(comedi_device *dev, comedi_subdevice *s, comedi_trig *it) - { + return 0; +} +#endif + +static void pci20xxx_do(comedi_device * dev, comedi_subdevice * s) +{ + /* XXX if the channel is configured for input, does this + do bad things? */ + /* XXX it would be a good idea to only update the registers + that _need_ to be updated. This requires changes to + comedi, however. */ + writeb((s->state>>0)&0xff, dev->iobase + PCI20000_DIO_0 ); + writeb((s->state>>8)&0xff, dev->iobase + PCI20000_DIO_1 ); + writeb((s->state>>16)&0xff, dev->iobase + PCI20000_DIO_2 ); + writeb((s->state>>24)&0xff, dev->iobase + PCI20000_DIO_3 ); +} + +static unsigned int pci20xxx_di(comedi_device * dev, comedi_subdevice * s) +{ + /* XXX same note as above */ unsigned int bits; - - bits = readb(dev->iobase + devpriv->dio_port[PCI20000_DI_PORT]); - return di_unpack(bits, it); - } + bits = readb(dev->iobase + PCI20000_DIO_0 ); + bits |= readb(dev->iobase + PCI20000_DIO_1 )<<8; + bits |= readb(dev->iobase + PCI20000_DIO_2 )<<16; + bits |= readb(dev->iobase + PCI20000_DIO_3 )<<24; + + return bits; +} #ifdef MODULE int init_module(void) - { +{ comedi_driver_register(&driver_pci20xxx); return 0; - } +} void cleanup_module(void) - { +{ comedi_driver_unregister(&driver_pci20xxx); - } -#endif - - +} +#endif