2 * comedi/drivers/adl_pci9118.c
4 * hardware driver for ADLink cards:
5 * card: PCI-9118DG, PCI-9118HG, PCI-9118HR
6 * driver: pci9118dg, pci9118hg, pci9118hr
8 * Author: Michal Dobes <dobes@tesnet.cz>
14 * Description: Adlink PCI-9118DG, PCI-9118HG, PCI-9118HR
15 * Author: Michal Dobes <dobes@tesnet.cz>
16 * Devices: [ADLink] PCI-9118DG (pci9118dg), PCI-9118HG (pci9118hg),
17 * PCI-9118HR (pci9118hr)
20 * This driver supports AI, AO, DI and DO subdevices.
21 * AI subdevice supports cmd and insn interface,
22 * other subdevices support only insn interface.
24 * - If cmd->scan_begin_src=TRIG_EXT then trigger input is TGIN (pin 46).
25 * - If cmd->convert_src=TRIG_EXT then trigger input is EXTTRG (pin 44).
26 * - If cmd->start_src/stop_src=TRIG_EXT then trigger input is TGIN (pin 46).
27 * - It is not necessary to have cmd.scan_end_arg=cmd.chanlist_len but
28 * cmd.scan_end_arg modulo cmd.chanlist_len must by 0.
29 * - If return value of cmdtest is 5 then you've bad channel list
30 * (it isn't possible mixture S.E. and DIFF inputs or bipolar and unipolar
33 * There are some hardware limitations:
34 * a) You cann't use mixture of unipolar/bipoar ranges or differencial/single
36 * b) DMA transfers must have the length aligned to two samples (32 bit),
37 * so there is some problems if cmd->chanlist_len is odd. This driver tries
38 * bypass this with adding one sample to the end of the every scan and discard
39 * it on output but this can't be used if cmd->scan_begin_src=TRIG_FOLLOW
40 * and is used flag CMDF_WAKE_EOS, then driver switch to interrupt driven mode
41 * with interrupt after every sample.
42 * c) If isn't used DMA then you can use only mode where
43 * cmd->scan_begin_src=TRIG_FOLLOW.
45 * Configuration options:
46 * [0] - PCI bus of device (optional)
47 * [1] - PCI slot of device (optional)
48 * If bus/slot is not specified, then first available PCI
50 * [2] - 0= standard 8 DIFF/16 SE channels configuration
51 * n = external multiplexer connected, 1 <= n <= 256
53 * [4] - sample&hold signal - card can generate signal for external S&H board
54 * 0 = use SSHO(pin 45) signal is generated in onboard hardware S&H logic
55 * 0 != use ADCHN7(pin 23) signal is generated from driver, number say how
56 * long delay is requested in ns and sign polarity of the hold
57 * (in this case external multiplexor can serve only 128 channels)
64 * All the supported boards have the same PCI vendor and device IDs, so
65 * auto-attachment of PCI devices will always find the first board type.
67 * Perhaps the boards have different subdevice IDs that we could use to
70 * Need some device attributes so the board type can be corrected after
71 * attachment if necessary, and possibly to set other options supported by
75 #include <linux/module.h>
76 #include <linux/pci.h>
77 #include <linux/delay.h>
78 #include <linux/gfp.h>
79 #include <linux/interrupt.h>
82 #include "../comedidev.h"
84 #include "amcc_s5933.h"
86 #include "comedi_fc.h"
88 #define IORANGE_9118 64 /* I hope */
89 #define PCI9118_CHANLEN 255 /*
90 * len of chanlist, some source say 256,
91 * but reality looks like 255 :-(
95 * PCI BAR2 Register map (dev->iobase)
97 #define PCI9118_TIMER_REG(x) (0x00 + ((x) * 4))
98 #define PCI9118_TIMER_CTRL_REG 0x0c
99 #define PCI9118_AI_FIFO_REG 0x10
100 #define PCI9118_AO_REG(x) (0x10 + ((x) * 4))
101 #define PCI9118_AI_STATUS_REG 0x18
102 #define PCI9118_AI_STATUS_NFULL (1 << 8) /* 0=FIFO full (fatal) */
103 #define PCI9118_AI_STATUS_NHFULL (1 << 7) /* 0=FIFO half full */
104 #define PCI9118_AI_STATUS_NEPTY (1 << 6) /* 0=FIFO empty */
105 #define PCI9118_AI_STATUS_ACMP (1 << 5) /* 1=about trigger complete */
106 #define PCI9118_AI_STATUS_DTH (1 << 4) /* 1=ext. digital trigger */
107 #define PCI9118_AI_STATUS_BOVER (1 << 3) /* 1=burst overrun (fatal) */
108 #define PCI9118_AI_STATUS_ADOS (1 << 2) /* 1=A/D over speed (warn) */
109 #define PCI9118_AI_STATUS_ADOR (1 << 1) /* 1=A/D overrun (fatal) */
110 #define PCI9118_AI_STATUS_ADRDY (1 << 0) /* 1=A/D ready */
111 #define PCI9118_AI_CTRL_REG 0x18
112 #define PCI9118_AI_CTRL_UNIP (1 << 7) /* 1=unipolar */
113 #define PCI9118_AI_CTRL_DIFF (1 << 6) /* 1=differential inputs */
114 #define PCI9118_AI_CTRL_SOFTG (1 << 5) /* 1=8254 software gate */
115 #define PCI9118_AI_CTRL_EXTG (1 << 4) /* 1=8254 TGIN(pin 46) gate */
116 #define PCI9118_AI_CTRL_EXTM (1 << 3) /* 1=ext. trigger (pin 44) */
117 #define PCI9118_AI_CTRL_TMRTR (1 << 2) /* 1=8254 is trigger source */
118 #define PCI9118_AI_CTRL_INT (1 << 1) /* 1=enable interrupt */
119 #define PCI9118_AI_CTRL_DMA (1 << 0) /* 1=enable DMA */
120 #define PCI9118_DIO_REG 0x1c
121 #define PCI9118_SOFTTRG_REG 0x20
122 #define PCI9118_AI_CHANLIST_REG 0x24
123 #define PCI9118_AI_CHANLIST_RANGE(x) (((x) & 0x3) << 8)
124 #define PCI9118_AI_CHANLIST_CHAN(x) ((x) << 0)
125 #define PCI9118_AI_BURST_NUM_REG 0x28
126 #define PCI9118_AI_AUTOSCAN_MODE_REG 0x2c
127 #define PCI9118_AI_CFG_REG 0x30
128 #define PCI9118_AI_CFG_PDTRG (1 << 7) /* 1=positive trigger */
129 #define PCI9118_AI_CFG_PETRG (1 << 6) /* 1=positive ext. trigger */
130 #define PCI9118_AI_CFG_BSSH (1 << 5) /* 1=with sample & hold */
131 #define PCI9118_AI_CFG_BM (1 << 4) /* 1=burst mode */
132 #define PCI9118_AI_CFG_BS (1 << 3) /* 1=burst mode start */
133 #define PCI9118_AI_CFG_PM (1 << 2) /* 1=post trigger */
134 #define PCI9118_AI_CFG_AM (1 << 1) /* 1=about trigger */
135 #define PCI9118_AI_CFG_START (1 << 0) /* 1=trigger start */
136 #define PCI9118_FIFO_RESET_REG 0x34
137 #define PCI9118_INT_CTRL_REG 0x38
138 #define PCI9118_INT_CTRL_TIMER (1 << 3) /* timer interrupt */
139 #define PCI9118_INT_CTRL_ABOUT (1 << 2) /* about trigger complete */
140 #define PCI9118_INT_CTRL_HFULL (1 << 1) /* A/D FIFO half full */
141 #define PCI9118_INT_CTRL_DTRG (1 << 0) /* ext. digital trigger */
143 #define START_AI_EXT 0x01 /* start measure on external trigger */
144 #define STOP_AI_EXT 0x02 /* stop measure on external trigger */
145 #define STOP_AI_INT 0x08 /* stop measure on internal trigger */
147 #define PCI9118_HALF_FIFO_SZ (1024 / 2)
149 static const struct comedi_lrange pci9118_ai_range
= {
162 static const struct comedi_lrange pci9118hg_ai_range
= {
175 #define PCI9118_BIPOLAR_RANGES 4 /*
176 * used for test on mixture
180 enum pci9118_boardid
{
186 struct pci9118_boardinfo
{
188 unsigned int ai_is_16bit
:1;
189 unsigned int is_hg
:1;
192 static const struct pci9118_boardinfo pci9118_boards
[] = {
193 [BOARD_PCI9118DG
] = {
196 [BOARD_PCI9118HG
] = {
200 [BOARD_PCI9118HR
] = {
206 struct pci9118_dmabuf
{
207 unsigned short *virt
; /* virtual address of buffer */
208 dma_addr_t hw
; /* hardware (bus) address of buffer */
209 unsigned int size
; /* size of dma buffer in bytes */
210 unsigned int use_size
; /* which size we may now use for transfer */
213 struct pci9118_private
{
214 unsigned long iobase_a
; /* base+size for AMCC chip */
215 unsigned int master
:1;
216 unsigned int dma_doublebuf
:1;
217 unsigned int ai_neverending
:1;
218 unsigned int usedma
:1;
219 unsigned int usemux
:1;
220 unsigned char ai_ctrl
;
221 unsigned char int_ctrl
;
222 unsigned char ai_cfg
;
223 unsigned int ai_do
; /* what do AI? 0=nothing, 1 to 4 mode */
224 unsigned int ai_n_realscanlen
; /*
225 * what we must transfer for one
226 * outgoing scan include front/back adds
228 unsigned int ai_act_dmapos
; /* position in actual real stream */
229 unsigned int ai_add_front
; /*
230 * how many channels we must add
231 * before scan to satisfy S&H?
233 unsigned int ai_add_back
; /*
234 * how many channels we must add
235 * before scan to satisfy DMA?
237 unsigned int ai_flags
;
238 char ai12_startstop
; /*
239 * measure can start/stop
240 * on external trigger
242 unsigned int ai_divisor1
, ai_divisor2
; /*
243 * divisors for start of measure
246 unsigned int dma_actbuf
; /* which buffer is used now */
247 struct pci9118_dmabuf dmabuf
[2];
249 * >0 use software S&H,
250 * numer is requested delay in ns
252 unsigned char softsshsample
; /*
253 * polarity of S&H signal
256 unsigned char softsshhold
; /*
257 * polarity of S&H signal
260 unsigned int ai_ns_min
;
263 static void pci9118_amcc_setup_dma(struct comedi_device
*dev
, unsigned int buf
)
265 struct pci9118_private
*devpriv
= dev
->private;
266 struct pci9118_dmabuf
*dmabuf
= &devpriv
->dmabuf
[buf
];
268 /* set the master write address and transfer count */
269 outl(dmabuf
->hw
, devpriv
->iobase_a
+ AMCC_OP_REG_MWAR
);
270 outl(dmabuf
->use_size
, devpriv
->iobase_a
+ AMCC_OP_REG_MWTC
);
273 static void pci9118_amcc_dma_ena(struct comedi_device
*dev
, bool enable
)
275 struct pci9118_private
*devpriv
= dev
->private;
278 mcsr
= inl(devpriv
->iobase_a
+ AMCC_OP_REG_MCSR
);
280 mcsr
|= RESET_A2P_FLAGS
| A2P_HI_PRIORITY
| EN_A2P_TRANSFERS
;
282 mcsr
&= ~EN_A2P_TRANSFERS
;
283 outl(mcsr
, devpriv
->iobase_a
+ AMCC_OP_REG_MCSR
);
286 static void pci9118_amcc_int_ena(struct comedi_device
*dev
, bool enable
)
288 struct pci9118_private
*devpriv
= dev
->private;
291 /* enable/disable interrupt for AMCC Incoming Mailbox 4 (32-bit) */
292 intcsr
= inl(devpriv
->iobase_a
+ AMCC_OP_REG_INTCSR
);
297 outl(intcsr
, devpriv
->iobase_a
+ AMCC_OP_REG_INTCSR
);
300 static void pci9118_timer_write(struct comedi_device
*dev
,
301 unsigned int timer
, unsigned int val
)
303 outl(val
& 0xff, dev
->iobase
+ PCI9118_TIMER_REG(timer
));
304 outl((val
>> 8) & 0xff, dev
->iobase
+ PCI9118_TIMER_REG(timer
));
307 static void pci9118_timer_set_mode(struct comedi_device
*dev
,
308 unsigned int timer
, unsigned int mode
)
312 val
= timer
<< 6; /* select timer */
313 val
|= 0x30; /* load low then high byte */
314 val
|= mode
; /* set timer mode and BCD|binary */
315 outl(val
, dev
->iobase
+ PCI9118_TIMER_CTRL_REG
);
318 static void pci9118_ai_reset_fifo(struct comedi_device
*dev
)
320 /* writing any value resets the A/D FIFO */
321 outl(0, dev
->iobase
+ PCI9118_FIFO_RESET_REG
);
324 static int check_channel_list(struct comedi_device
*dev
,
325 struct comedi_subdevice
*s
, int n_chan
,
326 unsigned int *chanlist
, int frontadd
, int backadd
)
328 struct pci9118_private
*devpriv
= dev
->private;
329 unsigned int i
, differencial
= 0, bipolar
= 0;
331 /* correct channel and range number check itself comedi/range.c */
333 dev_err(dev
->class_dev
, "range/channel list is empty!\n");
336 if ((frontadd
+ n_chan
+ backadd
) > s
->len_chanlist
) {
337 dev_err(dev
->class_dev
,
338 "range/channel list is too long for actual configuration!\n");
342 if (CR_AREF(chanlist
[0]) == AREF_DIFF
)
343 differencial
= 1; /* all input must be diff */
344 if (CR_RANGE(chanlist
[0]) < PCI9118_BIPOLAR_RANGES
)
345 bipolar
= 1; /* all input must be bipolar */
347 for (i
= 1; i
< n_chan
; i
++) { /* check S.E/diff */
348 if ((CR_AREF(chanlist
[i
]) == AREF_DIFF
) !=
350 dev_err(dev
->class_dev
,
351 "Differential and single ended inputs can't be mixed!\n");
354 if ((CR_RANGE(chanlist
[i
]) < PCI9118_BIPOLAR_RANGES
) !=
356 dev_err(dev
->class_dev
,
357 "Bipolar and unipolar ranges can't be mixed!\n");
360 if (!devpriv
->usemux
&& differencial
&&
361 (CR_CHAN(chanlist
[i
]) >= (s
->n_chan
/ 2))) {
362 dev_err(dev
->class_dev
,
363 "AREF_DIFF is only available for the first 8 channels!\n");
371 static void pci9118_set_chanlist(struct comedi_device
*dev
,
372 struct comedi_subdevice
*s
,
373 int n_chan
, unsigned int *chanlist
,
374 int frontadd
, int backadd
)
376 struct pci9118_private
*devpriv
= dev
->private;
377 unsigned int chan0
= CR_CHAN(chanlist
[0]);
378 unsigned int range0
= CR_RANGE(chanlist
[0]);
379 unsigned int aref0
= CR_AREF(chanlist
[0]);
380 unsigned int ssh
= 0x00;
385 * Configure analog input based on the first chanlist entry.
386 * All entries are either unipolar or bipolar and single-ended
389 devpriv
->ai_ctrl
= 0;
390 if (comedi_range_is_unipolar(s
, range0
))
391 devpriv
->ai_ctrl
|= PCI9118_AI_CTRL_UNIP
;
392 if (aref0
== AREF_DIFF
)
393 devpriv
->ai_ctrl
|= PCI9118_AI_CTRL_DIFF
;
394 outl(devpriv
->ai_ctrl
, dev
->iobase
+ PCI9118_AI_CTRL_REG
);
396 /* gods know why this sequence! */
397 outl(2, dev
->iobase
+ PCI9118_AI_AUTOSCAN_MODE_REG
);
398 outl(0, dev
->iobase
+ PCI9118_AI_AUTOSCAN_MODE_REG
);
399 outl(1, dev
->iobase
+ PCI9118_AI_AUTOSCAN_MODE_REG
);
401 /* insert channels for S&H */
403 val
= PCI9118_AI_CHANLIST_CHAN(chan0
) |
404 PCI9118_AI_CHANLIST_RANGE(range0
);
405 ssh
= devpriv
->softsshsample
;
406 for (i
= 0; i
< frontadd
; i
++) {
407 outl(val
| ssh
, dev
->iobase
+ PCI9118_AI_CHANLIST_REG
);
408 ssh
= devpriv
->softsshhold
;
413 for (i
= 0; i
< n_chan
; i
++) {
414 unsigned int chan
= CR_CHAN(chanlist
[i
]);
415 unsigned int range
= CR_RANGE(chanlist
[i
]);
417 val
= PCI9118_AI_CHANLIST_CHAN(chan
) |
418 PCI9118_AI_CHANLIST_RANGE(range
);
419 outl(val
| ssh
, dev
->iobase
+ PCI9118_AI_CHANLIST_REG
);
422 /* insert channels to fit onto 32bit DMA */
424 val
= PCI9118_AI_CHANLIST_CHAN(chan0
) |
425 PCI9118_AI_CHANLIST_RANGE(range0
);
426 for (i
= 0; i
< backadd
; i
++)
427 outl(val
| ssh
, dev
->iobase
+ PCI9118_AI_CHANLIST_REG
);
429 /* close scan queue */
430 outl(0, dev
->iobase
+ PCI9118_AI_AUTOSCAN_MODE_REG
);
431 /* udelay(100); important delay, or first sample will be crippled */
434 static void interrupt_pci9118_ai_mode4_switch(struct comedi_device
*dev
,
435 unsigned int next_buf
)
437 struct pci9118_private
*devpriv
= dev
->private;
438 struct pci9118_dmabuf
*dmabuf
= &devpriv
->dmabuf
[next_buf
];
440 devpriv
->ai_cfg
= PCI9118_AI_CFG_PDTRG
| PCI9118_AI_CFG_PETRG
|
442 outl(devpriv
->ai_cfg
, dev
->iobase
+ PCI9118_AI_CFG_REG
);
443 pci9118_timer_set_mode(dev
, 0, I8254_MODE0
);
444 pci9118_timer_write(dev
, 0, dmabuf
->hw
>> 1);
445 devpriv
->ai_cfg
|= PCI9118_AI_CFG_START
;
446 outl(devpriv
->ai_cfg
, dev
->iobase
+ PCI9118_AI_CFG_REG
);
449 static unsigned int valid_samples_in_act_dma_buf(struct comedi_device
*dev
,
450 struct comedi_subdevice
*s
,
451 unsigned int n_raw_samples
)
453 struct pci9118_private
*devpriv
= dev
->private;
454 struct comedi_cmd
*cmd
= &s
->async
->cmd
;
455 unsigned int start_pos
= devpriv
->ai_add_front
;
456 unsigned int stop_pos
= start_pos
+ cmd
->chanlist_len
;
457 unsigned int span_len
= stop_pos
+ devpriv
->ai_add_back
;
458 unsigned int dma_pos
= devpriv
->ai_act_dmapos
;
459 unsigned int whole_spans
, n_samples
, x
;
461 if (span_len
== cmd
->chanlist_len
)
462 return n_raw_samples
; /* use all samples */
465 * Not all samples are to be used. Buffer contents consist of a
466 * possibly non-whole number of spans and a region of each span
469 * Account for samples in whole number of spans.
471 whole_spans
= n_raw_samples
/ span_len
;
472 n_samples
= whole_spans
* cmd
->chanlist_len
;
473 n_raw_samples
-= whole_spans
* span_len
;
476 * Deal with remaining samples which could overlap up to two spans.
478 while (n_raw_samples
) {
479 if (dma_pos
< start_pos
) {
480 /* Skip samples before start position. */
481 x
= start_pos
- dma_pos
;
482 if (x
> n_raw_samples
)
489 if (dma_pos
< stop_pos
) {
490 /* Include samples before stop position. */
491 x
= stop_pos
- dma_pos
;
492 if (x
> n_raw_samples
)
498 /* Advance to next span. */
499 start_pos
+= span_len
;
500 stop_pos
+= span_len
;
505 static void move_block_from_dma(struct comedi_device
*dev
,
506 struct comedi_subdevice
*s
,
507 unsigned short *dma_buffer
,
508 unsigned int n_raw_samples
)
510 struct pci9118_private
*devpriv
= dev
->private;
511 struct comedi_cmd
*cmd
= &s
->async
->cmd
;
512 unsigned int start_pos
= devpriv
->ai_add_front
;
513 unsigned int stop_pos
= start_pos
+ cmd
->chanlist_len
;
514 unsigned int span_len
= stop_pos
+ devpriv
->ai_add_back
;
515 unsigned int dma_pos
= devpriv
->ai_act_dmapos
;
518 if (span_len
== cmd
->chanlist_len
) {
519 /* All samples are to be copied. */
520 comedi_buf_write_samples(s
, dma_buffer
, n_raw_samples
);
521 dma_pos
+= n_raw_samples
;
524 * Not all samples are to be copied. Buffer contents consist
525 * of a possibly non-whole number of spans and a region of
526 * each span is to be copied.
528 while (n_raw_samples
) {
529 if (dma_pos
< start_pos
) {
530 /* Skip samples before start position. */
531 x
= start_pos
- dma_pos
;
532 if (x
> n_raw_samples
)
539 if (dma_pos
< stop_pos
) {
540 /* Copy samples before stop position. */
541 x
= stop_pos
- dma_pos
;
542 if (x
> n_raw_samples
)
544 comedi_buf_write_samples(s
, dma_buffer
, x
);
548 /* Advance to next span. */
549 start_pos
+= span_len
;
550 stop_pos
+= span_len
;
553 /* Update position in span for next time. */
554 devpriv
->ai_act_dmapos
= dma_pos
% span_len
;
557 static void pci9118_exttrg_enable(struct comedi_device
*dev
, bool enable
)
559 struct pci9118_private
*devpriv
= dev
->private;
562 devpriv
->int_ctrl
|= PCI9118_INT_CTRL_DTRG
;
564 devpriv
->int_ctrl
&= ~PCI9118_INT_CTRL_DTRG
;
565 outl(devpriv
->int_ctrl
, dev
->iobase
+ PCI9118_INT_CTRL_REG
);
567 if (devpriv
->int_ctrl
)
568 pci9118_amcc_int_ena(dev
, true);
570 pci9118_amcc_int_ena(dev
, false);
573 static void pci9118_calc_divisors(struct comedi_device
*dev
,
574 struct comedi_subdevice
*s
,
575 unsigned int *tim1
, unsigned int *tim2
,
576 unsigned int flags
, int chans
,
577 unsigned int *div1
, unsigned int *div2
,
578 unsigned int chnsshfront
)
580 struct comedi_cmd
*cmd
= &s
->async
->cmd
;
582 *div1
= *tim2
/ I8254_OSC_BASE_4MHZ
; /* convert timer (burst) */
583 *div2
= *tim1
/ I8254_OSC_BASE_4MHZ
; /* scan timer */
584 *div2
= *div2
/ *div1
; /* major timer is c1*c2 */
588 *tim2
= *div1
* I8254_OSC_BASE_4MHZ
; /* real convert timer */
590 if (cmd
->convert_src
== TRIG_NOW
&& !chnsshfront
) {
591 /* use BSSH signal */
592 if (*div2
< (chans
+ 2))
596 *tim1
= *div1
* *div2
* I8254_OSC_BASE_4MHZ
;
599 static void pci9118_start_pacer(struct comedi_device
*dev
, int mode
)
601 struct pci9118_private
*devpriv
= dev
->private;
603 pci9118_timer_set_mode(dev
, 1, I8254_MODE2
);
604 pci9118_timer_set_mode(dev
, 2, I8254_MODE2
);
607 if ((mode
== 1) || (mode
== 2) || (mode
== 4)) {
608 pci9118_timer_write(dev
, 2, devpriv
->ai_divisor2
);
609 pci9118_timer_write(dev
, 1, devpriv
->ai_divisor1
);
613 static int pci9118_ai_cancel(struct comedi_device
*dev
,
614 struct comedi_subdevice
*s
)
616 struct pci9118_private
*devpriv
= dev
->private;
619 pci9118_amcc_dma_ena(dev
, false);
620 pci9118_exttrg_enable(dev
, false);
621 pci9118_start_pacer(dev
, 0); /* stop 8254 counters */
622 /* set default config (disable burst and triggers) */
623 devpriv
->ai_cfg
= PCI9118_AI_CFG_PDTRG
| PCI9118_AI_CFG_PETRG
;
624 outl(devpriv
->ai_cfg
, dev
->iobase
+ PCI9118_AI_CFG_REG
);
625 /* reset acqusition control */
626 devpriv
->ai_ctrl
= 0;
627 outl(devpriv
->ai_ctrl
, dev
->iobase
+ PCI9118_AI_CTRL_REG
);
628 outl(0, dev
->iobase
+ PCI9118_AI_BURST_NUM_REG
);
629 /* reset scan queue */
630 outl(1, dev
->iobase
+ PCI9118_AI_AUTOSCAN_MODE_REG
);
631 outl(2, dev
->iobase
+ PCI9118_AI_AUTOSCAN_MODE_REG
);
632 pci9118_ai_reset_fifo(dev
);
634 devpriv
->int_ctrl
= 0;
635 outl(devpriv
->int_ctrl
, dev
->iobase
+ PCI9118_INT_CTRL_REG
);
636 pci9118_amcc_int_ena(dev
, false);
641 devpriv
->ai_act_dmapos
= 0;
642 s
->async
->inttrig
= NULL
;
643 devpriv
->ai_neverending
= 0;
644 devpriv
->dma_actbuf
= 0;
649 static void pci9118_ai_munge(struct comedi_device
*dev
,
650 struct comedi_subdevice
*s
, void *data
,
651 unsigned int num_bytes
,
652 unsigned int start_chan_index
)
654 struct pci9118_private
*devpriv
= dev
->private;
655 unsigned short *array
= data
;
656 unsigned int num_samples
= comedi_bytes_to_samples(s
, num_bytes
);
659 for (i
= 0; i
< num_samples
; i
++) {
661 array
[i
] = be16_to_cpu(array
[i
]);
662 if (s
->maxdata
== 0xffff)
665 array
[i
] = (array
[i
] >> 4) & 0x0fff;
670 static void interrupt_pci9118_ai_onesample(struct comedi_device
*dev
,
671 struct comedi_subdevice
*s
)
673 struct pci9118_private
*devpriv
= dev
->private;
674 struct comedi_cmd
*cmd
= &s
->async
->cmd
;
675 unsigned short sampl
;
677 sampl
= inl(dev
->iobase
+ PCI9118_AI_FIFO_REG
);
679 comedi_buf_write_samples(s
, &sampl
, 1);
681 if (!devpriv
->ai_neverending
) {
682 if (s
->async
->scans_done
>= cmd
->stop_arg
)
683 s
->async
->events
|= COMEDI_CB_EOA
;
687 static void interrupt_pci9118_ai_dma(struct comedi_device
*dev
,
688 struct comedi_subdevice
*s
)
690 struct pci9118_private
*devpriv
= dev
->private;
691 struct comedi_cmd
*cmd
= &s
->async
->cmd
;
692 struct pci9118_dmabuf
*dmabuf
= &devpriv
->dmabuf
[devpriv
->dma_actbuf
];
693 unsigned int n_all
= comedi_bytes_to_samples(s
, dmabuf
->use_size
);
694 unsigned int n_valid
;
697 /* determine whether more DMA buffers to do after this one */
698 n_valid
= valid_samples_in_act_dma_buf(dev
, s
, n_all
);
699 more_dma
= n_valid
< comedi_nsamples_left(s
, n_valid
+ 1);
701 /* switch DMA buffers and restart DMA if double buffering */
702 if (more_dma
&& devpriv
->dma_doublebuf
) {
703 devpriv
->dma_actbuf
= 1 - devpriv
->dma_actbuf
;
704 pci9118_amcc_setup_dma(dev
, devpriv
->dma_actbuf
);
705 if (devpriv
->ai_do
== 4) {
706 interrupt_pci9118_ai_mode4_switch(dev
,
707 devpriv
->dma_actbuf
);
712 move_block_from_dma(dev
, s
, dmabuf
->virt
, n_all
);
714 if (!devpriv
->ai_neverending
) {
715 if (s
->async
->scans_done
>= cmd
->stop_arg
)
716 s
->async
->events
|= COMEDI_CB_EOA
;
719 if (s
->async
->events
& COMEDI_CB_CANCEL_MASK
)
722 /* restart DMA if not double buffering */
723 if (more_dma
&& !devpriv
->dma_doublebuf
) {
724 pci9118_amcc_setup_dma(dev
, 0);
725 if (devpriv
->ai_do
== 4)
726 interrupt_pci9118_ai_mode4_switch(dev
, 0);
730 static irqreturn_t
pci9118_interrupt(int irq
, void *d
)
732 struct comedi_device
*dev
= d
;
733 struct comedi_subdevice
*s
= dev
->read_subdev
;
734 struct pci9118_private
*devpriv
= dev
->private;
735 unsigned int intsrc
; /* IRQ reasons from card */
736 unsigned int intcsr
; /* INT register from AMCC chip */
737 unsigned int adstat
; /* STATUS register */
742 intsrc
= inl(dev
->iobase
+ PCI9118_INT_CTRL_REG
) & 0xf;
743 intcsr
= inl(devpriv
->iobase_a
+ AMCC_OP_REG_INTCSR
);
745 if (!intsrc
&& !(intcsr
& ANY_S593X_INT
))
748 outl(intcsr
| 0x00ff0000, devpriv
->iobase_a
+ AMCC_OP_REG_INTCSR
);
750 if (intcsr
& MASTER_ABORT_INT
) {
751 dev_err(dev
->class_dev
, "AMCC IRQ - MASTER DMA ABORT!\n");
752 s
->async
->events
|= COMEDI_CB_ERROR
;
756 if (intcsr
& TARGET_ABORT_INT
) {
757 dev_err(dev
->class_dev
, "AMCC IRQ - TARGET DMA ABORT!\n");
758 s
->async
->events
|= COMEDI_CB_ERROR
;
762 adstat
= inl(dev
->iobase
+ PCI9118_AI_STATUS_REG
);
763 if ((adstat
& PCI9118_AI_STATUS_NFULL
) == 0) {
764 dev_err(dev
->class_dev
,
765 "A/D FIFO Full status (Fatal Error!)\n");
766 s
->async
->events
|= COMEDI_CB_ERROR
| COMEDI_CB_OVERFLOW
;
769 if (adstat
& PCI9118_AI_STATUS_BOVER
) {
770 dev_err(dev
->class_dev
,
771 "A/D Burst Mode Overrun Status (Fatal Error!)\n");
772 s
->async
->events
|= COMEDI_CB_ERROR
| COMEDI_CB_OVERFLOW
;
775 if (adstat
& PCI9118_AI_STATUS_ADOS
) {
776 dev_err(dev
->class_dev
, "A/D Over Speed Status (Warning!)\n");
777 s
->async
->events
|= COMEDI_CB_ERROR
;
780 if (adstat
& PCI9118_AI_STATUS_ADOR
) {
781 dev_err(dev
->class_dev
, "A/D Overrun Status (Fatal Error!)\n");
782 s
->async
->events
|= COMEDI_CB_ERROR
| COMEDI_CB_OVERFLOW
;
789 if (devpriv
->ai12_startstop
) {
790 if ((adstat
& PCI9118_AI_STATUS_DTH
) &&
791 (intsrc
& PCI9118_INT_CTRL_DTRG
)) {
792 /* start/stop of measure */
793 if (devpriv
->ai12_startstop
& START_AI_EXT
) {
794 /* deactivate EXT trigger */
795 devpriv
->ai12_startstop
&= ~START_AI_EXT
;
796 if (!(devpriv
->ai12_startstop
& STOP_AI_EXT
))
797 pci9118_exttrg_enable(dev
, false);
800 pci9118_start_pacer(dev
, devpriv
->ai_do
);
801 outl(devpriv
->ai_ctrl
,
802 dev
->iobase
+ PCI9118_AI_CTRL_REG
);
803 } else if (devpriv
->ai12_startstop
& STOP_AI_EXT
) {
804 /* deactivate EXT trigger */
805 devpriv
->ai12_startstop
&= ~STOP_AI_EXT
;
806 pci9118_exttrg_enable(dev
, false);
808 /* on next interrupt measure will stop */
809 devpriv
->ai_neverending
= 0;
815 interrupt_pci9118_ai_dma(dev
, s
);
817 interrupt_pci9118_ai_onesample(dev
, s
);
820 comedi_handle_events(dev
, s
);
824 static void pci9118_ai_cmd_start(struct comedi_device
*dev
)
826 struct pci9118_private
*devpriv
= dev
->private;
828 outl(devpriv
->int_ctrl
, dev
->iobase
+ PCI9118_INT_CTRL_REG
);
829 outl(devpriv
->ai_cfg
, dev
->iobase
+ PCI9118_AI_CFG_REG
);
830 if (devpriv
->ai_do
!= 3) {
831 pci9118_start_pacer(dev
, devpriv
->ai_do
);
832 devpriv
->ai_ctrl
|= PCI9118_AI_CTRL_SOFTG
;
834 outl(devpriv
->ai_ctrl
, dev
->iobase
+ PCI9118_AI_CTRL_REG
);
837 static int pci9118_ai_inttrig(struct comedi_device
*dev
,
838 struct comedi_subdevice
*s
,
839 unsigned int trig_num
)
841 struct comedi_cmd
*cmd
= &s
->async
->cmd
;
843 if (trig_num
!= cmd
->start_arg
)
846 s
->async
->inttrig
= NULL
;
847 pci9118_ai_cmd_start(dev
);
852 static int Compute_and_setup_dma(struct comedi_device
*dev
,
853 struct comedi_subdevice
*s
)
855 struct pci9118_private
*devpriv
= dev
->private;
856 struct comedi_cmd
*cmd
= &s
->async
->cmd
;
857 struct pci9118_dmabuf
*dmabuf0
= &devpriv
->dmabuf
[0];
858 struct pci9118_dmabuf
*dmabuf1
= &devpriv
->dmabuf
[1];
859 unsigned int dmalen0
, dmalen1
, i
;
861 dmalen0
= dmabuf0
->size
;
862 dmalen1
= dmabuf1
->size
;
863 /* isn't output buff smaller that our DMA buff? */
864 if (dmalen0
> s
->async
->prealloc_bufsz
) {
865 /* align to 32bit down */
866 dmalen0
= s
->async
->prealloc_bufsz
& ~3L;
868 if (dmalen1
> s
->async
->prealloc_bufsz
) {
869 /* align to 32bit down */
870 dmalen1
= s
->async
->prealloc_bufsz
& ~3L;
873 /* we want wake up every scan? */
874 if (devpriv
->ai_flags
& CMDF_WAKE_EOS
) {
875 if (dmalen0
< (devpriv
->ai_n_realscanlen
<< 1)) {
876 /* uff, too short DMA buffer, disable EOS support! */
877 devpriv
->ai_flags
&= (~CMDF_WAKE_EOS
);
878 dev_info(dev
->class_dev
,
879 "WAR: DMA0 buf too short, can't support CMDF_WAKE_EOS (%d<%d)\n",
880 dmalen0
, devpriv
->ai_n_realscanlen
<< 1);
882 /* short first DMA buffer to one scan */
883 dmalen0
= devpriv
->ai_n_realscanlen
<< 1;
885 dev_info(dev
->class_dev
,
886 "ERR: DMA0 buf len bug? (%d<4)\n",
892 if (devpriv
->ai_flags
& CMDF_WAKE_EOS
) {
893 if (dmalen1
< (devpriv
->ai_n_realscanlen
<< 1)) {
894 /* uff, too short DMA buffer, disable EOS support! */
895 devpriv
->ai_flags
&= (~CMDF_WAKE_EOS
);
896 dev_info(dev
->class_dev
,
897 "WAR: DMA1 buf too short, can't support CMDF_WAKE_EOS (%d<%d)\n",
898 dmalen1
, devpriv
->ai_n_realscanlen
<< 1);
900 /* short second DMA buffer to one scan */
901 dmalen1
= devpriv
->ai_n_realscanlen
<< 1;
903 dev_info(dev
->class_dev
,
904 "ERR: DMA1 buf len bug? (%d<4)\n",
911 /* transfer without CMDF_WAKE_EOS */
912 if (!(devpriv
->ai_flags
& CMDF_WAKE_EOS
)) {
913 /* if it's possible then align DMA buffers to length of scan */
916 (dmalen0
/ (devpriv
->ai_n_realscanlen
<< 1)) *
917 (devpriv
->ai_n_realscanlen
<< 1);
920 dmalen0
= i
; /* uff. very long scan? */
923 (dmalen1
/ (devpriv
->ai_n_realscanlen
<< 1)) *
924 (devpriv
->ai_n_realscanlen
<< 1);
927 dmalen1
= i
; /* uff. very long scan? */
929 * if measure isn't neverending then test, if it fits whole
930 * into one or two DMA buffers
932 if (!devpriv
->ai_neverending
) {
933 /* fits whole measure into one DMA buffer? */
935 ((devpriv
->ai_n_realscanlen
<< 1) *
938 (devpriv
->ai_n_realscanlen
<< 1) *
942 * fits whole measure into
946 ((devpriv
->ai_n_realscanlen
<< 1) *
947 cmd
->stop_arg
- dmalen0
))
949 (devpriv
->ai_n_realscanlen
<< 1) *
950 cmd
->stop_arg
- dmalen0
;
956 /* these DMA buffer size will be used */
957 devpriv
->dma_actbuf
= 0;
958 dmabuf0
->use_size
= dmalen0
;
959 dmabuf1
->use_size
= dmalen1
;
961 pci9118_amcc_dma_ena(dev
, false);
962 pci9118_amcc_setup_dma(dev
, 0);
963 /* init DMA transfer */
964 outl(0x00000000 | AINT_WRITE_COMPL
,
965 devpriv
->iobase_a
+ AMCC_OP_REG_INTCSR
);
966 /* outl(0x02000000|AINT_WRITE_COMPL, devpriv->iobase_a+AMCC_OP_REG_INTCSR); */
967 pci9118_amcc_dma_ena(dev
, true);
968 outl(inl(devpriv
->iobase_a
+ AMCC_OP_REG_INTCSR
) | EN_A2P_TRANSFERS
,
969 devpriv
->iobase_a
+ AMCC_OP_REG_INTCSR
);
970 /* allow bus mastering */
975 static int pci9118_ai_cmd(struct comedi_device
*dev
, struct comedi_subdevice
*s
)
977 struct pci9118_private
*devpriv
= dev
->private;
978 struct comedi_cmd
*cmd
= &s
->async
->cmd
;
979 unsigned int addchans
= 0;
981 devpriv
->ai12_startstop
= 0;
982 devpriv
->ai_flags
= cmd
->flags
;
983 devpriv
->ai_add_front
= 0;
984 devpriv
->ai_add_back
= 0;
986 /* prepare for start/stop conditions */
987 if (cmd
->start_src
== TRIG_EXT
)
988 devpriv
->ai12_startstop
|= START_AI_EXT
;
989 if (cmd
->stop_src
== TRIG_EXT
) {
990 devpriv
->ai_neverending
= 1;
991 devpriv
->ai12_startstop
|= STOP_AI_EXT
;
993 if (cmd
->stop_src
== TRIG_NONE
)
994 devpriv
->ai_neverending
= 1;
995 if (cmd
->stop_src
== TRIG_COUNT
)
996 devpriv
->ai_neverending
= 0;
999 * use additional sample at end of every scan
1000 * to satisty DMA 32 bit transfer?
1002 devpriv
->ai_add_front
= 0;
1003 devpriv
->ai_add_back
= 0;
1004 if (devpriv
->master
) {
1005 devpriv
->usedma
= 1;
1006 if ((cmd
->flags
& CMDF_WAKE_EOS
) &&
1007 (cmd
->scan_end_arg
== 1)) {
1008 if (cmd
->convert_src
== TRIG_NOW
)
1009 devpriv
->ai_add_back
= 1;
1010 if (cmd
->convert_src
== TRIG_TIMER
) {
1011 devpriv
->usedma
= 0;
1013 * use INT transfer if scanlist
1014 * have only one channel
1018 if ((cmd
->flags
& CMDF_WAKE_EOS
) &&
1019 (cmd
->scan_end_arg
& 1) &&
1020 (cmd
->scan_end_arg
> 1)) {
1021 if (cmd
->scan_begin_src
== TRIG_FOLLOW
) {
1022 devpriv
->usedma
= 0;
1024 * XXX maybe can be corrected to use 16 bit DMA
1027 * well, we must insert one sample
1028 * to end of EOS to meet 32 bit transfer
1030 devpriv
->ai_add_back
= 1;
1033 } else { /* interrupt transfer don't need any correction */
1034 devpriv
->usedma
= 0;
1038 * we need software S&H signal?
1039 * It adds two samples before every scan as minimum
1041 if (cmd
->convert_src
== TRIG_NOW
&& devpriv
->softsshdelay
) {
1042 devpriv
->ai_add_front
= 2;
1043 if ((devpriv
->usedma
== 1) && (devpriv
->ai_add_back
== 1)) {
1044 /* move it to front */
1045 devpriv
->ai_add_front
++;
1046 devpriv
->ai_add_back
= 0;
1048 if (cmd
->convert_arg
< devpriv
->ai_ns_min
)
1049 cmd
->convert_arg
= devpriv
->ai_ns_min
;
1050 addchans
= devpriv
->softsshdelay
/ cmd
->convert_arg
;
1051 if (devpriv
->softsshdelay
% cmd
->convert_arg
)
1053 if (addchans
> (devpriv
->ai_add_front
- 1)) {
1054 /* uff, still short */
1055 devpriv
->ai_add_front
= addchans
+ 1;
1056 if (devpriv
->usedma
== 1)
1057 if ((devpriv
->ai_add_front
+
1059 devpriv
->ai_add_back
) & 1)
1060 devpriv
->ai_add_front
++;
1061 /* round up to 32 bit */
1064 /* well, we now know what must be all added */
1065 devpriv
->ai_n_realscanlen
= /*
1066 * what we must take from card in real
1067 * to have cmd->scan_end_arg on output?
1069 (devpriv
->ai_add_front
+ cmd
->chanlist_len
+
1070 devpriv
->ai_add_back
) * (cmd
->scan_end_arg
/
1073 /* check and setup channel list */
1074 if (!check_channel_list(dev
, s
, cmd
->chanlist_len
,
1075 cmd
->chanlist
, devpriv
->ai_add_front
,
1076 devpriv
->ai_add_back
))
1080 * Configure analog input and load the chanlist.
1081 * The acqusition control bits are enabled later.
1083 pci9118_set_chanlist(dev
, s
, cmd
->chanlist_len
, cmd
->chanlist
,
1084 devpriv
->ai_add_front
, devpriv
->ai_add_back
);
1086 /* Determine acqusition mode and calculate timing */
1088 if (cmd
->scan_begin_src
!= TRIG_TIMER
&&
1089 cmd
->convert_src
== TRIG_TIMER
) {
1090 /* cascaded timers 1 and 2 are used for convert timing */
1091 if (cmd
->scan_begin_src
== TRIG_EXT
)
1096 i8253_cascade_ns_to_timer(I8254_OSC_BASE_4MHZ
,
1097 &devpriv
->ai_divisor1
,
1098 &devpriv
->ai_divisor2
,
1101 CMDF_ROUND_NEAREST
);
1103 devpriv
->ai_ctrl
|= PCI9118_AI_CTRL_TMRTR
;
1105 if (!devpriv
->usedma
) {
1106 devpriv
->ai_ctrl
|= PCI9118_AI_CTRL_INT
;
1107 devpriv
->int_ctrl
|= PCI9118_INT_CTRL_TIMER
;
1110 if (cmd
->scan_begin_src
== TRIG_EXT
) {
1111 struct pci9118_dmabuf
*dmabuf
= &devpriv
->dmabuf
[0];
1113 devpriv
->ai_cfg
|= PCI9118_AI_CFG_AM
;
1114 outl(devpriv
->ai_cfg
, dev
->iobase
+ PCI9118_AI_CFG_REG
);
1115 pci9118_timer_set_mode(dev
, 0, I8254_MODE0
);
1116 pci9118_timer_write(dev
, 0, dmabuf
->hw
>> 1);
1117 devpriv
->ai_cfg
|= PCI9118_AI_CFG_START
;
1121 if (cmd
->scan_begin_src
== TRIG_TIMER
&&
1122 cmd
->convert_src
!= TRIG_EXT
) {
1123 if (!devpriv
->usedma
) {
1124 dev_err(dev
->class_dev
,
1125 "cmd->scan_begin_src=TRIG_TIMER works only with bus mastering!\n");
1129 /* double timed action */
1132 pci9118_calc_divisors(dev
, s
,
1133 &cmd
->scan_begin_arg
, &cmd
->convert_arg
,
1135 devpriv
->ai_n_realscanlen
,
1136 &devpriv
->ai_divisor1
,
1137 &devpriv
->ai_divisor2
,
1138 devpriv
->ai_add_front
);
1140 devpriv
->ai_ctrl
|= PCI9118_AI_CTRL_TMRTR
;
1141 devpriv
->ai_cfg
|= PCI9118_AI_CFG_BM
| PCI9118_AI_CFG_BS
;
1142 if (cmd
->convert_src
== TRIG_NOW
&& !devpriv
->softsshdelay
)
1143 devpriv
->ai_cfg
|= PCI9118_AI_CFG_BSSH
;
1144 outl(devpriv
->ai_n_realscanlen
,
1145 dev
->iobase
+ PCI9118_AI_BURST_NUM_REG
);
1148 if (cmd
->scan_begin_src
== TRIG_FOLLOW
&&
1149 cmd
->convert_src
== TRIG_EXT
) {
1150 /* external trigger conversion */
1153 devpriv
->ai_ctrl
|= PCI9118_AI_CTRL_EXTM
;
1156 if (devpriv
->ai_do
== 0) {
1157 dev_err(dev
->class_dev
,
1158 "Unable to determine acqusition mode! BUG in (*do_cmdtest)?\n");
1162 if (devpriv
->usedma
)
1163 devpriv
->ai_ctrl
|= PCI9118_AI_CTRL_DMA
;
1165 pci9118_start_pacer(dev
, -1); /* stop pacer */
1167 /* set default config (disable burst and triggers) */
1168 devpriv
->ai_cfg
= PCI9118_AI_CFG_PDTRG
| PCI9118_AI_CFG_PETRG
;
1169 outl(devpriv
->ai_cfg
, dev
->iobase
+ PCI9118_AI_CFG_REG
);
1171 pci9118_ai_reset_fifo(dev
);
1173 /* clear A/D and INT status registers */
1174 inl(dev
->iobase
+ PCI9118_AI_STATUS_REG
);
1175 inl(dev
->iobase
+ PCI9118_INT_CTRL_REG
);
1177 devpriv
->ai_act_dmapos
= 0;
1179 if (devpriv
->usedma
) {
1180 Compute_and_setup_dma(dev
, s
);
1182 outl(0x02000000 | AINT_WRITE_COMPL
,
1183 devpriv
->iobase_a
+ AMCC_OP_REG_INTCSR
);
1185 pci9118_amcc_int_ena(dev
, true);
1188 /* start async command now or wait for internal trigger */
1189 if (cmd
->start_src
== TRIG_NOW
)
1190 pci9118_ai_cmd_start(dev
);
1191 else if (cmd
->start_src
== TRIG_INT
)
1192 s
->async
->inttrig
= pci9118_ai_inttrig
;
1194 /* enable external trigger for command start/stop */
1195 if (cmd
->start_src
== TRIG_EXT
|| cmd
->stop_src
== TRIG_EXT
)
1196 pci9118_exttrg_enable(dev
, true);
1201 static int pci9118_ai_cmdtest(struct comedi_device
*dev
,
1202 struct comedi_subdevice
*s
,
1203 struct comedi_cmd
*cmd
)
1205 struct pci9118_private
*devpriv
= dev
->private;
1209 unsigned int divisor1
= 0, divisor2
= 0;
1211 /* Step 1 : check if triggers are trivially valid */
1213 err
|= cfc_check_trigger_src(&cmd
->start_src
,
1214 TRIG_NOW
| TRIG_EXT
| TRIG_INT
);
1216 flags
= TRIG_FOLLOW
;
1217 if (devpriv
->master
)
1218 flags
|= TRIG_TIMER
| TRIG_EXT
;
1219 err
|= cfc_check_trigger_src(&cmd
->scan_begin_src
, flags
);
1221 flags
= TRIG_TIMER
| TRIG_EXT
;
1222 if (devpriv
->master
)
1224 err
|= cfc_check_trigger_src(&cmd
->convert_src
, flags
);
1226 err
|= cfc_check_trigger_src(&cmd
->scan_end_src
, TRIG_COUNT
);
1227 err
|= cfc_check_trigger_src(&cmd
->stop_src
,
1228 TRIG_COUNT
| TRIG_NONE
| TRIG_EXT
);
1233 /* Step 2a : make sure trigger sources are unique */
1235 err
|= cfc_check_trigger_is_unique(cmd
->start_src
);
1236 err
|= cfc_check_trigger_is_unique(cmd
->scan_begin_src
);
1237 err
|= cfc_check_trigger_is_unique(cmd
->convert_src
);
1238 err
|= cfc_check_trigger_is_unique(cmd
->stop_src
);
1240 /* Step 2b : and mutually compatible */
1242 if (cmd
->start_src
== TRIG_EXT
&& cmd
->scan_begin_src
== TRIG_EXT
)
1245 if (cmd
->start_src
== TRIG_INT
&& cmd
->scan_begin_src
== TRIG_INT
)
1248 if ((cmd
->scan_begin_src
& (TRIG_TIMER
| TRIG_EXT
)) &&
1249 (!(cmd
->convert_src
& (TRIG_TIMER
| TRIG_NOW
))))
1252 if ((cmd
->scan_begin_src
== TRIG_FOLLOW
) &&
1253 (!(cmd
->convert_src
& (TRIG_TIMER
| TRIG_EXT
))))
1256 if (cmd
->stop_src
== TRIG_EXT
&& cmd
->scan_begin_src
== TRIG_EXT
)
1262 /* Step 3: check if arguments are trivially valid */
1264 switch (cmd
->start_src
) {
1267 err
|= cfc_check_trigger_arg_is(&cmd
->start_arg
, 0);
1270 /* start_arg is the internal trigger (any value) */
1274 if (cmd
->scan_begin_src
& (TRIG_FOLLOW
| TRIG_EXT
))
1275 err
|= cfc_check_trigger_arg_is(&cmd
->scan_begin_arg
, 0);
1277 if ((cmd
->scan_begin_src
== TRIG_TIMER
) &&
1278 (cmd
->convert_src
== TRIG_TIMER
) && (cmd
->scan_end_arg
== 1)) {
1279 cmd
->scan_begin_src
= TRIG_FOLLOW
;
1280 cmd
->convert_arg
= cmd
->scan_begin_arg
;
1281 cmd
->scan_begin_arg
= 0;
1284 if (cmd
->scan_begin_src
== TRIG_TIMER
)
1285 err
|= cfc_check_trigger_arg_min(&cmd
->scan_begin_arg
,
1286 devpriv
->ai_ns_min
);
1288 if (cmd
->scan_begin_src
== TRIG_EXT
)
1289 if (cmd
->scan_begin_arg
) {
1290 cmd
->scan_begin_arg
= 0;
1292 err
|= cfc_check_trigger_arg_max(&cmd
->scan_end_arg
,
1296 if (cmd
->convert_src
& (TRIG_TIMER
| TRIG_NOW
))
1297 err
|= cfc_check_trigger_arg_min(&cmd
->convert_arg
,
1298 devpriv
->ai_ns_min
);
1300 if (cmd
->convert_src
== TRIG_EXT
)
1301 err
|= cfc_check_trigger_arg_is(&cmd
->convert_arg
, 0);
1303 if (cmd
->stop_src
== TRIG_COUNT
)
1304 err
|= cfc_check_trigger_arg_min(&cmd
->stop_arg
, 1);
1305 else /* TRIG_NONE */
1306 err
|= cfc_check_trigger_arg_is(&cmd
->stop_arg
, 0);
1308 err
|= cfc_check_trigger_arg_min(&cmd
->chanlist_len
, 1);
1310 err
|= cfc_check_trigger_arg_min(&cmd
->scan_end_arg
,
1313 if ((cmd
->scan_end_arg
% cmd
->chanlist_len
)) {
1315 cmd
->chanlist_len
* (cmd
->scan_end_arg
/ cmd
->chanlist_len
);
1322 /* step 4: fix up any arguments */
1324 if (cmd
->scan_begin_src
== TRIG_TIMER
) {
1325 arg
= cmd
->scan_begin_arg
;
1326 i8253_cascade_ns_to_timer(I8254_OSC_BASE_4MHZ
,
1327 &divisor1
, &divisor2
,
1329 err
|= cfc_check_trigger_arg_is(&cmd
->scan_begin_arg
, arg
);
1332 if (cmd
->convert_src
& (TRIG_TIMER
| TRIG_NOW
)) {
1333 arg
= cmd
->convert_arg
;
1334 i8253_cascade_ns_to_timer(I8254_OSC_BASE_4MHZ
,
1335 &divisor1
, &divisor2
,
1337 err
|= cfc_check_trigger_arg_is(&cmd
->convert_arg
, arg
);
1339 if (cmd
->scan_begin_src
== TRIG_TIMER
&&
1340 cmd
->convert_src
== TRIG_NOW
) {
1341 if (cmd
->convert_arg
== 0) {
1342 arg
= devpriv
->ai_ns_min
*
1343 (cmd
->scan_end_arg
+ 2);
1345 arg
= cmd
->convert_arg
* cmd
->chanlist_len
;
1347 err
|= cfc_check_trigger_arg_min(&cmd
->scan_begin_arg
,
1356 if (!check_channel_list(dev
, s
, cmd
->chanlist_len
,
1357 cmd
->chanlist
, 0, 0))
1358 return 5; /* incorrect channels list */
1363 static int pci9118_ai_eoc(struct comedi_device
*dev
,
1364 struct comedi_subdevice
*s
,
1365 struct comedi_insn
*insn
,
1366 unsigned long context
)
1368 unsigned int status
;
1370 status
= inl(dev
->iobase
+ PCI9118_AI_STATUS_REG
);
1371 if (status
& PCI9118_AI_STATUS_ADRDY
)
1376 static void pci9118_ai_start_conv(struct comedi_device
*dev
)
1378 /* writing any value triggers an A/D conversion */
1379 outl(0, dev
->iobase
+ PCI9118_SOFTTRG_REG
);
1382 static int pci9118_ai_insn_read(struct comedi_device
*dev
,
1383 struct comedi_subdevice
*s
,
1384 struct comedi_insn
*insn
,
1387 struct pci9118_private
*devpriv
= dev
->private;
1393 * Configure analog input based on the chanspec.
1394 * Acqusition is software controlled without interrupts.
1396 pci9118_set_chanlist(dev
, s
, 1, &insn
->chanspec
, 0, 0);
1398 /* set default config (disable burst and triggers) */
1399 devpriv
->ai_cfg
= PCI9118_AI_CFG_PDTRG
| PCI9118_AI_CFG_PETRG
;
1400 outl(devpriv
->ai_cfg
, dev
->iobase
+ PCI9118_AI_CFG_REG
);
1402 pci9118_ai_reset_fifo(dev
);
1404 for (i
= 0; i
< insn
->n
; i
++) {
1405 pci9118_ai_start_conv(dev
);
1407 ret
= comedi_timeout(dev
, s
, insn
, pci9118_ai_eoc
, 0);
1411 val
= inl(dev
->iobase
+ PCI9118_AI_FIFO_REG
);
1412 if (s
->maxdata
== 0xffff)
1413 data
[i
] = (val
& 0xffff) ^ 0x8000;
1415 data
[i
] = (val
>> 4) & 0xfff;
1421 static int pci9118_ao_insn_write(struct comedi_device
*dev
,
1422 struct comedi_subdevice
*s
,
1423 struct comedi_insn
*insn
,
1426 unsigned int chan
= CR_CHAN(insn
->chanspec
);
1427 unsigned int val
= s
->readback
[chan
];
1430 for (i
= 0; i
< insn
->n
; i
++) {
1432 outl(val
, dev
->iobase
+ PCI9118_AO_REG(chan
));
1434 s
->readback
[chan
] = val
;
1439 static int pci9118_di_insn_bits(struct comedi_device
*dev
,
1440 struct comedi_subdevice
*s
,
1441 struct comedi_insn
*insn
,
1445 * The digital inputs and outputs share the read register.
1446 * bits [7:4] are the digital outputs
1447 * bits [3:0] are the digital inputs
1449 data
[1] = inl(dev
->iobase
+ PCI9118_DIO_REG
) & 0xf;
1454 static int pci9118_do_insn_bits(struct comedi_device
*dev
,
1455 struct comedi_subdevice
*s
,
1456 struct comedi_insn
*insn
,
1460 * The digital outputs are set with the same register that
1461 * the digital inputs and outputs are read from. But the
1462 * outputs are set with bits [3:0] so we can simply write
1463 * the s->state to set them.
1465 if (comedi_dio_update_state(s
, data
))
1466 outl(s
->state
, dev
->iobase
+ PCI9118_DIO_REG
);
1473 static void pci9118_reset(struct comedi_device
*dev
)
1475 /* reset analog input subsystem */
1476 outl(0, dev
->iobase
+ PCI9118_INT_CTRL_REG
);
1477 outl(0, dev
->iobase
+ PCI9118_AI_CTRL_REG
);
1478 outl(0, dev
->iobase
+ PCI9118_AI_CFG_REG
);
1479 pci9118_ai_reset_fifo(dev
);
1481 /* clear any pending interrupts and status */
1482 inl(dev
->iobase
+ PCI9118_INT_CTRL_REG
);
1483 inl(dev
->iobase
+ PCI9118_AI_STATUS_REG
);
1485 /* reset and stop counters */
1486 pci9118_timer_set_mode(dev
, 0, I8254_MODE0
);
1487 pci9118_start_pacer(dev
, 0);
1489 /* reset DMA and scan queue */
1490 outl(0, dev
->iobase
+ PCI9118_AI_BURST_NUM_REG
);
1491 outl(1, dev
->iobase
+ PCI9118_AI_AUTOSCAN_MODE_REG
);
1492 outl(2, dev
->iobase
+ PCI9118_AI_AUTOSCAN_MODE_REG
);
1494 /* reset analog outputs to 0V */
1495 outl(2047, dev
->iobase
+ PCI9118_AO_REG(0));
1496 outl(2047, dev
->iobase
+ PCI9118_AO_REG(1));
1499 static struct pci_dev
*pci9118_find_pci(struct comedi_device
*dev
,
1500 struct comedi_devconfig
*it
)
1502 struct pci_dev
*pcidev
= NULL
;
1503 int bus
= it
->options
[0];
1504 int slot
= it
->options
[1];
1506 for_each_pci_dev(pcidev
) {
1507 if (pcidev
->vendor
!= PCI_VENDOR_ID_AMCC
)
1509 if (pcidev
->device
!= 0x80d9)
1512 /* requested particular bus/slot */
1513 if (pcidev
->bus
->number
!= bus
||
1514 PCI_SLOT(pcidev
->devfn
) != slot
)
1519 dev_err(dev
->class_dev
,
1520 "no supported board found! (req. bus/slot : %d/%d)\n",
1525 static void pci9118_alloc_dma(struct comedi_device
*dev
)
1527 struct pci9118_private
*devpriv
= dev
->private;
1528 struct pci9118_dmabuf
*dmabuf
;
1532 for (i
= 0; i
< 2; i
++) {
1533 dmabuf
= &devpriv
->dmabuf
[i
];
1534 for (order
= 2; order
>= 0; order
--) {
1536 dma_alloc_coherent(dev
->hw_dev
, PAGE_SIZE
<< order
,
1537 &dmabuf
->hw
, GFP_KERNEL
);
1543 dmabuf
->size
= PAGE_SIZE
<< order
;
1546 devpriv
->master
= 1;
1548 devpriv
->dma_doublebuf
= 1;
1552 static void pci9118_free_dma(struct comedi_device
*dev
)
1554 struct pci9118_private
*devpriv
= dev
->private;
1555 struct pci9118_dmabuf
*dmabuf
;
1561 for (i
= 0; i
< 2; i
++) {
1562 dmabuf
= &devpriv
->dmabuf
[i
];
1564 dma_free_coherent(dev
->hw_dev
, dmabuf
->size
,
1565 dmabuf
->virt
, dmabuf
->hw
);
1570 static int pci9118_common_attach(struct comedi_device
*dev
,
1571 int ext_mux
, int softsshdelay
)
1573 const struct pci9118_boardinfo
*board
= dev
->board_ptr
;
1574 struct pci_dev
*pcidev
= comedi_to_pci_dev(dev
);
1575 struct pci9118_private
*devpriv
;
1576 struct comedi_subdevice
*s
;
1581 devpriv
= comedi_alloc_devpriv(dev
, sizeof(*devpriv
));
1585 ret
= comedi_pci_enable(dev
);
1588 pci_set_master(pcidev
);
1590 devpriv
->iobase_a
= pci_resource_start(pcidev
, 0);
1591 dev
->iobase
= pci_resource_start(pcidev
, 2);
1596 ret
= request_irq(pcidev
->irq
, pci9118_interrupt
, IRQF_SHARED
,
1597 dev
->board_name
, dev
);
1599 dev
->irq
= pcidev
->irq
;
1601 pci9118_alloc_dma(dev
);
1607 ext_mux
= 256; /* max 256 channels! */
1608 if (softsshdelay
> 0)
1611 devpriv
->usemux
= 1;
1613 devpriv
->usemux
= 0;
1616 if (softsshdelay
< 0) {
1617 /* select sample&hold signal polarity */
1618 devpriv
->softsshdelay
= -softsshdelay
;
1619 devpriv
->softsshsample
= 0x80;
1620 devpriv
->softsshhold
= 0x00;
1622 devpriv
->softsshdelay
= softsshdelay
;
1623 devpriv
->softsshsample
= 0x00;
1624 devpriv
->softsshhold
= 0x80;
1627 pci_read_config_word(pcidev
, PCI_COMMAND
, &u16w
);
1628 pci_write_config_word(pcidev
, PCI_COMMAND
, u16w
| 64);
1629 /* Enable parity check for parity error */
1631 ret
= comedi_alloc_subdevices(dev
, 4);
1635 /* Analog Input subdevice */
1636 s
= &dev
->subdevices
[0];
1637 s
->type
= COMEDI_SUBD_AI
;
1638 s
->subdev_flags
= SDF_READABLE
| SDF_COMMON
| SDF_GROUND
| SDF_DIFF
;
1639 s
->n_chan
= (devpriv
->usemux
) ? ext_mux
: 16;
1640 s
->maxdata
= board
->ai_is_16bit
? 0xffff : 0x0fff;
1641 s
->range_table
= board
->is_hg
? &pci9118hg_ai_range
1642 : &pci9118_ai_range
;
1643 s
->insn_read
= pci9118_ai_insn_read
;
1645 dev
->read_subdev
= s
;
1646 s
->subdev_flags
|= SDF_CMD_READ
;
1647 s
->len_chanlist
= PCI9118_CHANLEN
;
1648 s
->do_cmdtest
= pci9118_ai_cmdtest
;
1649 s
->do_cmd
= pci9118_ai_cmd
;
1650 s
->cancel
= pci9118_ai_cancel
;
1651 s
->munge
= pci9118_ai_munge
;
1654 if (s
->maxdata
== 0xffff) {
1656 * 16-bit samples are from an ADS7805 A/D converter.
1657 * Minimum sampling rate is 10us.
1659 devpriv
->ai_ns_min
= 10000;
1662 * 12-bit samples are from an ADS7800 A/D converter.
1663 * Minimum sampling rate is 3us.
1665 devpriv
->ai_ns_min
= 3000;
1668 /* Analog Output subdevice */
1669 s
= &dev
->subdevices
[1];
1670 s
->type
= COMEDI_SUBD_AO
;
1671 s
->subdev_flags
= SDF_WRITABLE
| SDF_GROUND
| SDF_COMMON
;
1673 s
->maxdata
= 0x0fff;
1674 s
->range_table
= &range_bipolar10
;
1675 s
->insn_write
= pci9118_ao_insn_write
;
1677 ret
= comedi_alloc_subdev_readback(s
);
1681 /* the analog outputs were reset to 0V, make the readback match */
1682 for (i
= 0; i
< s
->n_chan
; i
++)
1683 s
->readback
[i
] = 2047;
1685 /* Digital Input subdevice */
1686 s
= &dev
->subdevices
[2];
1687 s
->type
= COMEDI_SUBD_DI
;
1688 s
->subdev_flags
= SDF_READABLE
;
1691 s
->range_table
= &range_digital
;
1692 s
->insn_bits
= pci9118_di_insn_bits
;
1694 /* Digital Output subdevice */
1695 s
= &dev
->subdevices
[3];
1696 s
->type
= COMEDI_SUBD_DO
;
1697 s
->subdev_flags
= SDF_WRITABLE
;
1700 s
->range_table
= &range_digital
;
1701 s
->insn_bits
= pci9118_do_insn_bits
;
1703 /* get the current state of the digital outputs */
1704 s
->state
= inl(dev
->iobase
+ PCI9118_DIO_REG
) >> 4;
1709 static int pci9118_attach(struct comedi_device
*dev
,
1710 struct comedi_devconfig
*it
)
1712 struct pci_dev
*pcidev
;
1713 int ext_mux
, softsshdelay
;
1715 ext_mux
= it
->options
[2];
1716 softsshdelay
= it
->options
[4];
1718 pcidev
= pci9118_find_pci(dev
, it
);
1721 comedi_set_hw_dev(dev
, &pcidev
->dev
);
1723 return pci9118_common_attach(dev
, ext_mux
, softsshdelay
);
1726 static int pci9118_auto_attach(struct comedi_device
*dev
,
1727 unsigned long context
)
1729 struct pci_dev
*pcidev
= comedi_to_pci_dev(dev
);
1730 const struct pci9118_boardinfo
*board
= NULL
;
1732 if (context
< ARRAY_SIZE(pci9118_boards
))
1733 board
= &pci9118_boards
[context
];
1736 dev
->board_ptr
= board
;
1737 dev
->board_name
= board
->name
;
1740 * Need to 'get' the PCI device to match the 'put' in pci9118_detach().
1741 * (The 'put' also matches the implicit 'get' by pci9118_find_pci().)
1743 pci_dev_get(pcidev
);
1744 /* no external mux, no sample-hold delay */
1745 return pci9118_common_attach(dev
, 0, 0);
1748 static void pci9118_detach(struct comedi_device
*dev
)
1750 struct pci_dev
*pcidev
= comedi_to_pci_dev(dev
);
1754 comedi_pci_detach(dev
);
1755 pci9118_free_dma(dev
);
1757 pci_dev_put(pcidev
);
1760 static struct comedi_driver adl_pci9118_driver
= {
1761 .driver_name
= "adl_pci9118",
1762 .module
= THIS_MODULE
,
1763 .attach
= pci9118_attach
,
1764 .auto_attach
= pci9118_auto_attach
,
1765 .detach
= pci9118_detach
,
1766 .num_names
= ARRAY_SIZE(pci9118_boards
),
1767 .board_name
= &pci9118_boards
[0].name
,
1768 .offset
= sizeof(struct pci9118_boardinfo
),
1771 static int adl_pci9118_pci_probe(struct pci_dev
*dev
,
1772 const struct pci_device_id
*id
)
1774 return comedi_pci_auto_config(dev
, &adl_pci9118_driver
,
1778 /* FIXME: All the supported board types have the same device ID! */
1779 static const struct pci_device_id adl_pci9118_pci_table
[] = {
1780 { PCI_VDEVICE(AMCC
, 0x80d9), BOARD_PCI9118DG
},
1781 /* { PCI_VDEVICE(AMCC, 0x80d9), BOARD_PCI9118HG }, */
1782 /* { PCI_VDEVICE(AMCC, 0x80d9), BOARD_PCI9118HR }, */
1785 MODULE_DEVICE_TABLE(pci
, adl_pci9118_pci_table
);
1787 static struct pci_driver adl_pci9118_pci_driver
= {
1788 .name
= "adl_pci9118",
1789 .id_table
= adl_pci9118_pci_table
,
1790 .probe
= adl_pci9118_pci_probe
,
1791 .remove
= comedi_pci_auto_unconfig
,
1793 module_comedi_pci_driver(adl_pci9118_driver
, adl_pci9118_pci_driver
);
1795 MODULE_AUTHOR("Comedi http://www.comedi.org");
1796 MODULE_DESCRIPTION("Comedi low-level driver");
1797 MODULE_LICENSE("GPL");