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>
58 #include "../comedi_pci.h"
60 #include "comedi_8254.h"
62 #include "amcc_s5933.h"
64 #define AI_BUFFER_SIZE 1024 /* max ai fifo size */
65 #define AO_BUFFER_SIZE 1024 /* max ao fifo size */
68 * PCI BAR1 Register map (devpriv->pcibar1)
70 #define PCIDAS_CTRL_REG 0x00 /* INTERRUPT / ADC FIFO register */
71 #define PCIDAS_CTRL_INT(x) (((x) & 0x3) << 0)
72 #define PCIDAS_CTRL_INT_NONE PCIDAS_CTRL_INT(0) /* no int selected */
73 #define PCIDAS_CTRL_INT_EOS PCIDAS_CTRL_INT(1) /* int on end of scan */
74 #define PCIDAS_CTRL_INT_FHF PCIDAS_CTRL_INT(2) /* int on fifo half full */
75 #define PCIDAS_CTRL_INT_FNE PCIDAS_CTRL_INT(3) /* int on fifo not empty */
76 #define PCIDAS_CTRL_INT_MASK PCIDAS_CTRL_INT(3) /* mask of int select bits */
77 #define PCIDAS_CTRL_INTE BIT(2) /* int enable */
78 #define PCIDAS_CTRL_DAHFIE BIT(3) /* dac half full int enable */
79 #define PCIDAS_CTRL_EOAIE BIT(4) /* end of acq. int enable */
80 #define PCIDAS_CTRL_DAHFI BIT(5) /* dac half full status / clear */
81 #define PCIDAS_CTRL_EOAI BIT(6) /* end of acq. int status / clear */
82 #define PCIDAS_CTRL_INT_CLR BIT(7) /* int status / clear */
83 #define PCIDAS_CTRL_EOBI BIT(9) /* end of burst int status */
84 #define PCIDAS_CTRL_ADHFI BIT(10) /* half-full int status */
85 #define PCIDAS_CTRL_ADNEI BIT(11) /* fifo not empty int status (latch) */
86 #define PCIDAS_CTRL_ADNE BIT(12) /* fifo not empty status (realtime) */
87 #define PCIDAS_CTRL_DAEMIE BIT(12) /* dac empty int enable */
88 #define PCIDAS_CTRL_LADFUL BIT(13) /* fifo overflow / clear */
89 #define PCIDAS_CTRL_DAEMI BIT(14) /* dac fifo empty int status / clear */
91 #define PCIDAS_CTRL_AI_INT (PCIDAS_CTRL_EOAI | PCIDAS_CTRL_EOBI | \
92 PCIDAS_CTRL_ADHFI | PCIDAS_CTRL_ADNEI | \
94 #define PCIDAS_CTRL_AO_INT (PCIDAS_CTRL_DAHFI | PCIDAS_CTRL_DAEMI)
96 #define PCIDAS_AI_REG 0x02 /* ADC CHANNEL MUX AND CONTROL reg */
97 #define PCIDAS_AI_FIRST(x) ((x) & 0xf)
98 #define PCIDAS_AI_LAST(x) (((x) & 0xf) << 4)
99 #define PCIDAS_AI_CHAN(x) (PCIDAS_AI_FIRST(x) | PCIDAS_AI_LAST(x))
100 #define PCIDAS_AI_GAIN(x) (((x) & 0x3) << 8)
101 #define PCIDAS_AI_SE BIT(10) /* Inputs in single-ended mode */
102 #define PCIDAS_AI_UNIP BIT(11) /* Analog front-end unipolar mode */
103 #define PCIDAS_AI_PACER(x) (((x) & 0x3) << 12)
104 #define PCIDAS_AI_PACER_SW PCIDAS_AI_PACER(0) /* software pacer */
105 #define PCIDAS_AI_PACER_INT PCIDAS_AI_PACER(1) /* int. pacer */
106 #define PCIDAS_AI_PACER_EXTN PCIDAS_AI_PACER(2) /* ext. falling edge */
107 #define PCIDAS_AI_PACER_EXTP PCIDAS_AI_PACER(3) /* ext. rising edge */
108 #define PCIDAS_AI_PACER_MASK PCIDAS_AI_PACER(3) /* pacer source bits */
109 #define PCIDAS_AI_EOC BIT(14) /* adc not busy */
111 #define PCIDAS_TRIG_REG 0x04 /* TRIGGER CONTROL/STATUS register */
112 #define PCIDAS_TRIG_SEL(x) (((x) & 0x3) << 0)
113 #define PCIDAS_TRIG_SEL_NONE PCIDAS_TRIG_SEL(0) /* no start trigger */
114 #define PCIDAS_TRIG_SEL_SW PCIDAS_TRIG_SEL(1) /* software start trigger */
115 #define PCIDAS_TRIG_SEL_EXT PCIDAS_TRIG_SEL(2) /* ext. start trigger */
116 #define PCIDAS_TRIG_SEL_ANALOG PCIDAS_TRIG_SEL(3) /* ext. analog trigger */
117 #define PCIDAS_TRIG_SEL_MASK PCIDAS_TRIG_SEL(3) /* start trigger mask */
118 #define PCIDAS_TRIG_POL BIT(2) /* invert trigger (1602 only) */
119 #define PCIDAS_TRIG_MODE BIT(3) /* edge/level triggered (1602 only) */
120 #define PCIDAS_TRIG_EN BIT(4) /* enable external start trigger */
121 #define PCIDAS_TRIG_BURSTE BIT(5) /* burst mode enable */
122 #define PCIDAS_TRIG_CLR BIT(7) /* clear external trigger */
124 #define PCIDAS_CALIB_REG 0x06 /* CALIBRATION register */
125 #define PCIDAS_CALIB_8800_SEL BIT(8) /* select 8800 caldac */
126 #define PCIDAS_CALIB_TRIM_SEL BIT(9) /* select ad7376 trim pot */
127 #define PCIDAS_CALIB_DAC08_SEL BIT(10) /* select dac08 caldac */
128 #define PCIDAS_CALIB_SRC(x) (((x) & 0x7) << 11)
129 #define PCIDAS_CALIB_EN BIT(14) /* calibration source enable */
130 #define PCIDAS_CALIB_DATA BIT(15) /* serial data bit going to caldac */
132 #define PCIDAS_AO_REG 0x08 /* dac control and status register */
133 #define PCIDAS_AO_EMPTY BIT(0) /* fifo empty, write clear (1602) */
134 #define PCIDAS_AO_DACEN BIT(1) /* dac enable */
135 #define PCIDAS_AO_START BIT(2) /* start/arm fifo (1602) */
136 #define PCIDAS_AO_PACER(x) (((x) & 0x3) << 3) /* (1602) */
137 #define PCIDAS_AO_PACER_SW PCIDAS_AO_PACER(0) /* software pacer */
138 #define PCIDAS_AO_PACER_INT PCIDAS_AO_PACER(1) /* int. pacer */
139 #define PCIDAS_AO_PACER_EXTN PCIDAS_AO_PACER(2) /* ext. falling edge */
140 #define PCIDAS_AO_PACER_EXTP PCIDAS_AO_PACER(3) /* ext. rising edge */
141 #define PCIDAS_AO_PACER_MASK PCIDAS_AO_PACER(3) /* pacer source bits */
142 #define PCIDAS_AO_CHAN_EN(c) BIT(5 + ((c) & 0x1))
143 #define PCIDAS_AO_CHAN_MASK (PCIDAS_AO_CHAN_EN(0) | PCIDAS_AO_CHAN_EN(1))
144 #define PCIDAS_AO_UPDATE_BOTH BIT(7) /* update both dacs */
145 #define PCIDAS_AO_RANGE(c, r) (((r) & 0x3) << (8 + 2 * ((c) & 0x1)))
146 #define PCIDAS_AO_RANGE_MASK(c) PCIDAS_AO_RANGE((c), 0x3)
149 * PCI BAR2 Register map (devpriv->pcibar2)
151 #define PCIDAS_AI_DATA_REG 0x00
152 #define PCIDAS_AI_FIFO_CLR_REG 0x02
155 * PCI BAR3 Register map (dev->iobase)
157 #define PCIDAS_AI_8254_BASE 0x00
158 #define PCIDAS_8255_BASE 0x04
159 #define PCIDAS_AO_8254_BASE 0x08
162 * PCI BAR4 Register map (devpriv->pcibar4)
164 #define PCIDAS_AO_DATA_REG(x) (0x00 + ((x) * 2))
165 #define PCIDAS_AO_FIFO_REG 0x00
166 #define PCIDAS_AO_FIFO_CLR_REG 0x02
168 /* analog input ranges for most boards */
169 static const struct comedi_lrange cb_pcidas_ranges
= {
182 /* pci-das1001 input ranges */
183 static const struct comedi_lrange cb_pcidas_alt_ranges
= {
196 /* analog output ranges */
197 static const struct comedi_lrange cb_pcidas_ao_ranges
= {
206 enum cb_pcidas_boardid
{
211 BOARD_PCIDAS1602_16_JR
,
217 struct cb_pcidas_board
{
219 int ai_speed
; /* fastest conversion period in ns */
220 int ao_scan_speed
; /* analog output scan speed for 1602 series */
221 int fifo_size
; /* number of samples fifo can hold */
222 unsigned int is_16bit
; /* ai/ao is 1=16-bit; 0=12-bit */
223 unsigned int use_alt_range
:1; /* use alternate ai range table */
224 unsigned int has_ao
:1; /* has 2 analog output channels */
225 unsigned int has_ao_fifo
:1; /* analog output has fifo */
226 unsigned int has_ad8402
:1; /* trimpot type 1=AD8402; 0=AD7376 */
227 unsigned int has_dac08
:1;
228 unsigned int is_1602
:1;
231 static const struct cb_pcidas_board cb_pcidas_boards
[] = {
232 [BOARD_PCIDAS1602_16
] = {
233 .name
= "pci-das1602/16",
235 .ao_scan_speed
= 10000,
244 [BOARD_PCIDAS1200
] = {
245 .name
= "pci-das1200",
250 [BOARD_PCIDAS1602_12
] = {
251 .name
= "pci-das1602/12",
253 .ao_scan_speed
= 4000,
259 [BOARD_PCIDAS1200_JR
] = {
260 .name
= "pci-das1200/jr",
264 [BOARD_PCIDAS1602_16_JR
] = {
265 .name
= "pci-das1602/16/jr",
273 [BOARD_PCIDAS1000
] = {
274 .name
= "pci-das1000",
278 [BOARD_PCIDAS1001
] = {
279 .name
= "pci-das1001",
285 [BOARD_PCIDAS1002
] = {
286 .name
= "pci-das1002",
293 struct cb_pcidas_private
{
294 struct comedi_8254
*ao_pacer
;
296 unsigned long amcc
; /* pcibar0 */
297 unsigned long pcibar1
;
298 unsigned long pcibar2
;
299 unsigned long pcibar4
;
300 /* bits to write to registers */
302 unsigned int amcc_intcsr
;
303 unsigned int ao_ctrl
;
305 unsigned short ai_buffer
[AI_BUFFER_SIZE
];
306 unsigned short ao_buffer
[AO_BUFFER_SIZE
];
307 unsigned int calib_src
;
310 static int cb_pcidas_ai_eoc(struct comedi_device
*dev
,
311 struct comedi_subdevice
*s
,
312 struct comedi_insn
*insn
,
313 unsigned long context
)
315 struct cb_pcidas_private
*devpriv
= dev
->private;
318 status
= inw(devpriv
->pcibar1
+ PCIDAS_AI_REG
);
319 if (status
& PCIDAS_AI_EOC
)
324 static int cb_pcidas_ai_insn_read(struct comedi_device
*dev
,
325 struct comedi_subdevice
*s
,
326 struct comedi_insn
*insn
,
329 struct cb_pcidas_private
*devpriv
= dev
->private;
330 unsigned int chan
= CR_CHAN(insn
->chanspec
);
331 unsigned int range
= CR_RANGE(insn
->chanspec
);
332 unsigned int aref
= CR_AREF(insn
->chanspec
);
337 /* enable calibration input if appropriate */
338 if (insn
->chanspec
& CR_ALT_SOURCE
) {
339 outw(PCIDAS_CALIB_EN
| PCIDAS_CALIB_SRC(devpriv
->calib_src
),
340 devpriv
->pcibar1
+ PCIDAS_CALIB_REG
);
343 outw(0, devpriv
->pcibar1
+ PCIDAS_CALIB_REG
);
346 /* set mux limits and gain */
347 bits
= PCIDAS_AI_CHAN(chan
) | PCIDAS_AI_GAIN(range
);
348 /* set unipolar/bipolar */
349 if (comedi_range_is_unipolar(s
, range
))
350 bits
|= PCIDAS_AI_UNIP
;
351 /* set single-ended/differential */
352 if (aref
!= AREF_DIFF
)
353 bits
|= PCIDAS_AI_SE
;
354 outw(bits
, devpriv
->pcibar1
+ PCIDAS_AI_REG
);
357 outw(0, devpriv
->pcibar2
+ PCIDAS_AI_FIFO_CLR_REG
);
359 /* convert n samples */
360 for (n
= 0; n
< insn
->n
; n
++) {
361 /* trigger conversion */
362 outw(0, devpriv
->pcibar2
+ PCIDAS_AI_DATA_REG
);
364 /* wait for conversion to end */
365 ret
= comedi_timeout(dev
, s
, insn
, cb_pcidas_ai_eoc
, 0);
370 data
[n
] = inw(devpriv
->pcibar2
+ PCIDAS_AI_DATA_REG
);
373 /* return the number of samples read/written */
377 static int cb_pcidas_ai_insn_config(struct comedi_device
*dev
,
378 struct comedi_subdevice
*s
,
379 struct comedi_insn
*insn
,
382 struct cb_pcidas_private
*devpriv
= dev
->private;
384 unsigned int source
= data
[1];
387 case INSN_CONFIG_ALT_SOURCE
:
389 dev_err(dev
->class_dev
,
390 "invalid calibration source: %i\n",
394 devpriv
->calib_src
= source
;
402 /* analog output insn for pcidas-1000 and 1200 series */
403 static int cb_pcidas_ao_nofifo_insn_write(struct comedi_device
*dev
,
404 struct comedi_subdevice
*s
,
405 struct comedi_insn
*insn
,
408 struct cb_pcidas_private
*devpriv
= dev
->private;
409 unsigned int chan
= CR_CHAN(insn
->chanspec
);
410 unsigned int range
= CR_RANGE(insn
->chanspec
);
411 unsigned int val
= s
->readback
[chan
];
415 /* set channel and range */
416 spin_lock_irqsave(&dev
->spinlock
, flags
);
417 devpriv
->ao_ctrl
&= ~(PCIDAS_AO_UPDATE_BOTH
|
418 PCIDAS_AO_RANGE_MASK(chan
));
419 devpriv
->ao_ctrl
|= PCIDAS_AO_DACEN
| PCIDAS_AO_RANGE(chan
, range
);
420 outw(devpriv
->ao_ctrl
, devpriv
->pcibar1
+ PCIDAS_AO_REG
);
421 spin_unlock_irqrestore(&dev
->spinlock
, flags
);
423 for (i
= 0; i
< insn
->n
; i
++) {
425 outw(val
, devpriv
->pcibar4
+ PCIDAS_AO_DATA_REG(chan
));
428 s
->readback
[chan
] = val
;
433 /* analog output insn for pcidas-1602 series */
434 static int cb_pcidas_ao_fifo_insn_write(struct comedi_device
*dev
,
435 struct comedi_subdevice
*s
,
436 struct comedi_insn
*insn
,
439 struct cb_pcidas_private
*devpriv
= dev
->private;
440 unsigned int chan
= CR_CHAN(insn
->chanspec
);
441 unsigned int range
= CR_RANGE(insn
->chanspec
);
442 unsigned int val
= s
->readback
[chan
];
447 outw(0, devpriv
->pcibar4
+ PCIDAS_AO_FIFO_CLR_REG
);
449 /* set channel and range */
450 spin_lock_irqsave(&dev
->spinlock
, flags
);
451 devpriv
->ao_ctrl
&= ~(PCIDAS_AO_CHAN_MASK
| PCIDAS_AO_RANGE_MASK(chan
) |
452 PCIDAS_AO_PACER_MASK
);
453 devpriv
->ao_ctrl
|= PCIDAS_AO_DACEN
| PCIDAS_AO_RANGE(chan
, range
) |
454 PCIDAS_AO_CHAN_EN(chan
) | PCIDAS_AO_START
;
455 outw(devpriv
->ao_ctrl
, devpriv
->pcibar1
+ PCIDAS_AO_REG
);
456 spin_unlock_irqrestore(&dev
->spinlock
, flags
);
458 for (i
= 0; i
< insn
->n
; i
++) {
460 outw(val
, devpriv
->pcibar4
+ PCIDAS_AO_FIFO_REG
);
463 s
->readback
[chan
] = val
;
468 static int cb_pcidas_eeprom_ready(struct comedi_device
*dev
,
469 struct comedi_subdevice
*s
,
470 struct comedi_insn
*insn
,
471 unsigned long context
)
473 struct cb_pcidas_private
*devpriv
= dev
->private;
476 status
= inb(devpriv
->amcc
+ AMCC_OP_REG_MCSR_NVCMD
);
477 if ((status
& MCSR_NV_BUSY
) == 0)
482 static int cb_pcidas_eeprom_insn_read(struct comedi_device
*dev
,
483 struct comedi_subdevice
*s
,
484 struct comedi_insn
*insn
,
487 struct cb_pcidas_private
*devpriv
= dev
->private;
488 unsigned int chan
= CR_CHAN(insn
->chanspec
);
492 for (i
= 0; i
< insn
->n
; i
++) {
493 /* make sure eeprom is ready */
494 ret
= comedi_timeout(dev
, s
, insn
, cb_pcidas_eeprom_ready
, 0);
498 /* set address (chan) and read operation */
499 outb(MCSR_NV_ENABLE
| MCSR_NV_LOAD_LOW_ADDR
,
500 devpriv
->amcc
+ AMCC_OP_REG_MCSR_NVCMD
);
501 outb(chan
& 0xff, devpriv
->amcc
+ AMCC_OP_REG_MCSR_NVDATA
);
502 outb(MCSR_NV_ENABLE
| MCSR_NV_LOAD_HIGH_ADDR
,
503 devpriv
->amcc
+ AMCC_OP_REG_MCSR_NVCMD
);
504 outb((chan
>> 8) & 0xff,
505 devpriv
->amcc
+ AMCC_OP_REG_MCSR_NVDATA
);
506 outb(MCSR_NV_ENABLE
| MCSR_NV_READ
,
507 devpriv
->amcc
+ AMCC_OP_REG_MCSR_NVCMD
);
509 /* wait for data to be returned */
510 ret
= comedi_timeout(dev
, s
, insn
, cb_pcidas_eeprom_ready
, 0);
514 data
[i
] = inb(devpriv
->amcc
+ AMCC_OP_REG_MCSR_NVDATA
);
520 static void cb_pcidas_calib_write(struct comedi_device
*dev
,
521 unsigned int val
, unsigned int len
,
524 struct cb_pcidas_private
*devpriv
= dev
->private;
525 unsigned int calib_bits
;
528 calib_bits
= PCIDAS_CALIB_EN
| PCIDAS_CALIB_SRC(devpriv
->calib_src
);
531 calib_bits
|= PCIDAS_CALIB_TRIM_SEL
;
532 outw(calib_bits
, devpriv
->pcibar1
+ PCIDAS_CALIB_REG
);
535 /* write bitstream to calibration device */
536 for (bit
= 1 << (len
- 1); bit
; bit
>>= 1) {
538 calib_bits
|= PCIDAS_CALIB_DATA
;
540 calib_bits
&= ~PCIDAS_CALIB_DATA
;
542 outw(calib_bits
, devpriv
->pcibar1
+ PCIDAS_CALIB_REG
);
546 calib_bits
= PCIDAS_CALIB_EN
| PCIDAS_CALIB_SRC(devpriv
->calib_src
);
550 outw(calib_bits
| PCIDAS_CALIB_8800_SEL
,
551 devpriv
->pcibar1
+ PCIDAS_CALIB_REG
);
555 /* latch value to trimpot/caldac */
556 outw(calib_bits
, devpriv
->pcibar1
+ PCIDAS_CALIB_REG
);
559 static int cb_pcidas_caldac_insn_write(struct comedi_device
*dev
,
560 struct comedi_subdevice
*s
,
561 struct comedi_insn
*insn
,
564 unsigned int chan
= CR_CHAN(insn
->chanspec
);
567 unsigned int val
= data
[insn
->n
- 1];
569 if (s
->readback
[chan
] != val
) {
570 /* write 11-bit channel/value to caldac */
571 cb_pcidas_calib_write(dev
, (chan
<< 8) | val
, 11,
573 s
->readback
[chan
] = val
;
580 static void cb_pcidas_dac08_write(struct comedi_device
*dev
, unsigned int val
)
582 struct cb_pcidas_private
*devpriv
= dev
->private;
584 val
|= PCIDAS_CALIB_EN
| PCIDAS_CALIB_SRC(devpriv
->calib_src
);
586 /* latch the new value into the caldac */
587 outw(val
, devpriv
->pcibar1
+ PCIDAS_CALIB_REG
);
589 outw(val
| PCIDAS_CALIB_DAC08_SEL
,
590 devpriv
->pcibar1
+ PCIDAS_CALIB_REG
);
592 outw(val
, devpriv
->pcibar1
+ PCIDAS_CALIB_REG
);
596 static int cb_pcidas_dac08_insn_write(struct comedi_device
*dev
,
597 struct comedi_subdevice
*s
,
598 struct comedi_insn
*insn
,
601 unsigned int chan
= CR_CHAN(insn
->chanspec
);
604 unsigned int val
= data
[insn
->n
- 1];
606 if (s
->readback
[chan
] != val
) {
607 cb_pcidas_dac08_write(dev
, val
);
608 s
->readback
[chan
] = val
;
615 static void cb_pcidas_trimpot_write(struct comedi_device
*dev
,
616 unsigned int chan
, unsigned int val
)
618 const struct cb_pcidas_board
*board
= dev
->board_ptr
;
620 if (board
->has_ad8402
) {
621 /* write 10-bit channel/value to AD8402 trimpot */
622 cb_pcidas_calib_write(dev
, (chan
<< 8) | val
, 10, true);
624 /* write 7-bit value to AD7376 trimpot */
625 cb_pcidas_calib_write(dev
, val
, 7, true);
629 static int cb_pcidas_trimpot_insn_write(struct comedi_device
*dev
,
630 struct comedi_subdevice
*s
,
631 struct comedi_insn
*insn
,
634 unsigned int chan
= CR_CHAN(insn
->chanspec
);
637 unsigned int val
= data
[insn
->n
- 1];
639 if (s
->readback
[chan
] != val
) {
640 cb_pcidas_trimpot_write(dev
, chan
, val
);
641 s
->readback
[chan
] = val
;
648 static int cb_pcidas_ai_check_chanlist(struct comedi_device
*dev
,
649 struct comedi_subdevice
*s
,
650 struct comedi_cmd
*cmd
)
652 unsigned int chan0
= CR_CHAN(cmd
->chanlist
[0]);
653 unsigned int range0
= CR_RANGE(cmd
->chanlist
[0]);
656 for (i
= 1; i
< cmd
->chanlist_len
; i
++) {
657 unsigned int chan
= CR_CHAN(cmd
->chanlist
[i
]);
658 unsigned int range
= CR_RANGE(cmd
->chanlist
[i
]);
660 if (chan
!= (chan0
+ i
) % s
->n_chan
) {
661 dev_dbg(dev
->class_dev
,
662 "entries in chanlist must be consecutive channels, counting upwards\n");
666 if (range
!= range0
) {
667 dev_dbg(dev
->class_dev
,
668 "entries in chanlist must all have the same gain\n");
675 static int cb_pcidas_ai_cmdtest(struct comedi_device
*dev
,
676 struct comedi_subdevice
*s
,
677 struct comedi_cmd
*cmd
)
679 const struct cb_pcidas_board
*board
= dev
->board_ptr
;
683 /* Step 1 : check if triggers are trivially valid */
685 err
|= comedi_check_trigger_src(&cmd
->start_src
, TRIG_NOW
| TRIG_EXT
);
686 err
|= comedi_check_trigger_src(&cmd
->scan_begin_src
,
687 TRIG_FOLLOW
| TRIG_TIMER
| TRIG_EXT
);
688 err
|= comedi_check_trigger_src(&cmd
->convert_src
,
689 TRIG_TIMER
| TRIG_NOW
| TRIG_EXT
);
690 err
|= comedi_check_trigger_src(&cmd
->scan_end_src
, TRIG_COUNT
);
691 err
|= comedi_check_trigger_src(&cmd
->stop_src
, TRIG_COUNT
| TRIG_NONE
);
696 /* Step 2a : make sure trigger sources are unique */
698 err
|= comedi_check_trigger_is_unique(cmd
->start_src
);
699 err
|= comedi_check_trigger_is_unique(cmd
->scan_begin_src
);
700 err
|= comedi_check_trigger_is_unique(cmd
->convert_src
);
701 err
|= comedi_check_trigger_is_unique(cmd
->stop_src
);
703 /* Step 2b : and mutually compatible */
705 if (cmd
->scan_begin_src
== TRIG_FOLLOW
&& cmd
->convert_src
== TRIG_NOW
)
707 if (cmd
->scan_begin_src
!= TRIG_FOLLOW
&& cmd
->convert_src
!= TRIG_NOW
)
709 if (cmd
->start_src
== TRIG_EXT
&&
710 (cmd
->convert_src
== TRIG_EXT
|| cmd
->scan_begin_src
== TRIG_EXT
))
716 /* Step 3: check if arguments are trivially valid */
718 switch (cmd
->start_src
) {
720 err
|= comedi_check_trigger_arg_is(&cmd
->start_arg
, 0);
723 /* External trigger, only CR_EDGE and CR_INVERT flags allowed */
725 & (CR_FLAGS_MASK
& ~(CR_EDGE
| CR_INVERT
))) != 0) {
726 cmd
->start_arg
&= ~(CR_FLAGS_MASK
&
727 ~(CR_EDGE
| CR_INVERT
));
730 if (!board
->is_1602
&& (cmd
->start_arg
& CR_INVERT
)) {
731 cmd
->start_arg
&= (CR_FLAGS_MASK
& ~CR_INVERT
);
737 if (cmd
->scan_begin_src
== TRIG_TIMER
) {
738 err
|= comedi_check_trigger_arg_min(&cmd
->scan_begin_arg
,
743 if (cmd
->convert_src
== TRIG_TIMER
) {
744 err
|= comedi_check_trigger_arg_min(&cmd
->convert_arg
,
748 err
|= comedi_check_trigger_arg_is(&cmd
->scan_end_arg
,
751 if (cmd
->stop_src
== TRIG_COUNT
)
752 err
|= comedi_check_trigger_arg_min(&cmd
->stop_arg
, 1);
754 err
|= comedi_check_trigger_arg_is(&cmd
->stop_arg
, 0);
759 /* step 4: fix up any arguments */
761 if (cmd
->scan_begin_src
== TRIG_TIMER
) {
762 arg
= cmd
->scan_begin_arg
;
763 comedi_8254_cascade_ns_to_timer(dev
->pacer
, &arg
, cmd
->flags
);
764 err
|= comedi_check_trigger_arg_is(&cmd
->scan_begin_arg
, arg
);
766 if (cmd
->convert_src
== TRIG_TIMER
) {
767 arg
= cmd
->convert_arg
;
768 comedi_8254_cascade_ns_to_timer(dev
->pacer
, &arg
, cmd
->flags
);
769 err
|= comedi_check_trigger_arg_is(&cmd
->convert_arg
, arg
);
775 /* Step 5: check channel list if it exists */
776 if (cmd
->chanlist
&& cmd
->chanlist_len
> 0)
777 err
|= cb_pcidas_ai_check_chanlist(dev
, s
, cmd
);
785 static int cb_pcidas_ai_cmd(struct comedi_device
*dev
,
786 struct comedi_subdevice
*s
)
788 const struct cb_pcidas_board
*board
= dev
->board_ptr
;
789 struct cb_pcidas_private
*devpriv
= dev
->private;
790 struct comedi_async
*async
= s
->async
;
791 struct comedi_cmd
*cmd
= &async
->cmd
;
792 unsigned int range0
= CR_RANGE(cmd
->chanlist
[0]);
796 /* make sure PCIDAS_CALIB_EN is disabled */
797 outw(0, devpriv
->pcibar1
+ PCIDAS_CALIB_REG
);
798 /* initialize before settings pacer source and count values */
799 outw(PCIDAS_TRIG_SEL_NONE
, devpriv
->pcibar1
+ PCIDAS_TRIG_REG
);
801 outw(0, devpriv
->pcibar2
+ PCIDAS_AI_FIFO_CLR_REG
);
803 /* set mux limits, gain and pacer source */
804 bits
= PCIDAS_AI_FIRST(CR_CHAN(cmd
->chanlist
[0])) |
805 PCIDAS_AI_LAST(CR_CHAN(cmd
->chanlist
[cmd
->chanlist_len
- 1])) |
806 PCIDAS_AI_GAIN(range0
);
807 /* set unipolar/bipolar */
808 if (comedi_range_is_unipolar(s
, range0
))
809 bits
|= PCIDAS_AI_UNIP
;
810 /* set singleended/differential */
811 if (CR_AREF(cmd
->chanlist
[0]) != AREF_DIFF
)
812 bits
|= PCIDAS_AI_SE
;
813 /* set pacer source */
814 if (cmd
->convert_src
== TRIG_EXT
|| cmd
->scan_begin_src
== TRIG_EXT
)
815 bits
|= PCIDAS_AI_PACER_EXTP
;
817 bits
|= PCIDAS_AI_PACER_INT
;
818 outw(bits
, devpriv
->pcibar1
+ PCIDAS_AI_REG
);
821 if (cmd
->scan_begin_src
== TRIG_TIMER
||
822 cmd
->convert_src
== TRIG_TIMER
) {
823 comedi_8254_update_divisors(dev
->pacer
);
824 comedi_8254_pacer_enable(dev
->pacer
, 1, 2, true);
827 /* enable interrupts */
828 spin_lock_irqsave(&dev
->spinlock
, flags
);
829 devpriv
->ctrl
|= PCIDAS_CTRL_INTE
;
830 devpriv
->ctrl
&= ~PCIDAS_CTRL_INT_MASK
;
831 if (cmd
->flags
& CMDF_WAKE_EOS
) {
832 if (cmd
->convert_src
== TRIG_NOW
&& cmd
->chanlist_len
> 1) {
833 /* interrupt end of burst */
834 devpriv
->ctrl
|= PCIDAS_CTRL_INT_EOS
;
836 /* interrupt fifo not empty */
837 devpriv
->ctrl
|= PCIDAS_CTRL_INT_FNE
;
840 /* interrupt fifo half full */
841 devpriv
->ctrl
|= PCIDAS_CTRL_INT_FHF
;
844 /* enable (and clear) interrupts */
846 PCIDAS_CTRL_EOAI
| PCIDAS_CTRL_INT_CLR
| PCIDAS_CTRL_LADFUL
,
847 devpriv
->pcibar1
+ PCIDAS_CTRL_REG
);
848 spin_unlock_irqrestore(&dev
->spinlock
, flags
);
850 /* set start trigger and burst mode */
852 if (cmd
->start_src
== TRIG_NOW
) {
853 bits
|= PCIDAS_TRIG_SEL_SW
;
854 } else { /* TRIG_EXT */
855 bits
|= PCIDAS_TRIG_SEL_EXT
| PCIDAS_TRIG_EN
| PCIDAS_TRIG_CLR
;
856 if (board
->is_1602
) {
857 if (cmd
->start_arg
& CR_INVERT
)
858 bits
|= PCIDAS_TRIG_POL
;
859 if (cmd
->start_arg
& CR_EDGE
)
860 bits
|= PCIDAS_TRIG_MODE
;
863 if (cmd
->convert_src
== TRIG_NOW
&& cmd
->chanlist_len
> 1)
864 bits
|= PCIDAS_TRIG_BURSTE
;
865 outw(bits
, devpriv
->pcibar1
+ PCIDAS_TRIG_REG
);
870 static int cb_pcidas_ao_check_chanlist(struct comedi_device
*dev
,
871 struct comedi_subdevice
*s
,
872 struct comedi_cmd
*cmd
)
874 unsigned int chan0
= CR_CHAN(cmd
->chanlist
[0]);
876 if (cmd
->chanlist_len
> 1) {
877 unsigned int chan1
= CR_CHAN(cmd
->chanlist
[1]);
879 if (chan0
!= 0 || chan1
!= 1) {
880 dev_dbg(dev
->class_dev
,
881 "channels must be ordered channel 0, channel 1 in chanlist\n");
889 static int cb_pcidas_ao_cmdtest(struct comedi_device
*dev
,
890 struct comedi_subdevice
*s
,
891 struct comedi_cmd
*cmd
)
893 const struct cb_pcidas_board
*board
= dev
->board_ptr
;
894 struct cb_pcidas_private
*devpriv
= dev
->private;
897 /* Step 1 : check if triggers are trivially valid */
899 err
|= comedi_check_trigger_src(&cmd
->start_src
, TRIG_INT
);
900 err
|= comedi_check_trigger_src(&cmd
->scan_begin_src
,
901 TRIG_TIMER
| TRIG_EXT
);
902 err
|= comedi_check_trigger_src(&cmd
->convert_src
, TRIG_NOW
);
903 err
|= comedi_check_trigger_src(&cmd
->scan_end_src
, TRIG_COUNT
);
904 err
|= comedi_check_trigger_src(&cmd
->stop_src
, TRIG_COUNT
| TRIG_NONE
);
909 /* Step 2a : make sure trigger sources are unique */
911 err
|= comedi_check_trigger_is_unique(cmd
->scan_begin_src
);
912 err
|= comedi_check_trigger_is_unique(cmd
->stop_src
);
914 /* Step 2b : and mutually compatible */
919 /* Step 3: check if arguments are trivially valid */
921 err
|= comedi_check_trigger_arg_is(&cmd
->start_arg
, 0);
923 if (cmd
->scan_begin_src
== TRIG_TIMER
) {
924 err
|= comedi_check_trigger_arg_min(&cmd
->scan_begin_arg
,
925 board
->ao_scan_speed
);
928 err
|= comedi_check_trigger_arg_is(&cmd
->scan_end_arg
,
931 if (cmd
->stop_src
== TRIG_COUNT
)
932 err
|= comedi_check_trigger_arg_min(&cmd
->stop_arg
, 1);
934 err
|= comedi_check_trigger_arg_is(&cmd
->stop_arg
, 0);
939 /* step 4: fix up any arguments */
941 if (cmd
->scan_begin_src
== TRIG_TIMER
) {
942 unsigned int arg
= cmd
->scan_begin_arg
;
944 comedi_8254_cascade_ns_to_timer(devpriv
->ao_pacer
,
946 err
|= comedi_check_trigger_arg_is(&cmd
->scan_begin_arg
, arg
);
952 /* Step 5: check channel list if it exists */
953 if (cmd
->chanlist
&& cmd
->chanlist_len
> 0)
954 err
|= cb_pcidas_ao_check_chanlist(dev
, s
, cmd
);
962 static int cb_pcidas_ai_cancel(struct comedi_device
*dev
,
963 struct comedi_subdevice
*s
)
965 struct cb_pcidas_private
*devpriv
= dev
->private;
968 spin_lock_irqsave(&dev
->spinlock
, flags
);
969 /* disable interrupts */
970 devpriv
->ctrl
&= ~(PCIDAS_CTRL_INTE
| PCIDAS_CTRL_EOAIE
);
971 outw(devpriv
->ctrl
, devpriv
->pcibar1
+ PCIDAS_CTRL_REG
);
972 spin_unlock_irqrestore(&dev
->spinlock
, flags
);
974 /* disable start trigger source and burst mode */
975 outw(PCIDAS_TRIG_SEL_NONE
, devpriv
->pcibar1
+ PCIDAS_TRIG_REG
);
976 outw(PCIDAS_AI_PACER_SW
, devpriv
->pcibar1
+ PCIDAS_AI_REG
);
981 static void cb_pcidas_ao_load_fifo(struct comedi_device
*dev
,
982 struct comedi_subdevice
*s
,
983 unsigned int nsamples
)
985 struct cb_pcidas_private
*devpriv
= dev
->private;
988 nsamples
= comedi_nsamples_left(s
, nsamples
);
989 nbytes
= comedi_buf_read_samples(s
, devpriv
->ao_buffer
, nsamples
);
991 nsamples
= comedi_bytes_to_samples(s
, nbytes
);
992 outsw(devpriv
->pcibar4
+ PCIDAS_AO_FIFO_REG
,
993 devpriv
->ao_buffer
, nsamples
);
996 static int cb_pcidas_ao_inttrig(struct comedi_device
*dev
,
997 struct comedi_subdevice
*s
,
998 unsigned int trig_num
)
1000 const struct cb_pcidas_board
*board
= dev
->board_ptr
;
1001 struct cb_pcidas_private
*devpriv
= dev
->private;
1002 struct comedi_async
*async
= s
->async
;
1003 struct comedi_cmd
*cmd
= &async
->cmd
;
1004 unsigned long flags
;
1006 if (trig_num
!= cmd
->start_arg
)
1009 cb_pcidas_ao_load_fifo(dev
, s
, board
->fifo_size
);
1011 /* enable dac half-full and empty interrupts */
1012 spin_lock_irqsave(&dev
->spinlock
, flags
);
1013 devpriv
->ctrl
|= PCIDAS_CTRL_DAEMIE
| PCIDAS_CTRL_DAHFIE
;
1015 /* enable and clear interrupts */
1016 outw(devpriv
->ctrl
| PCIDAS_CTRL_DAEMI
| PCIDAS_CTRL_DAHFI
,
1017 devpriv
->pcibar1
+ PCIDAS_CTRL_REG
);
1020 devpriv
->ao_ctrl
|= PCIDAS_AO_START
| PCIDAS_AO_DACEN
| PCIDAS_AO_EMPTY
;
1021 outw(devpriv
->ao_ctrl
, devpriv
->pcibar1
+ PCIDAS_AO_REG
);
1023 spin_unlock_irqrestore(&dev
->spinlock
, flags
);
1025 async
->inttrig
= NULL
;
1030 static int cb_pcidas_ao_cmd(struct comedi_device
*dev
,
1031 struct comedi_subdevice
*s
)
1033 struct cb_pcidas_private
*devpriv
= dev
->private;
1034 struct comedi_async
*async
= s
->async
;
1035 struct comedi_cmd
*cmd
= &async
->cmd
;
1037 unsigned long flags
;
1039 /* set channel limits, gain */
1040 spin_lock_irqsave(&dev
->spinlock
, flags
);
1041 for (i
= 0; i
< cmd
->chanlist_len
; i
++) {
1042 unsigned int chan
= CR_CHAN(cmd
->chanlist
[i
]);
1043 unsigned int range
= CR_RANGE(cmd
->chanlist
[i
]);
1045 /* enable channel */
1046 devpriv
->ao_ctrl
|= PCIDAS_AO_CHAN_EN(chan
);
1048 devpriv
->ao_ctrl
|= PCIDAS_AO_RANGE(chan
, range
);
1051 /* disable analog out before settings pacer source and count values */
1052 outw(devpriv
->ao_ctrl
, devpriv
->pcibar1
+ PCIDAS_AO_REG
);
1053 spin_unlock_irqrestore(&dev
->spinlock
, flags
);
1056 outw(0, devpriv
->pcibar4
+ PCIDAS_AO_FIFO_CLR_REG
);
1059 if (cmd
->scan_begin_src
== TRIG_TIMER
) {
1060 comedi_8254_update_divisors(devpriv
->ao_pacer
);
1061 comedi_8254_pacer_enable(devpriv
->ao_pacer
, 1, 2, true);
1064 /* set pacer source */
1065 spin_lock_irqsave(&dev
->spinlock
, flags
);
1066 switch (cmd
->scan_begin_src
) {
1068 devpriv
->ao_ctrl
|= PCIDAS_AO_PACER_INT
;
1071 devpriv
->ao_ctrl
|= PCIDAS_AO_PACER_EXTP
;
1074 spin_unlock_irqrestore(&dev
->spinlock
, flags
);
1075 dev_err(dev
->class_dev
, "error setting dac pacer source\n");
1078 spin_unlock_irqrestore(&dev
->spinlock
, flags
);
1080 async
->inttrig
= cb_pcidas_ao_inttrig
;
1085 static int cb_pcidas_ao_cancel(struct comedi_device
*dev
,
1086 struct comedi_subdevice
*s
)
1088 struct cb_pcidas_private
*devpriv
= dev
->private;
1089 unsigned long flags
;
1091 spin_lock_irqsave(&dev
->spinlock
, flags
);
1092 /* disable interrupts */
1093 devpriv
->ctrl
&= ~(PCIDAS_CTRL_DAHFIE
| PCIDAS_CTRL_DAEMIE
);
1094 outw(devpriv
->ctrl
, devpriv
->pcibar1
+ PCIDAS_CTRL_REG
);
1096 /* disable output */
1097 devpriv
->ao_ctrl
&= ~(PCIDAS_AO_DACEN
| PCIDAS_AO_PACER_MASK
);
1098 outw(devpriv
->ao_ctrl
, devpriv
->pcibar1
+ PCIDAS_AO_REG
);
1099 spin_unlock_irqrestore(&dev
->spinlock
, flags
);
1104 static unsigned int cb_pcidas_ao_interrupt(struct comedi_device
*dev
,
1105 unsigned int status
)
1107 const struct cb_pcidas_board
*board
= dev
->board_ptr
;
1108 struct cb_pcidas_private
*devpriv
= dev
->private;
1109 struct comedi_subdevice
*s
= dev
->write_subdev
;
1110 struct comedi_async
*async
= s
->async
;
1111 struct comedi_cmd
*cmd
= &async
->cmd
;
1112 unsigned int irq_clr
= 0;
1114 if (status
& PCIDAS_CTRL_DAEMI
) {
1115 irq_clr
|= PCIDAS_CTRL_DAEMI
;
1117 if (inw(devpriv
->pcibar4
+ PCIDAS_AO_REG
) & PCIDAS_AO_EMPTY
) {
1118 if (cmd
->stop_src
== TRIG_COUNT
&&
1119 async
->scans_done
>= cmd
->stop_arg
) {
1120 async
->events
|= COMEDI_CB_EOA
;
1122 dev_err(dev
->class_dev
, "dac fifo underflow\n");
1123 async
->events
|= COMEDI_CB_ERROR
;
1126 } else if (status
& PCIDAS_CTRL_DAHFI
) {
1127 irq_clr
|= PCIDAS_CTRL_DAHFI
;
1129 cb_pcidas_ao_load_fifo(dev
, s
, board
->fifo_size
/ 2);
1132 comedi_handle_events(dev
, s
);
1137 static unsigned int cb_pcidas_ai_interrupt(struct comedi_device
*dev
,
1138 unsigned int status
)
1140 const struct cb_pcidas_board
*board
= dev
->board_ptr
;
1141 struct cb_pcidas_private
*devpriv
= dev
->private;
1142 struct comedi_subdevice
*s
= dev
->read_subdev
;
1143 struct comedi_async
*async
= s
->async
;
1144 struct comedi_cmd
*cmd
= &async
->cmd
;
1145 unsigned int irq_clr
= 0;
1147 if (status
& PCIDAS_CTRL_ADHFI
) {
1148 unsigned int num_samples
;
1150 irq_clr
|= PCIDAS_CTRL_INT_CLR
;
1152 /* FIFO is half-full - read data */
1153 num_samples
= comedi_nsamples_left(s
, board
->fifo_size
/ 2);
1154 insw(devpriv
->pcibar2
+ PCIDAS_AI_DATA_REG
,
1155 devpriv
->ai_buffer
, num_samples
);
1156 comedi_buf_write_samples(s
, devpriv
->ai_buffer
, num_samples
);
1158 if (cmd
->stop_src
== TRIG_COUNT
&&
1159 async
->scans_done
>= cmd
->stop_arg
)
1160 async
->events
|= COMEDI_CB_EOA
;
1161 } else if (status
& (PCIDAS_CTRL_ADNEI
| PCIDAS_CTRL_EOBI
)) {
1164 irq_clr
|= PCIDAS_CTRL_INT_CLR
;
1166 /* FIFO is not empty - read data until empty or timeoout */
1167 for (i
= 0; i
< 10000; i
++) {
1170 /* break if fifo is empty */
1171 if ((inw(devpriv
->pcibar1
+ PCIDAS_CTRL_REG
) &
1172 PCIDAS_CTRL_ADNE
) == 0)
1174 val
= inw(devpriv
->pcibar2
+ PCIDAS_AI_DATA_REG
);
1175 comedi_buf_write_samples(s
, &val
, 1);
1177 if (cmd
->stop_src
== TRIG_COUNT
&&
1178 async
->scans_done
>= cmd
->stop_arg
) {
1179 async
->events
|= COMEDI_CB_EOA
;
1183 } else if (status
& PCIDAS_CTRL_EOAI
) {
1184 irq_clr
|= PCIDAS_CTRL_EOAI
;
1186 dev_err(dev
->class_dev
,
1187 "bug! encountered end of acquisition interrupt?\n");
1190 /* check for fifo overflow */
1191 if (status
& PCIDAS_CTRL_LADFUL
) {
1192 irq_clr
|= PCIDAS_CTRL_LADFUL
;
1194 dev_err(dev
->class_dev
, "fifo overflow\n");
1195 async
->events
|= COMEDI_CB_ERROR
;
1198 comedi_handle_events(dev
, s
);
1203 static irqreturn_t
cb_pcidas_interrupt(int irq
, void *d
)
1205 struct comedi_device
*dev
= d
;
1206 struct cb_pcidas_private
*devpriv
= dev
->private;
1207 unsigned int irq_clr
= 0;
1208 unsigned int amcc_status
;
1209 unsigned int status
;
1214 amcc_status
= inl(devpriv
->amcc
+ AMCC_OP_REG_INTCSR
);
1216 if ((INTCSR_INTR_ASSERTED
& amcc_status
) == 0)
1219 /* make sure mailbox 4 is empty */
1220 inl_p(devpriv
->amcc
+ AMCC_OP_REG_IMB4
);
1221 /* clear interrupt on amcc s5933 */
1222 outl(devpriv
->amcc_intcsr
| INTCSR_INBOX_INTR_STATUS
,
1223 devpriv
->amcc
+ AMCC_OP_REG_INTCSR
);
1225 status
= inw(devpriv
->pcibar1
+ PCIDAS_CTRL_REG
);
1227 /* handle analog output interrupts */
1228 if (status
& PCIDAS_CTRL_AO_INT
)
1229 irq_clr
|= cb_pcidas_ao_interrupt(dev
, status
);
1231 /* handle analog input interrupts */
1232 if (status
& PCIDAS_CTRL_AI_INT
)
1233 irq_clr
|= cb_pcidas_ai_interrupt(dev
, status
);
1236 unsigned long flags
;
1238 spin_lock_irqsave(&dev
->spinlock
, flags
);
1239 outw(devpriv
->ctrl
| irq_clr
,
1240 devpriv
->pcibar1
+ PCIDAS_CTRL_REG
);
1241 spin_unlock_irqrestore(&dev
->spinlock
, flags
);
1247 static int cb_pcidas_auto_attach(struct comedi_device
*dev
,
1248 unsigned long context
)
1250 struct pci_dev
*pcidev
= comedi_to_pci_dev(dev
);
1251 const struct cb_pcidas_board
*board
= NULL
;
1252 struct cb_pcidas_private
*devpriv
;
1253 struct comedi_subdevice
*s
;
1257 if (context
< ARRAY_SIZE(cb_pcidas_boards
))
1258 board
= &cb_pcidas_boards
[context
];
1261 dev
->board_ptr
= board
;
1262 dev
->board_name
= board
->name
;
1264 devpriv
= comedi_alloc_devpriv(dev
, sizeof(*devpriv
));
1268 ret
= comedi_pci_enable(dev
);
1272 devpriv
->amcc
= pci_resource_start(pcidev
, 0);
1273 devpriv
->pcibar1
= pci_resource_start(pcidev
, 1);
1274 devpriv
->pcibar2
= pci_resource_start(pcidev
, 2);
1275 dev
->iobase
= pci_resource_start(pcidev
, 3);
1277 devpriv
->pcibar4
= pci_resource_start(pcidev
, 4);
1279 /* disable and clear interrupts on amcc s5933 */
1280 outl(INTCSR_INBOX_INTR_STATUS
,
1281 devpriv
->amcc
+ AMCC_OP_REG_INTCSR
);
1283 ret
= request_irq(pcidev
->irq
, cb_pcidas_interrupt
, IRQF_SHARED
,
1284 dev
->board_name
, dev
);
1286 dev_dbg(dev
->class_dev
, "unable to allocate irq %d\n",
1290 dev
->irq
= pcidev
->irq
;
1292 dev
->pacer
= comedi_8254_init(dev
->iobase
+ PCIDAS_AI_8254_BASE
,
1293 I8254_OSC_BASE_10MHZ
, I8254_IO8
, 0);
1297 devpriv
->ao_pacer
= comedi_8254_init(dev
->iobase
+ PCIDAS_AO_8254_BASE
,
1298 I8254_OSC_BASE_10MHZ
,
1300 if (!devpriv
->ao_pacer
)
1303 ret
= comedi_alloc_subdevices(dev
, 7);
1307 /* Analog Input subdevice */
1308 s
= &dev
->subdevices
[0];
1309 s
->type
= COMEDI_SUBD_AI
;
1310 s
->subdev_flags
= SDF_READABLE
| SDF_GROUND
| SDF_DIFF
;
1312 s
->maxdata
= board
->is_16bit
? 0xffff : 0x0fff;
1313 s
->range_table
= board
->use_alt_range
? &cb_pcidas_alt_ranges
1314 : &cb_pcidas_ranges
;
1315 s
->insn_read
= cb_pcidas_ai_insn_read
;
1316 s
->insn_config
= cb_pcidas_ai_insn_config
;
1318 dev
->read_subdev
= s
;
1319 s
->subdev_flags
|= SDF_CMD_READ
;
1320 s
->len_chanlist
= s
->n_chan
;
1321 s
->do_cmd
= cb_pcidas_ai_cmd
;
1322 s
->do_cmdtest
= cb_pcidas_ai_cmdtest
;
1323 s
->cancel
= cb_pcidas_ai_cancel
;
1326 /* Analog Output subdevice */
1327 s
= &dev
->subdevices
[1];
1328 if (board
->has_ao
) {
1329 s
->type
= COMEDI_SUBD_AO
;
1330 s
->subdev_flags
= SDF_WRITABLE
| SDF_GROUND
;
1332 s
->maxdata
= board
->is_16bit
? 0xffff : 0x0fff;
1333 s
->range_table
= &cb_pcidas_ao_ranges
;
1334 s
->insn_write
= (board
->has_ao_fifo
)
1335 ? cb_pcidas_ao_fifo_insn_write
1336 : cb_pcidas_ao_nofifo_insn_write
;
1338 ret
= comedi_alloc_subdev_readback(s
);
1342 if (dev
->irq
&& board
->has_ao_fifo
) {
1343 dev
->write_subdev
= s
;
1344 s
->subdev_flags
|= SDF_CMD_WRITE
;
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_init(dev
, s
, NULL
, 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 kfree(devpriv
->ao_pacer
);
1458 comedi_pci_detach(dev
);
1461 static struct comedi_driver cb_pcidas_driver
= {
1462 .driver_name
= "cb_pcidas",
1463 .module
= THIS_MODULE
,
1464 .auto_attach
= cb_pcidas_auto_attach
,
1465 .detach
= cb_pcidas_detach
,
1468 static int cb_pcidas_pci_probe(struct pci_dev
*dev
,
1469 const struct pci_device_id
*id
)
1471 return comedi_pci_auto_config(dev
, &cb_pcidas_driver
,
1475 static const struct pci_device_id cb_pcidas_pci_table
[] = {
1476 { PCI_VDEVICE(CB
, 0x0001), BOARD_PCIDAS1602_16
},
1477 { PCI_VDEVICE(CB
, 0x000f), BOARD_PCIDAS1200
},
1478 { PCI_VDEVICE(CB
, 0x0010), BOARD_PCIDAS1602_12
},
1479 { PCI_VDEVICE(CB
, 0x0019), BOARD_PCIDAS1200_JR
},
1480 { PCI_VDEVICE(CB
, 0x001c), BOARD_PCIDAS1602_16_JR
},
1481 { PCI_VDEVICE(CB
, 0x004c), BOARD_PCIDAS1000
},
1482 { PCI_VDEVICE(CB
, 0x001a), BOARD_PCIDAS1001
},
1483 { PCI_VDEVICE(CB
, 0x001b), BOARD_PCIDAS1002
},
1486 MODULE_DEVICE_TABLE(pci
, cb_pcidas_pci_table
);
1488 static struct pci_driver cb_pcidas_pci_driver
= {
1489 .name
= "cb_pcidas",
1490 .id_table
= cb_pcidas_pci_table
,
1491 .probe
= cb_pcidas_pci_probe
,
1492 .remove
= comedi_pci_auto_unconfig
,
1494 module_comedi_pci_driver(cb_pcidas_driver
, cb_pcidas_pci_driver
);
1496 MODULE_AUTHOR("Comedi http://www.comedi.org");
1497 MODULE_DESCRIPTION("Comedi driver for MeasurementComputing PCI-DAS series");
1498 MODULE_LICENSE("GPL");