From e0cd4af5c9494c58f6aabc9cd33a4dcc06ddd87f Mon Sep 17 00:00:00 2001 From: Frank Mori Hess Date: Wed, 20 Jun 2001 20:19:47 +0000 Subject: [PATCH] implemented insns, everything seems to work okay so far --- comedi/drivers/das16m1.c | 181 +++++++++++++++++++-------------------- 1 file changed, 89 insertions(+), 92 deletions(-) diff --git a/comedi/drivers/das16m1.c b/comedi/drivers/das16m1.c index 6bfdf595..31652edc 100644 --- a/comedi/drivers/das16m1.c +++ b/comedi/drivers/das16m1.c @@ -113,7 +113,6 @@ static int das16m1_cmd_test(comedi_device *dev,comedi_subdevice *s,comedi_cmd *c static int das16m1_cmd_exec(comedi_device *dev,comedi_subdevice *s); static int das16m1_cancel(comedi_device *dev, comedi_subdevice *s); -static void das16m1_reset(comedi_device *dev); static void das16m1_interrupt(int irq, void *d, struct pt_regs *regs); static unsigned int das16m1_set_pacer(comedi_device *dev, unsigned int ns, int round_flag); @@ -151,6 +150,7 @@ comedi_driver driver_das16m1={ struct das16m1_private_struct { unsigned int control_state; volatile unsigned int adc_count; + unsigned int do_bits; // saves status of digital output bits unsigned int divisor1; // divides master clock to obtain conversion speed unsigned int divisor2; // divides master clock to obtain conversion speed }; @@ -161,7 +161,7 @@ COMEDI_INITCLEANUP(driver_das16m1); static int das16m1_cmd_test(comedi_device *dev,comedi_subdevice *s, comedi_cmd *cmd) { - unsigned int err=0, tmp; + unsigned int err=0, tmp, i; /* make sure triggers are valid */ tmp=cmd->start_src; @@ -230,6 +230,25 @@ static int das16m1_cmd_test(comedi_device *dev,comedi_subdevice *s, comedi_cmd * err++; } } + // check chanlist agains board's peculiarities + if(cmd->chanlist_len > 1) + { + for(i = 0; i < cmd->chanlist_len; i++) + { + // even/odd channels must go into even/odd queue addresses + if((i % 2) != (CR_CHAN(cmd->chanlist[i]) % 2)) + { + comedi_error(dev, "bad chanlist:\n" + " even/odd channels must go have even/odd chanlist indices"); + err++; + } + } + if((cmd->chanlist_len % 2) != 0) + { + comedi_error(dev, "chanlist must be of even length or length 1"); + err++; + } + } if(err) return 3; @@ -243,7 +262,6 @@ static int das16m1_cmd_test(comedi_device *dev,comedi_subdevice *s, comedi_cmd * &(devpriv->divisor2), &(cmd->convert_arg), cmd->flags & TRIG_ROUND_MASK); if(tmp != cmd->convert_arg) err++; } - // XXX we need to check constraints on chanlist here if(err) return 4; @@ -264,17 +282,15 @@ static int das16m1_cmd_exec(comedi_device *dev,comedi_subdevice *s) byte = Q_CHAN(CR_CHAN(cmd->chanlist[i])) | Q_RANGE(CR_RANGE(cmd->chanlist[i])); outb(byte, dev->iobase + DAS16M1_QUEUE_DATA); } - outb(0, dev->iobase + DAS16M1_QUEUE_ADDR); /* set counter mode and counts */ das16m1_set_pacer(dev, cmd->convert_arg, cmd->flags & TRIG_ROUND_MASK); - /* clear interrupt bit */ - outb(0, dev->iobase + DAS16M1_CLEAR_INTR); - // set control & status register byte = 0; outb(byte, dev->iobase + DAS16M1_CS); + /* clear interrupt bit */ + outb(0, dev->iobase + DAS16M1_CLEAR_INTR); /* enable interrupts and internal pacer */ devpriv->control_state |= INTE | INT_PACER; outb(devpriv->control_state, dev->iobase + DAS16M1_INTR_CONTROL); @@ -284,58 +300,52 @@ static int das16m1_cmd_exec(comedi_device *dev,comedi_subdevice *s) static int das16m1_cancel(comedi_device *dev, comedi_subdevice *s) { - devpriv->adc_count = 0; devpriv->control_state &= ~INTE; devpriv->control_state &= ~PACER_MASK; outb(devpriv->control_state, dev->iobase + DAS16M1_INTR_CONTROL); + devpriv->adc_count = 0; return 0; } -#if 0 // insns haven't been converted from das16 driver yet static int das16m1_ai_rinsn(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data) { - int i,n; - int range; - int chan; - int msb,lsb; - - /* clear crap */ - inb(dev->iobase+DAS16M1_AI_LSB); - inb(dev->iobase+DAS16M1_AI_MSB); - - /* set multiplexer */ - chan = CR_CHAN(insn->chanspec); - outb_p(chan,dev->iobase+DAS16M1_MUX); - - /* set gain */ - if(thisboard->ai_pg != das16m1_pg_none){ - range = CR_RANGE(insn->chanspec); - outb((das16m1_gainlists[thisboard->ai_pg])[range], - dev->iobase+DAS16M1_GAIN); - } + int i, n; + int byte; + int data_point; + const int timeout = 1000; - /* How long should we wait for MUX to settle? */ - //udelay(5); + /* disable interrupts and internal pacer */ + devpriv->control_state &= ~INTE & ~PACER_MASK; + outb(devpriv->control_state, dev->iobase + DAS16M1_INTR_CONTROL); - for(n=0;nn;n++){ + /* setup channel/gain queue */ + outb(0, dev->iobase + DAS16M1_QUEUE_ADDR); + byte = Q_CHAN(CR_CHAN(insn->chanspec)) | Q_RANGE(CR_RANGE(insn->chanspec)); + outb(byte, dev->iobase + DAS16M1_QUEUE_DATA); + + for(n = 0; n < insn->n; n++) + { /* trigger conversion */ - outb_p(0,dev->iobase+DAS16M1_TRIG); + outb(0, dev->iobase); - for(i=0;iiobase + DAS16M1_CS) & IRQDATA) break; } - if(i==DAS16M1_TIMEOUT){ - rt_printk("das16m1: timeout\n"); + if(i == timeout) + { + comedi_error(dev, "timeout"); return -ETIME; } - msb = inb(dev->iobase + DAS16M1_AI_MSB); - lsb = inb(dev->iobase + DAS16M1_AI_LSB); - if(thisboard->ai_nbits==12){ - data[n] = (lsb>>4) | (msb << 4); - }else{ - data[n] = lsb | (msb << 8); + data_point = inw(dev->iobase); + if(thisboard->n_bits == 12) + { + data[n] = AI_DATA(data_point); + }else + { + data[n] = data_point; } } @@ -344,80 +354,64 @@ static int das16m1_ai_rinsn(comedi_device *dev,comedi_subdevice *s,comedi_insn * static int das16m1_di_rbits(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data) { - data[0]=inb(dev->iobase+DAS16M1_DIO)&0xf; + lsampl_t bits; - return 1; + bits = inb(dev->iobase + DAS16M1_DIO) & 0xf; + data[1] = bits; + data[0] = 0; + + return 2; } static int das16m1_do_wbits(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data) { - outb(data[0],dev->iobase+DAS16M1_DIO); - - return 1; -} + lsampl_t wbits; -static int das16m1_ao_winsn(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data) -{ - int i; - int lsb,msb; - int chan; - - chan=CR_CHAN(insn->chanspec); - - for(i=0;in;i++){ - if(thisboard->ao_nbits==12){ - lsb=(data[i]<<4)&0xff; - msb=(data[i]>>4)&0xff; - }else{ - lsb=data[i]&0xff; - msb=(data[i]>>8)&0xff; - } + // only set bits that have been masked + data[0] &= 0xf; + wbits = devpriv->do_bits; + // zero bits that have been masked + wbits &= ~data[0]; + // set masked bits + wbits |= data[0] & data[1]; + devpriv->do_bits = wbits; + data[1] = wbits; -#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+DAS16M1_AO_LSB(chan)); - outb(msb,dev->iobase+DAS16M1_AO_MSB(chan)); -#endif - } + outb(devpriv->do_bits, dev->iobase + DAS16M1_DIO); - return i; + return 2; } -#endif // insns haven't been converted from das16 driver yet - static void das16m1_interrupt(int irq, void *d, struct pt_regs *regs) { int i, status; sampl_t data_point; - comedi_device *dev = d; comedi_subdevice *s = dev->subdevices; - comedi_async *async = s->async; + comedi_async *async; - status = inb(dev->iobase + DAS16M1_CS); - - if((status & IRQDATA) == 0) + if(dev->attached == 0) { - comedi_error(dev, "spurious interrupt"); + comedi_error(dev, "premature interrupt"); return; } - if(dev->attached == 0) + + status = inb(dev->iobase + DAS16M1_CS); + + if((status & (IRQDATA | OVRUN)) == 0) { - comedi_error(dev, "premature interrupt"); - /* clear interrupt */ - outb(0, dev->iobase + DAS16M1_CLEAR_INTR); + comedi_error(dev, "spurious interrupt"); return; } + // initialize async here to avoid freak out on premature interrupt + async = s->async; for(i = 0; i < HALF_FIFO; i++) { - data_point = inw(dev->iobase + DAS16M1_AI); - data_point = AI_DATA(data_point); + data_point = AI_DATA(inw(dev->iobase + DAS16M1_AI)); comedi_buf_put(async, data_point); - if(--devpriv->adc_count <= 0) { /* end of acquisition */ + if(--devpriv->adc_count == 0) { /* end of acquisition */ das16m1_cancel(dev, s); async->events |= COMEDI_CB_EOA; break; @@ -428,6 +422,7 @@ static void das16m1_interrupt(int irq, void *d, struct pt_regs *regs) { das16m1_cancel(dev, s); async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR; + comedi_error(dev, "fifo overflow"); } async->events |= COMEDI_CB_BLOCK; @@ -562,7 +557,7 @@ static int das16m1_attach(comedi_device *dev, comedi_devconfig *it) s->len_chanlist = 256; s->maxdata = (1 << 12) - 1; s->range_table = &range_das16m1; -// s->insn_read = das16m1_ai_rinsn; + s->insn_read = das16m1_ai_rinsn; s->do_cmdtest = das16m1_cmd_test; s->do_cmd = das16m1_cmd_exec; s->cancel = das16m1_cancel; @@ -574,7 +569,7 @@ static int das16m1_attach(comedi_device *dev, comedi_devconfig *it) s->n_chan = 4; s->maxdata = 1; s->range_table = &range_digital; -// s->insn_bits = das16m1_di_rbits; + s->insn_bits = das16m1_di_rbits; s = dev->subdevices + 2; /* do */ @@ -583,13 +578,15 @@ static int das16m1_attach(comedi_device *dev, comedi_devconfig *it) s->n_chan = 4; s->maxdata = 1; s->range_table = &range_digital; -// s->insn_write = das16m1_do_wbits; + s->insn_bits = das16m1_do_wbits; s = dev->subdevices + 3; /* 8255 */ subdev_8255_init(dev, s, NULL, (void*)(dev->iobase + DAS16M1_82C55)); - // XXX should init digital output levels here also + // initialize digital output lines + outb(devpriv->do_bits, dev->iobase + DAS16M1_DIO); + /* set the interrupt level */ devpriv->control_state = das16m1_irq_bits(dev->irq); outb(devpriv->control_state, dev->iobase + DAS16M1_INTR_CONTROL); -- 2.26.2