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