1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101#include <linux/module.h>
102#include <linux/pci.h>
103#include <linux/interrupt.h>
104#include <linux/slab.h>
105
106#include "../comedidev.h"
107
108#include "comedi_fc.h"
109#include "8253.h"
110
111#define DRIVER_NAME "amplc_pci224"
112
113
114
115
116#define PCI_DEVICE_ID_AMPLICON_PCI224 0x0007
117#define PCI_DEVICE_ID_AMPLICON_PCI234 0x0008
118#define PCI_DEVICE_ID_INVALID 0xffff
119
120
121
122
123#define PCI224_IO1_SIZE 0x20
124#define PCI224_Z2_CT0 0x14
125#define PCI224_Z2_CT1 0x15
126#define PCI224_Z2_CT2 0x16
127#define PCI224_Z2_CTC 0x17
128#define PCI224_ZCLK_SCE 0x1A
129#define PCI224_ZGAT_SCE 0x1D
130#define PCI224_INT_SCE 0x1E
131
132
133
134
135
136#define PCI224_IO2_SIZE 0x10
137#define PCI224_DACDATA 0x00
138#define PCI224_SOFTTRIG 0x00
139#define PCI224_DACCON 0x02
140#define PCI224_FIFOSIZ 0x04
141#define PCI224_DACCEN 0x06
142
143
144
145
146
147#define PCI224_DACCON_TRIG_MASK (7 << 0)
148#define PCI224_DACCON_TRIG_NONE (0 << 0)
149#define PCI224_DACCON_TRIG_SW (1 << 0)
150#define PCI224_DACCON_TRIG_EXTP (2 << 0)
151#define PCI224_DACCON_TRIG_EXTN (3 << 0)
152#define PCI224_DACCON_TRIG_Z2CT0 (4 << 0)
153#define PCI224_DACCON_TRIG_Z2CT1 (5 << 0)
154#define PCI224_DACCON_TRIG_Z2CT2 (6 << 0)
155
156#define PCI224_DACCON_POLAR_MASK (1 << 3)
157#define PCI224_DACCON_POLAR_UNI (0 << 3)
158#define PCI224_DACCON_POLAR_BI (1 << 3)
159
160#define PCI224_DACCON_VREF_MASK (3 << 4)
161#define PCI224_DACCON_VREF_1_25 (0 << 4)
162#define PCI224_DACCON_VREF_2_5 (1 << 4)
163#define PCI224_DACCON_VREF_5 (2 << 4)
164#define PCI224_DACCON_VREF_10 (3 << 4)
165
166#define PCI224_DACCON_FIFOWRAP (1 << 7)
167
168#define PCI224_DACCON_FIFOENAB (1 << 8)
169
170#define PCI224_DACCON_FIFOINTR_MASK (7 << 9)
171#define PCI224_DACCON_FIFOINTR_EMPTY (0 << 9)
172#define PCI224_DACCON_FIFOINTR_NEMPTY (1 << 9)
173#define PCI224_DACCON_FIFOINTR_NHALF (2 << 9)
174#define PCI224_DACCON_FIFOINTR_HALF (3 << 9)
175#define PCI224_DACCON_FIFOINTR_NFULL (4 << 9)
176#define PCI224_DACCON_FIFOINTR_FULL (5 << 9)
177
178#define PCI224_DACCON_FIFOFL_MASK (7 << 12)
179#define PCI224_DACCON_FIFOFL_EMPTY (1 << 12)
180#define PCI224_DACCON_FIFOFL_ONETOHALF (0 << 12)
181#define PCI224_DACCON_FIFOFL_HALFTOFULL (4 << 12)
182#define PCI224_DACCON_FIFOFL_FULL (6 << 12)
183
184#define PCI224_DACCON_BUSY (1 << 15)
185
186#define PCI224_DACCON_FIFORESET (1 << 12)
187
188#define PCI224_DACCON_GLOBALRESET (1 << 13)
189
190
191
192
193#define PCI224_FIFO_SIZE 4096
194
195
196
197
198
199
200#define PCI224_FIFO_ROOM_EMPTY PCI224_FIFO_SIZE
201#define PCI224_FIFO_ROOM_ONETOHALF (PCI224_FIFO_SIZE / 2)
202#define PCI224_FIFO_ROOM_HALFTOFULL 1
203#define PCI224_FIFO_ROOM_FULL 0
204
205
206
207
208#define CLK_CLK 0
209#define CLK_10MHZ 1
210#define CLK_1MHZ 2
211#define CLK_100KHZ 3
212#define CLK_10KHZ 4
213#define CLK_1KHZ 5
214#define CLK_OUTNM1 6
215#define CLK_EXT 7
216
217#define CLK_CONFIG(chan, src) ((((chan) & 3) << 3) | ((src) & 7))
218
219#define TIMEBASE_10MHZ 100
220#define TIMEBASE_1MHZ 1000
221#define TIMEBASE_100KHZ 10000
222#define TIMEBASE_10KHZ 100000
223#define TIMEBASE_1KHZ 1000000
224
225
226
227
228#define GAT_VCC 0
229#define GAT_GND 1
230#define GAT_EXT 2
231#define GAT_NOUTNM2 3
232
233#define GAT_CONFIG(chan, src) ((((chan) & 3) << 3) | ((src) & 7))
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250#define PCI224_INTR_EXT 0x01
251#define PCI224_INTR_DAC 0x04
252#define PCI224_INTR_Z2CT1 0x20
253
254#define PCI224_INTR_EDGE_BITS (PCI224_INTR_EXT | PCI224_INTR_Z2CT1)
255#define PCI224_INTR_LEVEL_BITS PCI224_INTR_DACFIFO
256
257
258
259
260
261
262#define COMBINE(old, new, mask) (((old) & ~(mask)) | ((new) & (mask)))
263
264
265#define THISCPU smp_processor_id()
266
267
268#define AO_CMD_STARTED 0
269
270
271
272
273
274
275static const struct comedi_lrange range_pci224_internal = {
276 8,
277 {
278 BIP_RANGE(10),
279 BIP_RANGE(5),
280 BIP_RANGE(2.5),
281 BIP_RANGE(1.25),
282 UNI_RANGE(10),
283 UNI_RANGE(5),
284 UNI_RANGE(2.5),
285 UNI_RANGE(1.25),
286 }
287};
288
289static const unsigned short hwrange_pci224_internal[8] = {
290 PCI224_DACCON_POLAR_BI | PCI224_DACCON_VREF_10,
291 PCI224_DACCON_POLAR_BI | PCI224_DACCON_VREF_5,
292 PCI224_DACCON_POLAR_BI | PCI224_DACCON_VREF_2_5,
293 PCI224_DACCON_POLAR_BI | PCI224_DACCON_VREF_1_25,
294 PCI224_DACCON_POLAR_UNI | PCI224_DACCON_VREF_10,
295 PCI224_DACCON_POLAR_UNI | PCI224_DACCON_VREF_5,
296 PCI224_DACCON_POLAR_UNI | PCI224_DACCON_VREF_2_5,
297 PCI224_DACCON_POLAR_UNI | PCI224_DACCON_VREF_1_25,
298};
299
300
301static const struct comedi_lrange range_pci224_external = {
302 2,
303 {
304 RANGE_ext(-1, 1),
305 RANGE_ext(0, 1),
306 }
307};
308
309static const unsigned short hwrange_pci224_external[2] = {
310 PCI224_DACCON_POLAR_BI,
311 PCI224_DACCON_POLAR_UNI,
312};
313
314
315
316static const struct comedi_lrange range_pci234_ext2 = {
317 1,
318 {
319 RANGE_ext(-2, 2),
320 }
321};
322
323
324
325static const struct comedi_lrange range_pci234_ext = {
326 1,
327 {
328 RANGE_ext(-1, 1),
329 }
330};
331
332
333static const unsigned short hwrange_pci234[1] = {
334 PCI224_DACCON_POLAR_BI,
335};
336
337
338
339
340
341enum pci224_model { any_model, pci224_model, pci234_model };
342
343struct pci224_board {
344 const char *name;
345 unsigned short devid;
346 enum pci224_model model;
347 unsigned int ao_chans;
348 unsigned int ao_bits;
349};
350
351static const struct pci224_board pci224_boards[] = {
352 {
353 .name = "pci224",
354 .devid = PCI_DEVICE_ID_AMPLICON_PCI224,
355 .model = pci224_model,
356 .ao_chans = 16,
357 .ao_bits = 12,
358 },
359 {
360 .name = "pci234",
361 .devid = PCI_DEVICE_ID_AMPLICON_PCI234,
362 .model = pci234_model,
363 .ao_chans = 4,
364 .ao_bits = 16,
365 },
366 {
367 .name = DRIVER_NAME,
368 .devid = PCI_DEVICE_ID_INVALID,
369 .model = any_model,
370 },
371};
372
373
374
375
376struct pci224_private {
377 const unsigned short *hwrange;
378 unsigned long iobase1;
379 unsigned long state;
380 spinlock_t ao_spinlock;
381 unsigned int *ao_readback;
382 short *ao_scan_vals;
383 unsigned char *ao_scan_order;
384 int intr_cpuid;
385 short intr_running;
386 unsigned short daccon;
387 unsigned int cached_div1;
388 unsigned int cached_div2;
389 unsigned int ao_stop_count;
390 short ao_stop_continuous;
391 unsigned short ao_enab;
392 unsigned char intsce;
393};
394
395
396
397
398static void
399pci224_ao_set_data(struct comedi_device *dev, int chan, int range,
400 unsigned int data)
401{
402 const struct pci224_board *thisboard = comedi_board(dev);
403 struct pci224_private *devpriv = dev->private;
404 unsigned short mangled;
405
406
407 devpriv->ao_readback[chan] = data;
408
409 outw(1 << chan, dev->iobase + PCI224_DACCEN);
410
411 devpriv->daccon = COMBINE(devpriv->daccon, devpriv->hwrange[range],
412 (PCI224_DACCON_POLAR_MASK |
413 PCI224_DACCON_VREF_MASK));
414 outw(devpriv->daccon | PCI224_DACCON_FIFORESET,
415 dev->iobase + PCI224_DACCON);
416
417
418
419
420
421 mangled = (unsigned short)data << (16 - thisboard->ao_bits);
422 if ((devpriv->daccon & PCI224_DACCON_POLAR_MASK) ==
423 PCI224_DACCON_POLAR_BI) {
424 mangled ^= 0x8000;
425 }
426
427 outw(mangled, dev->iobase + PCI224_DACDATA);
428
429 inw(dev->iobase + PCI224_SOFTTRIG);
430}
431
432
433
434
435static int
436pci224_ao_insn_write(struct comedi_device *dev, struct comedi_subdevice *s,
437 struct comedi_insn *insn, unsigned int *data)
438{
439 int i;
440 int chan, range;
441
442
443 chan = CR_CHAN(insn->chanspec);
444 range = CR_RANGE(insn->chanspec);
445
446
447
448 for (i = 0; i < insn->n; i++)
449 pci224_ao_set_data(dev, chan, range, data[i]);
450
451 return i;
452}
453
454
455
456
457
458
459
460
461
462static int
463pci224_ao_insn_read(struct comedi_device *dev, struct comedi_subdevice *s,
464 struct comedi_insn *insn, unsigned int *data)
465{
466 struct pci224_private *devpriv = dev->private;
467 int i;
468 int chan;
469
470 chan = CR_CHAN(insn->chanspec);
471
472 for (i = 0; i < insn->n; i++)
473 data[i] = devpriv->ao_readback[chan];
474
475
476 return i;
477}
478
479
480
481
482static void
483pci224_cascade_ns_to_timer(int osc_base, unsigned int *d1, unsigned int *d2,
484 unsigned int *nanosec, int round_mode)
485{
486 i8253_cascade_ns_to_timer(osc_base, d1, d2, nanosec, round_mode);
487}
488
489
490
491
492static void pci224_ao_stop(struct comedi_device *dev,
493 struct comedi_subdevice *s)
494{
495 struct pci224_private *devpriv = dev->private;
496 unsigned long flags;
497
498 if (!test_and_clear_bit(AO_CMD_STARTED, &devpriv->state))
499 return;
500
501
502 spin_lock_irqsave(&devpriv->ao_spinlock, flags);
503
504 devpriv->intsce = 0;
505 outb(0, devpriv->iobase1 + PCI224_INT_SCE);
506
507
508
509
510
511
512
513
514
515
516
517 while (devpriv->intr_running && devpriv->intr_cpuid != THISCPU) {
518 spin_unlock_irqrestore(&devpriv->ao_spinlock, flags);
519 spin_lock_irqsave(&devpriv->ao_spinlock, flags);
520 }
521 spin_unlock_irqrestore(&devpriv->ao_spinlock, flags);
522
523 outw(0, dev->iobase + PCI224_DACCEN);
524 devpriv->daccon = COMBINE(devpriv->daccon,
525 PCI224_DACCON_TRIG_SW |
526 PCI224_DACCON_FIFOINTR_EMPTY,
527 PCI224_DACCON_TRIG_MASK |
528 PCI224_DACCON_FIFOINTR_MASK);
529 outw(devpriv->daccon | PCI224_DACCON_FIFORESET,
530 dev->iobase + PCI224_DACCON);
531}
532
533
534
535
536static void pci224_ao_start(struct comedi_device *dev,
537 struct comedi_subdevice *s)
538{
539 struct pci224_private *devpriv = dev->private;
540 struct comedi_cmd *cmd = &s->async->cmd;
541 unsigned long flags;
542
543 set_bit(AO_CMD_STARTED, &devpriv->state);
544 if (!devpriv->ao_stop_continuous && devpriv->ao_stop_count == 0) {
545
546 pci224_ao_stop(dev, s);
547 s->async->events |= COMEDI_CB_EOA;
548 comedi_event(dev, s);
549 } else {
550
551 spin_lock_irqsave(&devpriv->ao_spinlock, flags);
552 if (cmd->stop_src == TRIG_EXT)
553 devpriv->intsce = PCI224_INTR_EXT | PCI224_INTR_DAC;
554 else
555 devpriv->intsce = PCI224_INTR_DAC;
556
557 outb(devpriv->intsce, devpriv->iobase1 + PCI224_INT_SCE);
558 spin_unlock_irqrestore(&devpriv->ao_spinlock, flags);
559 }
560}
561
562
563
564
565static void pci224_ao_handle_fifo(struct comedi_device *dev,
566 struct comedi_subdevice *s)
567{
568 struct pci224_private *devpriv = dev->private;
569 struct comedi_cmd *cmd = &s->async->cmd;
570 unsigned int num_scans;
571 unsigned int room;
572 unsigned short dacstat;
573 unsigned int i, n;
574 unsigned int bytes_per_scan;
575
576 if (cmd->chanlist_len) {
577 bytes_per_scan = cmd->chanlist_len * sizeof(short);
578 } else {
579
580 bytes_per_scan = sizeof(short);
581 }
582
583 num_scans = comedi_buf_read_n_available(s->async) / bytes_per_scan;
584 if (!devpriv->ao_stop_continuous) {
585
586 if (num_scans > devpriv->ao_stop_count)
587 num_scans = devpriv->ao_stop_count;
588
589 }
590
591
592 dacstat = inw(dev->iobase + PCI224_DACCON);
593 switch (dacstat & PCI224_DACCON_FIFOFL_MASK) {
594 case PCI224_DACCON_FIFOFL_EMPTY:
595 room = PCI224_FIFO_ROOM_EMPTY;
596 if (!devpriv->ao_stop_continuous && devpriv->ao_stop_count == 0) {
597
598 pci224_ao_stop(dev, s);
599 s->async->events |= COMEDI_CB_EOA;
600 comedi_event(dev, s);
601 return;
602 }
603 break;
604 case PCI224_DACCON_FIFOFL_ONETOHALF:
605 room = PCI224_FIFO_ROOM_ONETOHALF;
606 break;
607 case PCI224_DACCON_FIFOFL_HALFTOFULL:
608 room = PCI224_FIFO_ROOM_HALFTOFULL;
609 break;
610 default:
611 room = PCI224_FIFO_ROOM_FULL;
612 break;
613 }
614 if (room >= PCI224_FIFO_ROOM_ONETOHALF) {
615
616 if (num_scans == 0) {
617
618 pci224_ao_stop(dev, s);
619 s->async->events |= COMEDI_CB_OVERFLOW;
620 dev_err(dev->class_dev, "AO buffer underrun\n");
621 }
622 }
623
624 if (cmd->chanlist_len)
625 room /= cmd->chanlist_len;
626
627
628 if (num_scans > room)
629 num_scans = room;
630
631
632 for (n = 0; n < num_scans; n++) {
633 cfc_read_array_from_buffer(s, &devpriv->ao_scan_vals[0],
634 bytes_per_scan);
635 for (i = 0; i < cmd->chanlist_len; i++) {
636 outw(devpriv->ao_scan_vals[devpriv->ao_scan_order[i]],
637 dev->iobase + PCI224_DACDATA);
638 }
639 }
640 if (!devpriv->ao_stop_continuous) {
641 devpriv->ao_stop_count -= num_scans;
642 if (devpriv->ao_stop_count == 0) {
643
644
645
646
647 devpriv->daccon = COMBINE(devpriv->daccon,
648 PCI224_DACCON_FIFOINTR_EMPTY,
649 PCI224_DACCON_FIFOINTR_MASK);
650 outw(devpriv->daccon, dev->iobase + PCI224_DACCON);
651 }
652 }
653 if ((devpriv->daccon & PCI224_DACCON_TRIG_MASK) ==
654 PCI224_DACCON_TRIG_NONE) {
655 unsigned short trig;
656
657
658
659
660
661
662
663
664
665
666
667
668
669 if (cmd->scan_begin_src == TRIG_TIMER) {
670 trig = PCI224_DACCON_TRIG_Z2CT0;
671 } else {
672
673 if (cmd->scan_begin_arg & CR_INVERT)
674 trig = PCI224_DACCON_TRIG_EXTN;
675 else
676 trig = PCI224_DACCON_TRIG_EXTP;
677
678 }
679 devpriv->daccon = COMBINE(devpriv->daccon, trig,
680 PCI224_DACCON_TRIG_MASK);
681 outw(devpriv->daccon, dev->iobase + PCI224_DACCON);
682 }
683 if (s->async->events)
684 comedi_event(dev, s);
685
686}
687
688
689
690
691static int
692pci224_ao_inttrig_start(struct comedi_device *dev, struct comedi_subdevice *s,
693 unsigned int trignum)
694{
695 if (trignum != 0)
696 return -EINVAL;
697
698 s->async->inttrig = NULL;
699 pci224_ao_start(dev, s);
700
701 return 1;
702}
703
704#define MAX_SCAN_PERIOD 0xFFFFFFFFU
705#define MIN_SCAN_PERIOD 2500
706#define CONVERT_PERIOD 625
707
708
709
710
711static int
712pci224_ao_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
713 struct comedi_cmd *cmd)
714{
715 struct pci224_private *devpriv = dev->private;
716 int err = 0;
717 unsigned int tmp;
718
719
720
721 err |= cfc_check_trigger_src(&cmd->start_src, TRIG_INT | TRIG_EXT);
722 err |= cfc_check_trigger_src(&cmd->scan_begin_src,
723 TRIG_EXT | TRIG_TIMER);
724 err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_NOW);
725 err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
726 err |= cfc_check_trigger_src(&cmd->stop_src,
727 TRIG_COUNT | TRIG_EXT | TRIG_NONE);
728
729 if (err)
730 return 1;
731
732
733
734 err |= cfc_check_trigger_is_unique(cmd->start_src);
735 err |= cfc_check_trigger_is_unique(cmd->scan_begin_src);
736 err |= cfc_check_trigger_is_unique(cmd->stop_src);
737
738
739
740
741
742
743
744 tmp = 0;
745 if (cmd->start_src & TRIG_EXT)
746 tmp++;
747 if (cmd->scan_begin_src & TRIG_EXT)
748 tmp++;
749 if (cmd->stop_src & TRIG_EXT)
750 tmp++;
751 if (tmp > 1)
752 err |= -EINVAL;
753
754 if (err)
755 return 2;
756
757
758
759 switch (cmd->start_src) {
760 case TRIG_INT:
761 err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
762 break;
763 case TRIG_EXT:
764
765 if ((cmd->start_arg & ~CR_FLAGS_MASK) != 0) {
766 cmd->start_arg = COMBINE(cmd->start_arg, 0,
767 ~CR_FLAGS_MASK);
768 err |= -EINVAL;
769 }
770
771 if ((cmd->start_arg & CR_FLAGS_MASK & ~CR_EDGE) != 0) {
772 cmd->start_arg = COMBINE(cmd->start_arg, 0,
773 CR_FLAGS_MASK & ~CR_EDGE);
774 err |= -EINVAL;
775 }
776 break;
777 }
778
779 switch (cmd->scan_begin_src) {
780 case TRIG_TIMER:
781 err |= cfc_check_trigger_arg_max(&cmd->scan_begin_arg,
782 MAX_SCAN_PERIOD);
783
784 tmp = cmd->chanlist_len * CONVERT_PERIOD;
785 if (tmp < MIN_SCAN_PERIOD)
786 tmp = MIN_SCAN_PERIOD;
787 err |= cfc_check_trigger_arg_min(&cmd->scan_begin_arg, tmp);
788 break;
789 case TRIG_EXT:
790
791 if ((cmd->scan_begin_arg & ~CR_FLAGS_MASK) != 0) {
792 cmd->scan_begin_arg = COMBINE(cmd->scan_begin_arg, 0,
793 ~CR_FLAGS_MASK);
794 err |= -EINVAL;
795 }
796
797 if ((cmd->scan_begin_arg & CR_FLAGS_MASK &
798 ~(CR_EDGE | CR_INVERT)) != 0) {
799 cmd->scan_begin_arg = COMBINE(cmd->scan_begin_arg, 0,
800 CR_FLAGS_MASK &
801 ~(CR_EDGE | CR_INVERT));
802 err |= -EINVAL;
803 }
804 break;
805 }
806
807 err |= cfc_check_trigger_arg_is(&cmd->convert_arg, 0);
808 err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
809
810 switch (cmd->stop_src) {
811 case TRIG_COUNT:
812
813 break;
814 case TRIG_EXT:
815
816 if ((cmd->stop_arg & ~CR_FLAGS_MASK) != 0) {
817 cmd->stop_arg = COMBINE(cmd->stop_arg, 0,
818 ~CR_FLAGS_MASK);
819 err |= -EINVAL;
820 }
821
822 if ((cmd->stop_arg & CR_FLAGS_MASK & ~CR_EDGE) != 0) {
823 cmd->stop_arg = COMBINE(cmd->stop_arg, 0,
824 CR_FLAGS_MASK & ~CR_EDGE);
825 }
826 break;
827 case TRIG_NONE:
828 err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
829 break;
830 }
831
832 if (err)
833 return 3;
834
835
836
837 if (cmd->scan_begin_src == TRIG_TIMER) {
838 unsigned int div1, div2, round;
839 int round_mode = cmd->flags & TRIG_ROUND_MASK;
840
841 tmp = cmd->scan_begin_arg;
842
843 switch (round_mode) {
844 case TRIG_ROUND_NEAREST:
845 default:
846 round = TIMEBASE_10MHZ / 2;
847 break;
848 case TRIG_ROUND_DOWN:
849 round = 0;
850 break;
851 case TRIG_ROUND_UP:
852 round = TIMEBASE_10MHZ - 1;
853 break;
854 }
855
856 div2 = cmd->scan_begin_arg / TIMEBASE_10MHZ;
857 div2 += (round + cmd->scan_begin_arg % TIMEBASE_10MHZ) /
858 TIMEBASE_10MHZ;
859 if (div2 <= 0x10000) {
860
861 if (div2 < 2)
862 div2 = 2;
863 cmd->scan_begin_arg = div2 * TIMEBASE_10MHZ;
864 if (cmd->scan_begin_arg < div2 ||
865 cmd->scan_begin_arg < TIMEBASE_10MHZ) {
866
867 cmd->scan_begin_arg = MAX_SCAN_PERIOD;
868 }
869 } else {
870
871 div1 = devpriv->cached_div1;
872 div2 = devpriv->cached_div2;
873 pci224_cascade_ns_to_timer(TIMEBASE_10MHZ, &div1, &div2,
874 &cmd->scan_begin_arg,
875 round_mode);
876 devpriv->cached_div1 = div1;
877 devpriv->cached_div2 = div2;
878 }
879 if (tmp != cmd->scan_begin_arg)
880 err++;
881
882 }
883
884 if (err)
885 return 4;
886
887
888
889 if (cmd->chanlist && (cmd->chanlist_len > 0)) {
890 unsigned int range;
891 enum { range_err = 1, dupchan_err = 2, };
892 unsigned errors;
893 unsigned int n;
894 unsigned int ch;
895
896
897
898
899
900
901
902 range = CR_RANGE(cmd->chanlist[0]);
903 errors = 0;
904 tmp = 0;
905 for (n = 0; n < cmd->chanlist_len; n++) {
906 ch = CR_CHAN(cmd->chanlist[n]);
907 if (tmp & (1U << ch))
908 errors |= dupchan_err;
909
910 tmp |= (1U << ch);
911 if (CR_RANGE(cmd->chanlist[n]) != range)
912 errors |= range_err;
913
914 }
915 if (errors) {
916 if (errors & dupchan_err) {
917 DPRINTK("comedi%d: " DRIVER_NAME
918 ": ao_cmdtest: "
919 "entries in chanlist must contain no "
920 "duplicate channels\n", dev->minor);
921 }
922 if (errors & range_err) {
923 DPRINTK("comedi%d: " DRIVER_NAME
924 ": ao_cmdtest: "
925 "entries in chanlist must all have "
926 "the same range index\n", dev->minor);
927 }
928 err++;
929 }
930 }
931
932 if (err)
933 return 5;
934
935 return 0;
936}
937
938
939
940
941static int pci224_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
942{
943 struct pci224_private *devpriv = dev->private;
944 struct comedi_cmd *cmd = &s->async->cmd;
945 int range;
946 unsigned int i, j;
947 unsigned int ch;
948 unsigned int rank;
949 unsigned long flags;
950
951
952 if (cmd->chanlist == NULL || cmd->chanlist_len == 0)
953 return -EINVAL;
954
955
956
957 devpriv->ao_enab = 0;
958
959 for (i = 0; i < cmd->chanlist_len; i++) {
960 ch = CR_CHAN(cmd->chanlist[i]);
961 devpriv->ao_enab |= 1U << ch;
962 rank = 0;
963 for (j = 0; j < cmd->chanlist_len; j++) {
964 if (CR_CHAN(cmd->chanlist[j]) < ch)
965 rank++;
966
967 }
968 devpriv->ao_scan_order[rank] = i;
969 }
970
971
972 outw(devpriv->ao_enab, dev->iobase + PCI224_DACCEN);
973
974
975 range = CR_RANGE(cmd->chanlist[0]);
976
977
978
979
980
981
982
983
984
985 devpriv->daccon = COMBINE(devpriv->daccon,
986 (devpriv->
987 hwrange[range] | PCI224_DACCON_TRIG_NONE |
988 PCI224_DACCON_FIFOINTR_NHALF),
989 (PCI224_DACCON_POLAR_MASK |
990 PCI224_DACCON_VREF_MASK |
991 PCI224_DACCON_TRIG_MASK |
992 PCI224_DACCON_FIFOINTR_MASK));
993 outw(devpriv->daccon | PCI224_DACCON_FIFORESET,
994 dev->iobase + PCI224_DACCON);
995
996 if (cmd->scan_begin_src == TRIG_TIMER) {
997 unsigned int div1, div2, round;
998 unsigned int ns = cmd->scan_begin_arg;
999 int round_mode = cmd->flags & TRIG_ROUND_MASK;
1000
1001
1002 switch (round_mode) {
1003 case TRIG_ROUND_NEAREST:
1004 default:
1005 round = TIMEBASE_10MHZ / 2;
1006 break;
1007 case TRIG_ROUND_DOWN:
1008 round = 0;
1009 break;
1010 case TRIG_ROUND_UP:
1011 round = TIMEBASE_10MHZ - 1;
1012 break;
1013 }
1014
1015 div2 = cmd->scan_begin_arg / TIMEBASE_10MHZ;
1016 div2 += (round + cmd->scan_begin_arg % TIMEBASE_10MHZ) /
1017 TIMEBASE_10MHZ;
1018 if (div2 <= 0x10000) {
1019
1020 if (div2 < 2)
1021 div2 = 2;
1022 div2 &= 0xffff;
1023 div1 = 1;
1024 } else {
1025
1026 div1 = devpriv->cached_div1;
1027 div2 = devpriv->cached_div2;
1028 pci224_cascade_ns_to_timer(TIMEBASE_10MHZ, &div1, &div2,
1029 &ns, round_mode);
1030 }
1031
1032
1033
1034
1035
1036
1037 outb(GAT_CONFIG(0, GAT_VCC),
1038 devpriv->iobase1 + PCI224_ZGAT_SCE);
1039 if (div1 == 1) {
1040
1041 outb(CLK_CONFIG(0, CLK_10MHZ),
1042 devpriv->iobase1 + PCI224_ZCLK_SCE);
1043 } else {
1044
1045
1046 outb(GAT_CONFIG(2, GAT_VCC),
1047 devpriv->iobase1 + PCI224_ZGAT_SCE);
1048
1049 outb(CLK_CONFIG(2, CLK_10MHZ),
1050 devpriv->iobase1 + PCI224_ZCLK_SCE);
1051
1052 i8254_load(devpriv->iobase1 + PCI224_Z2_CT0, 0,
1053 2, div1, 2);
1054
1055 outb(CLK_CONFIG(0, CLK_OUTNM1),
1056 devpriv->iobase1 + PCI224_ZCLK_SCE);
1057 }
1058
1059 i8254_load(devpriv->iobase1 + PCI224_Z2_CT0, 0, 0, div2, 2);
1060 }
1061
1062
1063
1064
1065 switch (cmd->stop_src) {
1066 case TRIG_COUNT:
1067
1068 devpriv->ao_stop_continuous = 0;
1069 devpriv->ao_stop_count = cmd->stop_arg;
1070 break;
1071 default:
1072
1073 devpriv->ao_stop_continuous = 1;
1074 devpriv->ao_stop_count = 0;
1075 break;
1076 }
1077
1078
1079
1080
1081 switch (cmd->start_src) {
1082 case TRIG_INT:
1083 spin_lock_irqsave(&devpriv->ao_spinlock, flags);
1084 s->async->inttrig = &pci224_ao_inttrig_start;
1085 spin_unlock_irqrestore(&devpriv->ao_spinlock, flags);
1086 break;
1087 case TRIG_EXT:
1088
1089 spin_lock_irqsave(&devpriv->ao_spinlock, flags);
1090 devpriv->intsce |= PCI224_INTR_EXT;
1091 outb(devpriv->intsce, devpriv->iobase1 + PCI224_INT_SCE);
1092 spin_unlock_irqrestore(&devpriv->ao_spinlock, flags);
1093 break;
1094 }
1095
1096 return 0;
1097}
1098
1099
1100
1101
1102static int pci224_ao_cancel(struct comedi_device *dev,
1103 struct comedi_subdevice *s)
1104{
1105 pci224_ao_stop(dev, s);
1106 return 0;
1107}
1108
1109
1110
1111
1112static void
1113pci224_ao_munge(struct comedi_device *dev, struct comedi_subdevice *s,
1114 void *data, unsigned int num_bytes, unsigned int chan_index)
1115{
1116 const struct pci224_board *thisboard = comedi_board(dev);
1117 struct pci224_private *devpriv = dev->private;
1118 struct comedi_async *async = s->async;
1119 short *array = data;
1120 unsigned int length = num_bytes / sizeof(*array);
1121 unsigned int offset;
1122 unsigned int shift;
1123 unsigned int i;
1124
1125
1126 shift = 16 - thisboard->ao_bits;
1127
1128 if ((devpriv->hwrange[CR_RANGE(async->cmd.chanlist[0])] &
1129 PCI224_DACCON_POLAR_MASK) == PCI224_DACCON_POLAR_UNI) {
1130
1131 offset = 0;
1132 } else {
1133
1134 offset = 32768;
1135 }
1136
1137 for (i = 0; i < length; i++)
1138 array[i] = (array[i] << shift) - offset;
1139
1140}
1141
1142
1143
1144
1145static irqreturn_t pci224_interrupt(int irq, void *d)
1146{
1147 struct comedi_device *dev = d;
1148 struct pci224_private *devpriv = dev->private;
1149 struct comedi_subdevice *s = &dev->subdevices[0];
1150 struct comedi_cmd *cmd;
1151 unsigned char intstat, valid_intstat;
1152 unsigned char curenab;
1153 int retval = 0;
1154 unsigned long flags;
1155
1156 intstat = inb(devpriv->iobase1 + PCI224_INT_SCE) & 0x3F;
1157 if (intstat) {
1158 retval = 1;
1159 spin_lock_irqsave(&devpriv->ao_spinlock, flags);
1160 valid_intstat = devpriv->intsce & intstat;
1161
1162 curenab = devpriv->intsce & ~intstat;
1163 outb(curenab, devpriv->iobase1 + PCI224_INT_SCE);
1164 devpriv->intr_running = 1;
1165 devpriv->intr_cpuid = THISCPU;
1166 spin_unlock_irqrestore(&devpriv->ao_spinlock, flags);
1167 if (valid_intstat != 0) {
1168 cmd = &s->async->cmd;
1169 if (valid_intstat & PCI224_INTR_EXT) {
1170 devpriv->intsce &= ~PCI224_INTR_EXT;
1171 if (cmd->start_src == TRIG_EXT)
1172 pci224_ao_start(dev, s);
1173 else if (cmd->stop_src == TRIG_EXT)
1174 pci224_ao_stop(dev, s);
1175
1176 }
1177 if (valid_intstat & PCI224_INTR_DAC)
1178 pci224_ao_handle_fifo(dev, s);
1179
1180 }
1181
1182 spin_lock_irqsave(&devpriv->ao_spinlock, flags);
1183 if (curenab != devpriv->intsce) {
1184 outb(devpriv->intsce,
1185 devpriv->iobase1 + PCI224_INT_SCE);
1186 }
1187 devpriv->intr_running = 0;
1188 spin_unlock_irqrestore(&devpriv->ao_spinlock, flags);
1189 }
1190 return IRQ_RETVAL(retval);
1191}
1192
1193
1194
1195
1196static const struct pci224_board
1197*pci224_find_pci_board(struct pci_dev *pci_dev)
1198{
1199 int i;
1200
1201 for (i = 0; i < ARRAY_SIZE(pci224_boards); i++)
1202 if (pci_dev->device == pci224_boards[i].devid)
1203 return &pci224_boards[i];
1204 return NULL;
1205}
1206
1207
1208
1209
1210
1211static struct pci_dev *pci224_find_pci_dev(struct comedi_device *dev,
1212 struct comedi_devconfig *it)
1213{
1214 const struct pci224_board *thisboard = comedi_board(dev);
1215 struct pci_dev *pci_dev = NULL;
1216 int bus = it->options[0];
1217 int slot = it->options[1];
1218
1219 for_each_pci_dev(pci_dev) {
1220 if (bus || slot) {
1221 if (bus != pci_dev->bus->number ||
1222 slot != PCI_SLOT(pci_dev->devfn))
1223 continue;
1224 }
1225 if (pci_dev->vendor != PCI_VENDOR_ID_AMPLICON)
1226 continue;
1227
1228 if (thisboard->model == any_model) {
1229
1230 const struct pci224_board *board_ptr;
1231
1232 board_ptr = pci224_find_pci_board(pci_dev);
1233 if (board_ptr == NULL)
1234 continue;
1235
1236 dev->board_ptr = board_ptr;
1237 } else {
1238
1239 if (thisboard->devid != pci_dev->device)
1240 continue;
1241 }
1242 return pci_dev;
1243 }
1244 dev_err(dev->class_dev,
1245 "No supported board found! (req. bus %d, slot %d)\n",
1246 bus, slot);
1247 return NULL;
1248}
1249
1250static void pci224_report_attach(struct comedi_device *dev, unsigned int irq)
1251{
1252 struct pci_dev *pcidev = comedi_to_pci_dev(dev);
1253 char tmpbuf[30];
1254
1255 if (irq)
1256 snprintf(tmpbuf, sizeof(tmpbuf), "irq %u%s", irq,
1257 (dev->irq ? "" : " UNAVAILABLE"));
1258 else
1259 snprintf(tmpbuf, sizeof(tmpbuf), "no irq");
1260 dev_info(dev->class_dev, "%s (pci %s) (%s) attached\n",
1261 dev->board_name, pci_name(pcidev), tmpbuf);
1262}
1263
1264
1265
1266
1267static int pci224_attach_common(struct comedi_device *dev,
1268 struct pci_dev *pci_dev, int *options)
1269{
1270 const struct pci224_board *thisboard = comedi_board(dev);
1271 struct pci224_private *devpriv = dev->private;
1272 struct comedi_subdevice *s;
1273 unsigned int irq;
1274 unsigned n;
1275 int ret;
1276
1277 comedi_set_hw_dev(dev, &pci_dev->dev);
1278
1279 ret = comedi_pci_enable(dev);
1280 if (ret)
1281 return ret;
1282
1283 spin_lock_init(&devpriv->ao_spinlock);
1284
1285 devpriv->iobase1 = pci_resource_start(pci_dev, 2);
1286 dev->iobase = pci_resource_start(pci_dev, 3);
1287 irq = pci_dev->irq;
1288
1289
1290 devpriv->ao_readback = kmalloc(sizeof(devpriv->ao_readback[0]) *
1291 thisboard->ao_chans, GFP_KERNEL);
1292 if (!devpriv->ao_readback)
1293 return -ENOMEM;
1294
1295
1296
1297 devpriv->ao_scan_vals = kmalloc(sizeof(devpriv->ao_scan_vals[0]) *
1298 thisboard->ao_chans, GFP_KERNEL);
1299 if (!devpriv->ao_scan_vals)
1300 return -ENOMEM;
1301
1302
1303
1304 devpriv->ao_scan_order = kmalloc(sizeof(devpriv->ao_scan_order[0]) *
1305 thisboard->ao_chans, GFP_KERNEL);
1306 if (!devpriv->ao_scan_order)
1307 return -ENOMEM;
1308
1309
1310
1311 devpriv->intsce = 0;
1312 outb(0, devpriv->iobase1 + PCI224_INT_SCE);
1313
1314
1315 outw(PCI224_DACCON_GLOBALRESET, dev->iobase + PCI224_DACCON);
1316 outw(0, dev->iobase + PCI224_DACCEN);
1317 outw(0, dev->iobase + PCI224_FIFOSIZ);
1318 devpriv->daccon = (PCI224_DACCON_TRIG_SW | PCI224_DACCON_POLAR_BI |
1319 PCI224_DACCON_FIFOENAB |
1320 PCI224_DACCON_FIFOINTR_EMPTY);
1321 outw(devpriv->daccon | PCI224_DACCON_FIFORESET,
1322 dev->iobase + PCI224_DACCON);
1323
1324 ret = comedi_alloc_subdevices(dev, 1);
1325 if (ret)
1326 return ret;
1327
1328 s = &dev->subdevices[0];
1329
1330 s->type = COMEDI_SUBD_AO;
1331 s->subdev_flags = SDF_WRITABLE | SDF_GROUND | SDF_CMD_WRITE;
1332 s->n_chan = thisboard->ao_chans;
1333 s->maxdata = (1 << thisboard->ao_bits) - 1;
1334 s->insn_write = &pci224_ao_insn_write;
1335 s->insn_read = &pci224_ao_insn_read;
1336 s->len_chanlist = s->n_chan;
1337
1338 dev->write_subdev = s;
1339 s->do_cmd = &pci224_ao_cmd;
1340 s->do_cmdtest = &pci224_ao_cmdtest;
1341 s->cancel = &pci224_ao_cancel;
1342 s->munge = &pci224_ao_munge;
1343
1344
1345 if (thisboard->model == pci234_model) {
1346
1347 const struct comedi_lrange **range_table_list;
1348
1349 s->range_table_list = range_table_list =
1350 kmalloc(sizeof(struct comedi_lrange *) * s->n_chan,
1351 GFP_KERNEL);
1352 if (!s->range_table_list)
1353 return -ENOMEM;
1354
1355 if (options) {
1356 for (n = 2; n < 3 + s->n_chan; n++) {
1357 if (options[n] < 0 || options[n] > 1) {
1358 dev_warn(dev->class_dev, DRIVER_NAME
1359 ": warning! bad options[%u]=%d\n",
1360 n, options[n]);
1361 }
1362 }
1363 }
1364 for (n = 0; n < s->n_chan; n++) {
1365 if (n < COMEDI_NDEVCONFOPTS - 3 && options &&
1366 options[3 + n] == 1) {
1367 if (options[2] == 1)
1368 range_table_list[n] = &range_pci234_ext;
1369 else
1370 range_table_list[n] = &range_bipolar5;
1371
1372 } else {
1373 if (options && options[2] == 1) {
1374 range_table_list[n] =
1375 &range_pci234_ext2;
1376 } else {
1377 range_table_list[n] = &range_bipolar10;
1378 }
1379 }
1380 }
1381 devpriv->hwrange = hwrange_pci234;
1382 } else {
1383
1384 if (options && options[2] == 1) {
1385 s->range_table = &range_pci224_external;
1386 devpriv->hwrange = hwrange_pci224_external;
1387 } else {
1388 if (options && options[2] != 0) {
1389 dev_warn(dev->class_dev, DRIVER_NAME
1390 ": warning! bad options[2]=%d\n",
1391 options[2]);
1392 }
1393 s->range_table = &range_pci224_internal;
1394 devpriv->hwrange = hwrange_pci224_internal;
1395 }
1396 }
1397
1398 dev->board_name = thisboard->name;
1399
1400 if (irq) {
1401 ret = request_irq(irq, pci224_interrupt, IRQF_SHARED,
1402 DRIVER_NAME, dev);
1403 if (ret < 0) {
1404 dev_err(dev->class_dev,
1405 "error! unable to allocate irq %u\n", irq);
1406 return ret;
1407 } else {
1408 dev->irq = irq;
1409 }
1410 }
1411
1412 pci224_report_attach(dev, irq);
1413 return 1;
1414}
1415
1416static int pci224_attach(struct comedi_device *dev, struct comedi_devconfig *it)
1417{
1418 struct pci224_private *devpriv;
1419 struct pci_dev *pci_dev;
1420
1421 dev_info(dev->class_dev, DRIVER_NAME ": attach\n");
1422
1423 devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
1424 if (!devpriv)
1425 return -ENOMEM;
1426
1427 pci_dev = pci224_find_pci_dev(dev, it);
1428 if (!pci_dev)
1429 return -EIO;
1430
1431 return pci224_attach_common(dev, pci_dev, it->options);
1432}
1433
1434static int
1435pci224_auto_attach(struct comedi_device *dev, unsigned long context_unused)
1436{
1437 struct pci_dev *pci_dev = comedi_to_pci_dev(dev);
1438 struct pci224_private *devpriv;
1439
1440 dev_info(dev->class_dev, DRIVER_NAME ": attach pci %s\n",
1441 pci_name(pci_dev));
1442
1443 devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
1444 if (!devpriv)
1445 return -ENOMEM;
1446
1447 dev->board_ptr = pci224_find_pci_board(pci_dev);
1448 if (dev->board_ptr == NULL) {
1449 dev_err(dev->class_dev,
1450 DRIVER_NAME ": BUG! cannot determine board type!\n");
1451 return -EINVAL;
1452 }
1453
1454
1455
1456
1457
1458
1459 pci_dev_get(pci_dev);
1460 return pci224_attach_common(dev, pci_dev, NULL);
1461}
1462
1463static void pci224_detach(struct comedi_device *dev)
1464{
1465 struct pci224_private *devpriv = dev->private;
1466 struct pci_dev *pcidev = comedi_to_pci_dev(dev);
1467
1468 if (dev->irq)
1469 free_irq(dev->irq, dev);
1470 if (dev->subdevices) {
1471 struct comedi_subdevice *s;
1472
1473 s = &dev->subdevices[0];
1474
1475 kfree(s->range_table_list);
1476 }
1477 if (devpriv) {
1478 kfree(devpriv->ao_readback);
1479 kfree(devpriv->ao_scan_vals);
1480 kfree(devpriv->ao_scan_order);
1481 }
1482 comedi_pci_disable(dev);
1483 if (pcidev)
1484 pci_dev_put(pcidev);
1485}
1486
1487static struct comedi_driver amplc_pci224_driver = {
1488 .driver_name = "amplc_pci224",
1489 .module = THIS_MODULE,
1490 .attach = pci224_attach,
1491 .detach = pci224_detach,
1492 .auto_attach = pci224_auto_attach,
1493 .board_name = &pci224_boards[0].name,
1494 .offset = sizeof(struct pci224_board),
1495 .num_names = ARRAY_SIZE(pci224_boards),
1496};
1497
1498static int amplc_pci224_pci_probe(struct pci_dev *dev,
1499 const struct pci_device_id *id)
1500{
1501 return comedi_pci_auto_config(dev, &lc_pci224_driver,
1502 id->driver_data);
1503}
1504
1505static DEFINE_PCI_DEVICE_TABLE(amplc_pci224_pci_table) = {
1506 { PCI_DEVICE(PCI_VENDOR_ID_AMPLICON, PCI_DEVICE_ID_AMPLICON_PCI224) },
1507 { PCI_DEVICE(PCI_VENDOR_ID_AMPLICON, PCI_DEVICE_ID_AMPLICON_PCI234) },
1508 { 0 }
1509};
1510MODULE_DEVICE_TABLE(pci, amplc_pci224_pci_table);
1511
1512static struct pci_driver amplc_pci224_pci_driver = {
1513 .name = "amplc_pci224",
1514 .id_table = amplc_pci224_pci_table,
1515 .probe = amplc_pci224_pci_probe,
1516 .remove = comedi_pci_auto_unconfig,
1517};
1518module_comedi_pci_driver(amplc_pci224_driver, amplc_pci224_pci_driver);
1519
1520MODULE_AUTHOR("Comedi http://www.comedi.org");
1521MODULE_DESCRIPTION("Comedi low-level driver");
1522MODULE_LICENSE("GPL");
1523