1 // SPDX-License-Identifier: GPL-2.0+
4 * Developed by Ivan Martinez and Frank Mori Hess, with valuable help from
5 * David Schleef and the rest of the Comedi developers comunity.
7 * Copyright (C) 2001-2003 Ivan Martinez <imr@oersted.dtu.dk>
8 * Copyright (C) 2001,2002 Frank Mori Hess <fmhess@users.sourceforge.net>
10 * COMEDI - Linux Control and Measurement Device Interface
11 * Copyright (C) 1997-8 David A. Schleef <ds@schleef.org>
16 * Description: MeasurementComputing PCI-DAS series
17 * with the AMCC S5933 PCI controller
18 * Devices: [Measurement Computing] PCI-DAS1602/16 (cb_pcidas),
19 * PCI-DAS1602/16jr, PCI-DAS1602/12, PCI-DAS1200, PCI-DAS1200jr,
20 * PCI-DAS1000, PCI-DAS1001, PCI_DAS1002
21 * Author: Ivan Martinez <imr@oersted.dtu.dk>,
22 * Frank Mori Hess <fmhess@users.sourceforge.net>
26 * There are many reports of the driver being used with most of the
27 * supported cards. Despite no detailed log is maintained, it can
28 * be said that the driver is quite tested and stable.
30 * The boards may be autocalibrated using the comedi_calibrate
33 * Configuration options: not applicable, uses PCI auto config
35 * For commands, the scanned channels must be consecutive
36 * (i.e. 4-5-6-7, 2-3-4,...), and must all have the same
40 * For start_src == TRIG_EXT, the A/D EXTERNAL TRIGGER IN (pin 45) is used.
41 * For 1602 series, the start_arg is interpreted as follows:
42 * start_arg == 0 => gated trigger (level high)
43 * start_arg == CR_INVERT => gated trigger (level low)
44 * start_arg == CR_EDGE => Rising edge
45 * start_arg == CR_EDGE | CR_INVERT => Falling edge
46 * For the other boards the trigger will be done on rising edge
51 * analog triggering on 1602 series
54 #include <linux/module.h>
55 #include <linux/delay.h>
56 #include <linux/interrupt.h>
57 #include <linux/comedi/comedi_pci.h>
58 #include <linux/comedi/comedi_8255.h>
59 #include <linux/comedi/comedi_8254.h>
61 #include "amcc_s5933.h"
63 #define AI_BUFFER_SIZE 1024 /* max ai fifo size */
64 #define AO_BUFFER_SIZE 1024 /* max ao fifo size */
67 * PCI BAR1 Register map (devpriv->pcibar1)
69 #define PCIDAS_CTRL_REG 0x00 /* INTERRUPT / ADC FIFO register */
70 #define PCIDAS_CTRL_INT(x) (((x) & 0x3) << 0)
71 #define PCIDAS_CTRL_INT_NONE PCIDAS_CTRL_INT(0) /* no int selected */
72 #define PCIDAS_CTRL_INT_EOS PCIDAS_CTRL_INT(1) /* int on end of scan */
73 #define PCIDAS_CTRL_INT_FHF PCIDAS_CTRL_INT(2) /* int on fifo half full */
74 #define PCIDAS_CTRL_INT_FNE PCIDAS_CTRL_INT(3) /* int on fifo not empty */
75 #define PCIDAS_CTRL_INT_MASK PCIDAS_CTRL_INT(3) /* mask of int select bits */
76 #define PCIDAS_CTRL_INTE BIT(2) /* int enable */
77 #define PCIDAS_CTRL_DAHFIE BIT(3) /* dac half full int enable */
78 #define PCIDAS_CTRL_EOAIE BIT(4) /* end of acq. int enable */
79 #define PCIDAS_CTRL_DAHFI BIT(5) /* dac half full status / clear */
80 #define PCIDAS_CTRL_EOAI BIT(6) /* end of acq. int status / clear */
81 #define PCIDAS_CTRL_INT_CLR BIT(7) /* int status / clear */
82 #define PCIDAS_CTRL_EOBI BIT(9) /* end of burst int status */
83 #define PCIDAS_CTRL_ADHFI BIT(10) /* half-full int status */
84 #define PCIDAS_CTRL_ADNEI BIT(11) /* fifo not empty int status (latch) */
85 #define PCIDAS_CTRL_ADNE BIT(12) /* fifo not empty status (realtime) */
86 #define PCIDAS_CTRL_DAEMIE BIT(12) /* dac empty int enable */
87 #define PCIDAS_CTRL_LADFUL BIT(13) /* fifo overflow / clear */
88 #define PCIDAS_CTRL_DAEMI BIT(14) /* dac fifo empty int status / clear */
90 #define PCIDAS_CTRL_AI_INT (PCIDAS_CTRL_EOAI | PCIDAS_CTRL_EOBI | \
91 PCIDAS_CTRL_ADHFI | PCIDAS_CTRL_ADNEI | \
93 #define PCIDAS_CTRL_AO_INT (PCIDAS_CTRL_DAHFI | PCIDAS_CTRL_DAEMI)
95 #define PCIDAS_AI_REG 0x02 /* ADC CHANNEL MUX AND CONTROL reg */
96 #define PCIDAS_AI_FIRST(x) ((x) & 0xf)
97 #define PCIDAS_AI_LAST(x) (((x) & 0xf) << 4)
98 #define PCIDAS_AI_CHAN(x) (PCIDAS_AI_FIRST(x) | PCIDAS_AI_LAST(x))
99 #define PCIDAS_AI_GAIN(x) (((x) & 0x3) << 8)
100 #define PCIDAS_AI_SE BIT(10) /* Inputs in single-ended mode */
101 #define PCIDAS_AI_UNIP BIT(11) /* Analog front-end unipolar mode */
102 #define PCIDAS_AI_PACER(x) (((x) & 0x3) << 12)
103 #define PCIDAS_AI_PACER_SW PCIDAS_AI_PACER(0) /* software pacer */
104 #define PCIDAS_AI_PACER_INT PCIDAS_AI_PACER(1) /* int. pacer */
105 #define PCIDAS_AI_PACER_EXTN PCIDAS_AI_PACER(2) /* ext. falling edge */
106 #define PCIDAS_AI_PACER_EXTP PCIDAS_AI_PACER(3) /* ext. rising edge */
107 #define PCIDAS_AI_PACER_MASK PCIDAS_AI_PACER(3) /* pacer source bits */
108 #define PCIDAS_AI_EOC BIT(14) /* adc not busy */
110 #define PCIDAS_TRIG_REG 0x04 /* TRIGGER CONTROL/STATUS register */
111 #define PCIDAS_TRIG_SEL(x) (((x) & 0x3) << 0)
112 #define PCIDAS_TRIG_SEL_NONE PCIDAS_TRIG_SEL(0) /* no start trigger */
113 #define PCIDAS_TRIG_SEL_SW PCIDAS_TRIG_SEL(1) /* software start trigger */
114 #define PCIDAS_TRIG_SEL_EXT PCIDAS_TRIG_SEL(2) /* ext. start trigger */
115 #define PCIDAS_TRIG_SEL_ANALOG PCIDAS_TRIG_SEL(3) /* ext. analog trigger */
116 #define PCIDAS_TRIG_SEL_MASK PCIDAS_TRIG_SEL(3) /* start trigger mask */
117 #define PCIDAS_TRIG_POL BIT(2) /* invert trigger (1602 only) */
118 #define PCIDAS_TRIG_MODE BIT(3) /* edge/level triggered (1602 only) */
119 #define PCIDAS_TRIG_EN BIT(4) /* enable external start trigger */
120 #define PCIDAS_TRIG_BURSTE BIT(5) /* burst mode enable */
121 #define PCIDAS_TRIG_CLR BIT(7) /* clear external trigger */
123 #define PCIDAS_CALIB_REG 0x06 /* CALIBRATION register */
124 #define PCIDAS_CALIB_8800_SEL BIT(8) /* select 8800 caldac */
125 #define PCIDAS_CALIB_TRIM_SEL BIT(9) /* select ad7376 trim pot */
126 #define PCIDAS_CALIB_DAC08_SEL BIT(10) /* select dac08 caldac */
127 #define PCIDAS_CALIB_SRC(x) (((x) & 0x7) << 11)
128 #define PCIDAS_CALIB_EN BIT(14) /* calibration source enable */
129 #define PCIDAS_CALIB_DATA BIT(15) /* serial data bit going to caldac */
131 #define PCIDAS_AO_REG 0x08 /* dac control and status register */
132 #define PCIDAS_AO_EMPTY BIT(0) /* fifo empty, write clear (1602) */
133 #define PCIDAS_AO_DACEN BIT(1) /* dac enable */
134 #define PCIDAS_AO_START BIT(2) /* start/arm fifo (1602) */
135 #define PCIDAS_AO_PACER(x) (((x) & 0x3) << 3) /* (1602) */
136 #define PCIDAS_AO_PACER_SW PCIDAS_AO_PACER(0) /* software pacer */
137 #define PCIDAS_AO_PACER_INT PCIDAS_AO_PACER(1) /* int. pacer */
138 #define PCIDAS_AO_PACER_EXTN PCIDAS_AO_PACER(2) /* ext. falling edge */
139 #define PCIDAS_AO_PACER_EXTP PCIDAS_AO_PACER(3) /* ext. rising edge */
140 #define PCIDAS_AO_PACER_MASK PCIDAS_AO_PACER(3) /* pacer source bits */
141 #define PCIDAS_AO_CHAN_EN(c) BIT(5 + ((c) & 0x1))
142 #define PCIDAS_AO_CHAN_MASK (PCIDAS_AO_CHAN_EN(0) | PCIDAS_AO_CHAN_EN(1))
143 #define PCIDAS_AO_UPDATE_BOTH BIT(7) /* update both dacs */
144 #define PCIDAS_AO_RANGE(c, r) (((r) & 0x3) << (8 + 2 * ((c) & 0x1)))
145 #define PCIDAS_AO_RANGE_MASK(c) PCIDAS_AO_RANGE((c), 0x3)
148 * PCI BAR2 Register map (devpriv->pcibar2)
150 #define PCIDAS_AI_DATA_REG 0x00
151 #define PCIDAS_AI_FIFO_CLR_REG 0x02
154 * PCI BAR3 Register map (dev->iobase)
156 #define PCIDAS_AI_8254_BASE 0x00
157 #define PCIDAS_8255_BASE 0x04
158 #define PCIDAS_AO_8254_BASE 0x08
161 * PCI BAR4 Register map (devpriv->pcibar4)
163 #define PCIDAS_AO_DATA_REG(x) (0x00 + ((x) * 2))
164 #define PCIDAS_AO_FIFO_REG 0x00
165 #define PCIDAS_AO_FIFO_CLR_REG 0x02
167 /* analog input ranges for most boards */
168 static const struct comedi_lrange cb_pcidas_ranges
= {
181 /* pci-das1001 input ranges */
182 static const struct comedi_lrange cb_pcidas_alt_ranges
= {
195 /* analog output ranges */
196 static const struct comedi_lrange cb_pcidas_ao_ranges
= {
205 enum cb_pcidas_boardid
{
210 BOARD_PCIDAS1602_16_JR
,
216 struct cb_pcidas_board
{
218 int ai_speed
; /* fastest conversion period in ns */
219 int ao_scan_speed
; /* analog output scan speed for 1602 series */
220 int fifo_size
; /* number of samples fifo can hold */
221 unsigned int is_16bit
; /* ai/ao is 1=16-bit; 0=12-bit */
222 unsigned int use_alt_range
:1; /* use alternate ai range table */
223 unsigned int has_ao
:1; /* has 2 analog output channels */
224 unsigned int has_ao_fifo
:1; /* analog output has fifo */
225 unsigned int has_ad8402
:1; /* trimpot type 1=AD8402; 0=AD7376 */
226 unsigned int has_dac08
:1;
227 unsigned int is_1602
:1;
230 static const struct cb_pcidas_board cb_pcidas_boards
[] = {
231 [BOARD_PCIDAS1602_16
] = {
232 .name
= "pci-das1602/16",
234 .ao_scan_speed
= 10000,
243 [BOARD_PCIDAS1200
] = {
244 .name
= "pci-das1200",
249 [BOARD_PCIDAS1602_12
] = {
250 .name
= "pci-das1602/12",
252 .ao_scan_speed
= 4000,
258 [BOARD_PCIDAS1200_JR
] = {
259 .name
= "pci-das1200/jr",
263 [BOARD_PCIDAS1602_16_JR
] = {
264 .name
= "pci-das1602/16/jr",
272 [BOARD_PCIDAS1000
] = {
273 .name
= "pci-das1000",
277 [BOARD_PCIDAS1001
] = {
278 .name
= "pci-das1001",
284 [BOARD_PCIDAS1002
] = {
285 .name
= "pci-das1002",
292 struct cb_pcidas_private
{
293 struct comedi_8254
*ao_pacer
;
295 unsigned long amcc
; /* pcibar0 */
296 unsigned long pcibar1
;
297 unsigned long pcibar2
;
298 unsigned long pcibar4
;
299 /* bits to write to registers */
301 unsigned int amcc_intcsr
;
302 unsigned int ao_ctrl
;
304 unsigned short ai_buffer
[AI_BUFFER_SIZE
];
305 unsigned short ao_buffer
[AO_BUFFER_SIZE
];
306 unsigned int calib_src
;
309 static int cb_pcidas_ai_eoc(struct comedi_device
*dev
,
310 struct comedi_subdevice
*s
,
311 struct comedi_insn
*insn
,
312 unsigned long context
)
314 struct cb_pcidas_private
*devpriv
= dev
->private;
317 status
= inw(devpriv
->pcibar1
+ PCIDAS_AI_REG
);
318 if (status
& PCIDAS_AI_EOC
)
323 static int cb_pcidas_ai_insn_read(struct comedi_device
*dev
,
324 struct comedi_subdevice
*s
,
325 struct comedi_insn
*insn
,
328 struct cb_pcidas_private
*devpriv
= dev
->private;
329 unsigned int chan
= CR_CHAN(insn
->chanspec
);
330 unsigned int range
= CR_RANGE(insn
->chanspec
);
331 unsigned int aref
= CR_AREF(insn
->chanspec
);
336 /* enable calibration input if appropriate */
337 if (insn
->chanspec
& CR_ALT_SOURCE
) {
338 outw(PCIDAS_CALIB_EN
| PCIDAS_CALIB_SRC(devpriv
->calib_src
),
339 devpriv
->pcibar1
+ PCIDAS_CALIB_REG
);
342 outw(0, devpriv
->pcibar1
+ PCIDAS_CALIB_REG
);
345 /* set mux limits and gain */
346 bits
= PCIDAS_AI_CHAN(chan
) | PCIDAS_AI_GAIN(range
);
347 /* set unipolar/bipolar */
348 if (comedi_range_is_unipolar(s
, range
))
349 bits
|= PCIDAS_AI_UNIP
;
350 /* set single-ended/differential */
351 if (aref
!= AREF_DIFF
)
352 bits
|= PCIDAS_AI_SE
;
353 outw(bits
, devpriv
->pcibar1
+ PCIDAS_AI_REG
);
356 outw(0, devpriv
->pcibar2
+ PCIDAS_AI_FIFO_CLR_REG
);
358 /* convert n samples */
359 for (n
= 0; n
< insn
->n
; n
++) {
360 /* trigger conversion */
361 outw(0, devpriv
->pcibar2
+ PCIDAS_AI_DATA_REG
);
363 /* wait for conversion to end */
364 ret
= comedi_timeout(dev
, s
, insn
, cb_pcidas_ai_eoc
, 0);
369 data
[n
] = inw(devpriv
->pcibar2
+ PCIDAS_AI_DATA_REG
);
372 /* return the number of samples read/written */
376 static int cb_pcidas_ai_insn_config(struct comedi_device
*dev
,
377 struct comedi_subdevice
*s
,
378 struct comedi_insn
*insn
,
381 struct cb_pcidas_private
*devpriv
= dev
->private;
383 unsigned int source
= data
[1];
386 case INSN_CONFIG_ALT_SOURCE
:
388 dev_err(dev
->class_dev
,
389 "invalid calibration source: %i\n",
393 devpriv
->calib_src
= source
;
401 /* analog output insn for pcidas-1000 and 1200 series */
402 static int cb_pcidas_ao_nofifo_insn_write(struct comedi_device
*dev
,
403 struct comedi_subdevice
*s
,
404 struct comedi_insn
*insn
,
407 struct cb_pcidas_private
*devpriv
= dev
->private;
408 unsigned int chan
= CR_CHAN(insn
->chanspec
);
409 unsigned int range
= CR_RANGE(insn
->chanspec
);
410 unsigned int val
= s
->readback
[chan
];
414 /* set channel and range */
415 spin_lock_irqsave(&dev
->spinlock
, flags
);
416 devpriv
->ao_ctrl
&= ~(PCIDAS_AO_UPDATE_BOTH
|
417 PCIDAS_AO_RANGE_MASK(chan
));
418 devpriv
->ao_ctrl
|= PCIDAS_AO_DACEN
| PCIDAS_AO_RANGE(chan
, range
);
419 outw(devpriv
->ao_ctrl
, devpriv
->pcibar1
+ PCIDAS_AO_REG
);
420 spin_unlock_irqrestore(&dev
->spinlock
, flags
);
422 for (i
= 0; i
< insn
->n
; i
++) {
424 outw(val
, devpriv
->pcibar4
+ PCIDAS_AO_DATA_REG(chan
));
427 s
->readback
[chan
] = val
;
432 /* analog output insn for pcidas-1602 series */
433 static int cb_pcidas_ao_fifo_insn_write(struct comedi_device
*dev
,
434 struct comedi_subdevice
*s
,
435 struct comedi_insn
*insn
,
438 struct cb_pcidas_private
*devpriv
= dev
->private;
439 unsigned int chan
= CR_CHAN(insn
->chanspec
);
440 unsigned int range
= CR_RANGE(insn
->chanspec
);
441 unsigned int val
= s
->readback
[chan
];
446 outw(0, devpriv
->pcibar4
+ PCIDAS_AO_FIFO_CLR_REG
);
448 /* set channel and range */
449 spin_lock_irqsave(&dev
->spinlock
, flags
);
450 devpriv
->ao_ctrl
&= ~(PCIDAS_AO_CHAN_MASK
| PCIDAS_AO_RANGE_MASK(chan
) |
451 PCIDAS_AO_PACER_MASK
);
452 devpriv
->ao_ctrl
|= PCIDAS_AO_DACEN
| PCIDAS_AO_RANGE(chan
, range
) |
453 PCIDAS_AO_CHAN_EN(chan
) | PCIDAS_AO_START
;
454 outw(devpriv
->ao_ctrl
, devpriv
->pcibar1
+ PCIDAS_AO_REG
);
455 spin_unlock_irqrestore(&dev
->spinlock
, flags
);
457 for (i
= 0; i
< insn
->n
; i
++) {
459 outw(val
, devpriv
->pcibar4
+ PCIDAS_AO_FIFO_REG
);
462 s
->readback
[chan
] = val
;
467 static int cb_pcidas_eeprom_ready(struct comedi_device
*dev
,
468 struct comedi_subdevice
*s
,
469 struct comedi_insn
*insn
,
470 unsigned long context
)
472 struct cb_pcidas_private
*devpriv
= dev
->private;
475 status
= inb(devpriv
->amcc
+ AMCC_OP_REG_MCSR_NVCMD
);
476 if ((status
& MCSR_NV_BUSY
) == 0)
481 static int cb_pcidas_eeprom_insn_read(struct comedi_device
*dev
,
482 struct comedi_subdevice
*s
,
483 struct comedi_insn
*insn
,
486 struct cb_pcidas_private
*devpriv
= dev
->private;
487 unsigned int chan
= CR_CHAN(insn
->chanspec
);
491 for (i
= 0; i
< insn
->n
; i
++) {
492 /* make sure eeprom is ready */
493 ret
= comedi_timeout(dev
, s
, insn
, cb_pcidas_eeprom_ready
, 0);
497 /* set address (chan) and read operation */
498 outb(MCSR_NV_ENABLE
| MCSR_NV_LOAD_LOW_ADDR
,
499 devpriv
->amcc
+ AMCC_OP_REG_MCSR_NVCMD
);
500 outb(chan
& 0xff, devpriv
->amcc
+ AMCC_OP_REG_MCSR_NVDATA
);
501 outb(MCSR_NV_ENABLE
| MCSR_NV_LOAD_HIGH_ADDR
,
502 devpriv
->amcc
+ AMCC_OP_REG_MCSR_NVCMD
);
503 outb((chan
>> 8) & 0xff,
504 devpriv
->amcc
+ AMCC_OP_REG_MCSR_NVDATA
);
505 outb(MCSR_NV_ENABLE
| MCSR_NV_READ
,
506 devpriv
->amcc
+ AMCC_OP_REG_MCSR_NVCMD
);
508 /* wait for data to be returned */
509 ret
= comedi_timeout(dev
, s
, insn
, cb_pcidas_eeprom_ready
, 0);
513 data
[i
] = inb(devpriv
->amcc
+ AMCC_OP_REG_MCSR_NVDATA
);
519 static void cb_pcidas_calib_write(struct comedi_device
*dev
,
520 unsigned int val
, unsigned int len
,
523 struct cb_pcidas_private
*devpriv
= dev
->private;
524 unsigned int calib_bits
;
527 calib_bits
= PCIDAS_CALIB_EN
| PCIDAS_CALIB_SRC(devpriv
->calib_src
);
530 calib_bits
|= PCIDAS_CALIB_TRIM_SEL
;
531 outw(calib_bits
, devpriv
->pcibar1
+ PCIDAS_CALIB_REG
);
534 /* write bitstream to calibration device */
535 for (bit
= 1 << (len
- 1); bit
; bit
>>= 1) {
537 calib_bits
|= PCIDAS_CALIB_DATA
;
539 calib_bits
&= ~PCIDAS_CALIB_DATA
;
541 outw(calib_bits
, devpriv
->pcibar1
+ PCIDAS_CALIB_REG
);
545 calib_bits
= PCIDAS_CALIB_EN
| PCIDAS_CALIB_SRC(devpriv
->calib_src
);
549 outw(calib_bits
| PCIDAS_CALIB_8800_SEL
,
550 devpriv
->pcibar1
+ PCIDAS_CALIB_REG
);
554 /* latch value to trimpot/caldac */
555 outw(calib_bits
, devpriv
->pcibar1
+ PCIDAS_CALIB_REG
);
558 static int cb_pcidas_caldac_insn_write(struct comedi_device
*dev
,
559 struct comedi_subdevice
*s
,
560 struct comedi_insn
*insn
,
563 unsigned int chan
= CR_CHAN(insn
->chanspec
);
566 unsigned int val
= data
[insn
->n
- 1];
568 if (s
->readback
[chan
] != val
) {
569 /* write 11-bit channel/value to caldac */
570 cb_pcidas_calib_write(dev
, (chan
<< 8) | val
, 11,
572 s
->readback
[chan
] = val
;
579 static void cb_pcidas_dac08_write(struct comedi_device
*dev
, unsigned int val
)
581 struct cb_pcidas_private
*devpriv
= dev
->private;
583 val
|= PCIDAS_CALIB_EN
| PCIDAS_CALIB_SRC(devpriv
->calib_src
);
585 /* latch the new value into the caldac */
586 outw(val
, devpriv
->pcibar1
+ PCIDAS_CALIB_REG
);
588 outw(val
| PCIDAS_CALIB_DAC08_SEL
,
589 devpriv
->pcibar1
+ PCIDAS_CALIB_REG
);
591 outw(val
, devpriv
->pcibar1
+ PCIDAS_CALIB_REG
);
595 static int cb_pcidas_dac08_insn_write(struct comedi_device
*dev
,
596 struct comedi_subdevice
*s
,
597 struct comedi_insn
*insn
,
600 unsigned int chan
= CR_CHAN(insn
->chanspec
);
603 unsigned int val
= data
[insn
->n
- 1];
605 if (s
->readback
[chan
] != val
) {
606 cb_pcidas_dac08_write(dev
, val
);
607 s
->readback
[chan
] = val
;
614 static void cb_pcidas_trimpot_write(struct comedi_device
*dev
,
615 unsigned int chan
, unsigned int val
)
617 const struct cb_pcidas_board
*board
= dev
->board_ptr
;
619 if (board
->has_ad8402
) {
620 /* write 10-bit channel/value to AD8402 trimpot */
621 cb_pcidas_calib_write(dev
, (chan
<< 8) | val
, 10, true);
623 /* write 7-bit value to AD7376 trimpot */
624 cb_pcidas_calib_write(dev
, val
, 7, true);
628 static int cb_pcidas_trimpot_insn_write(struct comedi_device
*dev
,
629 struct comedi_subdevice
*s
,
630 struct comedi_insn
*insn
,
633 unsigned int chan
= CR_CHAN(insn
->chanspec
);
636 unsigned int val
= data
[insn
->n
- 1];
638 if (s
->readback
[chan
] != val
) {
639 cb_pcidas_trimpot_write(dev
, chan
, val
);
640 s
->readback
[chan
] = val
;
647 static int cb_pcidas_ai_check_chanlist(struct comedi_device
*dev
,
648 struct comedi_subdevice
*s
,
649 struct comedi_cmd
*cmd
)
651 unsigned int chan0
= CR_CHAN(cmd
->chanlist
[0]);
652 unsigned int range0
= CR_RANGE(cmd
->chanlist
[0]);
655 for (i
= 1; i
< cmd
->chanlist_len
; i
++) {
656 unsigned int chan
= CR_CHAN(cmd
->chanlist
[i
]);
657 unsigned int range
= CR_RANGE(cmd
->chanlist
[i
]);
659 if (chan
!= (chan0
+ i
) % s
->n_chan
) {
660 dev_dbg(dev
->class_dev
,
661 "entries in chanlist must be consecutive channels, counting upwards\n");
665 if (range
!= range0
) {
666 dev_dbg(dev
->class_dev
,
667 "entries in chanlist must all have the same gain\n");
674 static int cb_pcidas_ai_cmdtest(struct comedi_device
*dev
,
675 struct comedi_subdevice
*s
,
676 struct comedi_cmd
*cmd
)
678 const struct cb_pcidas_board
*board
= dev
->board_ptr
;
682 /* Step 1 : check if triggers are trivially valid */
684 err
|= comedi_check_trigger_src(&cmd
->start_src
, TRIG_NOW
| TRIG_EXT
);
685 err
|= comedi_check_trigger_src(&cmd
->scan_begin_src
,
686 TRIG_FOLLOW
| TRIG_TIMER
| TRIG_EXT
);
687 err
|= comedi_check_trigger_src(&cmd
->convert_src
,
688 TRIG_TIMER
| TRIG_NOW
| TRIG_EXT
);
689 err
|= comedi_check_trigger_src(&cmd
->scan_end_src
, TRIG_COUNT
);
690 err
|= comedi_check_trigger_src(&cmd
->stop_src
, TRIG_COUNT
| TRIG_NONE
);
695 /* Step 2a : make sure trigger sources are unique */
697 err
|= comedi_check_trigger_is_unique(cmd
->start_src
);
698 err
|= comedi_check_trigger_is_unique(cmd
->scan_begin_src
);
699 err
|= comedi_check_trigger_is_unique(cmd
->convert_src
);
700 err
|= comedi_check_trigger_is_unique(cmd
->stop_src
);
702 /* Step 2b : and mutually compatible */
704 if (cmd
->scan_begin_src
== TRIG_FOLLOW
&& cmd
->convert_src
== TRIG_NOW
)
706 if (cmd
->scan_begin_src
!= TRIG_FOLLOW
&& cmd
->convert_src
!= TRIG_NOW
)
708 if (cmd
->start_src
== TRIG_EXT
&&
709 (cmd
->convert_src
== TRIG_EXT
|| cmd
->scan_begin_src
== TRIG_EXT
))
715 /* Step 3: check if arguments are trivially valid */
717 switch (cmd
->start_src
) {
719 err
|= comedi_check_trigger_arg_is(&cmd
->start_arg
, 0);
722 /* External trigger, only CR_EDGE and CR_INVERT flags allowed */
724 & (CR_FLAGS_MASK
& ~(CR_EDGE
| CR_INVERT
))) != 0) {
725 cmd
->start_arg
&= ~(CR_FLAGS_MASK
&
726 ~(CR_EDGE
| CR_INVERT
));
729 if (!board
->is_1602
&& (cmd
->start_arg
& CR_INVERT
)) {
730 cmd
->start_arg
&= (CR_FLAGS_MASK
& ~CR_INVERT
);
736 if (cmd
->scan_begin_src
== TRIG_TIMER
) {
737 err
|= comedi_check_trigger_arg_min(&cmd
->scan_begin_arg
,
742 if (cmd
->convert_src
== TRIG_TIMER
) {
743 err
|= comedi_check_trigger_arg_min(&cmd
->convert_arg
,
747 err
|= comedi_check_trigger_arg_is(&cmd
->scan_end_arg
,
750 if (cmd
->stop_src
== TRIG_COUNT
)
751 err
|= comedi_check_trigger_arg_min(&cmd
->stop_arg
, 1);
753 err
|= comedi_check_trigger_arg_is(&cmd
->stop_arg
, 0);
758 /* step 4: fix up any arguments */
760 if (cmd
->scan_begin_src
== TRIG_TIMER
) {
761 arg
= cmd
->scan_begin_arg
;
762 comedi_8254_cascade_ns_to_timer(dev
->pacer
, &arg
, cmd
->flags
);
763 err
|= comedi_check_trigger_arg_is(&cmd
->scan_begin_arg
, arg
);
765 if (cmd
->convert_src
== TRIG_TIMER
) {
766 arg
= cmd
->convert_arg
;
767 comedi_8254_cascade_ns_to_timer(dev
->pacer
, &arg
, cmd
->flags
);
768 err
|= comedi_check_trigger_arg_is(&cmd
->convert_arg
, arg
);
774 /* Step 5: check channel list if it exists */
775 if (cmd
->chanlist
&& cmd
->chanlist_len
> 0)
776 err
|= cb_pcidas_ai_check_chanlist(dev
, s
, cmd
);
784 static int cb_pcidas_ai_cmd(struct comedi_device
*dev
,
785 struct comedi_subdevice
*s
)
787 const struct cb_pcidas_board
*board
= dev
->board_ptr
;
788 struct cb_pcidas_private
*devpriv
= dev
->private;
789 struct comedi_async
*async
= s
->async
;
790 struct comedi_cmd
*cmd
= &async
->cmd
;
791 unsigned int range0
= CR_RANGE(cmd
->chanlist
[0]);
795 /* make sure PCIDAS_CALIB_EN is disabled */
796 outw(0, devpriv
->pcibar1
+ PCIDAS_CALIB_REG
);
797 /* initialize before settings pacer source and count values */
798 outw(PCIDAS_TRIG_SEL_NONE
, devpriv
->pcibar1
+ PCIDAS_TRIG_REG
);
800 outw(0, devpriv
->pcibar2
+ PCIDAS_AI_FIFO_CLR_REG
);
802 /* set mux limits, gain and pacer source */
803 bits
= PCIDAS_AI_FIRST(CR_CHAN(cmd
->chanlist
[0])) |
804 PCIDAS_AI_LAST(CR_CHAN(cmd
->chanlist
[cmd
->chanlist_len
- 1])) |
805 PCIDAS_AI_GAIN(range0
);
806 /* set unipolar/bipolar */
807 if (comedi_range_is_unipolar(s
, range0
))
808 bits
|= PCIDAS_AI_UNIP
;
809 /* set singleended/differential */
810 if (CR_AREF(cmd
->chanlist
[0]) != AREF_DIFF
)
811 bits
|= PCIDAS_AI_SE
;
812 /* set pacer source */
813 if (cmd
->convert_src
== TRIG_EXT
|| cmd
->scan_begin_src
== TRIG_EXT
)
814 bits
|= PCIDAS_AI_PACER_EXTP
;
816 bits
|= PCIDAS_AI_PACER_INT
;
817 outw(bits
, devpriv
->pcibar1
+ PCIDAS_AI_REG
);
820 if (cmd
->scan_begin_src
== TRIG_TIMER
||
821 cmd
->convert_src
== TRIG_TIMER
) {
822 comedi_8254_update_divisors(dev
->pacer
);
823 comedi_8254_pacer_enable(dev
->pacer
, 1, 2, true);
826 /* enable interrupts */
827 spin_lock_irqsave(&dev
->spinlock
, flags
);
828 devpriv
->ctrl
|= PCIDAS_CTRL_INTE
;
829 devpriv
->ctrl
&= ~PCIDAS_CTRL_INT_MASK
;
830 if (cmd
->flags
& CMDF_WAKE_EOS
) {
831 if (cmd
->convert_src
== TRIG_NOW
&& cmd
->chanlist_len
> 1) {
832 /* interrupt end of burst */
833 devpriv
->ctrl
|= PCIDAS_CTRL_INT_EOS
;
835 /* interrupt fifo not empty */
836 devpriv
->ctrl
|= PCIDAS_CTRL_INT_FNE
;
839 /* interrupt fifo half full */
840 devpriv
->ctrl
|= PCIDAS_CTRL_INT_FHF
;
843 /* enable (and clear) interrupts */
845 PCIDAS_CTRL_EOAI
| PCIDAS_CTRL_INT_CLR
| PCIDAS_CTRL_LADFUL
,
846 devpriv
->pcibar1
+ PCIDAS_CTRL_REG
);
847 spin_unlock_irqrestore(&dev
->spinlock
, flags
);
849 /* set start trigger and burst mode */
851 if (cmd
->start_src
== TRIG_NOW
) {
852 bits
|= PCIDAS_TRIG_SEL_SW
;
853 } else { /* TRIG_EXT */
854 bits
|= PCIDAS_TRIG_SEL_EXT
| PCIDAS_TRIG_EN
| PCIDAS_TRIG_CLR
;
855 if (board
->is_1602
) {
856 if (cmd
->start_arg
& CR_INVERT
)
857 bits
|= PCIDAS_TRIG_POL
;
858 if (cmd
->start_arg
& CR_EDGE
)
859 bits
|= PCIDAS_TRIG_MODE
;
862 if (cmd
->convert_src
== TRIG_NOW
&& cmd
->chanlist_len
> 1)
863 bits
|= PCIDAS_TRIG_BURSTE
;
864 outw(bits
, devpriv
->pcibar1
+ PCIDAS_TRIG_REG
);
869 static int cb_pcidas_ao_check_chanlist(struct comedi_device
*dev
,
870 struct comedi_subdevice
*s
,
871 struct comedi_cmd
*cmd
)
873 unsigned int chan0
= CR_CHAN(cmd
->chanlist
[0]);
875 if (cmd
->chanlist_len
> 1) {
876 unsigned int chan1
= CR_CHAN(cmd
->chanlist
[1]);
878 if (chan0
!= 0 || chan1
!= 1) {
879 dev_dbg(dev
->class_dev
,
880 "channels must be ordered channel 0, channel 1 in chanlist\n");
888 static int cb_pcidas_ao_cmdtest(struct comedi_device
*dev
,
889 struct comedi_subdevice
*s
,
890 struct comedi_cmd
*cmd
)
892 const struct cb_pcidas_board
*board
= dev
->board_ptr
;
893 struct cb_pcidas_private
*devpriv
= dev
->private;
896 /* Step 1 : check if triggers are trivially valid */
898 err
|= comedi_check_trigger_src(&cmd
->start_src
, TRIG_INT
);
899 err
|= comedi_check_trigger_src(&cmd
->scan_begin_src
,
900 TRIG_TIMER
| TRIG_EXT
);
901 err
|= comedi_check_trigger_src(&cmd
->convert_src
, TRIG_NOW
);
902 err
|= comedi_check_trigger_src(&cmd
->scan_end_src
, TRIG_COUNT
);
903 err
|= comedi_check_trigger_src(&cmd
->stop_src
, TRIG_COUNT
| TRIG_NONE
);
908 /* Step 2a : make sure trigger sources are unique */
910 err
|= comedi_check_trigger_is_unique(cmd
->scan_begin_src
);
911 err
|= comedi_check_trigger_is_unique(cmd
->stop_src
);
913 /* Step 2b : and mutually compatible */
918 /* Step 3: check if arguments are trivially valid */
920 err
|= comedi_check_trigger_arg_is(&cmd
->start_arg
, 0);
922 if (cmd
->scan_begin_src
== TRIG_TIMER
) {
923 err
|= comedi_check_trigger_arg_min(&cmd
->scan_begin_arg
,
924 board
->ao_scan_speed
);
927 err
|= comedi_check_trigger_arg_is(&cmd
->scan_end_arg
,
930 if (cmd
->stop_src
== TRIG_COUNT
)
931 err
|= comedi_check_trigger_arg_min(&cmd
->stop_arg
, 1);
933 err
|= comedi_check_trigger_arg_is(&cmd
->stop_arg
, 0);
938 /* step 4: fix up any arguments */
940 if (cmd
->scan_begin_src
== TRIG_TIMER
) {
941 unsigned int arg
= cmd
->scan_begin_arg
;
943 comedi_8254_cascade_ns_to_timer(devpriv
->ao_pacer
,
945 err
|= comedi_check_trigger_arg_is(&cmd
->scan_begin_arg
, arg
);
951 /* Step 5: check channel list if it exists */
952 if (cmd
->chanlist
&& cmd
->chanlist_len
> 0)
953 err
|= cb_pcidas_ao_check_chanlist(dev
, s
, cmd
);
961 static int cb_pcidas_ai_cancel(struct comedi_device
*dev
,
962 struct comedi_subdevice
*s
)
964 struct cb_pcidas_private
*devpriv
= dev
->private;
967 spin_lock_irqsave(&dev
->spinlock
, flags
);
968 /* disable interrupts */
969 devpriv
->ctrl
&= ~(PCIDAS_CTRL_INTE
| PCIDAS_CTRL_EOAIE
);
970 outw(devpriv
->ctrl
, devpriv
->pcibar1
+ PCIDAS_CTRL_REG
);
971 spin_unlock_irqrestore(&dev
->spinlock
, flags
);
973 /* disable start trigger source and burst mode */
974 outw(PCIDAS_TRIG_SEL_NONE
, devpriv
->pcibar1
+ PCIDAS_TRIG_REG
);
975 outw(PCIDAS_AI_PACER_SW
, devpriv
->pcibar1
+ PCIDAS_AI_REG
);
980 static void cb_pcidas_ao_load_fifo(struct comedi_device
*dev
,
981 struct comedi_subdevice
*s
,
982 unsigned int nsamples
)
984 struct cb_pcidas_private
*devpriv
= dev
->private;
987 nsamples
= comedi_nsamples_left(s
, nsamples
);
988 nbytes
= comedi_buf_read_samples(s
, devpriv
->ao_buffer
, nsamples
);
990 nsamples
= comedi_bytes_to_samples(s
, nbytes
);
991 outsw(devpriv
->pcibar4
+ PCIDAS_AO_FIFO_REG
,
992 devpriv
->ao_buffer
, nsamples
);
995 static int cb_pcidas_ao_inttrig(struct comedi_device
*dev
,
996 struct comedi_subdevice
*s
,
997 unsigned int trig_num
)
999 const struct cb_pcidas_board
*board
= dev
->board_ptr
;
1000 struct cb_pcidas_private
*devpriv
= dev
->private;
1001 struct comedi_async
*async
= s
->async
;
1002 struct comedi_cmd
*cmd
= &async
->cmd
;
1003 unsigned long flags
;
1005 if (trig_num
!= cmd
->start_arg
)
1008 cb_pcidas_ao_load_fifo(dev
, s
, board
->fifo_size
);
1010 /* enable dac half-full and empty interrupts */
1011 spin_lock_irqsave(&dev
->spinlock
, flags
);
1012 devpriv
->ctrl
|= PCIDAS_CTRL_DAEMIE
| PCIDAS_CTRL_DAHFIE
;
1014 /* enable and clear interrupts */
1015 outw(devpriv
->ctrl
| PCIDAS_CTRL_DAEMI
| PCIDAS_CTRL_DAHFI
,
1016 devpriv
->pcibar1
+ PCIDAS_CTRL_REG
);
1019 devpriv
->ao_ctrl
|= PCIDAS_AO_START
| PCIDAS_AO_DACEN
| PCIDAS_AO_EMPTY
;
1020 outw(devpriv
->ao_ctrl
, devpriv
->pcibar1
+ PCIDAS_AO_REG
);
1022 spin_unlock_irqrestore(&dev
->spinlock
, flags
);
1024 async
->inttrig
= NULL
;
1029 static int cb_pcidas_ao_cmd(struct comedi_device
*dev
,
1030 struct comedi_subdevice
*s
)
1032 struct cb_pcidas_private
*devpriv
= dev
->private;
1033 struct comedi_async
*async
= s
->async
;
1034 struct comedi_cmd
*cmd
= &async
->cmd
;
1036 unsigned long flags
;
1038 /* set channel limits, gain */
1039 spin_lock_irqsave(&dev
->spinlock
, flags
);
1040 for (i
= 0; i
< cmd
->chanlist_len
; i
++) {
1041 unsigned int chan
= CR_CHAN(cmd
->chanlist
[i
]);
1042 unsigned int range
= CR_RANGE(cmd
->chanlist
[i
]);
1044 /* enable channel */
1045 devpriv
->ao_ctrl
|= PCIDAS_AO_CHAN_EN(chan
);
1047 devpriv
->ao_ctrl
|= PCIDAS_AO_RANGE(chan
, range
);
1050 /* disable analog out before settings pacer source and count values */
1051 outw(devpriv
->ao_ctrl
, devpriv
->pcibar1
+ PCIDAS_AO_REG
);
1052 spin_unlock_irqrestore(&dev
->spinlock
, flags
);
1055 outw(0, devpriv
->pcibar4
+ PCIDAS_AO_FIFO_CLR_REG
);
1058 if (cmd
->scan_begin_src
== TRIG_TIMER
) {
1059 comedi_8254_update_divisors(devpriv
->ao_pacer
);
1060 comedi_8254_pacer_enable(devpriv
->ao_pacer
, 1, 2, true);
1063 /* set pacer source */
1064 spin_lock_irqsave(&dev
->spinlock
, flags
);
1065 switch (cmd
->scan_begin_src
) {
1067 devpriv
->ao_ctrl
|= PCIDAS_AO_PACER_INT
;
1070 devpriv
->ao_ctrl
|= PCIDAS_AO_PACER_EXTP
;
1073 spin_unlock_irqrestore(&dev
->spinlock
, flags
);
1074 dev_err(dev
->class_dev
, "error setting dac pacer source\n");
1077 spin_unlock_irqrestore(&dev
->spinlock
, flags
);
1079 async
->inttrig
= cb_pcidas_ao_inttrig
;
1084 static int cb_pcidas_ao_cancel(struct comedi_device
*dev
,
1085 struct comedi_subdevice
*s
)
1087 struct cb_pcidas_private
*devpriv
= dev
->private;
1088 unsigned long flags
;
1090 spin_lock_irqsave(&dev
->spinlock
, flags
);
1091 /* disable interrupts */
1092 devpriv
->ctrl
&= ~(PCIDAS_CTRL_DAHFIE
| PCIDAS_CTRL_DAEMIE
);
1093 outw(devpriv
->ctrl
, devpriv
->pcibar1
+ PCIDAS_CTRL_REG
);
1095 /* disable output */
1096 devpriv
->ao_ctrl
&= ~(PCIDAS_AO_DACEN
| PCIDAS_AO_PACER_MASK
);
1097 outw(devpriv
->ao_ctrl
, devpriv
->pcibar1
+ PCIDAS_AO_REG
);
1098 spin_unlock_irqrestore(&dev
->spinlock
, flags
);
1103 static unsigned int cb_pcidas_ao_interrupt(struct comedi_device
*dev
,
1104 unsigned int status
)
1106 const struct cb_pcidas_board
*board
= dev
->board_ptr
;
1107 struct cb_pcidas_private
*devpriv
= dev
->private;
1108 struct comedi_subdevice
*s
= dev
->write_subdev
;
1109 struct comedi_async
*async
= s
->async
;
1110 struct comedi_cmd
*cmd
= &async
->cmd
;
1111 unsigned int irq_clr
= 0;
1113 if (status
& PCIDAS_CTRL_DAEMI
) {
1114 irq_clr
|= PCIDAS_CTRL_DAEMI
;
1116 if (inw(devpriv
->pcibar4
+ PCIDAS_AO_REG
) & PCIDAS_AO_EMPTY
) {
1117 if (cmd
->stop_src
== TRIG_COUNT
&&
1118 async
->scans_done
>= cmd
->stop_arg
) {
1119 async
->events
|= COMEDI_CB_EOA
;
1121 dev_err(dev
->class_dev
, "dac fifo underflow\n");
1122 async
->events
|= COMEDI_CB_ERROR
;
1125 } else if (status
& PCIDAS_CTRL_DAHFI
) {
1126 irq_clr
|= PCIDAS_CTRL_DAHFI
;
1128 cb_pcidas_ao_load_fifo(dev
, s
, board
->fifo_size
/ 2);
1131 comedi_handle_events(dev
, s
);
1136 static unsigned int cb_pcidas_ai_interrupt(struct comedi_device
*dev
,
1137 unsigned int status
)
1139 const struct cb_pcidas_board
*board
= dev
->board_ptr
;
1140 struct cb_pcidas_private
*devpriv
= dev
->private;
1141 struct comedi_subdevice
*s
= dev
->read_subdev
;
1142 struct comedi_async
*async
= s
->async
;
1143 struct comedi_cmd
*cmd
= &async
->cmd
;
1144 unsigned int irq_clr
= 0;
1146 if (status
& PCIDAS_CTRL_ADHFI
) {
1147 unsigned int num_samples
;
1149 irq_clr
|= PCIDAS_CTRL_INT_CLR
;
1151 /* FIFO is half-full - read data */
1152 num_samples
= comedi_nsamples_left(s
, board
->fifo_size
/ 2);
1153 insw(devpriv
->pcibar2
+ PCIDAS_AI_DATA_REG
,
1154 devpriv
->ai_buffer
, num_samples
);
1155 comedi_buf_write_samples(s
, devpriv
->ai_buffer
, num_samples
);
1157 if (cmd
->stop_src
== TRIG_COUNT
&&
1158 async
->scans_done
>= cmd
->stop_arg
)
1159 async
->events
|= COMEDI_CB_EOA
;
1160 } else if (status
& (PCIDAS_CTRL_ADNEI
| PCIDAS_CTRL_EOBI
)) {
1163 irq_clr
|= PCIDAS_CTRL_INT_CLR
;
1165 /* FIFO is not empty - read data until empty or timeoout */
1166 for (i
= 0; i
< 10000; i
++) {
1169 /* break if fifo is empty */
1170 if ((inw(devpriv
->pcibar1
+ PCIDAS_CTRL_REG
) &
1171 PCIDAS_CTRL_ADNE
) == 0)
1173 val
= inw(devpriv
->pcibar2
+ PCIDAS_AI_DATA_REG
);
1174 comedi_buf_write_samples(s
, &val
, 1);
1176 if (cmd
->stop_src
== TRIG_COUNT
&&
1177 async
->scans_done
>= cmd
->stop_arg
) {
1178 async
->events
|= COMEDI_CB_EOA
;
1182 } else if (status
& PCIDAS_CTRL_EOAI
) {
1183 irq_clr
|= PCIDAS_CTRL_EOAI
;
1185 dev_err(dev
->class_dev
,
1186 "bug! encountered end of acquisition interrupt?\n");
1189 /* check for fifo overflow */
1190 if (status
& PCIDAS_CTRL_LADFUL
) {
1191 irq_clr
|= PCIDAS_CTRL_LADFUL
;
1193 dev_err(dev
->class_dev
, "fifo overflow\n");
1194 async
->events
|= COMEDI_CB_ERROR
;
1197 comedi_handle_events(dev
, s
);
1202 static irqreturn_t
cb_pcidas_interrupt(int irq
, void *d
)
1204 struct comedi_device
*dev
= d
;
1205 struct cb_pcidas_private
*devpriv
= dev
->private;
1206 unsigned int irq_clr
= 0;
1207 unsigned int amcc_status
;
1208 unsigned int status
;
1213 amcc_status
= inl(devpriv
->amcc
+ AMCC_OP_REG_INTCSR
);
1215 if ((INTCSR_INTR_ASSERTED
& amcc_status
) == 0)
1218 /* make sure mailbox 4 is empty */
1219 inl_p(devpriv
->amcc
+ AMCC_OP_REG_IMB4
);
1220 /* clear interrupt on amcc s5933 */
1221 outl(devpriv
->amcc_intcsr
| INTCSR_INBOX_INTR_STATUS
,
1222 devpriv
->amcc
+ AMCC_OP_REG_INTCSR
);
1224 status
= inw(devpriv
->pcibar1
+ PCIDAS_CTRL_REG
);
1226 /* handle analog output interrupts */
1227 if (status
& PCIDAS_CTRL_AO_INT
)
1228 irq_clr
|= cb_pcidas_ao_interrupt(dev
, status
);
1230 /* handle analog input interrupts */
1231 if (status
& PCIDAS_CTRL_AI_INT
)
1232 irq_clr
|= cb_pcidas_ai_interrupt(dev
, status
);
1235 unsigned long flags
;
1237 spin_lock_irqsave(&dev
->spinlock
, flags
);
1238 outw(devpriv
->ctrl
| irq_clr
,
1239 devpriv
->pcibar1
+ PCIDAS_CTRL_REG
);
1240 spin_unlock_irqrestore(&dev
->spinlock
, flags
);
1246 static int cb_pcidas_auto_attach(struct comedi_device
*dev
,
1247 unsigned long context
)
1249 struct pci_dev
*pcidev
= comedi_to_pci_dev(dev
);
1250 const struct cb_pcidas_board
*board
= NULL
;
1251 struct cb_pcidas_private
*devpriv
;
1252 struct comedi_subdevice
*s
;
1256 if (context
< ARRAY_SIZE(cb_pcidas_boards
))
1257 board
= &cb_pcidas_boards
[context
];
1260 dev
->board_ptr
= board
;
1261 dev
->board_name
= board
->name
;
1263 devpriv
= comedi_alloc_devpriv(dev
, sizeof(*devpriv
));
1267 ret
= comedi_pci_enable(dev
);
1271 devpriv
->amcc
= pci_resource_start(pcidev
, 0);
1272 devpriv
->pcibar1
= pci_resource_start(pcidev
, 1);
1273 devpriv
->pcibar2
= pci_resource_start(pcidev
, 2);
1274 dev
->iobase
= pci_resource_start(pcidev
, 3);
1276 devpriv
->pcibar4
= pci_resource_start(pcidev
, 4);
1278 /* disable and clear interrupts on amcc s5933 */
1279 outl(INTCSR_INBOX_INTR_STATUS
,
1280 devpriv
->amcc
+ AMCC_OP_REG_INTCSR
);
1282 ret
= request_irq(pcidev
->irq
, cb_pcidas_interrupt
, IRQF_SHARED
,
1285 dev_dbg(dev
->class_dev
, "unable to allocate irq %d\n",
1289 dev
->irq
= pcidev
->irq
;
1291 dev
->pacer
= comedi_8254_io_alloc(dev
->iobase
+ PCIDAS_AI_8254_BASE
,
1292 I8254_OSC_BASE_10MHZ
, I8254_IO8
, 0);
1293 if (IS_ERR(dev
->pacer
))
1294 return PTR_ERR(dev
->pacer
);
1297 comedi_8254_io_alloc(dev
->iobase
+ PCIDAS_AO_8254_BASE
,
1298 I8254_OSC_BASE_10MHZ
, I8254_IO8
, 0);
1299 if (IS_ERR(devpriv
->ao_pacer
))
1300 return PTR_ERR(devpriv
->ao_pacer
);
1302 ret
= comedi_alloc_subdevices(dev
, 7);
1306 /* Analog Input subdevice */
1307 s
= &dev
->subdevices
[0];
1308 s
->type
= COMEDI_SUBD_AI
;
1309 s
->subdev_flags
= SDF_READABLE
| SDF_GROUND
| SDF_DIFF
;
1311 s
->maxdata
= board
->is_16bit
? 0xffff : 0x0fff;
1312 s
->range_table
= board
->use_alt_range
? &cb_pcidas_alt_ranges
1313 : &cb_pcidas_ranges
;
1314 s
->insn_read
= cb_pcidas_ai_insn_read
;
1315 s
->insn_config
= cb_pcidas_ai_insn_config
;
1317 dev
->read_subdev
= s
;
1318 s
->subdev_flags
|= SDF_CMD_READ
;
1319 s
->len_chanlist
= s
->n_chan
;
1320 s
->do_cmd
= cb_pcidas_ai_cmd
;
1321 s
->do_cmdtest
= cb_pcidas_ai_cmdtest
;
1322 s
->cancel
= cb_pcidas_ai_cancel
;
1325 /* Analog Output subdevice */
1326 s
= &dev
->subdevices
[1];
1327 if (board
->has_ao
) {
1328 s
->type
= COMEDI_SUBD_AO
;
1329 s
->subdev_flags
= SDF_WRITABLE
| SDF_GROUND
;
1331 s
->maxdata
= board
->is_16bit
? 0xffff : 0x0fff;
1332 s
->range_table
= &cb_pcidas_ao_ranges
;
1333 s
->insn_write
= (board
->has_ao_fifo
)
1334 ? cb_pcidas_ao_fifo_insn_write
1335 : cb_pcidas_ao_nofifo_insn_write
;
1337 ret
= comedi_alloc_subdev_readback(s
);
1341 if (dev
->irq
&& board
->has_ao_fifo
) {
1342 dev
->write_subdev
= s
;
1343 s
->subdev_flags
|= SDF_CMD_WRITE
;
1344 s
->len_chanlist
= s
->n_chan
;
1345 s
->do_cmdtest
= cb_pcidas_ao_cmdtest
;
1346 s
->do_cmd
= cb_pcidas_ao_cmd
;
1347 s
->cancel
= cb_pcidas_ao_cancel
;
1350 s
->type
= COMEDI_SUBD_UNUSED
;
1354 s
= &dev
->subdevices
[2];
1355 ret
= subdev_8255_io_init(dev
, s
, PCIDAS_8255_BASE
);
1359 /* Memory subdevice - serial EEPROM */
1360 s
= &dev
->subdevices
[3];
1361 s
->type
= COMEDI_SUBD_MEMORY
;
1362 s
->subdev_flags
= SDF_READABLE
| SDF_INTERNAL
;
1365 s
->insn_read
= cb_pcidas_eeprom_insn_read
;
1367 /* Calibration subdevice - 8800 caldac */
1368 s
= &dev
->subdevices
[4];
1369 s
->type
= COMEDI_SUBD_CALIB
;
1370 s
->subdev_flags
= SDF_WRITABLE
| SDF_INTERNAL
;
1373 s
->insn_write
= cb_pcidas_caldac_insn_write
;
1375 ret
= comedi_alloc_subdev_readback(s
);
1379 for (i
= 0; i
< s
->n_chan
; i
++) {
1380 unsigned int val
= s
->maxdata
/ 2;
1382 /* write 11-bit channel/value to caldac */
1383 cb_pcidas_calib_write(dev
, (i
<< 8) | val
, 11, false);
1384 s
->readback
[i
] = val
;
1387 /* Calibration subdevice - trim potentiometer */
1388 s
= &dev
->subdevices
[5];
1389 s
->type
= COMEDI_SUBD_CALIB
;
1390 s
->subdev_flags
= SDF_WRITABLE
| SDF_INTERNAL
;
1391 if (board
->has_ad8402
) {
1393 * pci-das1602/16 have an AD8402 trimpot:
1395 * chan 1 : adc postgain offset
1400 /* all other boards have an AD7376 trimpot */
1404 s
->insn_write
= cb_pcidas_trimpot_insn_write
;
1406 ret
= comedi_alloc_subdev_readback(s
);
1410 for (i
= 0; i
< s
->n_chan
; i
++) {
1411 cb_pcidas_trimpot_write(dev
, i
, s
->maxdata
/ 2);
1412 s
->readback
[i
] = s
->maxdata
/ 2;
1415 /* Calibration subdevice - pci-das1602/16 pregain offset (dac08) */
1416 s
= &dev
->subdevices
[6];
1417 if (board
->has_dac08
) {
1418 s
->type
= COMEDI_SUBD_CALIB
;
1419 s
->subdev_flags
= SDF_WRITABLE
| SDF_INTERNAL
;
1422 s
->insn_write
= cb_pcidas_dac08_insn_write
;
1424 ret
= comedi_alloc_subdev_readback(s
);
1428 for (i
= 0; i
< s
->n_chan
; i
++) {
1429 cb_pcidas_dac08_write(dev
, s
->maxdata
/ 2);
1430 s
->readback
[i
] = s
->maxdata
/ 2;
1433 s
->type
= COMEDI_SUBD_UNUSED
;
1436 /* make sure mailbox 4 is empty */
1437 inl(devpriv
->amcc
+ AMCC_OP_REG_IMB4
);
1438 /* Set bits to enable incoming mailbox interrupts on amcc s5933. */
1439 devpriv
->amcc_intcsr
= INTCSR_INBOX_BYTE(3) | INTCSR_INBOX_SELECT(3) |
1440 INTCSR_INBOX_FULL_INT
;
1441 /* clear and enable interrupt on amcc s5933 */
1442 outl(devpriv
->amcc_intcsr
| INTCSR_INBOX_INTR_STATUS
,
1443 devpriv
->amcc
+ AMCC_OP_REG_INTCSR
);
1448 static void cb_pcidas_detach(struct comedi_device
*dev
)
1450 struct cb_pcidas_private
*devpriv
= dev
->private;
1454 outl(INTCSR_INBOX_INTR_STATUS
,
1455 devpriv
->amcc
+ AMCC_OP_REG_INTCSR
);
1456 if (!IS_ERR(devpriv
->ao_pacer
))
1457 kfree(devpriv
->ao_pacer
);
1459 comedi_pci_detach(dev
);
1462 static struct comedi_driver cb_pcidas_driver
= {
1463 .driver_name
= "cb_pcidas",
1464 .module
= THIS_MODULE
,
1465 .auto_attach
= cb_pcidas_auto_attach
,
1466 .detach
= cb_pcidas_detach
,
1469 static int cb_pcidas_pci_probe(struct pci_dev
*dev
,
1470 const struct pci_device_id
*id
)
1472 return comedi_pci_auto_config(dev
, &cb_pcidas_driver
,
1476 static const struct pci_device_id cb_pcidas_pci_table
[] = {
1477 { PCI_VDEVICE(CB
, 0x0001), BOARD_PCIDAS1602_16
},
1478 { PCI_VDEVICE(CB
, 0x000f), BOARD_PCIDAS1200
},
1479 { PCI_VDEVICE(CB
, 0x0010), BOARD_PCIDAS1602_12
},
1480 { PCI_VDEVICE(CB
, 0x0019), BOARD_PCIDAS1200_JR
},
1481 { PCI_VDEVICE(CB
, 0x001c), BOARD_PCIDAS1602_16_JR
},
1482 { PCI_VDEVICE(CB
, 0x004c), BOARD_PCIDAS1000
},
1483 { PCI_VDEVICE(CB
, 0x001a), BOARD_PCIDAS1001
},
1484 { PCI_VDEVICE(CB
, 0x001b), BOARD_PCIDAS1002
},
1487 MODULE_DEVICE_TABLE(pci
, cb_pcidas_pci_table
);
1489 static struct pci_driver cb_pcidas_pci_driver
= {
1490 .name
= "cb_pcidas",
1491 .id_table
= cb_pcidas_pci_table
,
1492 .probe
= cb_pcidas_pci_probe
,
1493 .remove
= comedi_pci_auto_unconfig
,
1495 module_comedi_pci_driver(cb_pcidas_driver
, cb_pcidas_pci_driver
);
1497 MODULE_AUTHOR("Comedi https://www.comedi.org");
1498 MODULE_DESCRIPTION("Comedi driver for MeasurementComputing PCI-DAS series");
1499 MODULE_LICENSE("GPL");