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