Version:  2.0.40 2.2.26 2.4.37 3.9 3.10 3.11 3.12 3.13 3.14 3.15 3.16 3.17 3.18 3.19 4.0 4.1 4.2 4.3 4.4 4.5 4.6

Linux/drivers/staging/comedi/drivers/cb_pcidas.c

  1 /*
  2  * cb_pcidas.c
  3  * Developed by Ivan Martinez and Frank Mori Hess, with valuable help from
  4  * David Schleef and the rest of the Comedi developers comunity.
  5  *
  6  * Copyright (C) 2001-2003 Ivan Martinez <imr@oersted.dtu.dk>
  7  * Copyright (C) 2001,2002 Frank Mori Hess <fmhess@users.sourceforge.net>
  8  *
  9  * COMEDI - Linux Control and Measurement Device Interface
 10  * Copyright (C) 1997-8 David A. Schleef <ds@schleef.org>
 11  *
 12  * This program is free software; you can redistribute it and/or modify
 13  * it under the terms of the GNU General Public License as published by
 14  * the Free Software Foundation; either version 2 of the License, or
 15  * (at your option) any later version.
 16  *
 17  * This program is distributed in the hope that it will be useful,
 18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 20  * GNU General Public License for more details.
 21  */
 22 
 23 /*
 24  * Driver: cb_pcidas
 25  * Description: MeasurementComputing PCI-DAS series
 26  *   with the AMCC S5933 PCI controller
 27  * Devices: [Measurement Computing] PCI-DAS1602/16 (cb_pcidas),
 28  *   PCI-DAS1602/16jr, PCI-DAS1602/12, PCI-DAS1200, PCI-DAS1200jr,
 29  *   PCI-DAS1000, PCI-DAS1001, PCI_DAS1002
 30  * Author: Ivan Martinez <imr@oersted.dtu.dk>,
 31  *   Frank Mori Hess <fmhess@users.sourceforge.net>
 32  * Updated: 2003-3-11
 33  *
 34  * Status:
 35  * There are many reports of the driver being used with most of the
 36  * supported cards. Despite no detailed log is maintained, it can
 37  * be said that the driver is quite tested and stable.
 38  *
 39  * The boards may be autocalibrated using the comedi_calibrate
 40  * utility.
 41  *
 42  * Configuration options: not applicable, uses PCI auto config
 43  *
 44  * For commands, the scanned channels must be consecutive
 45  * (i.e. 4-5-6-7, 2-3-4,...), and must all have the same
 46  * range and aref.
 47  *
 48  * AI Triggering:
 49  * For start_src == TRIG_EXT, the A/D EXTERNAL TRIGGER IN (pin 45) is used.
 50  * For 1602 series, the start_arg is interpreted as follows:
 51  *      start_arg == 0                   => gated trigger (level high)
 52  *      start_arg == CR_INVERT           => gated trigger (level low)
 53  *      start_arg == CR_EDGE             => Rising edge
 54  *      start_arg == CR_EDGE | CR_INVERT => Falling edge
 55  * For the other boards the trigger will be done on rising edge
 56  */
 57 
 58 /*
 59  * TODO:
 60  * analog triggering on 1602 series
 61  */
 62 
 63 #include <linux/module.h>
 64 #include <linux/delay.h>
 65 #include <linux/interrupt.h>
 66 
 67 #include "../comedi_pci.h"
 68 
 69 #include "comedi_8254.h"
 70 #include "8255.h"
 71 #include "amcc_s5933.h"
 72 
 73 #define AI_BUFFER_SIZE          1024    /* max ai fifo size */
 74 #define AO_BUFFER_SIZE          1024    /* max ao fifo size */
 75 
 76 /*
 77  * PCI BAR1 Register map (devpriv->pcibar1)
 78  */
 79 #define PCIDAS_CTRL_REG         0x00    /* INTERRUPT / ADC FIFO register */
 80 #define PCIDAS_CTRL_INT(x)      (((x) & 0x3) << 0)
 81 #define PCIDAS_CTRL_INT_NONE    PCIDAS_CTRL_INT(0) /* no int selected */
 82 #define PCIDAS_CTRL_INT_EOS     PCIDAS_CTRL_INT(1) /* int on end of scan */
 83 #define PCIDAS_CTRL_INT_FHF     PCIDAS_CTRL_INT(2) /* int on fifo half full */
 84 #define PCIDAS_CTRL_INT_FNE     PCIDAS_CTRL_INT(3) /* int on fifo not empty */
 85 #define PCIDAS_CTRL_INT_MASK    PCIDAS_CTRL_INT(3) /* mask of int select bits */
 86 #define PCIDAS_CTRL_INTE        BIT(2)  /* int enable */
 87 #define PCIDAS_CTRL_DAHFIE      BIT(3)  /* dac half full int enable */
 88 #define PCIDAS_CTRL_EOAIE       BIT(4)  /* end of acq. int enable */
 89 #define PCIDAS_CTRL_DAHFI       BIT(5)  /* dac half full status / clear */
 90 #define PCIDAS_CTRL_EOAI        BIT(6)  /* end of acq. int status / clear */
 91 #define PCIDAS_CTRL_INT_CLR     BIT(7)  /* int status / clear */
 92 #define PCIDAS_CTRL_EOBI        BIT(9)  /* end of burst int status */
 93 #define PCIDAS_CTRL_ADHFI       BIT(10) /* half-full int status */
 94 #define PCIDAS_CTRL_ADNEI       BIT(11) /* fifo not empty int status (latch) */
 95 #define PCIDAS_CTRL_ADNE        BIT(12) /* fifo not empty status (realtime) */
 96 #define PCIDAS_CTRL_DAEMIE      BIT(12) /* dac empty int enable */
 97 #define PCIDAS_CTRL_LADFUL      BIT(13) /* fifo overflow / clear */
 98 #define PCIDAS_CTRL_DAEMI       BIT(14) /* dac fifo empty int status / clear */
 99 
