This source file includes following definitions.
- apci3120_addon_write
- apci3120_init_dma
- apci3120_setup_dma
- apci3120_ns_to_timer
- apci3120_clr_timer2_interrupt
- apci3120_timer_write
- apci3120_timer_read
- apci3120_timer_set_mode
- apci3120_timer_enable
- apci3120_exttrig_enable
- apci3120_set_chanlist
- apci3120_interrupt_dma
- apci3120_interrupt
- apci3120_ai_cmd
- apci3120_ai_cmdtest
- apci3120_cancel
- apci3120_ai_eoc
- apci3120_ai_insn_read
- apci3120_ao_ready
- apci3120_ao_insn_write
- apci3120_di_insn_bits
- apci3120_do_insn_bits
- apci3120_timer_insn_config
- apci3120_timer_insn_read
- apci3120_dma_alloc
- apci3120_dma_free
- apci3120_reset
- apci3120_auto_attach
- apci3120_detach
- apci3120_pci_probe
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 #include <linux/module.h>
16 #include <linux/interrupt.h>
17
18 #include "../comedi_pci.h"
19 #include "amcc_s5933.h"
20
21
22
23
24
25 #define APCI3120_FIFO_ADVANCE_ON_BYTE_2 BIT(29)
26
27
28
29
30 #define APCI3120_AI_FIFO_REG 0x00
31 #define APCI3120_CTRL_REG 0x00
32 #define APCI3120_CTRL_EXT_TRIG BIT(15)
33 #define APCI3120_CTRL_GATE(x) BIT(12 + (x))
34 #define APCI3120_CTRL_PR(x) (((x) & 0xf) << 8)
35 #define APCI3120_CTRL_PA(x) (((x) & 0xf) << 0)
36 #define APCI3120_AI_SOFTTRIG_REG 0x02
37 #define APCI3120_STATUS_REG 0x02
38 #define APCI3120_STATUS_EOC_INT BIT(15)
39 #define APCI3120_STATUS_AMCC_INT BIT(14)
40 #define APCI3120_STATUS_EOS_INT BIT(13)
41 #define APCI3120_STATUS_TIMER2_INT BIT(12)
42 #define APCI3120_STATUS_INT_MASK (0xf << 12)
43 #define APCI3120_STATUS_TO_DI_BITS(x) (((x) >> 8) & 0xf)
44 #define APCI3120_STATUS_TO_VERSION(x) (((x) >> 4) & 0xf)
45 #define APCI3120_STATUS_FIFO_FULL BIT(2)
46 #define APCI3120_STATUS_FIFO_EMPTY BIT(1)
47 #define APCI3120_STATUS_DA_READY BIT(0)
48 #define APCI3120_TIMER_REG 0x04
49 #define APCI3120_CHANLIST_REG 0x06
50 #define APCI3120_CHANLIST_INDEX(x) (((x) & 0xf) << 8)
51 #define APCI3120_CHANLIST_UNIPOLAR BIT(7)
52 #define APCI3120_CHANLIST_GAIN(x) (((x) & 0x3) << 4)
53 #define APCI3120_CHANLIST_MUX(x) (((x) & 0xf) << 0)
54 #define APCI3120_AO_REG(x) (0x08 + (((x) / 4) * 2))
55 #define APCI3120_AO_MUX(x) (((x) & 0x3) << 14)
56 #define APCI3120_AO_DATA(x) ((x) << 0)
57 #define APCI3120_TIMER_MODE_REG 0x0c
58 #define APCI3120_TIMER_MODE(_t, _m) ((_m) << ((_t) * 2))
59 #define APCI3120_TIMER_MODE0 0
60 #define APCI3120_TIMER_MODE2 1
61 #define APCI3120_TIMER_MODE4 2
62 #define APCI3120_TIMER_MODE5 3
63 #define APCI3120_TIMER_MODE_MASK(_t) (3 << ((_t) * 2))
64 #define APCI3120_CTR0_REG 0x0d
65 #define APCI3120_CTR0_DO_BITS(x) ((x) << 4)
66 #define APCI3120_CTR0_TIMER_SEL(x) ((x) << 0)
67 #define APCI3120_MODE_REG 0x0e
68 #define APCI3120_MODE_TIMER2_CLK(x) (((x) & 0x3) << 6)
69 #define APCI3120_MODE_TIMER2_CLK_OSC APCI3120_MODE_TIMER2_CLK(0)
70 #define APCI3120_MODE_TIMER2_CLK_OUT1 APCI3120_MODE_TIMER2_CLK(1)
71 #define APCI3120_MODE_TIMER2_CLK_EOC APCI3120_MODE_TIMER2_CLK(2)
72 #define APCI3120_MODE_TIMER2_CLK_EOS APCI3120_MODE_TIMER2_CLK(3)
73 #define APCI3120_MODE_TIMER2_CLK_MASK APCI3120_MODE_TIMER2_CLK(3)
74 #define APCI3120_MODE_TIMER2_AS(x) (((x) & 0x3) << 4)
75 #define APCI3120_MODE_TIMER2_AS_TIMER APCI3120_MODE_TIMER2_AS(0)
76 #define APCI3120_MODE_TIMER2_AS_COUNTER APCI3120_MODE_TIMER2_AS(1)
77 #define APCI3120_MODE_TIMER2_AS_WDOG APCI3120_MODE_TIMER2_AS(2)
78 #define APCI3120_MODE_TIMER2_AS_MASK APCI3120_MODE_TIMER2_AS(3)
79 #define APCI3120_MODE_SCAN_ENA BIT(3)
80 #define APCI3120_MODE_TIMER2_IRQ_ENA BIT(2)
81 #define APCI3120_MODE_EOS_IRQ_ENA BIT(1)
82 #define APCI3120_MODE_EOC_IRQ_ENA BIT(0)
83
84
85
86
87 #define APCI3120_ADDON_ADDR_REG 0x00
88 #define APCI3120_ADDON_DATA_REG 0x02
89 #define APCI3120_ADDON_CTRL_REG 0x04
90 #define APCI3120_ADDON_CTRL_AMWEN_ENA BIT(1)
91 #define APCI3120_ADDON_CTRL_A2P_FIFO_ENA BIT(0)
92
93
94
95
96 #define APCI3120_REVA 0xa
97 #define APCI3120_REVB 0xb
98 #define APCI3120_REVA_OSC_BASE 70
99 #define APCI3120_REVB_OSC_BASE 50
100
101 static const struct comedi_lrange apci3120_ai_range = {
102 8, {
103 BIP_RANGE(10),
104 BIP_RANGE(5),
105 BIP_RANGE(2),
106 BIP_RANGE(1),
107 UNI_RANGE(10),
108 UNI_RANGE(5),
109 UNI_RANGE(2),
110 UNI_RANGE(1)
111 }
112 };
113
114 enum apci3120_boardid {
115 BOARD_APCI3120,
116 BOARD_APCI3001,
117 };
118
119 struct apci3120_board {
120 const char *name;
121 unsigned int ai_is_16bit:1;
122 unsigned int has_ao:1;
123 };
124
125 static const struct apci3120_board apci3120_boardtypes[] = {
126 [BOARD_APCI3120] = {
127 .name = "apci3120",
128 .ai_is_16bit = 1,
129 .has_ao = 1,
130 },
131 [BOARD_APCI3001] = {
132 .name = "apci3001",
133 },
134 };
135
136 struct apci3120_dmabuf {
137 unsigned short *virt;
138 dma_addr_t hw;
139 unsigned int size;
140 unsigned int use_size;
141 };
142
143 struct apci3120_private {
144 unsigned long amcc;
145 unsigned long addon;
146 unsigned int osc_base;
147 unsigned int use_dma:1;
148 unsigned int use_double_buffer:1;
149 unsigned int cur_dmabuf:1;
150 struct apci3120_dmabuf dmabuf[2];
151 unsigned char do_bits;
152 unsigned char timer_mode;
153 unsigned char mode;
154 unsigned short ctrl;
155 };
156
157 static void apci3120_addon_write(struct comedi_device *dev,
158 unsigned int val, unsigned int reg)
159 {
160 struct apci3120_private *devpriv = dev->private;
161
162
163
164 outw(reg, devpriv->addon + APCI3120_ADDON_ADDR_REG);
165 outw(val & 0xffff, devpriv->addon + APCI3120_ADDON_DATA_REG);
166
167 outw(reg + 2, devpriv->addon + APCI3120_ADDON_ADDR_REG);
168 outw((val >> 16) & 0xffff, devpriv->addon + APCI3120_ADDON_DATA_REG);
169 }
170
171 static void apci3120_init_dma(struct comedi_device *dev,
172 struct apci3120_dmabuf *dmabuf)
173 {
174 struct apci3120_private *devpriv = dev->private;
175
176
177 outl(AGCSTS_TC_ENABLE | AGCSTS_RESET_A2P_FIFO,
178 devpriv->amcc + AMCC_OP_REG_AGCSTS);
179
180
181 apci3120_addon_write(dev, AGCSTS_TC_ENABLE | AGCSTS_RESET_A2P_FIFO,
182 AMCC_OP_REG_AGCSTS);
183
184
185 outl(RESET_A2P_FLAGS | EN_A2P_TRANSFERS,
186 devpriv->amcc + AMCC_OP_REG_MCSR);
187
188
189 apci3120_addon_write(dev, dmabuf->hw, AMCC_OP_REG_AMWAR);
190
191
192 apci3120_addon_write(dev, dmabuf->use_size, AMCC_OP_REG_AMWTC);
193
194
195 outl(APCI3120_FIFO_ADVANCE_ON_BYTE_2 | AINT_WRITE_COMPL,
196 devpriv->amcc + AMCC_OP_REG_INTCSR);
197
198
199 outw(APCI3120_ADDON_CTRL_AMWEN_ENA | APCI3120_ADDON_CTRL_A2P_FIFO_ENA,
200 devpriv->addon + APCI3120_ADDON_CTRL_REG);
201 }
202
203 static void apci3120_setup_dma(struct comedi_device *dev,
204 struct comedi_subdevice *s)
205 {
206 struct apci3120_private *devpriv = dev->private;
207 struct comedi_cmd *cmd = &s->async->cmd;
208 struct apci3120_dmabuf *dmabuf0 = &devpriv->dmabuf[0];
209 struct apci3120_dmabuf *dmabuf1 = &devpriv->dmabuf[1];
210 unsigned int dmalen0 = dmabuf0->size;
211 unsigned int dmalen1 = dmabuf1->size;
212 unsigned int scan_bytes;
213
214 scan_bytes = comedi_samples_to_bytes(s, cmd->scan_end_arg);
215
216 if (cmd->stop_src == TRIG_COUNT) {
217
218
219
220
221 if (dmalen0 > (cmd->stop_arg * scan_bytes))
222 dmalen0 = cmd->stop_arg * scan_bytes;
223 else if (dmalen1 > (cmd->stop_arg * scan_bytes - dmalen0))
224 dmalen1 = cmd->stop_arg * scan_bytes - dmalen0;
225 }
226
227 if (cmd->flags & CMDF_WAKE_EOS) {
228
229 if (dmalen0 > scan_bytes) {
230 dmalen0 = scan_bytes;
231 if (cmd->scan_end_arg & 1)
232 dmalen0 += 2;
233 }
234 if (dmalen1 > scan_bytes) {
235 dmalen1 = scan_bytes;
236 if (cmd->scan_end_arg & 1)
237 dmalen1 -= 2;
238 if (dmalen1 < 4)
239 dmalen1 = 4;
240 }
241 } else {
242
243 if (dmalen0 > s->async->prealloc_bufsz)
244 dmalen0 = s->async->prealloc_bufsz;
245 if (dmalen1 > s->async->prealloc_bufsz)
246 dmalen1 = s->async->prealloc_bufsz;
247 }
248 dmabuf0->use_size = dmalen0;
249 dmabuf1->use_size = dmalen1;
250
251 apci3120_init_dma(dev, dmabuf0);
252 }
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268 static unsigned int apci3120_ns_to_timer(struct comedi_device *dev,
269 unsigned int timer,
270 unsigned int ns,
271 unsigned int flags)
272 {
273 struct apci3120_private *devpriv = dev->private;
274 unsigned int prescale = (timer == 0) ? 10 : 1000;
275 unsigned int timer_base = devpriv->osc_base * prescale;
276 unsigned int divisor;
277
278 switch (flags & CMDF_ROUND_MASK) {
279 case CMDF_ROUND_UP:
280 divisor = DIV_ROUND_UP(ns, timer_base);
281 break;
282 case CMDF_ROUND_DOWN:
283 divisor = ns / timer_base;
284 break;
285 case CMDF_ROUND_NEAREST:
286 default:
287 divisor = DIV_ROUND_CLOSEST(ns, timer_base);
288 break;
289 }
290
291 if (timer == 2) {
292
293 if (divisor > 0x00ffffff)
294 divisor = 0x00ffffff;
295 } else {
296
297 if (divisor > 0xffff)
298 divisor = 0xffff;
299 }
300
301 if (divisor < 2)
302 divisor = 2;
303
304 return divisor;
305 }
306
307 static void apci3120_clr_timer2_interrupt(struct comedi_device *dev)
308 {
309
310 inb(dev->iobase + APCI3120_CTR0_REG);
311 }
312
313 static void apci3120_timer_write(struct comedi_device *dev,
314 unsigned int timer, unsigned int val)
315 {
316 struct apci3120_private *devpriv = dev->private;
317
318
319 outb(APCI3120_CTR0_DO_BITS(devpriv->do_bits) |
320 APCI3120_CTR0_TIMER_SEL(timer),
321 dev->iobase + APCI3120_CTR0_REG);
322 outw(val & 0xffff, dev->iobase + APCI3120_TIMER_REG);
323
324 if (timer == 2) {
325
326 outb(APCI3120_CTR0_DO_BITS(devpriv->do_bits) |
327 APCI3120_CTR0_TIMER_SEL(timer + 1),
328 dev->iobase + APCI3120_CTR0_REG);
329 outw((val >> 16) & 0xffff, dev->iobase + APCI3120_TIMER_REG);
330 }
331 }
332
333 static unsigned int apci3120_timer_read(struct comedi_device *dev,
334 unsigned int timer)
335 {
336 struct apci3120_private *devpriv = dev->private;
337 unsigned int val;
338
339
340 outb(APCI3120_CTR0_DO_BITS(devpriv->do_bits) |
341 APCI3120_CTR0_TIMER_SEL(timer),
342 dev->iobase + APCI3120_CTR0_REG);
343 val = inw(dev->iobase + APCI3120_TIMER_REG);
344
345 if (timer == 2) {
346
347 outb(APCI3120_CTR0_DO_BITS(devpriv->do_bits) |
348 APCI3120_CTR0_TIMER_SEL(timer + 1),
349 dev->iobase + APCI3120_CTR0_REG);
350 val |= (inw(dev->iobase + APCI3120_TIMER_REG) << 16);
351 }
352
353 return val;
354 }
355
356 static void apci3120_timer_set_mode(struct comedi_device *dev,
357 unsigned int timer, unsigned int mode)
358 {
359 struct apci3120_private *devpriv = dev->private;
360
361 devpriv->timer_mode &= ~APCI3120_TIMER_MODE_MASK(timer);
362 devpriv->timer_mode |= APCI3120_TIMER_MODE(timer, mode);
363 outb(devpriv->timer_mode, dev->iobase + APCI3120_TIMER_MODE_REG);
364 }
365
366 static void apci3120_timer_enable(struct comedi_device *dev,
367 unsigned int timer, bool enable)
368 {
369 struct apci3120_private *devpriv = dev->private;
370
371 if (enable)
372 devpriv->ctrl |= APCI3120_CTRL_GATE(timer);
373 else
374 devpriv->ctrl &= ~APCI3120_CTRL_GATE(timer);
375 outw(devpriv->ctrl, dev->iobase + APCI3120_CTRL_REG);
376 }
377
378 static void apci3120_exttrig_enable(struct comedi_device *dev, bool enable)
379 {
380 struct apci3120_private *devpriv = dev->private;
381
382 if (enable)
383 devpriv->ctrl |= APCI3120_CTRL_EXT_TRIG;
384 else
385 devpriv->ctrl &= ~APCI3120_CTRL_EXT_TRIG;
386 outw(devpriv->ctrl, dev->iobase + APCI3120_CTRL_REG);
387 }
388
389 static void apci3120_set_chanlist(struct comedi_device *dev,
390 struct comedi_subdevice *s,
391 int n_chan, unsigned int *chanlist)
392 {
393 struct apci3120_private *devpriv = dev->private;
394 int i;
395
396
397 for (i = 0; i < n_chan; i++) {
398 unsigned int chan = CR_CHAN(chanlist[i]);
399 unsigned int range = CR_RANGE(chanlist[i]);
400 unsigned int val;
401
402 val = APCI3120_CHANLIST_MUX(chan) |
403 APCI3120_CHANLIST_GAIN(range) |
404 APCI3120_CHANLIST_INDEX(i);
405
406 if (comedi_range_is_unipolar(s, range))
407 val |= APCI3120_CHANLIST_UNIPOLAR;
408
409 outw(val, dev->iobase + APCI3120_CHANLIST_REG);
410 }
411
412
413 inw(dev->iobase + APCI3120_TIMER_MODE_REG);
414
415
416 devpriv->ctrl = APCI3120_CTRL_PR(n_chan - 1) | APCI3120_CTRL_PA(0);
417 outw(devpriv->ctrl, dev->iobase + APCI3120_CTRL_REG);
418
419
420 if (n_chan > 1)
421 devpriv->mode |= APCI3120_MODE_SCAN_ENA;
422 }
423
424 static void apci3120_interrupt_dma(struct comedi_device *dev,
425 struct comedi_subdevice *s)
426 {
427 struct apci3120_private *devpriv = dev->private;
428 struct comedi_async *async = s->async;
429 struct comedi_cmd *cmd = &async->cmd;
430 struct apci3120_dmabuf *dmabuf;
431 unsigned int nbytes;
432 unsigned int nsamples;
433
434 dmabuf = &devpriv->dmabuf[devpriv->cur_dmabuf];
435
436 nbytes = dmabuf->use_size - inl(devpriv->amcc + AMCC_OP_REG_MWTC);
437
438 if (nbytes < dmabuf->use_size)
439 dev_err(dev->class_dev, "Interrupted DMA transfer!\n");
440 if (nbytes & 1) {
441 dev_err(dev->class_dev, "Odd count of bytes in DMA ring!\n");
442 async->events |= COMEDI_CB_ERROR;
443 return;
444 }
445
446 nsamples = comedi_bytes_to_samples(s, nbytes);
447 if (nsamples) {
448 comedi_buf_write_samples(s, dmabuf->virt, nsamples);
449
450 if (!(cmd->flags & CMDF_WAKE_EOS))
451 async->events |= COMEDI_CB_EOS;
452 }
453
454 if ((async->events & COMEDI_CB_CANCEL_MASK) ||
455 (cmd->stop_src == TRIG_COUNT && async->scans_done >= cmd->stop_arg))
456 return;
457
458 if (devpriv->use_double_buffer) {
459
460 devpriv->cur_dmabuf = !devpriv->cur_dmabuf;
461 dmabuf = &devpriv->dmabuf[devpriv->cur_dmabuf];
462 apci3120_init_dma(dev, dmabuf);
463 } else {
464
465 apci3120_init_dma(dev, dmabuf);
466 }
467 }
468
469 static irqreturn_t apci3120_interrupt(int irq, void *d)
470 {
471 struct comedi_device *dev = d;
472 struct apci3120_private *devpriv = dev->private;
473 struct comedi_subdevice *s = dev->read_subdev;
474 struct comedi_async *async = s->async;
475 struct comedi_cmd *cmd = &async->cmd;
476 unsigned int status;
477 unsigned int int_amcc;
478
479 status = inw(dev->iobase + APCI3120_STATUS_REG);
480 int_amcc = inl(devpriv->amcc + AMCC_OP_REG_INTCSR);
481
482 if (!(status & APCI3120_STATUS_INT_MASK) &&
483 !(int_amcc & ANY_S593X_INT)) {
484 dev_err(dev->class_dev, "IRQ from unknown source\n");
485 return IRQ_NONE;
486 }
487
488 outl(int_amcc | AINT_INT_MASK, devpriv->amcc + AMCC_OP_REG_INTCSR);
489
490 if (devpriv->ctrl & APCI3120_CTRL_EXT_TRIG)
491 apci3120_exttrig_enable(dev, false);
492
493 if (int_amcc & MASTER_ABORT_INT)
494 dev_err(dev->class_dev, "AMCC IRQ - MASTER DMA ABORT!\n");
495 if (int_amcc & TARGET_ABORT_INT)
496 dev_err(dev->class_dev, "AMCC IRQ - TARGET DMA ABORT!\n");
497
498 if ((status & APCI3120_STATUS_EOS_INT) &&
499 (devpriv->mode & APCI3120_MODE_EOS_IRQ_ENA)) {
500 unsigned short val;
501 int i;
502
503 for (i = 0; i < cmd->chanlist_len; i++) {
504 val = inw(dev->iobase + APCI3120_AI_FIFO_REG);
505 comedi_buf_write_samples(s, &val, 1);
506 }
507
508 devpriv->mode |= APCI3120_MODE_EOS_IRQ_ENA;
509 outb(devpriv->mode, dev->iobase + APCI3120_MODE_REG);
510 }
511
512 if (status & APCI3120_STATUS_TIMER2_INT) {
513
514
515
516
517 apci3120_clr_timer2_interrupt(dev);
518 }
519
520 if (status & APCI3120_STATUS_AMCC_INT) {
521
522 outl(AINT_WT_COMPLETE, devpriv->amcc + AMCC_OP_REG_INTCSR);
523
524
525 apci3120_interrupt_dma(dev, s);
526 }
527
528 if (cmd->stop_src == TRIG_COUNT && async->scans_done >= cmd->stop_arg)
529 async->events |= COMEDI_CB_EOA;
530
531 comedi_handle_events(dev, s);
532
533 return IRQ_HANDLED;
534 }
535
536 static int apci3120_ai_cmd(struct comedi_device *dev,
537 struct comedi_subdevice *s)
538 {
539 struct apci3120_private *devpriv = dev->private;
540 struct comedi_cmd *cmd = &s->async->cmd;
541 unsigned int divisor;
542
543
544 devpriv->mode = APCI3120_MODE_TIMER2_CLK_OSC |
545 APCI3120_MODE_TIMER2_AS_TIMER;
546
547
548 outl(AINT_WT_COMPLETE, devpriv->amcc + AMCC_OP_REG_INTCSR);
549
550 devpriv->cur_dmabuf = 0;
551
552
553 apci3120_set_chanlist(dev, s, cmd->chanlist_len, cmd->chanlist);
554
555 if (cmd->start_src == TRIG_EXT)
556 apci3120_exttrig_enable(dev, true);
557
558 if (cmd->scan_begin_src == TRIG_TIMER) {
559
560
561
562
563 divisor = apci3120_ns_to_timer(dev, 1, cmd->scan_begin_arg,
564 cmd->flags);
565 apci3120_timer_set_mode(dev, 1, APCI3120_TIMER_MODE2);
566 apci3120_timer_write(dev, 1, divisor);
567 }
568
569
570
571
572
573 divisor = apci3120_ns_to_timer(dev, 0, cmd->convert_arg, cmd->flags);
574 apci3120_timer_set_mode(dev, 0, APCI3120_TIMER_MODE2);
575 apci3120_timer_write(dev, 0, divisor);
576
577 if (devpriv->use_dma)
578 apci3120_setup_dma(dev, s);
579 else
580 devpriv->mode |= APCI3120_MODE_EOS_IRQ_ENA;
581
582
583 outb(devpriv->mode, dev->iobase + APCI3120_MODE_REG);
584
585 if (cmd->scan_begin_src == TRIG_TIMER)
586 apci3120_timer_enable(dev, 1, true);
587 apci3120_timer_enable(dev, 0, true);
588
589 return 0;
590 }
591
592 static int apci3120_ai_cmdtest(struct comedi_device *dev,
593 struct comedi_subdevice *s,
594 struct comedi_cmd *cmd)
595 {
596 unsigned int arg;
597 int err = 0;
598
599
600
601 err |= comedi_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_EXT);
602 err |= comedi_check_trigger_src(&cmd->scan_begin_src,
603 TRIG_TIMER | TRIG_FOLLOW);
604 err |= comedi_check_trigger_src(&cmd->convert_src, TRIG_TIMER);
605 err |= comedi_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
606 err |= comedi_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE);
607
608 if (err)
609 return 1;
610
611
612
613 err |= comedi_check_trigger_is_unique(cmd->start_src);
614 err |= comedi_check_trigger_is_unique(cmd->scan_begin_src);
615 err |= comedi_check_trigger_is_unique(cmd->stop_src);
616
617
618
619 if (err)
620 return 2;
621
622
623
624 err |= comedi_check_trigger_arg_is(&cmd->start_arg, 0);
625
626 if (cmd->scan_begin_src == TRIG_TIMER) {
627 err |= comedi_check_trigger_arg_min(&cmd->scan_begin_arg,
628 100000);
629 }
630
631
632 err |= comedi_check_trigger_arg_min(&cmd->convert_arg, 10000);
633
634 err |= comedi_check_trigger_arg_min(&cmd->chanlist_len, 1);
635 err |= comedi_check_trigger_arg_is(&cmd->scan_end_arg,
636 cmd->chanlist_len);
637
638 if (cmd->stop_src == TRIG_COUNT)
639 err |= comedi_check_trigger_arg_min(&cmd->stop_arg, 1);
640 else
641 err |= comedi_check_trigger_arg_is(&cmd->stop_arg, 0);
642
643 if (err)
644 return 3;
645
646
647
648 if (cmd->scan_begin_src == TRIG_TIMER) {
649
650 arg = cmd->convert_arg * cmd->scan_end_arg;
651 err |= comedi_check_trigger_arg_min(&cmd->scan_begin_arg, arg);
652 }
653
654 if (err)
655 return 4;
656
657
658
659 return 0;
660 }
661
662 static int apci3120_cancel(struct comedi_device *dev,
663 struct comedi_subdevice *s)
664 {
665 struct apci3120_private *devpriv = dev->private;
666
667
668 outw(0, devpriv->addon + 4);
669
670
671 apci3120_addon_write(dev, 0, AMCC_OP_REG_AGCSTS);
672
673
674 outl(0, devpriv->amcc + AMCC_OP_REG_MCSR);
675
676
677 devpriv->ctrl = 0;
678 outw(devpriv->ctrl, dev->iobase + APCI3120_CTRL_REG);
679
680
681 devpriv->mode = 0;
682 outb(devpriv->mode, dev->iobase + APCI3120_MODE_REG);
683
684 inw(dev->iobase + APCI3120_STATUS_REG);
685 devpriv->cur_dmabuf = 0;
686
687 return 0;
688 }
689
690 static int apci3120_ai_eoc(struct comedi_device *dev,
691 struct comedi_subdevice *s,
692 struct comedi_insn *insn,
693 unsigned long context)
694 {
695 unsigned int status;
696
697 status = inw(dev->iobase + APCI3120_STATUS_REG);
698 if ((status & APCI3120_STATUS_EOC_INT) == 0)
699 return 0;
700 return -EBUSY;
701 }
702
703 static int apci3120_ai_insn_read(struct comedi_device *dev,
704 struct comedi_subdevice *s,
705 struct comedi_insn *insn,
706 unsigned int *data)
707 {
708 struct apci3120_private *devpriv = dev->private;
709 unsigned int divisor;
710 int ret;
711 int i;
712
713
714 devpriv->mode = APCI3120_MODE_TIMER2_CLK_OSC |
715 APCI3120_MODE_TIMER2_AS_TIMER;
716 outb(devpriv->mode, dev->iobase + APCI3120_MODE_REG);
717
718
719 apci3120_set_chanlist(dev, s, 1, &insn->chanspec);
720
721
722
723
724
725
726
727 apci3120_timer_set_mode(dev, 0, APCI3120_TIMER_MODE4);
728 apci3120_timer_enable(dev, 0, true);
729
730
731 divisor = apci3120_ns_to_timer(dev, 0, 10000, CMDF_ROUND_NEAREST);
732
733 for (i = 0; i < insn->n; i++) {
734
735 apci3120_timer_write(dev, 0, divisor);
736
737 ret = comedi_timeout(dev, s, insn, apci3120_ai_eoc, 0);
738 if (ret)
739 return ret;
740
741 data[i] = inw(dev->iobase + APCI3120_AI_FIFO_REG);
742 }
743
744 return insn->n;
745 }
746
747 static int apci3120_ao_ready(struct comedi_device *dev,
748 struct comedi_subdevice *s,
749 struct comedi_insn *insn,
750 unsigned long context)
751 {
752 unsigned int status;
753
754 status = inw(dev->iobase + APCI3120_STATUS_REG);
755 if (status & APCI3120_STATUS_DA_READY)
756 return 0;
757 return -EBUSY;
758 }
759
760 static int apci3120_ao_insn_write(struct comedi_device *dev,
761 struct comedi_subdevice *s,
762 struct comedi_insn *insn,
763 unsigned int *data)
764 {
765 unsigned int chan = CR_CHAN(insn->chanspec);
766 int i;
767
768 for (i = 0; i < insn->n; i++) {
769 unsigned int val = data[i];
770 int ret;
771
772 ret = comedi_timeout(dev, s, insn, apci3120_ao_ready, 0);
773 if (ret)
774 return ret;
775
776 outw(APCI3120_AO_MUX(chan) | APCI3120_AO_DATA(val),
777 dev->iobase + APCI3120_AO_REG(chan));
778
779 s->readback[chan] = val;
780 }
781
782 return insn->n;
783 }
784
785 static int apci3120_di_insn_bits(struct comedi_device *dev,
786 struct comedi_subdevice *s,
787 struct comedi_insn *insn,
788 unsigned int *data)
789 {
790 unsigned int status;
791
792 status = inw(dev->iobase + APCI3120_STATUS_REG);
793 data[1] = APCI3120_STATUS_TO_DI_BITS(status);
794
795 return insn->n;
796 }
797
798 static int apci3120_do_insn_bits(struct comedi_device *dev,
799 struct comedi_subdevice *s,
800 struct comedi_insn *insn,
801 unsigned int *data)
802 {
803 struct apci3120_private *devpriv = dev->private;
804
805 if (comedi_dio_update_state(s, data)) {
806 devpriv->do_bits = s->state;
807 outb(APCI3120_CTR0_DO_BITS(devpriv->do_bits),
808 dev->iobase + APCI3120_CTR0_REG);
809 }
810
811 data[1] = s->state;
812
813 return insn->n;
814 }
815
816 static int apci3120_timer_insn_config(struct comedi_device *dev,
817 struct comedi_subdevice *s,
818 struct comedi_insn *insn,
819 unsigned int *data)
820 {
821 struct apci3120_private *devpriv = dev->private;
822 unsigned int divisor;
823 unsigned int status;
824 unsigned int mode;
825 unsigned int timer_mode;
826
827 switch (data[0]) {
828 case INSN_CONFIG_ARM:
829 apci3120_clr_timer2_interrupt(dev);
830 divisor = apci3120_ns_to_timer(dev, 2, data[1],
831 CMDF_ROUND_DOWN);
832 apci3120_timer_write(dev, 2, divisor);
833 apci3120_timer_enable(dev, 2, true);
834 break;
835
836 case INSN_CONFIG_DISARM:
837 apci3120_timer_enable(dev, 2, false);
838 apci3120_clr_timer2_interrupt(dev);
839 break;
840
841 case INSN_CONFIG_GET_COUNTER_STATUS:
842 data[1] = 0;
843 data[2] = COMEDI_COUNTER_ARMED | COMEDI_COUNTER_COUNTING |
844 COMEDI_COUNTER_TERMINAL_COUNT;
845
846 if (devpriv->ctrl & APCI3120_CTRL_GATE(2)) {
847 data[1] |= COMEDI_COUNTER_ARMED;
848 data[1] |= COMEDI_COUNTER_COUNTING;
849 }
850 status = inw(dev->iobase + APCI3120_STATUS_REG);
851 if (status & APCI3120_STATUS_TIMER2_INT) {
852 data[1] &= ~COMEDI_COUNTER_COUNTING;
853 data[1] |= COMEDI_COUNTER_TERMINAL_COUNT;
854 }
855 break;
856
857 case INSN_CONFIG_SET_COUNTER_MODE:
858 switch (data[1]) {
859 case I8254_MODE0:
860 mode = APCI3120_MODE_TIMER2_AS_COUNTER;
861 timer_mode = APCI3120_TIMER_MODE0;
862 break;
863 case I8254_MODE2:
864 mode = APCI3120_MODE_TIMER2_AS_TIMER;
865 timer_mode = APCI3120_TIMER_MODE2;
866 break;
867 case I8254_MODE4:
868 mode = APCI3120_MODE_TIMER2_AS_TIMER;
869 timer_mode = APCI3120_TIMER_MODE4;
870 break;
871 case I8254_MODE5:
872 mode = APCI3120_MODE_TIMER2_AS_WDOG;
873 timer_mode = APCI3120_TIMER_MODE5;
874 break;
875 default:
876 return -EINVAL;
877 }
878 apci3120_timer_enable(dev, 2, false);
879 apci3120_clr_timer2_interrupt(dev);
880 apci3120_timer_set_mode(dev, 2, timer_mode);
881 devpriv->mode &= ~APCI3120_MODE_TIMER2_AS_MASK;
882 devpriv->mode |= mode;
883 outb(devpriv->mode, dev->iobase + APCI3120_MODE_REG);
884 break;
885
886 default:
887 return -EINVAL;
888 }
889
890 return insn->n;
891 }
892
893 static int apci3120_timer_insn_read(struct comedi_device *dev,
894 struct comedi_subdevice *s,
895 struct comedi_insn *insn,
896 unsigned int *data)
897 {
898 int i;
899
900 for (i = 0; i < insn->n; i++)
901 data[i] = apci3120_timer_read(dev, 2);
902
903 return insn->n;
904 }
905
906 static void apci3120_dma_alloc(struct comedi_device *dev)
907 {
908 struct apci3120_private *devpriv = dev->private;
909 struct apci3120_dmabuf *dmabuf;
910 int order;
911 int i;
912
913 for (i = 0; i < 2; i++) {
914 dmabuf = &devpriv->dmabuf[i];
915 for (order = 2; order >= 0; order--) {
916 dmabuf->virt = dma_alloc_coherent(dev->hw_dev,
917 PAGE_SIZE << order,
918 &dmabuf->hw,
919 GFP_KERNEL);
920 if (dmabuf->virt)
921 break;
922 }
923 if (!dmabuf->virt)
924 break;
925 dmabuf->size = PAGE_SIZE << order;
926
927 if (i == 0)
928 devpriv->use_dma = 1;
929 if (i == 1)
930 devpriv->use_double_buffer = 1;
931 }
932 }
933
934 static void apci3120_dma_free(struct comedi_device *dev)
935 {
936 struct apci3120_private *devpriv = dev->private;
937 struct apci3120_dmabuf *dmabuf;
938 int i;
939
940 if (!devpriv)
941 return;
942
943 for (i = 0; i < 2; i++) {
944 dmabuf = &devpriv->dmabuf[i];
945 if (dmabuf->virt) {
946 dma_free_coherent(dev->hw_dev, dmabuf->size,
947 dmabuf->virt, dmabuf->hw);
948 }
949 }
950 }
951
952 static void apci3120_reset(struct comedi_device *dev)
953 {
954
955 outb(0, dev->iobase + APCI3120_MODE_REG);
956
957
958 outw(0, dev->iobase + APCI3120_CTRL_REG);
959
960
961 inw(dev->iobase + APCI3120_STATUS_REG);
962 }
963
964 static int apci3120_auto_attach(struct comedi_device *dev,
965 unsigned long context)
966 {
967 struct pci_dev *pcidev = comedi_to_pci_dev(dev);
968 const struct apci3120_board *board = NULL;
969 struct apci3120_private *devpriv;
970 struct comedi_subdevice *s;
971 unsigned int status;
972 int ret;
973
974 if (context < ARRAY_SIZE(apci3120_boardtypes))
975 board = &apci3120_boardtypes[context];
976 if (!board)
977 return -ENODEV;
978 dev->board_ptr = board;
979 dev->board_name = board->name;
980
981 devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
982 if (!devpriv)
983 return -ENOMEM;
984
985 ret = comedi_pci_enable(dev);
986 if (ret)
987 return ret;
988 pci_set_master(pcidev);
989
990 dev->iobase = pci_resource_start(pcidev, 1);
991 devpriv->amcc = pci_resource_start(pcidev, 0);
992 devpriv->addon = pci_resource_start(pcidev, 2);
993
994 apci3120_reset(dev);
995
996 if (pcidev->irq > 0) {
997 ret = request_irq(pcidev->irq, apci3120_interrupt, IRQF_SHARED,
998 dev->board_name, dev);
999 if (ret == 0) {
1000 dev->irq = pcidev->irq;
1001
1002 apci3120_dma_alloc(dev);
1003 }
1004 }
1005
1006 status = inw(dev->iobase + APCI3120_STATUS_REG);
1007 if (APCI3120_STATUS_TO_VERSION(status) == APCI3120_REVB ||
1008 context == BOARD_APCI3001)
1009 devpriv->osc_base = APCI3120_REVB_OSC_BASE;
1010 else
1011 devpriv->osc_base = APCI3120_REVA_OSC_BASE;
1012
1013 ret = comedi_alloc_subdevices(dev, 5);
1014 if (ret)
1015 return ret;
1016
1017
1018 s = &dev->subdevices[0];
1019 s->type = COMEDI_SUBD_AI;
1020 s->subdev_flags = SDF_READABLE | SDF_COMMON | SDF_GROUND | SDF_DIFF;
1021 s->n_chan = 16;
1022 s->maxdata = board->ai_is_16bit ? 0xffff : 0x0fff;
1023 s->range_table = &apci3120_ai_range;
1024 s->insn_read = apci3120_ai_insn_read;
1025 if (dev->irq) {
1026 dev->read_subdev = s;
1027 s->subdev_flags |= SDF_CMD_READ;
1028 s->len_chanlist = s->n_chan;
1029 s->do_cmdtest = apci3120_ai_cmdtest;
1030 s->do_cmd = apci3120_ai_cmd;
1031 s->cancel = apci3120_cancel;
1032 }
1033
1034
1035 s = &dev->subdevices[1];
1036 if (board->has_ao) {
1037 s->type = COMEDI_SUBD_AO;
1038 s->subdev_flags = SDF_WRITABLE | SDF_GROUND | SDF_COMMON;
1039 s->n_chan = 8;
1040 s->maxdata = 0x3fff;
1041 s->range_table = &range_bipolar10;
1042 s->insn_write = apci3120_ao_insn_write;
1043
1044 ret = comedi_alloc_subdev_readback(s);
1045 if (ret)
1046 return ret;
1047 } else {
1048 s->type = COMEDI_SUBD_UNUSED;
1049 }
1050
1051
1052 s = &dev->subdevices[2];
1053 s->type = COMEDI_SUBD_DI;
1054 s->subdev_flags = SDF_READABLE;
1055 s->n_chan = 4;
1056 s->maxdata = 1;
1057 s->range_table = &range_digital;
1058 s->insn_bits = apci3120_di_insn_bits;
1059
1060
1061 s = &dev->subdevices[3];
1062 s->type = COMEDI_SUBD_DO;
1063 s->subdev_flags = SDF_WRITABLE;
1064 s->n_chan = 4;
1065 s->maxdata = 1;
1066 s->range_table = &range_digital;
1067 s->insn_bits = apci3120_do_insn_bits;
1068
1069
1070 s = &dev->subdevices[4];
1071 s->type = COMEDI_SUBD_TIMER;
1072 s->subdev_flags = SDF_READABLE;
1073 s->n_chan = 1;
1074 s->maxdata = 0x00ffffff;
1075 s->insn_config = apci3120_timer_insn_config;
1076 s->insn_read = apci3120_timer_insn_read;
1077
1078 return 0;
1079 }
1080
1081 static void apci3120_detach(struct comedi_device *dev)
1082 {
1083 comedi_pci_detach(dev);
1084 apci3120_dma_free(dev);
1085 }
1086
1087 static struct comedi_driver apci3120_driver = {
1088 .driver_name = "addi_apci_3120",
1089 .module = THIS_MODULE,
1090 .auto_attach = apci3120_auto_attach,
1091 .detach = apci3120_detach,
1092 };
1093
1094 static int apci3120_pci_probe(struct pci_dev *dev,
1095 const struct pci_device_id *id)
1096 {
1097 return comedi_pci_auto_config(dev, &apci3120_driver, id->driver_data);
1098 }
1099
1100 static const struct pci_device_id apci3120_pci_table[] = {
1101 { PCI_VDEVICE(AMCC, 0x818d), BOARD_APCI3120 },
1102 { PCI_VDEVICE(AMCC, 0x828d), BOARD_APCI3001 },
1103 { 0 }
1104 };
1105 MODULE_DEVICE_TABLE(pci, apci3120_pci_table);
1106
1107 static struct pci_driver apci3120_pci_driver = {
1108 .name = "addi_apci_3120",
1109 .id_table = apci3120_pci_table,
1110 .probe = apci3120_pci_probe,
1111 .remove = comedi_pci_auto_unconfig,
1112 };
1113 module_comedi_pci_driver(apci3120_driver, apci3120_pci_driver);
1114
1115 MODULE_AUTHOR("Comedi http://www.comedi.org");
1116 MODULE_DESCRIPTION("ADDI-DATA APCI-3120, Analog input board");
1117 MODULE_LICENSE("GPL");