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
cb_pcidas_ai_eoc(struct comedi_device * dev,struct comedi_subdevice * s,struct comedi_insn * insn,unsigned long context)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
cb_pcidas_ai_insn_read(struct comedi_device * dev,struct comedi_subdevice * s,struct comedi_insn * insn,unsigned int * data)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
cb_pcidas_ai_insn_config(struct comedi_device * dev,struct comedi_subdevice * s,struct comedi_insn * insn,unsigned int * data)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 */
cb_pcidas_ao_nofifo_insn_write(struct comedi_device * dev,struct comedi_subdevice * s,struct comedi_insn * insn,unsigned int * data)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 */
cb_pcidas_ao_fifo_insn_write(struct comedi_device * dev,struct comedi_subdevice * s,struct comedi_insn * insn,unsigned int * data)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
cb_pcidas_eeprom_ready(struct comedi_device * dev,struct comedi_subdevice * s,struct comedi_insn * insn,unsigned long context)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
cb_pcidas_eeprom_insn_read(struct comedi_device * dev,struct comedi_subdevice * s,struct comedi_insn * insn,unsigned int * data)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
cb_pcidas_calib_write(struct comedi_device * dev,unsigned int val,unsigned int len,bool trimpot)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
cb_pcidas_caldac_insn_write(struct comedi_device * dev,struct comedi_subdevice * s,struct comedi_insn * insn,unsigned int * data)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
cb_pcidas_dac08_write(struct comedi_device * dev,unsigned int val)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
cb_pcidas_dac08_insn_write(struct comedi_device * dev,struct comedi_subdevice * s,struct comedi_insn * insn,unsigned int * data)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
cb_pcidas_trimpot_write(struct comedi_device * dev,unsigned int chan,unsigned int val)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
cb_pcidas_trimpot_insn_write(struct comedi_device * dev,struct comedi_subdevice * s,struct comedi_insn * insn,unsigned int * data)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
cb_pcidas_ai_check_chanlist(struct comedi_device * dev,struct comedi_subdevice * s,struct comedi_cmd * cmd)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
cb_pcidas_ai_cmdtest(struct comedi_device * dev,struct comedi_subdevice * s,struct comedi_cmd * cmd)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
cb_pcidas_ai_cmd(struct comedi_device * dev,struct comedi_subdevice * s)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
cb_pcidas_ao_check_chanlist(struct comedi_device * dev,struct comedi_subdevice * s,struct comedi_cmd * cmd)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
cb_pcidas_ao_cmdtest(struct comedi_device * dev,struct comedi_subdevice * s,struct comedi_cmd * cmd)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
cb_pcidas_ai_cancel(struct comedi_device * dev,struct comedi_subdevice * s)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
cb_pcidas_ao_load_fifo(struct comedi_device * dev,struct comedi_subdevice * s,unsigned int nsamples)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
cb_pcidas_ao_inttrig(struct comedi_device * dev,struct comedi_subdevice * s,unsigned int trig_num)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
cb_pcidas_ao_cmd(struct comedi_device * dev,struct comedi_subdevice * s)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
cb_pcidas_ao_cancel(struct comedi_device * dev,struct comedi_subdevice * s)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
cb_pcidas_ao_interrupt(struct comedi_device * dev,unsigned int status)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
cb_pcidas_ai_interrupt(struct comedi_device * dev,unsigned int status)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
cb_pcidas_interrupt(int irq,void * d)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
cb_pcidas_auto_attach(struct comedi_device * dev,unsigned long context)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
cb_pcidas_detach(struct comedi_device * dev)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
cb_pcidas_pci_probe(struct pci_dev * dev,const struct pci_device_id * id)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