100 #define PCIDAS_CTRL_AI_INT      (PCIDAS_CTRL_EOAI | PCIDAS_CTRL_EOBI |   \
101                                  PCIDAS_CTRL_ADHFI | PCIDAS_CTRL_ADNEI | \
102                                  PCIDAS_CTRL_LADFUL)
103 #define PCIDAS_CTRL_AO_INT      (PCIDAS_CTRL_DAHFI | PCIDAS_CTRL_DAEMI)
104 
105 #define PCIDAS_AI_REG           0x02    /* ADC CHANNEL MUX AND CONTROL reg */
106 #define PCIDAS_AI_FIRST(x)      ((x) & 0xf)
107 #define PCIDAS_AI_LAST(x)       (((x) & 0xf) << 4)
108 #define PCIDAS_AI_CHAN(x)       (PCIDAS_AI_FIRST(x) | PCIDAS_AI_LAST(x))
109 #define PCIDAS_AI_GAIN(x)       (((x) & 0x3) << 8)
110 #define PCIDAS_AI_SE            BIT(10) /* Inputs in single-ended mode */
111 #define PCIDAS_AI_UNIP          BIT(11) /* Analog front-end unipolar mode */
112 #define PCIDAS_AI_PACER(x)      (((x) & 0x3) << 12)
113 #define PCIDAS_AI_PACER_SW      PCIDAS_AI_PACER(0) /* software pacer */
114 #define PCIDAS_AI_PACER_INT     PCIDAS_AI_PACER(1) /* int. pacer */
115 #define PCIDAS_AI_PACER_EXTN    PCIDAS_AI_PACER(2) /* ext. falling edge */
116 #define PCIDAS_AI_PACER_EXTP    PCIDAS_AI_PACER(3) /* ext. rising edge */
117 #define PCIDAS_AI_PACER_MASK    PCIDAS_AI_PACER(3) /* pacer source bits */
118 #define PCIDAS_AI_EOC           BIT(14) /* adc not busy */
119 
120 #define PCIDAS_TRIG_REG         0x04    /* TRIGGER CONTROL/STATUS register */
121 #define PCIDAS_TRIG_SEL(x)      (((x) & 0x3) << 0)
122 #define PCIDAS_TRIG_SEL_NONE    PCIDAS_TRIG_SEL(0) /* no start trigger */
123 #define PCIDAS_TRIG_SEL_SW      PCIDAS_TRIG_SEL(1) /* software start trigger */
124 #define PCIDAS_TRIG_SEL_EXT     PCIDAS_TRIG_SEL(2) /* ext. start trigger */
125 #define PCIDAS_TRIG_SEL_ANALOG  PCIDAS_TRIG_SEL(3) /* ext. analog trigger */
126 #define PCIDAS_TRIG_SEL_MASK    PCIDAS_TRIG_SEL(3) /* start trigger mask */
127 #define PCIDAS_TRIG_POL         BIT(2)  /* invert trigger (1602 only) */
128 #define PCIDAS_TRIG_MODE        BIT(3)  /* edge/level trigerred (1602 only) */
129 #define PCIDAS_TRIG_EN          BIT(4)  /* enable external start trigger */
130 #define PCIDAS_TRIG_BURSTE      BIT(5)  /* burst mode enable */
131 #define PCIDAS_TRIG_CLR         BIT(7)  /* clear external trigger */
132 
133 #define PCIDAS_CALIB_REG        0x06    /* CALIBRATION register */
134 #define PCIDAS_CALIB_8800_SEL   BIT(8)  /* select 8800 caldac */
135 #define PCIDAS_CALIB_TRIM_SEL   BIT(9)  /* select ad7376 trim pot */
136 #define PCIDAS_CALIB_DAC08_SEL  BIT(10) /* select dac08 caldac */
137 #define PCIDAS_CALIB_SRC(x)     (((x) & 0x7) << 11)
138 #define PCIDAS_CALIB_EN         BIT(14) /* calibration source enable */
139 #define PCIDAS_CALIB_DATA       BIT(15) /* serial data bit going to caldac */
140 
141 #define PCIDAS_AO_REG           0x08    /* dac control and status register */
142 #define PCIDAS_AO_EMPTY         BIT(0)  /* fifo empty, write clear (1602) */
143 #define PCIDAS_AO_DACEN         BIT(1)  /* dac enable */
144 #define PCIDAS_AO_START         BIT(2)  /* start/arm fifo (1602) */
145 #define PCIDAS_AO_PACER(x)      (((x) & 0x3) << 3) /* (1602) */
146 #define PCIDAS_AO_PACER_SW      PCIDAS_AO_PACER(0) /* software pacer */
147 #define PCIDAS_AO_PACER_INT     PCIDAS_AO_PACER(1) /* int. pacer */
148 #define PCIDAS_AO_PACER_EXTN    PCIDAS_AO_PACER(2) /* ext. falling edge */
149 #define PCIDAS_AO_PACER_EXTP    PCIDAS_AO_PACER(3) /* ext. rising edge */
150 #define PCIDAS_AO_PACER_MASK    PCIDAS_AO_PACER(3) /* pacer source bits */
151 #define PCIDAS_AO_CHAN_EN(c)    BIT(5 + ((c) & 0x1))
152 #define PCIDAS_AO_CHAN_MASK     (PCIDAS_AO_CHAN_EN(0) | PCIDAS_AO_CHAN_EN(1))
153 #define PCIDAS_AO_UPDATE_BOTH   BIT(7)  /* update both dacs */
154 #define PCIDAS_AO_RANGE(c, r)   (((r) & 0x3) << (8 + 2 * ((c) & 0x1)))
155 #define PCIDAS_AO_RANGE_MASK(c) PCIDAS_AO_RANGE((c), 0x3)
156 
157 /*
158  * PCI BAR2 Register map (devpriv->pcibar2)
159  */
160 #define PCIDAS_AI_DATA_REG      0x00
161 #define PCIDAS_AI_FIFO_CLR_REG  0x02
162 
163 /*
164  * PCI BAR3 Register map (dev->iobase)
165  */
166 #define PCIDAS_AI_8254_BASE     0x00
167 #define PCIDAS_8255_BASE        0x04
168 #define PCIDAS_AO_8254_BASE     0x08
169 
170 /*
171  * PCI BAR4 Register map (devpriv->pcibar4)
172  */
173 #define PCIDAS_AO_DATA_REG(x)   (0x00 + ((x) * 2))
174 #define PCIDAS_AO_FIFO_REG      0x00
175 #define PCIDAS_AO_FIFO_CLR_REG  0x02
176 
177 /* analog input ranges for most boards */
178 static const struct comedi_lrange cb_pcidas_ranges = {
179         8, {
180                 BIP_RANGE(10),
181                 BIP_RANGE(5),
182                 BIP_RANGE(2.5),
183                 BIP_RANGE(1.25),
184                 UNI_RANGE(10),
185                 UNI_RANGE(5),
186                 UNI_RANGE(2.5),
187                 UNI_RANGE(1.25)
188         }
189 };
190 
191 /* pci-das1001 input ranges */
192 static const struct comedi_lrange cb_pcidas_alt_ranges = {
193         8, {
194                 BIP_RANGE(10),
195                 BIP_RANGE(1),
196                 BIP_RANGE(0.1),
197                 BIP_RANGE(0.01),
198                 UNI_RANGE(10),
199                 UNI_RANGE(1),
200                 UNI_RANGE(0.1),
201                 UNI_RANGE(0.01)
202         }
203 };
204 
205 /* analog output ranges */
206 static const struct comedi_lrange cb_pcidas_ao_ranges = {
207         4, {
208                 BIP_RANGE(5),
209                 BIP_RANGE(10),
210                 UNI_RANGE(5),
211                 UNI_RANGE(10)
212         }
213 };
214 
215 enum cb_pcidas_boardid {
216         BOARD_PCIDAS1602_16,
217         BOARD_PCIDAS1200,
218         BOARD_PCIDAS1602_12,
219         BOARD_PCIDAS1200_JR,
220         BOARD_PCIDAS1602_16_JR,
221         BOARD_PCIDAS1000,
222         BOARD_PCIDAS1001,
223         BOARD_PCIDAS1002,
224 };
225 
226 struct cb_pcidas_board {
227         const char *name;
228         int ai_speed;           /*  fastest conversion period in ns */
229         int ao_scan_speed;      /*  analog output scan speed for 1602 series */
230         int fifo_size;          /*  number of samples fifo can hold */
231         unsigned int is_16bit;          /* ai/ao is 1=16-bit; 0=12-bit */
232         unsigned int use_alt_range:1;   /* use alternate ai range table */
233         unsigned int has_ao:1;          /* has 2 analog output channels */
234         unsigned int has_ao_fifo:1;     /* analog output has fifo */
235         unsigned int has_ad8402:1;      /* trimpot type 1=AD8402; 0=AD7376 */
236         unsigned int has_dac08:1;
237         unsigned int is_1602:1;
238 };
239 
240 static const struct cb_pcidas_board cb_pcidas_boards[] = {
241         [BOARD_PCIDAS1602_16] = {
242                 .name           = "pci-das1602/16",
243                 .ai_speed       = 5000,
244                 .ao_scan_speed  = 10000,
245                 .fifo_size      = 512,
246                 .is_16bit       = 1,
247                 .has_ao         = 1,
248                 .has_ao_fifo    = 1,
249                 .has_ad8402     = 1,
250                 .has_dac08      = 1,
251                 .is_1602        = 1,
252         },
253         [BOARD_PCIDAS1200] = {
254                 .name           = "pci-das1200",
255                 .ai_speed       = 3200,
256                 .fifo_size      = 1024,
257                 .has_ao         = 1,
258         },
259         [BOARD_PCIDAS1602_12] = {
260                 .name           = "pci-das1602/12",
261                 .ai_speed       = 3200,
262                 .ao_scan_speed  = 4000,
263                 .fifo_size      = 1024,
264                 .has_ao         = 1,
265                 .has_ao_fifo    = 1,
266                 .is_1602        = 1,
267         },
268         [BOARD_PCIDAS1200_JR] = {
269                 .name           = "pci-das1200/jr",
270                 .ai_speed       = 3200,
271                 .fifo_size      = 1024,
272         },
273         [BOARD_PCIDAS1602_16_JR] = {
274                 .name           = "pci-das1602/16/jr",
275                 .ai_speed       = 5000,
276                 .fifo_size      = 512,
277                 .is_16bit       = 1,
278                 .has_ad8402     = 1,
279                 .has_dac08      = 1,
280                 .is_1602        = 1,
281         },
282         [BOARD_PCIDAS1000] = {
283                 .name           = "pci-das1000",
284                 .ai_speed       = 4000,
285                 .fifo_size      = 1024,
286         },
287         [BOARD_PCIDAS1001] = {
288                 .name           = "pci-das1001",
289                 .ai_speed       = 6800,
290                 .fifo_size      = 1024,
291                 .use_alt_range  = 1,
292                 .has_ao         = 1,
293         },
294         [BOARD_PCIDAS1002] = {
295                 .name           = "pci-das1002",
296                 .ai_speed       = 6800,
297                 .fifo_size      = 1024,
298                 .has_ao         = 1,
299         },
300 };
301 
302 struct cb_pcidas_private {
303         struct comedi_8254 *ao_pacer;
304         /* base addresses */
305         unsigned long amcc;     /* pcibar0 */
306         unsigned long pcibar1;
307         unsigned long pcibar2;
308         unsigned long pcibar4;
309         /* bits to write to registers */
310         unsigned int ctrl;
311         unsigned int amcc_intcsr;
312         unsigned int ao_ctrl;
313         /* fifo buffers */
314         unsigned short ai_buffer[AI_BUFFER_SIZE];
315         unsigned short ao_buffer[AO_BUFFER_SIZE];
316         unsigned int calib_src;
317 };
318 
319 static int cb_pcidas_ai_eoc(struct comedi_device *dev,
320                             struct comedi_subdevice *s,
321                             struct comedi_insn *insn,
322                             unsigned long context)
323 {
324         struct cb_pcidas_private *devpriv = dev->private;
325         unsigned int status;
326 
327         status = inw(devpriv->pcibar1 + PCIDAS_AI_REG);
328         if (status & PCIDAS_AI_EOC)
329                 return 0;
330         return -EBUSY;
331 }
332 
333 static int cb_pcidas_ai_insn_read(struct comedi_device *dev,
334                                   struct comedi_subdevice *s,
335                                   struct comedi_insn *insn,
336                                   unsigned int *data)
337 {
338         struct cb_pcidas_private *devpriv = dev->private;
339         unsigned int chan = CR_CHAN(insn->chanspec);
340         unsigned int range = CR_RANGE(insn->chanspec);
341         unsigned int aref = CR_AREF(insn->chanspec);
342         unsigned int bits;
343         int ret;
344         int n;
345 
346         /* enable calibration input if appropriate */
347         if (insn->chanspec & CR_ALT_SOURCE) {
348                 outw(PCIDAS_CALIB_EN | PCIDAS_CALIB_SRC(devpriv->calib_src),
349                      devpriv->pcibar1 + PCIDAS_CALIB_REG);
350                 chan = 0;
351         } else {
352                 outw(0, devpriv->pcibar1 + PCIDAS_CALIB_REG);
353         }
354 
355         /* set mux limits and gain */
356         bits = PCIDAS_AI_CHAN(chan) | PCIDAS_AI_GAIN(range);
357         /* set unipolar/bipolar */
358         if (comedi_range_is_unipolar(s, range))
359                 bits |= PCIDAS_AI_UNIP;
360         /* set single-ended/differential */
361         if (aref != AREF_DIFF)
362                 bits |= PCIDAS_AI_SE;
363         outw(bits, devpriv->pcibar1 + PCIDAS_AI_REG);
364 
365         /* clear fifo */
366         outw(0, devpriv->pcibar2 + PCIDAS_AI_FIFO_CLR_REG);
367 
368         /* convert n samples */
369         for (n = 0; n < insn->n; n++) {
370                 /* trigger conversion */
371                 outw(0, devpriv->pcibar2 + PCIDAS_AI_DATA_REG);
372 
373                 /* wait for conversion to end */
374                 ret = comedi_timeout(dev, s, insn, cb_pcidas_ai_eoc, 0);
375                 if (ret)
376                         return ret;
377 
378                 /* read data */
379                 data[n] = inw(devpriv->pcibar2 + PCIDAS_AI_DATA_REG);
380         }
381 
382         /* return the number of samples read/written */
383         return n;
384 }
385 
386 static int cb_pcidas_ai_insn_config(struct comedi_device *dev,
387                                     struct comedi_subdevice *s,
388                                     struct comedi_insn *insn,
389                                     unsigned int *data)
390 {
391         struct cb_pcidas_private *devpriv = dev->private;
392         int id = data[0];
393         unsigned int source = data[1];
394 
395         switch (id) {
396         case INSN_CONFIG_ALT_SOURCE:
397                 if (source >= 8) {
398                         dev_err(dev->class_dev,
399                                 "invalid calibration source: %i\n",
400                                 source);
401                         return -EINVAL;
402                 }
403                 devpriv->calib_src = source;
404                 break;
405         default:
406                 return -EINVAL;
407         }
408         return insn->n;
409 }
410 
411 /* analog output insn for pcidas-1000 and 1200 series */
412 static int cb_pcidas_ao_nofifo_insn_write(struct comedi_device *dev,
413                                           struct comedi_subdevice *s,
414                                           struct comedi_insn *insn,
415                                           unsigned int *data)
416 {
417         struct cb_pcidas_private *devpriv = dev->private;
418         unsigned int chan = CR_CHAN(insn->chanspec);
419         unsigned int range = CR_RANGE(insn->chanspec);
420         unsigned int val = s->readback[chan];
421         unsigned long flags;
422         int i;
423 
424         /* set channel and range */
425         spin_lock_irqsave(&dev->spinlock, flags);
426         devpriv->ao_ctrl &= ~(PCIDAS_AO_UPDATE_BOTH |
427                               PCIDAS_AO_RANGE_MASK(chan));
428         devpriv->ao_ctrl |= PCIDAS_AO_DACEN | PCIDAS_AO_RANGE(chan, range);
429         outw(devpriv->ao_ctrl, devpriv->pcibar1 + PCIDAS_AO_REG);
430         spin_unlock_irqrestore(&dev->spinlock, flags);
431 
432         for (i = 0; i < insn->n; i++) {
433                 val = data[i];
434                 outw(val, devpriv->pcibar4 + PCIDAS_AO_DATA_REG(chan));
435         }
436 
437         s->readback[chan] = val;
438 
439         return insn->n;
440 }
441 
442 /* analog output insn for pcidas-1602 series */
443 static int cb_pcidas_ao_fifo_insn_write(struct comedi_device *dev,
444                                         struct comedi_subdevice *s,
445                                         struct comedi_insn *insn,
446                                         unsigned int *data)
447 {
448         struct cb_pcidas_private *devpriv = dev->private;
449         unsigned int chan = CR_CHAN(insn->chanspec);
450         unsigned int range = CR_RANGE(insn->chanspec);
451         unsigned int val = s->readback[chan];
452         unsigned long flags;
453         int i;
454 
455         /* clear dac fifo */
456         outw(0, devpriv->pcibar4 + PCIDAS_AO_FIFO_CLR_REG);
457 
458         /* set channel and range */
459         spin_lock_irqsave(&dev->spinlock, flags);
460         devpriv->ao_ctrl &= ~(PCIDAS_AO_CHAN_MASK | PCIDAS_AO_RANGE_MASK(chan) |
461                               PCIDAS_AO_PACER_MASK);
462         devpriv->ao_ctrl |= PCIDAS_AO_DACEN | PCIDAS_AO_RANGE(chan, range) |
463                             PCIDAS_AO_CHAN_EN(chan) | PCIDAS_AO_START;
464         outw(devpriv->ao_ctrl, devpriv->pcibar1 + PCIDAS_AO_REG);
465         spin_unlock_irqrestore(&dev->spinlock, flags);
466 
467         for (i = 0; i < insn->n; i++) {
468                 val = data[i];
469                 outw(val, devpriv->pcibar4 + PCIDAS_AO_FIFO_REG);
470         }
471 
472         s->readback[chan] = val;
473 
474         return insn->n;
475 }
476 
477 static int cb_pcidas_eeprom_ready(struct comedi_device *dev,
478                                   struct comedi_subdevice *s,
479                                   struct comedi_insn *insn,
480                                   unsigned long context)
481 {
482         struct cb_pcidas_private *devpriv = dev->private;
483         unsigned int status;
484 
485         status = inb(devpriv->amcc + AMCC_OP_REG_MCSR_NVCMD);
486         if ((status & MCSR_NV_BUSY) == 0)
487                 return 0;
488         return -EBUSY;
489 }
490 
491 static int cb_pcidas_eeprom_insn_read(struct comedi_device *dev,
492                                       struct comedi_subdevice *s,
493                                       struct comedi_insn *insn,
494                                       unsigned int *data)
495 {
496         struct cb_pcidas_private *devpriv = dev->private;
497         unsigned int chan = CR_CHAN(insn->chanspec);
498         int ret;
499         int i;
500 
501         for (i = 0; i < insn->n; i++) {
502                 /* make sure eeprom is ready */
503                 ret = comedi_timeout(dev, s, insn, cb_pcidas_eeprom_ready, 0);
504                 if (ret)
505                         return ret;
506 
507                 /* set address (chan) and read operation */
508                 outb(MCSR_NV_ENABLE | MCSR_NV_LOAD_LOW_ADDR,
509                      devpriv->amcc + AMCC_OP_REG_MCSR_NVCMD);
510                 outb(chan & 0xff, devpriv->amcc + AMCC_OP_REG_MCSR_NVDATA);
511                 outb(MCSR_NV_ENABLE | MCSR_NV_LOAD_HIGH_ADDR,
512                      devpriv->amcc + AMCC_OP_REG_MCSR_NVCMD);
513                 outb((chan >> 8) & 0xff,
514                      devpriv->amcc + AMCC_OP_REG_MCSR_NVDATA);
515                 outb(MCSR_NV_ENABLE | MCSR_NV_READ,
516                      devpriv->amcc + AMCC_OP_REG_MCSR_NVCMD);
517 
518                 /* wait for data to be returned */
519                 ret = comedi_timeout(dev, s, insn, cb_pcidas_eeprom_ready, 0);
520                 if (ret)
521                         return ret;
522 
523                 data[i] = inb(devpriv->amcc + AMCC_OP_REG_MCSR_NVDATA);
524         }
525 
526         return insn->n;
527 }
528 
529 static void cb_pcidas_calib_write(struct comedi_device *dev,
530                                   unsigned int val, unsigned int len,
531                                   bool trimpot)
532 {
533         struct cb_pcidas_private *devpriv = dev->private;
534         unsigned int calib_bits;
535         unsigned int bit;
536 
537         calib_bits = PCIDAS_CALIB_EN | PCIDAS_CALIB_SRC(devpriv->calib_src);
538         if (trimpot) {
539                 /* select trimpot */
540                 calib_bits |= PCIDAS_CALIB_TRIM_SEL;
541                 outw(calib_bits, devpriv->pcibar1 + PCIDAS_CALIB_REG);
542         }
543 
544         /* write bitstream to calibration device */
545         for (bit = 1 << (len - 1); bit; bit >>= 1) {
546                 if (val & bit)
547                         calib_bits |= PCIDAS_CALIB_DATA;
548                 else
549                         calib_bits &= ~PCIDAS_CALIB_DATA;
550                 udelay(1);
551                 outw(calib_bits, devpriv->pcibar1 + PCIDAS_CALIB_REG);
552         }
553         udelay(1);
554 
555         calib_bits = PCIDAS_CALIB_EN | PCIDAS_CALIB_SRC(devpriv->calib_src);
556 
557         if (!trimpot) {
558                 /* select caldac */
559                 outw(calib_bits | PCIDAS_CALIB_8800_SEL,
560                      devpriv->pcibar1 + PCIDAS_CALIB_REG);
561                 udelay(1);
562         }
563 
564         /* latch value to trimpot/caldac */
565         outw(calib_bits, devpriv->pcibar1 + PCIDAS_CALIB_REG);
566 }
567 
568 static int cb_pcidas_caldac_insn_write(struct comedi_device *dev,
569                                        struct comedi_subdevice *s,
570                                        struct comedi_insn *insn,
571                                        unsigned int *data)
572 {
573         unsigned int chan = CR_CHAN(insn->chanspec);
574 
575         if (insn->n) {
576                 unsigned int val = data[insn->n - 1];
577 
578                 if (s->readback[chan] != val) {
579                         /* write 11-bit channel/value to caldac */
580                         cb_pcidas_calib_write(dev, (chan << 8) | val, 11,
581                                               false);
582                         s->readback[chan] = val;
583                 }
584         }
585 
586         return insn->n;
587 }
588 
589 static void cb_pcidas_dac08_write(struct comedi_device *dev, unsigned int val)
590 {
591         struct cb_pcidas_private *devpriv = dev->private;
592 
593         val |= PCIDAS_CALIB_EN | PCIDAS_CALIB_SRC(devpriv->calib_src);
594 
595         /* latch the new value into the caldac */
596         outw(val, devpriv->pcibar1 + PCIDAS_CALIB_REG);
597         udelay(1);
598         outw(val | PCIDAS_CALIB_DAC08_SEL,
599              devpriv->pcibar1 + PCIDAS_CALIB_REG);
600         udelay(1);
601         outw(val, devpriv->pcibar1 + PCIDAS_CALIB_REG);
602         udelay(1);
603 }
604 
605 static int cb_pcidas_dac08_insn_write(struct comedi_device *dev,
606                                       struct comedi_subdevice *s,
607                                       struct comedi_insn *insn,
608                                       unsigned int *data)
609 {
610         unsigned int chan = CR_CHAN(insn->chanspec);
611 
612         if (insn->n) {
613                 unsigned int val = data[insn->n - 1];
614 
615                 if (s->readback[chan] != val) {
616                         cb_pcidas_dac08_write(dev, val);
617                         s->readback[chan] = val;
618                 }
619         }
620 
621         return insn->n;
622 }
623 
624 static void cb_pcidas_trimpot_write(struct comedi_device *dev,
625                                     unsigned int chan, unsigned int val)
626 {
627         const struct cb_pcidas_board *board = dev->board_ptr;
628 
629         if (board->has_ad8402) {
630                 /* write 10-bit channel/value to AD8402 trimpot */
631                 cb_pcidas_calib_write(dev, (chan << 8) | val, 10, true);
632         } else {
633                 /* write 7-bit value to AD7376 trimpot */
634                 cb_pcidas_calib_write(dev, val, 7, true);
635         }
636 }
637 
638 static int cb_pcidas_trimpot_insn_write(struct comedi_device *dev,
639                                         struct comedi_subdevice *s,
640                                         struct comedi_insn *insn,
641                                         unsigned int *data)
642 {
643         unsigned int chan = CR_CHAN(insn->chanspec);
644 
645         if (insn->n) {
646                 unsigned int val = data[insn->n - 1];
647 
648                 if (s->readback[chan] != val) {
649                         cb_pcidas_trimpot_write(dev, chan, val);
650                         s->readback[chan] = val;
651                 }
652         }
653 
654         return insn->n;
655 }
656 
657 static int cb_pcidas_ai_check_chanlist(struct comedi_device *dev,
658                                        struct comedi_subdevice *s,
659                                        struct comedi_cmd *cmd)
660 {
661         unsigned int chan0 = CR_CHAN(cmd->chanlist[0]);
662         unsigned int range0 = CR_RANGE(cmd->chanlist[0]);
663         int i;
664 
665         for (i = 1; i < cmd->chanlist_len; i++) {
666                 unsigned int chan = CR_CHAN(cmd->chanlist[i]);
667                 unsigned int range = CR_RANGE(cmd->chanlist[i]);
668 
669                 if (chan != (chan0 + i) % s->n_chan) {
670                         dev_dbg(dev->class_dev,
671                                 "entries in chanlist must be consecutive channels, counting upwards\n");
672                         return -EINVAL;
673                 }
674 
675                 if (range != range0) {
676                         dev_dbg(dev->class_dev,
677                                 "entries in chanlist must all have the same gain\n");
678                         return -EINVAL;
679                 }
680         }
681         return 0;
682 }
683 
684 static int cb_pcidas_ai_cmdtest(struct comedi_device *dev,
685                                 struct comedi_subdevice *s,
686                                 struct comedi_cmd *cmd)
687 {
688         const struct cb_pcidas_board *board = dev->board_ptr;
689         int err = 0;
690         unsigned int arg;
691 
692         /* Step 1 : check if triggers are trivially valid */
693 
694         err |= comedi_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_EXT);
695         err |= comedi_check_trigger_src(&cmd->scan_begin_src,
696                                         TRIG_FOLLOW | TRIG_TIMER | TRIG_EXT);
697         err |= comedi_check_trigger_src(&cmd->convert_src,
698                                         TRIG_TIMER | TRIG_NOW | TRIG_EXT);
699         err |= comedi_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
700         err |= comedi_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE);
701 
702         if (err)
703                 return 1;
704 
705         /* Step 2a : make sure trigger sources are unique */
706 
707         err |= comedi_check_trigger_is_unique(cmd->start_src);
708         err |= comedi_check_trigger_is_unique(cmd->scan_begin_src);
709         err |= comedi_check_trigger_is_unique(cmd->convert_src);
710         err |= comedi_check_trigger_is_unique(cmd->stop_src);
711 
712         /* Step 2b : and mutually compatible */
713 
714         if (cmd->scan_begin_src == TRIG_FOLLOW && cmd->convert_src == TRIG_NOW)
715                 err |= -EINVAL;
716         if (cmd->scan_begin_src != TRIG_FOLLOW && cmd->convert_src != TRIG_NOW)
717                 err |= -EINVAL;
718         if (cmd->start_src == TRIG_EXT &&
719             (cmd->convert_src == TRIG_EXT || cmd->scan_begin_src == TRIG_EXT))
720                 err |= -EINVAL;
721 
722         if (err)
723                 return 2;
724 
725         /* Step 3: check if arguments are trivially valid */
726 
727         switch (cmd->start_src) {
728         case TRIG_NOW:
729                 err |= comedi_check_trigger_arg_is(&cmd->start_arg, 0);
730                 break;
731         case TRIG_EXT:
732                 /* External trigger, only CR_EDGE and CR_INVERT flags allowed */
733                 if ((cmd->start_arg
734                      & (CR_FLAGS_MASK & ~(CR_EDGE | CR_INVERT))) != 0) {
735                         cmd->start_arg &= ~(CR_FLAGS_MASK &
736                                                 ~(CR_EDGE | CR_INVERT));
737                         err |= -EINVAL;
738                 }
739                 if (!board->is_1602 && (cmd->start_arg & CR_INVERT)) {
740                         cmd->start_arg &= (CR_FLAGS_MASK & ~CR_INVERT);
741                         err |= -EINVAL;
742                 }
743                 break;
744         }
745 
746         if (cmd->scan_begin_src == TRIG_TIMER) {
747                 err |= comedi_check_trigger_arg_min(&cmd->scan_begin_arg,
748                                                     board->ai_speed *
749                                                     cmd->chanlist_len);
750         }
751 
752         if (cmd->convert_src == TRIG_TIMER) {
753                 err |= comedi_check_trigger_arg_min(&cmd->convert_arg,
754                                                     board->ai_speed);
755         }
756 
757         err |= comedi_check_trigger_arg_is(&cmd->scan_end_arg,
758                                            cmd->chanlist_len);
759 
760         if (cmd->stop_src == TRIG_COUNT)
761                 err |= comedi_check_trigger_arg_min(&cmd->stop_arg, 1);
762         else    /* TRIG_NONE */
763                 err |= comedi_check_trigger_arg_is(&cmd->stop_arg, 0);
764 
765         if (err)
766                 return 3;
767 
768         /* step 4: fix up any arguments */
769 
770         if (cmd->scan_begin_src == TRIG_TIMER) {
771                 arg = cmd->scan_begin_arg;
772                 comedi_8254_cascade_ns_to_timer(dev->pacer, &arg, cmd->flags);
773                 err |= comedi_check_trigger_arg_is(&cmd->scan_begin_arg, arg);
774         }
775         if (cmd->convert_src == TRIG_TIMER) {
776                 arg = cmd->convert_arg;
777                 comedi_8254_cascade_ns_to_timer(dev->pacer, &arg, cmd->flags);
778                 err |= comedi_check_trigger_arg_is(&cmd->convert_arg, arg);
779         }
780 
781         if (err)
782                 return 4;
783 
784         /* Step 5: check channel list if it exists */
785         if (cmd->chanlist && cmd->chanlist_len > 0)
786                 err |= cb_pcidas_ai_check_chanlist(dev, s, cmd);
787 
788         if (err)
789                 return 5;
790 
791         return 0;
792 }
793 
794 static int cb_pcidas_ai_cmd(struct comedi_device *dev,
795                             struct comedi_subdevice *s)
796 {
797         const struct cb_pcidas_board *board = dev->board_ptr;
798         struct cb_pcidas_private *devpriv = dev->private;
799         struct comedi_async *async = s->async;
800         struct comedi_cmd *cmd = &async->cmd;
801         unsigned int range0 = CR_RANGE(cmd->chanlist[0]);
802         unsigned int bits;
803         unsigned long flags;
804 
805         /*  make sure PCIDAS_CALIB_EN is disabled */
806         outw(0, devpriv->pcibar1 + PCIDAS_CALIB_REG);
807         /*  initialize before settings pacer source and count values */
808         outw(PCIDAS_TRIG_SEL_NONE, devpriv->pcibar1 + PCIDAS_TRIG_REG);
809         /*  clear fifo */
810         outw(0, devpriv->pcibar2 + PCIDAS_AI_FIFO_CLR_REG);
811 
812         /*  set mux limits, gain and pacer source */
813         bits = PCIDAS_AI_FIRST(CR_CHAN(cmd->chanlist[0])) |
814                PCIDAS_AI_LAST(CR_CHAN(cmd->chanlist[cmd->chanlist_len - 1])) |
815                PCIDAS_AI_GAIN(range0);
816         /*  set unipolar/bipolar */
817         if (comedi_range_is_unipolar(s, range0))
818                 bits |= PCIDAS_AI_UNIP;
819         /*  set singleended/differential */
820         if (CR_AREF(cmd->chanlist[0]) != AREF_DIFF)
821                 bits |= PCIDAS_AI_SE;
822         /*  set pacer source */
823         if (cmd->convert_src == TRIG_EXT || cmd->scan_begin_src == TRIG_EXT)
824                 bits |= PCIDAS_AI_PACER_EXTP;
825         else
826                 bits |= PCIDAS_AI_PACER_INT;
827         outw(bits, devpriv->pcibar1 + PCIDAS_AI_REG);
828 
829         /*  load counters */
830         if (cmd->scan_begin_src == TRIG_TIMER ||
831             cmd->convert_src == TRIG_TIMER) {
832                 comedi_8254_update_divisors(dev->pacer);
833                 comedi_8254_pacer_enable(dev->pacer, 1, 2, true);
834         }
835 
836         /*  enable interrupts */
837         spin_lock_irqsave(&dev->spinlock, flags);
838         devpriv->ctrl |= PCIDAS_CTRL_INTE;
839         devpriv->ctrl &= ~PCIDAS_CTRL_INT_MASK;
840         if (cmd->flags & CMDF_WAKE_EOS) {
841                 if (cmd->convert_src == TRIG_NOW && cmd->chanlist_len > 1) {
842                         /* interrupt end of burst */
843                         devpriv->ctrl |= PCIDAS_CTRL_INT_EOS;
844                 } else {
845                         /* interrupt fifo not empty */
846                         devpriv->ctrl |= PCIDAS_CTRL_INT_FNE;
847                 }
848         } else {
849                 /* interrupt fifo half full */
850                 devpriv->ctrl |= PCIDAS_CTRL_INT_FHF;
851         }
852 
853         /*  enable (and clear) interrupts */
854         outw(devpriv->ctrl |
855              PCIDAS_CTRL_EOAI | PCIDAS_CTRL_INT_CLR | PCIDAS_CTRL_LADFUL,
856              devpriv->pcibar1 + PCIDAS_CTRL_REG);
857         spin_unlock_irqrestore(&dev->spinlock, flags);
858 
859         /*  set start trigger and burst mode */
860         bits = 0;
861         if (cmd->start_src == TRIG_NOW) {
862                 bits |= PCIDAS_TRIG_SEL_SW;
863         } else {        /* TRIG_EXT */
864                 bits |= PCIDAS_TRIG_SEL_EXT | PCIDAS_TRIG_EN | PCIDAS_TRIG_CLR;
865                 if (board->is_1602) {
866                         if (cmd->start_arg & CR_INVERT)
867                                 bits |= PCIDAS_TRIG_POL;
868                         if (cmd->start_arg & CR_EDGE)
869                                 bits |= PCIDAS_TRIG_MODE;
870                 }
871         }
872         if (cmd->convert_src == TRIG_NOW && cmd->chanlist_len > 1)
873                 bits |= PCIDAS_TRIG_BURSTE;
874         outw(bits, devpriv->pcibar1 + PCIDAS_TRIG_REG);
875 
876         return 0;
877 }
878 
879 static int cb_pcidas_ao_check_chanlist(struct comedi_device *dev,
880                                        struct comedi_subdevice *s,
881                                        struct comedi_cmd *cmd)
882 {
883         unsigned int chan0 = CR_CHAN(cmd->chanlist[0]);
884 
885         if (cmd->chanlist_len > 1) {
886                 unsigned int chan1 = CR_CHAN(cmd->chanlist[1]);
887 
888                 if (chan0 != 0 || chan1 != 1) {
889                         dev_dbg(dev->class_dev,
890                                 "channels must be ordered channel 0, channel 1 in chanlist\n");
891                         return -EINVAL;
892                 }
893         }
894 
895         return 0;
896 }
897 
898 static int cb_pcidas_ao_cmdtest(struct comedi_device *dev,
899                                 struct comedi_subdevice *s,
900                                 struct comedi_cmd *cmd)
901 {
902         const struct cb_pcidas_board *board = dev->board_ptr;
903         struct cb_pcidas_private *devpriv = dev->private;
904         int err = 0;
905 
906         /* Step 1 : check if triggers are trivially valid */
907 
908         err |= comedi_check_trigger_src(&cmd->start_src, TRIG_INT);
909         err |= comedi_check_trigger_src(&cmd->scan_begin_src,
910                                         TRIG_TIMER | TRIG_EXT);
911         err |= comedi_check_trigger_src(&cmd->convert_src, TRIG_NOW);
912         err |= comedi_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
913         err |= comedi_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE);
914 
915         if (err)
916                 return 1;
917 
918         /* Step 2a : make sure trigger sources are unique */
919 
920         err |= comedi_check_trigger_is_unique(cmd->scan_begin_src);
921         err |= comedi_check_trigger_is_unique(cmd->stop_src);
922 
923         /* Step 2b : and mutually compatible */
924 
925         if (err)
926                 return 2;
927 
928         /* Step 3: check if arguments are trivially valid */
929 
930         err |= comedi_check_trigger_arg_is(&cmd->start_arg, 0);
931 
932         if (cmd->scan_begin_src == TRIG_TIMER) {
933                 err |= comedi_check_trigger_arg_min(&cmd->scan_begin_arg,
934                                                     board->ao_scan_speed);
935         }
936 
937         err |= comedi_check_trigger_arg_is(&cmd->scan_end_arg,
938                                            cmd->chanlist_len);
939 
940         if (cmd->stop_src == TRIG_COUNT)
941                 err |= comedi_check_trigger_arg_min(&cmd->stop_arg, 1);
942         else    /* TRIG_NONE */
943                 err |= comedi_check_trigger_arg_is(&cmd->stop_arg, 0);
944 
945         if (err)
946                 return 3;
947 
948         /* step 4: fix up any arguments */
949 
950         if (cmd->scan_begin_src == TRIG_TIMER) {
951                 unsigned int arg = cmd->scan_begin_arg;
952 
953                 comedi_8254_cascade_ns_to_timer(devpriv->ao_pacer,
954                                                 &arg, cmd->flags);
955                 err |= comedi_check_trigger_arg_is(&cmd->scan_begin_arg, arg);
956         }
957 
958         if (err)
959                 return 4;
960 
961         /* Step 5: check channel list if it exists */
962         if (cmd->chanlist && cmd->chanlist_len > 0)
963                 err |= cb_pcidas_ao_check_chanlist(dev, s, cmd);
964 
965         if (err)
966                 return 5;
967 
968         return 0;
969 }
970 
971 static int cb_pcidas_ai_cancel(struct comedi_device *dev,
972                                struct comedi_subdevice *s)
973 {
974         struct cb_pcidas_private *devpriv = dev->private;
975         unsigned long flags;
976 
977         spin_lock_irqsave(&dev->spinlock, flags);
978         /*  disable interrupts */
979         devpriv->ctrl &= ~(PCIDAS_CTRL_INTE | PCIDAS_CTRL_EOAIE);
980         outw(devpriv->ctrl, devpriv->pcibar1 + PCIDAS_CTRL_REG);
981         spin_unlock_irqrestore(&dev->spinlock, flags);
982 
983         /*  disable start trigger source and burst mode */
984         outw(PCIDAS_TRIG_SEL_NONE, devpriv->pcibar1 + PCIDAS_TRIG_REG);
985         outw(PCIDAS_AI_PACER_SW, devpriv->pcibar1 + PCIDAS_AI_REG);
986 
987         return 0;
988 }
989 
990 static void cb_pcidas_ao_load_fifo(struct comedi_device *dev,
991                                    struct comedi_subdevice *s,
992                                    unsigned int nsamples)
993 {
994         struct cb_pcidas_private *devpriv = dev->private;
995         unsigned int nbytes;
996 
997         nsamples = comedi_nsamples_left(s, nsamples);
998         nbytes = comedi_buf_read_samples(s, devpriv->ao_buffer, nsamples);
999 
1000         nsamples = comedi_bytes_to_samples(s, nbytes);
1001         outsw(devpriv->pcibar4 + PCIDAS_AO_FIFO_REG,
1002               devpriv->ao_buffer, nsamples);
1003 }
1004 
1005 static int cb_pcidas_ao_inttrig(struct comedi_device *dev,
1006                                 struct comedi_subdevice *s,
1007                                 unsigned int trig_num)
1008 {
1009         const struct cb_pcidas_board *board = dev->board_ptr;
1010         struct cb_pcidas_private *devpriv = dev->private;
1011         struct comedi_async *async = s->async;
1012         struct comedi_cmd *cmd = &async->cmd;
1013         unsigned long flags;
1014 
1015         if (trig_num != cmd->start_arg)
1016                 return -EINVAL;
1017 
1018         cb_pcidas_ao_load_fifo(dev, s, board->fifo_size);
1019 
1020         /*  enable dac half-full and empty interrupts */
1021         spin_lock_irqsave(&dev->spinlock, flags);
1022         devpriv->ctrl |= PCIDAS_CTRL_DAEMIE | PCIDAS_CTRL_DAHFIE;
1023 
1024         /*  enable and clear interrupts */
1025         outw(devpriv->ctrl | PCIDAS_CTRL_DAEMI | PCIDAS_CTRL_DAHFI,
1026              devpriv->pcibar1 + PCIDAS_CTRL_REG);
1027 
1028         /*  start dac */
1029         devpriv->ao_ctrl |= PCIDAS_AO_START | PCIDAS_AO_DACEN | PCIDAS_AO_EMPTY;
1030         outw(devpriv->ao_ctrl, devpriv->pcibar1 + PCIDAS_AO_REG);
1031 
1032         spin_unlock_irqrestore(&dev->spinlock, flags);
1033 
1034         async->inttrig = NULL;
1035 
1036         return 0;
1037 }
1038 
1039 static int cb_pcidas_ao_cmd(struct comedi_device *dev,
1040                             struct comedi_subdevice *s)
1041 {
1042         struct cb_pcidas_private *devpriv = dev->private;
1043         struct comedi_async *async = s->async;
1044         struct comedi_cmd *cmd = &async->cmd;
1045         unsigned int i;
1046         unsigned long flags;
1047 
1048         /*  set channel limits, gain */
1049         spin_lock_irqsave(&dev->spinlock, flags);
1050         for (i = 0; i < cmd->chanlist_len; i++) {
1051                 unsigned int chan = CR_CHAN(cmd->chanlist[i]);
1052                 unsigned int range = CR_RANGE(cmd->chanlist[i]);
1053 
1054                 /*  enable channel */
1055                 devpriv->ao_ctrl |= PCIDAS_AO_CHAN_EN(chan);
1056                 /*  set range */
1057                 devpriv->ao_ctrl |= PCIDAS_AO_RANGE(chan, range);
1058         }
1059 
1060         /*  disable analog out before settings pacer source and count values */
1061         outw(devpriv->ao_ctrl, devpriv->pcibar1 + PCIDAS_AO_REG);
1062         spin_unlock_irqrestore(&dev->spinlock, flags);
1063 
1064         /*  clear fifo */
1065         outw(0, devpriv->pcibar4 + PCIDAS_AO_FIFO_CLR_REG);
1066 
1067         /*  load counters */
1068         if (cmd->scan_begin_src == TRIG_TIMER) {
1069                 comedi_8254_update_divisors(devpriv->ao_pacer);
1070                 comedi_8254_pacer_enable(devpriv->ao_pacer, 1, 2, true);
1071         }
1072 
1073         /*  set pacer source */
1074         spin_lock_irqsave(&dev->spinlock, flags);
1075         switch (cmd->scan_begin_src) {
1076         case TRIG_TIMER:
1077                 devpriv->ao_ctrl |= PCIDAS_AO_PACER_INT;
1078                 break;
1079         case TRIG_EXT:
1080                 devpriv->ao_ctrl |= PCIDAS_AO_PACER_EXTP;
1081                 break;
1082         default:
1083                 spin_unlock_irqrestore(&dev->spinlock, flags);
1084                 dev_err(dev->class_dev, "error setting dac pacer source\n");
1085                 return -1;
1086         }
1087         spin_unlock_irqrestore(&dev->spinlock, flags);
1088 
1089         async->inttrig = cb_pcidas_ao_inttrig;
1090 
1091         return 0;
1092 }
1093 
1094 static int cb_pcidas_ao_cancel(struct comedi_device *dev,
1095                                struct comedi_subdevice *s)
1096 {
1097         struct cb_pcidas_private *devpriv = dev->private;
1098         unsigned long flags;
1099 
1100         spin_lock_irqsave(&dev->spinlock, flags);
1101         /*  disable interrupts */
1102         devpriv->ctrl &= ~(PCIDAS_CTRL_DAHFIE | PCIDAS_CTRL_DAEMIE);
1103         outw(devpriv->ctrl, devpriv->pcibar1 + PCIDAS_CTRL_REG);
1104 
1105         /*  disable output */
1106         devpriv->ao_ctrl &= ~(PCIDAS_AO_DACEN | PCIDAS_AO_PACER_MASK);
1107         outw(devpriv->ao_ctrl, devpriv->pcibar1 + PCIDAS_AO_REG);
1108         spin_unlock_irqrestore(&dev->spinlock, flags);
1109 
1110         return 0;
1111 }
1112 
1113 static unsigned int cb_pcidas_ao_interrupt(struct comedi_device *dev,
1114                                            unsigned int status)
1115 {
1116         const struct cb_pcidas_board *board = dev->board_ptr;
1117         struct cb_pcidas_private *devpriv = dev->private;
1118         struct comedi_subdevice *s = dev->write_subdev;
1119         struct comedi_async *async = s->async;
1120         struct comedi_cmd *cmd = &async->cmd;
1121         unsigned int irq_clr = 0;
1122 
1123         if (status & PCIDAS_CTRL_DAEMI) {
1124                 irq_clr |= PCIDAS_CTRL_DAEMI;
1125 
1126                 if (inw(devpriv->pcibar4 + PCIDAS_AO_REG) & PCIDAS_AO_EMPTY) {
1127                         if (cmd->stop_src == TRIG_COUNT &&
1128                             async->scans_done >= cmd->stop_arg) {
1129                                 async->events |= COMEDI_CB_EOA;
1130                         } else {
1131                                 dev_err(dev->class_dev, "dac fifo underflow\n");
1132                                 async->events |= COMEDI_CB_ERROR;
1133                         }
1134                 }
1135         } else if (status & PCIDAS_CTRL_DAHFI) {
1136                 irq_clr |= PCIDAS_CTRL_DAHFI;
1137 
1138                 cb_pcidas_ao_load_fifo(dev, s, board->fifo_size / 2);
1139         }
1140 
1141         comedi_handle_events(dev, s);
1142 
1143         return irq_clr;
1144 }
1145 
1146 static unsigned int cb_pcidas_ai_interrupt(struct comedi_device *dev,
1147                                            unsigned int status)
1148 {
1149         const struct cb_pcidas_board *board = dev->board_ptr;
1150         struct cb_pcidas_private *devpriv = dev->private;
1151         struct comedi_subdevice *s = dev->read_subdev;
1152         struct comedi_async *async = s->async;
1153         struct comedi_cmd *cmd = &async->cmd;
1154         unsigned int irq_clr = 0;
1155 
1156         if (status & PCIDAS_CTRL_ADHFI) {
1157                 unsigned int num_samples;
1158 
1159                 irq_clr |= PCIDAS_CTRL_INT_CLR;
1160 
1161                 /* FIFO is half-full - read data */
1162                 num_samples = comedi_nsamples_left(s, board->fifo_size / 2);
1163                 insw(devpriv->pcibar2 + PCIDAS_AI_DATA_REG,
1164                      devpriv->ai_buffer, num_samples);
1165                 comedi_buf_write_samples(s, devpriv->ai_buffer, num_samples);
1166 
1167                 if (cmd->stop_src == TRIG_COUNT &&
1168                     async->scans_done >= cmd->stop_arg)
1169                         async->events |= COMEDI_CB_EOA;
1170         } else if (status & (PCIDAS_CTRL_ADNEI | PCIDAS_CTRL_EOBI)) {
1171                 unsigned int i;
1172 
1173                 irq_clr |= PCIDAS_CTRL_INT_CLR;
1174 
1175                 /* FIFO is not empty - read data until empty or timeoout */
1176                 for (i = 0; i < 10000; i++) {
1177                         unsigned short val;
1178 
1179                         /*  break if fifo is empty */
1180                         if ((inw(devpriv->pcibar1 + PCIDAS_CTRL_REG) &
1181                             PCIDAS_CTRL_ADNE) == 0)
1182                                 break;
1183                         val = inw(devpriv->pcibar2 + PCIDAS_AI_DATA_REG);
1184                         comedi_buf_write_samples(s, &val, 1);
1185 
1186                         if (cmd->stop_src == TRIG_COUNT &&
1187                             async->scans_done >= cmd->stop_arg) {
1188                                 async->events |= COMEDI_CB_EOA;
1189                                 break;
1190                         }
1191                 }
1192         } else if (status & PCIDAS_CTRL_EOAI) {
1193                 irq_clr |= PCIDAS_CTRL_EOAI;
1194 
1195                 dev_err(dev->class_dev,
1196                         "bug! encountered end of acquisition interrupt?\n");
1197         }
1198 
1199         /* check for fifo overflow */
1200         if (status & PCIDAS_CTRL_LADFUL) {
1201                 irq_clr |= PCIDAS_CTRL_LADFUL;
1202 
1203                 dev_err(dev->class_dev, "fifo overflow\n");
1204                 async->events |= COMEDI_CB_ERROR;
1205         }
1206 
1207         comedi_handle_events(dev, s);
1208 
1209         return irq_clr;
1210 }
1211 
1212 static irqreturn_t cb_pcidas_interrupt(int irq, void *d)
1213 {
1214         struct comedi_device *dev = d;
1215         struct cb_pcidas_private *devpriv = dev->private;
1216         unsigned int irq_clr = 0;
1217         unsigned int amcc_status;
1218         unsigned int status;
1219 
1220         if (!dev->attached)
1221                 return IRQ_NONE;
1222 
1223         amcc_status = inl(devpriv->amcc + AMCC_OP_REG_INTCSR);
1224 
1225         if ((INTCSR_INTR_ASSERTED & amcc_status) == 0)
1226                 return IRQ_NONE;
1227 
1228         /*  make sure mailbox 4 is empty */
1229         inl_p(devpriv->amcc + AMCC_OP_REG_IMB4);
1230         /*  clear interrupt on amcc s5933 */
1231         outl(devpriv->amcc_intcsr | INTCSR_INBOX_INTR_STATUS,
1232              devpriv->amcc + AMCC_OP_REG_INTCSR);
1233 
1234         status = inw(devpriv->pcibar1 + PCIDAS_CTRL_REG);
1235 
1236         /* handle analog output interrupts */
1237         if (status & PCIDAS_CTRL_AO_INT)
1238                 irq_clr |= cb_pcidas_ao_interrupt(dev, status);
1239 
1240         /* handle analog input interrupts */
1241         if (status & PCIDAS_CTRL_AI_INT)
1242                 irq_clr |= cb_pcidas_ai_interrupt(dev, status);
1243 
1244         if (irq_clr) {
1245                 unsigned long flags;
1246 
1247                 spin_lock_irqsave(&dev->spinlock, flags);
1248                 outw(devpriv->ctrl | irq_clr,
1249                      devpriv->pcibar1 + PCIDAS_CTRL_REG);
1250                 spin_unlock_irqrestore(&dev->spinlock, flags);
1251         }
1252 
1253         return IRQ_HANDLED;
1254 }
1255 
1256 static int cb_pcidas_auto_attach(struct comedi_device *dev,
1257                                  unsigned long context)
1258 {
1259         struct pci_dev *pcidev = comedi_to_pci_dev(dev);
1260         const struct cb_pcidas_board *board = NULL;
1261         struct cb_pcidas_private *devpriv;
1262         struct comedi_subdevice *s;
1263         int i;
1264         int ret;
1265 
1266         if (context < ARRAY_SIZE(cb_pcidas_boards))
1267                 board = &cb_pcidas_boards[context];
1268         if (!board)
1269                 return -ENODEV;
1270         dev->board_ptr  = board;
1271         dev->board_name = board->name;
1272 
1273         devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
1274         if (!devpriv)
1275                 return -ENOMEM;
1276 
1277         ret = comedi_pci_enable(dev);
1278         if (ret)
1279                 return ret;
1280 
1281         devpriv->amcc = pci_resource_start(pcidev, 0);
1282         devpriv->pcibar1 = pci_resource_start(pcidev, 1);
1283         devpriv->pcibar2 = pci_resource_start(pcidev, 2);
1284         dev->iobase = pci_resource_start(pcidev, 3);
1285         if (board->has_ao)
1286                 devpriv->pcibar4 = pci_resource_start(pcidev, 4);
1287 
1288         /*  disable and clear interrupts on amcc s5933 */
1289         outl(INTCSR_INBOX_INTR_STATUS,
1290              devpriv->amcc + AMCC_OP_REG_INTCSR);
1291 
1292         ret = request_irq(pcidev->irq, cb_pcidas_interrupt, IRQF_SHARED,
1293                           dev->board_name, dev);
1294         if (ret) {
1295                 dev_dbg(dev->class_dev, "unable to allocate irq %d\n",
1296                         pcidev->irq);
1297                 return ret;
1298         }
1299         dev->irq = pcidev->irq;
1300 
1301         dev->pacer = comedi_8254_init(dev->iobase + PCIDAS_AI_8254_BASE,
1302                                       I8254_OSC_BASE_10MHZ, I8254_IO8, 0);
1303         if (!dev->pacer)
1304                 return -ENOMEM;
1305 
1306         devpriv->ao_pacer = comedi_8254_init(dev->iobase + PCIDAS_AO_8254_BASE,
1307                                              I8254_OSC_BASE_10MHZ,
1308                                              I8254_IO8, 0);
1309         if (!devpriv->ao_pacer)
1310                 return -ENOMEM;
1311 
1312         ret = comedi_alloc_subdevices(dev, 7);
1313         if (ret)
1314                 return ret;
1315 
1316         /* Analog Input subdevice */
1317         s = &dev->subdevices[0];
1318         s->type         = COMEDI_SUBD_AI;
1319         s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_DIFF;
1320         s->n_chan       = 16;
1321         s->maxdata      = board->is_16bit ? 0xffff : 0x0fff;
1322         s->range_table  = board->use_alt_range ? &cb_pcidas_alt_ranges
1323                                                : &cb_pcidas_ranges;
1324         s->insn_read    = cb_pcidas_ai_insn_read;
1325         s->insn_config  = cb_pcidas_ai_insn_config;
1326         if (dev->irq) {
1327                 dev->read_subdev = s;
1328                 s->subdev_flags |= SDF_CMD_READ;
1329                 s->len_chanlist = s->n_chan;
1330                 s->do_cmd       = cb_pcidas_ai_cmd;
1331                 s->do_cmdtest   = cb_pcidas_ai_cmdtest;
1332                 s->cancel       = cb_pcidas_ai_cancel;
1333         }
1334 
1335         /* Analog Output subdevice */
1336         s = &dev->subdevices[1];
1337         if (board->has_ao) {
1338                 s->type         = COMEDI_SUBD_AO;
1339                 s->subdev_flags = SDF_WRITABLE | SDF_GROUND;
1340                 s->n_chan       = 2;
1341                 s->maxdata      = board->is_16bit ? 0xffff : 0x0fff;
1342                 s->range_table  = &cb_pcidas_ao_ranges;
1343                 s->insn_write   = (board->has_ao_fifo)
1344                                         ? cb_pcidas_ao_fifo_insn_write
1345                                         : cb_pcidas_ao_nofifo_insn_write;
1346 
1347                 ret = comedi_alloc_subdev_readback(s);
1348                 if (ret)
1349                         return ret;
1350 
1351                 if (dev->irq && board->has_ao_fifo) {
1352                         dev->write_subdev = s;
1353                         s->subdev_flags |= SDF_CMD_WRITE;
1354                         s->do_cmdtest   = cb_pcidas_ao_cmdtest;
1355                         s->do_cmd       = cb_pcidas_ao_cmd;
1356                         s->cancel       = cb_pcidas_ao_cancel;
1357                 }
1358         } else {
1359                 s->type         = COMEDI_SUBD_UNUSED;
1360         }
1361 
1362         /* 8255 */
1363         s = &dev->subdevices[2];
1364         ret = subdev_8255_init(dev, s, NULL, PCIDAS_8255_BASE);
1365         if (ret)
1366                 return ret;
1367 
1368         /* Memory subdevice - serial EEPROM */
1369         s = &dev->subdevices[3];
1370         s->type         = COMEDI_SUBD_MEMORY;
1371         s->subdev_flags = SDF_READABLE | SDF_INTERNAL;
1372         s->n_chan       = 256;
1373         s->maxdata      = 0xff;
1374         s->insn_read    = cb_pcidas_eeprom_insn_read;
1375 
1376         /* Calibration subdevice - 8800 caldac */
1377         s = &dev->subdevices[4];
1378         s->type         = COMEDI_SUBD_CALIB;
1379         s->subdev_flags = SDF_WRITABLE | SDF_INTERNAL;
1380         s->n_chan       = 8;
1381         s->maxdata      = 0xff;
1382         s->insn_write   = cb_pcidas_caldac_insn_write;
1383 
1384         ret = comedi_alloc_subdev_readback(s);
1385         if (ret)
1386                 return ret;
1387 
1388         for (i = 0; i < s->n_chan; i++) {
1389                 unsigned int val = s->maxdata / 2;
1390 
1391                 /* write 11-bit channel/value to caldac */
1392                 cb_pcidas_calib_write(dev, (i << 8) | val, 11, false);
1393                 s->readback[i] = val;
1394         }
1395 
1396         /* Calibration subdevice - trim potentiometer */
1397         s = &dev->subdevices[5];
1398         s->type         = COMEDI_SUBD_CALIB;
1399         s->subdev_flags = SDF_WRITABLE | SDF_INTERNAL;
1400         if (board->has_ad8402) {
1401                 /*
1402                  * pci-das1602/16 have an AD8402 trimpot:
1403                  *   chan 0 : adc gain
1404                  *   chan 1 : adc postgain offset
1405                  */
1406                 s->n_chan       = 2;
1407                 s->maxdata      = 0xff;
1408         } else {
1409                 /* all other boards have an AD7376 trimpot */
1410                 s->n_chan       = 1;
1411                 s->maxdata      = 0x7f;
1412         }
1413         s->insn_write   = cb_pcidas_trimpot_insn_write;
1414 
1415         ret = comedi_alloc_subdev_readback(s);
1416         if (ret)
1417                 return ret;
1418 
1419         for (i = 0; i < s->n_chan; i++) {
1420                 cb_pcidas_trimpot_write(dev, i, s->maxdata / 2);
1421                 s->readback[i] = s->maxdata / 2;
1422         }
1423 
1424         /* Calibration subdevice - pci-das1602/16 pregain offset (dac08) */
1425         s = &dev->subdevices[6];
1426         if (board->has_dac08) {
1427                 s->type         = COMEDI_SUBD_CALIB;
1428                 s->subdev_flags = SDF_WRITABLE | SDF_INTERNAL;
1429                 s->n_chan       = 1;
1430                 s->maxdata      = 0xff;
1431                 s->insn_write   = cb_pcidas_dac08_insn_write;
1432 
1433                 ret = comedi_alloc_subdev_readback(s);
1434                 if (ret)
1435                         return ret;
1436 
1437                 for (i = 0; i < s->n_chan; i++) {
1438                         cb_pcidas_dac08_write(dev, s->maxdata / 2);
1439                         s->readback[i] = s->maxdata / 2;
1440                 }
1441         } else {
1442                 s->type         = COMEDI_SUBD_UNUSED;
1443         }
1444 
1445         /*  make sure mailbox 4 is empty */
1446         inl(devpriv->amcc + AMCC_OP_REG_IMB4);
1447         /* Set bits to enable incoming mailbox interrupts on amcc s5933. */
1448         devpriv->amcc_intcsr = INTCSR_INBOX_BYTE(3) | INTCSR_INBOX_SELECT(3) |
1449                                INTCSR_INBOX_FULL_INT;
1450         /*  clear and enable interrupt on amcc s5933 */
1451         outl(devpriv->amcc_intcsr | INTCSR_INBOX_INTR_STATUS,
1452              devpriv->amcc + AMCC_OP_REG_INTCSR);
1453 
1454         return 0;
1455 }
1456 
1457 static void cb_pcidas_detach(struct comedi_device *dev)
1458 {
1459         struct cb_pcidas_private *devpriv = dev->private;
1460 
1461         if (devpriv) {
1462                 if (devpriv->amcc)
1463                         outl(INTCSR_INBOX_INTR_STATUS,
1464                              devpriv->amcc + AMCC_OP_REG_INTCSR);
1465                 kfree(devpriv->ao_pacer);
1466         }
1467         comedi_pci_detach(dev);
1468 }
1469 
1470 static struct comedi_driver cb_pcidas_driver = {
1471         .driver_name    = "cb_pcidas",
1472         .module         = THIS_MODULE,
1473         .auto_attach    = cb_pcidas_auto_attach,
1474         .detach         = cb_pcidas_detach,
1475 };
1476 
1477 static int cb_pcidas_pci_probe(struct pci_dev *dev,
1478                                const struct pci_device_id *id)
1479 {
1480         return comedi_pci_auto_config(dev, &cb_pcidas_driver,
1481                                       id->driver_data);
1482 }
1483 
1484 static const struct pci_device_id cb_pcidas_pci_table[] = {
1485         { PCI_VDEVICE(CB, 0x0001), BOARD_PCIDAS1602_16 },
1486         { PCI_VDEVICE(CB, 0x000f), BOARD_PCIDAS1200 },
1487         { PCI_VDEVICE(CB, 0x0010), BOARD_PCIDAS1602_12 },
1488         { PCI_VDEVICE(CB, 0x0019), BOARD_PCIDAS1200_JR },
1489         { PCI_VDEVICE(CB, 0x001c), BOARD_PCIDAS1602_16_JR },
1490         { PCI_VDEVICE(CB, 0x004c), BOARD_PCIDAS1000 },
1491         { PCI_VDEVICE(CB, 0x001a), BOARD_PCIDAS1001 },
1492         { PCI_VDEVICE(CB, 0x001b), BOARD_PCIDAS1002 },
1493         { 0 }
1494 };
1495 MODULE_DEVICE_TABLE(pci, cb_pcidas_pci_table);
1496 
1497 static struct pci_driver cb_pcidas_pci_driver = {
1498         .name           = "cb_pcidas",
1499         .id_table       = cb_pcidas_pci_table,
1500         .probe          = cb_pcidas_pci_probe,
1501         .remove         = comedi_pci_auto_unconfig,
1502 };
1503 module_comedi_pci_driver(cb_pcidas_driver, cb_pcidas_pci_driver);
1504 
1505 MODULE_AUTHOR("Comedi http://www.comedi.org");
1506 MODULE_DESCRIPTION("Comedi driver for MeasurementComputing PCI-DAS series");
1507 MODULE_LICENSE("GPL");
1508 

This page was automatically generated by LXR 0.3.1 (source).  •  Linux is a registered trademark of Linus Torvalds  •  Contact us