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#include "../comedidev.h"
50
51#include "comedi_pci.h"
52#include "8255.h"
53
54#define PCI_VENDOR_ID_CB 0x1307
55#define N_BOARDS 10
56#define EEPROM_SIZE 128
57#define MAX_AO_CHANNELS 8
58
59
60#define DIGITALIO_BADRINDEX 2
61
62#define DIGITALIO_SIZE 8
63
64#define DAC_BADRINDEX 3
65
66
67
68#define PORT1A 0
69
70#define PORT1B 1
71
72#define PORT1C 2
73
74#define CONTROL1 3
75
76#define PORT2A 4
77
78#define PORT2B 5
79
80#define PORT2C 6
81
82#define CONTROL2 7
83
84
85#define DACONTROL 0
86#define SU 0000001
87#define NOSU 0000000
88#define ENABLEDAC 0000002
89#define DISABLEDAC 0000000
90#define RANGE2V5 0000000
91#define RANGE5V 0000200
92#define RANGE10V 0000300
93#define UNIP 0000400
94#define BIP 0000000
95
96#define DACALIBRATION1 4
97
98#define SERIAL_IN_BIT 0x1
99#define CAL_CHANNEL_MASK (0x7 << 1)
100#define CAL_CHANNEL_BITS(channel) (((channel) << 1) & CAL_CHANNEL_MASK)
101
102#define CAL_COUNTER_MASK 0x1f
103#define CAL_COUNTER_OVERFLOW_BIT 0x20
104#define AO_BELOW_REF_BIT 0x40
105#define SERIAL_OUT_BIT 0x80
106
107#define DACALIBRATION2 6
108#define SELECT_EEPROM_BIT 0x1
109#define DESELECT_REF_DAC_BIT 0x2
110#define DESELECT_CALDAC_BIT(n) (0x4 << (n))
111#define DUMMY_BIT 0x40
112
113#define DADATA 8
114
115static const struct comedi_lrange cb_pcidda_ranges = {
116 6,
117 {
118 BIP_RANGE(10),
119 BIP_RANGE(5),
120 BIP_RANGE(2.5),
121 UNI_RANGE(10),
122 UNI_RANGE(5),
123 UNI_RANGE(2.5),
124 }
125};
126
127
128
129
130
131
132struct cb_pcidda_board {
133 const char *name;
134 char status;
135
136
137
138
139
140
141
142 unsigned short device_id;
143 int ao_chans;
144 int ao_bits;
145 const struct comedi_lrange *ranges;
146};
147
148static const struct cb_pcidda_board cb_pcidda_boards[] = {
149 {
150 .name = "pci-dda02/12",
151 .status = 1,
152 .device_id = 0x20,
153 .ao_chans = 2,
154 .ao_bits = 12,
155 .ranges = &cb_pcidda_ranges,
156 },
157 {
158 .name = "pci-dda04/12",
159 .status = 1,
160 .device_id = 0x21,
161 .ao_chans = 4,
162 .ao_bits = 12,
163 .ranges = &cb_pcidda_ranges,
164 },
165 {
166 .name = "pci-dda08/12",
167 .status = 0,
168 .device_id = 0x22,
169 .ao_chans = 8,
170 .ao_bits = 12,
171 .ranges = &cb_pcidda_ranges,
172 },
173 {
174 .name = "pci-dda02/16",
175 .status = 2,
176 .device_id = 0x23,
177 .ao_chans = 2,
178 .ao_bits = 16,
179 .ranges = &cb_pcidda_ranges,
180 },
181 {
182 .name = "pci-dda04/16",
183 .status = 2,
184 .device_id = 0x24,
185 .ao_chans = 4,
186 .ao_bits = 16,
187 .ranges = &cb_pcidda_ranges,
188 },
189 {
190 .name = "pci-dda08/16",
191 .status = 0,
192 .device_id = 0x25,
193 .ao_chans = 8,
194 .ao_bits = 16,
195 .ranges = &cb_pcidda_ranges,
196 },
197};
198
199static DEFINE_PCI_DEVICE_TABLE(cb_pcidda_pci_table) = {
200 {
201 PCI_VENDOR_ID_CB, 0x0020, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {
202 PCI_VENDOR_ID_CB, 0x0021, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {
203 PCI_VENDOR_ID_CB, 0x0022, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {
204 PCI_VENDOR_ID_CB, 0x0023, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {
205 PCI_VENDOR_ID_CB, 0x0024, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {
206 PCI_VENDOR_ID_CB, 0x0025, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {
207 0}
208};
209
210MODULE_DEVICE_TABLE(pci, cb_pcidda_pci_table);
211
212
213
214
215#define thisboard ((const struct cb_pcidda_board *)dev->board_ptr)
216
217
218
219
220struct cb_pcidda_private {
221 int data;
222
223
224 struct pci_dev *pci_dev;
225
226 unsigned long digitalio;
227 unsigned long dac;
228
229
230
231
232 unsigned int dac_cal1_bits;
233 unsigned int ao_range[MAX_AO_CHANNELS];
234 u16 eeprom_data[EEPROM_SIZE];
235};
236
237
238
239
240
241#define devpriv ((struct cb_pcidda_private *)dev->private)
242
243static int cb_pcidda_attach(struct comedi_device *dev,
244 struct comedi_devconfig *it);
245static int cb_pcidda_detach(struct comedi_device *dev);
246
247static int cb_pcidda_ao_winsn(struct comedi_device *dev,
248 struct comedi_subdevice *s,
249 struct comedi_insn *insn, unsigned int *data);
250
251
252
253
254
255static unsigned int cb_pcidda_serial_in(struct comedi_device *dev);
256static void cb_pcidda_serial_out(struct comedi_device *dev, unsigned int value,
257 unsigned int num_bits);
258static unsigned int cb_pcidda_read_eeprom(struct comedi_device *dev,
259 unsigned int address);
260static void cb_pcidda_calibrate(struct comedi_device *dev, unsigned int channel,
261 unsigned int range);
262
263
264
265
266
267
268
269static struct comedi_driver driver_cb_pcidda = {
270 .driver_name = "cb_pcidda",
271 .module = THIS_MODULE,
272 .attach = cb_pcidda_attach,
273 .detach = cb_pcidda_detach,
274};
275
276
277
278
279
280static int cb_pcidda_attach(struct comedi_device *dev,
281 struct comedi_devconfig *it)
282{
283 struct comedi_subdevice *s;
284 struct pci_dev *pcidev;
285 int index;
286
287 printk("comedi%d: cb_pcidda: ", dev->minor);
288
289
290
291
292 if (alloc_private(dev, sizeof(struct cb_pcidda_private)) < 0)
293 return -ENOMEM;
294
295
296
297
298 printk("\n");
299
300 for (pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, NULL);
301 pcidev != NULL;
302 pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pcidev)) {
303 if (pcidev->vendor == PCI_VENDOR_ID_CB) {
304 if (it->options[0] || it->options[1]) {
305 if (pcidev->bus->number != it->options[0] ||
306 PCI_SLOT(pcidev->devfn) != it->options[1]) {
307 continue;
308 }
309 }
310 for (index = 0; index < N_BOARDS; index++) {
311 if (cb_pcidda_boards[index].device_id ==
312 pcidev->device) {
313 goto found;
314 }
315 }
316 }
317 }
318 if (!pcidev) {
319 printk
320 ("Not a ComputerBoards/MeasurementComputing card on requested position\n");
321 return -EIO;
322 }
323found:
324 devpriv->pci_dev = pcidev;
325 dev->board_ptr = cb_pcidda_boards + index;
326
327 printk("Found %s at requested position\n", thisboard->name);
328
329
330
331
332 if (comedi_pci_enable(pcidev, thisboard->name)) {
333 printk
334 ("cb_pcidda: failed to enable PCI device and request regions\n");
335 return -EIO;
336 }
337
338
339
340
341 devpriv->digitalio =
342 pci_resource_start(devpriv->pci_dev, DIGITALIO_BADRINDEX);
343 devpriv->dac = pci_resource_start(devpriv->pci_dev, DAC_BADRINDEX);
344
345
346
347
348 if (thisboard->status == 2)
349 printk
350 ("WARNING: DRIVER FOR THIS BOARD NOT CHECKED WITH MANUAL. "
351 "WORKS ASSUMING FULL COMPATIBILITY WITH PCI-DDA08/12. "
352 "PLEASE REPORT USAGE TO <ivanmr@altavista.com>.\n");
353
354
355
356
357 dev->board_name = thisboard->name;
358
359
360
361
362 if (alloc_subdevices(dev, 3) < 0)
363 return -ENOMEM;
364
365 s = dev->subdevices + 0;
366
367 s->type = COMEDI_SUBD_AO;
368 s->subdev_flags = SDF_WRITABLE;
369 s->n_chan = thisboard->ao_chans;
370 s->maxdata = (1 << thisboard->ao_bits) - 1;
371 s->range_table = thisboard->ranges;
372 s->insn_write = cb_pcidda_ao_winsn;
373
374
375
376
377
378
379 s = dev->subdevices + 1;
380 subdev_8255_init(dev, s, NULL, devpriv->digitalio);
381 s = dev->subdevices + 2;
382 subdev_8255_init(dev, s, NULL, devpriv->digitalio + PORT2A);
383
384 printk(" eeprom:");
385 for (index = 0; index < EEPROM_SIZE; index++) {
386 devpriv->eeprom_data[index] = cb_pcidda_read_eeprom(dev, index);
387 printk(" %i:0x%x ", index, devpriv->eeprom_data[index]);
388 }
389 printk("\n");
390
391
392 for (index = 0; index < thisboard->ao_chans; index++)
393 cb_pcidda_calibrate(dev, index, devpriv->ao_range[index]);
394
395 return 1;
396}
397
398
399
400
401
402
403
404
405
406static int cb_pcidda_detach(struct comedi_device *dev)
407{
408
409
410
411 if (devpriv) {
412 if (devpriv->pci_dev) {
413 if (devpriv->dac) {
414 comedi_pci_disable(devpriv->pci_dev);
415 }
416 pci_dev_put(devpriv->pci_dev);
417 }
418 }
419
420 if (dev->subdevices) {
421 subdev_8255_cleanup(dev, dev->subdevices + 1);
422 subdev_8255_cleanup(dev, dev->subdevices + 2);
423 }
424
425 printk("comedi%d: cb_pcidda: remove\n", dev->minor);
426
427 return 0;
428}
429
430
431
432
433#if 0
434static int cb_pcidda_ai_cmd(struct comedi_device *dev,
435 struct comedi_subdevice *s)
436{
437 printk("cb_pcidda_ai_cmd\n");
438 printk("subdev: %d\n", cmd->subdev);
439 printk("flags: %d\n", cmd->flags);
440 printk("start_src: %d\n", cmd->start_src);
441 printk("start_arg: %d\n", cmd->start_arg);
442 printk("scan_begin_src: %d\n", cmd->scan_begin_src);
443 printk("convert_src: %d\n", cmd->convert_src);
444 printk("convert_arg: %d\n", cmd->convert_arg);
445 printk("scan_end_src: %d\n", cmd->scan_end_src);
446 printk("scan_end_arg: %d\n", cmd->scan_end_arg);
447 printk("stop_src: %d\n", cmd->stop_src);
448 printk("stop_arg: %d\n", cmd->stop_arg);
449 printk("chanlist_len: %d\n", cmd->chanlist_len);
450}
451#endif
452
453#if 0
454static int cb_pcidda_ai_cmdtest(struct comedi_device *dev,
455 struct comedi_subdevice *s,
456 struct comedi_cmd *cmd)
457{
458 int err = 0;
459 int tmp;
460
461
462
463
464
465
466
467
468
469
470 tmp = cmd->start_src;
471 cmd->start_src &= TRIG_NOW;
472 if (!cmd->start_src || tmp != cmd->start_src)
473 err++;
474
475 tmp = cmd->scan_begin_src;
476 cmd->scan_begin_src &= TRIG_TIMER | TRIG_EXT;
477 if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
478 err++;
479
480 tmp = cmd->convert_src;
481 cmd->convert_src &= TRIG_TIMER | TRIG_EXT;
482 if (!cmd->convert_src || tmp != cmd->convert_src)
483 err++;
484
485 tmp = cmd->scan_end_src;
486 cmd->scan_end_src &= TRIG_COUNT;
487 if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
488 err++;
489
490 tmp = cmd->stop_src;
491 cmd->stop_src &= TRIG_COUNT | TRIG_NONE;
492 if (!cmd->stop_src || tmp != cmd->stop_src)
493 err++;
494
495 if (err)
496 return 1;
497
498
499
500
501 if (cmd->scan_begin_src != TRIG_TIMER
502 && cmd->scan_begin_src != TRIG_EXT)
503 err++;
504 if (cmd->convert_src != TRIG_TIMER && cmd->convert_src != TRIG_EXT)
505 err++;
506 if (cmd->stop_src != TRIG_TIMER && cmd->stop_src != TRIG_EXT)
507 err++;
508
509 if (err)
510 return 2;
511
512
513
514 if (cmd->start_arg != 0) {
515 cmd->start_arg = 0;
516 err++;
517 }
518#define MAX_SPEED 10000
519#define MIN_SPEED 1000000000
520
521 if (cmd->scan_begin_src == TRIG_TIMER) {
522 if (cmd->scan_begin_arg < MAX_SPEED) {
523 cmd->scan_begin_arg = MAX_SPEED;
524 err++;
525 }
526 if (cmd->scan_begin_arg > MIN_SPEED) {
527 cmd->scan_begin_arg = MIN_SPEED;
528 err++;
529 }
530 } else {
531
532
533
534 if (cmd->scan_begin_arg > 9) {
535 cmd->scan_begin_arg = 9;
536 err++;
537 }
538 }
539 if (cmd->convert_src == TRIG_TIMER) {
540 if (cmd->convert_arg < MAX_SPEED) {
541 cmd->convert_arg = MAX_SPEED;
542 err++;
543 }
544 if (cmd->convert_arg > MIN_SPEED) {
545 cmd->convert_arg = MIN_SPEED;
546 err++;
547 }
548 } else {
549
550
551 if (cmd->convert_arg > 9) {
552 cmd->convert_arg = 9;
553 err++;
554 }
555 }
556
557 if (cmd->scan_end_arg != cmd->chanlist_len) {
558 cmd->scan_end_arg = cmd->chanlist_len;
559 err++;
560 }
561 if (cmd->stop_src == TRIG_COUNT) {
562 if (cmd->stop_arg > 0x00ffffff) {
563 cmd->stop_arg = 0x00ffffff;
564 err++;
565 }
566 } else {
567
568 if (cmd->stop_arg != 0) {
569 cmd->stop_arg = 0;
570 err++;
571 }
572 }
573
574 if (err)
575 return 3;
576
577
578
579 if (cmd->scan_begin_src == TRIG_TIMER) {
580 tmp = cmd->scan_begin_arg;
581 cb_pcidda_ns_to_timer(&cmd->scan_begin_arg,
582 cmd->flags & TRIG_ROUND_MASK);
583 if (tmp != cmd->scan_begin_arg)
584 err++;
585 }
586 if (cmd->convert_src == TRIG_TIMER) {
587 tmp = cmd->convert_arg;
588 cb_pcidda_ns_to_timer(&cmd->convert_arg,
589 cmd->flags & TRIG_ROUND_MASK);
590 if (tmp != cmd->convert_arg)
591 err++;
592 if (cmd->scan_begin_src == TRIG_TIMER &&
593 cmd->scan_begin_arg <
594 cmd->convert_arg * cmd->scan_end_arg) {
595 cmd->scan_begin_arg =
596 cmd->convert_arg * cmd->scan_end_arg;
597 err++;
598 }
599 }
600
601 if (err)
602 return 4;
603
604 return 0;
605}
606#endif
607
608
609
610
611
612
613#if 0
614static int cb_pcidda_ns_to_timer(unsigned int *ns, int round)
615{
616
617 return *ns;
618}
619#endif
620
621static int cb_pcidda_ao_winsn(struct comedi_device *dev,
622 struct comedi_subdevice *s,
623 struct comedi_insn *insn, unsigned int *data)
624{
625 unsigned int command;
626 unsigned int channel, range;
627
628 channel = CR_CHAN(insn->chanspec);
629 range = CR_RANGE(insn->chanspec);
630
631
632 if (range != devpriv->ao_range[channel])
633 cb_pcidda_calibrate(dev, channel, range);
634
635
636 command = NOSU | ENABLEDAC;
637
638
639 switch (range) {
640 case 0:
641 command |= BIP | RANGE10V;
642 break;
643 case 1:
644 command |= BIP | RANGE5V;
645 break;
646 case 2:
647 command |= BIP | RANGE2V5;
648 break;
649 case 3:
650 command |= UNIP | RANGE10V;
651 break;
652 case 4:
653 command |= UNIP | RANGE5V;
654 break;
655 case 5:
656 command |= UNIP | RANGE2V5;
657 break;
658 };
659
660
661 command |= channel << 2;
662 outw(command, devpriv->dac + DACONTROL);
663
664
665 outw(data[0], devpriv->dac + DADATA + channel * 2);
666
667
668 return 1;
669}
670
671
672static unsigned int cb_pcidda_serial_in(struct comedi_device *dev)
673{
674 unsigned int value = 0;
675 int i;
676 const int value_width = 16;
677
678 for (i = 1; i <= value_width; i++) {
679
680 if (inw_p(devpriv->dac + DACALIBRATION1) & SERIAL_OUT_BIT) {
681 value |= 1 << (value_width - i);
682 }
683 }
684
685 return value;
686}
687
688
689static void cb_pcidda_serial_out(struct comedi_device *dev, unsigned int value,
690 unsigned int num_bits)
691{
692 int i;
693
694 for (i = 1; i <= num_bits; i++) {
695
696 if (value & (1 << (num_bits - i)))
697 devpriv->dac_cal1_bits |= SERIAL_IN_BIT;
698 else
699 devpriv->dac_cal1_bits &= ~SERIAL_IN_BIT;
700 outw_p(devpriv->dac_cal1_bits, devpriv->dac + DACALIBRATION1);
701 }
702}
703
704
705static unsigned int cb_pcidda_read_eeprom(struct comedi_device *dev,
706 unsigned int address)
707{
708 unsigned int i;
709 unsigned int cal2_bits;
710 unsigned int value;
711 const int max_num_caldacs = 4;
712 const int read_instruction = 0x6;
713 const int instruction_length = 3;
714 const int address_length = 8;
715
716
717 cal2_bits = SELECT_EEPROM_BIT | DESELECT_REF_DAC_BIT | DUMMY_BIT;
718
719 for (i = 0; i < max_num_caldacs; i++) {
720 cal2_bits |= DESELECT_CALDAC_BIT(i);
721 }
722 outw_p(cal2_bits, devpriv->dac + DACALIBRATION2);
723
724
725 cb_pcidda_serial_out(dev, read_instruction, instruction_length);
726
727 cb_pcidda_serial_out(dev, address, address_length);
728
729 value = cb_pcidda_serial_in(dev);
730
731
732 cal2_bits &= ~SELECT_EEPROM_BIT;
733 outw_p(cal2_bits, devpriv->dac + DACALIBRATION2);
734
735 return value;
736}
737
738
739static void cb_pcidda_write_caldac(struct comedi_device *dev,
740 unsigned int caldac, unsigned int channel,
741 unsigned int value)
742{
743 unsigned int cal2_bits;
744 unsigned int i;
745 const int num_channel_bits = 3;
746 const int num_caldac_bits = 8;
747 const int max_num_caldacs = 4;
748
749
750 cb_pcidda_serial_out(dev, channel, num_channel_bits);
751
752 cb_pcidda_serial_out(dev, value, num_caldac_bits);
753
754
755
756
757 cal2_bits = DESELECT_REF_DAC_BIT | DUMMY_BIT;
758
759 for (i = 0; i < max_num_caldacs; i++) {
760 cal2_bits |= DESELECT_CALDAC_BIT(i);
761 }
762
763 cal2_bits &= ~DESELECT_CALDAC_BIT(caldac);
764 outw_p(cal2_bits, devpriv->dac + DACALIBRATION2);
765
766 cal2_bits |= DESELECT_CALDAC_BIT(caldac);
767 outw_p(cal2_bits, devpriv->dac + DACALIBRATION2);
768}
769
770
771static unsigned int caldac_number(unsigned int channel)
772{
773 return channel / 2;
774}
775
776
777static unsigned int fine_gain_channel(unsigned int ao_channel)
778{
779 return 4 * (ao_channel % 2);
780}
781
782
783static unsigned int coarse_gain_channel(unsigned int ao_channel)
784{
785 return 1 + 4 * (ao_channel % 2);
786}
787
788
789static unsigned int coarse_offset_channel(unsigned int ao_channel)
790{
791 return 2 + 4 * (ao_channel % 2);
792}
793
794
795static unsigned int fine_offset_channel(unsigned int ao_channel)
796{
797 return 3 + 4 * (ao_channel % 2);
798}
799
800
801static unsigned int offset_eeprom_address(unsigned int ao_channel,
802 unsigned int range)
803{
804 return 0x7 + 2 * range + 12 * ao_channel;
805}
806
807
808static unsigned int gain_eeprom_address(unsigned int ao_channel,
809 unsigned int range)
810{
811 return 0x8 + 2 * range + 12 * ao_channel;
812}
813
814
815static unsigned int eeprom_coarse_byte(unsigned int word)
816{
817 return (word >> 8) & 0xff;
818}
819
820
821static unsigned int eeprom_fine_byte(unsigned int word)
822{
823 return word & 0xff;
824}
825
826
827static void cb_pcidda_calibrate(struct comedi_device *dev, unsigned int channel,
828 unsigned int range)
829{
830 unsigned int coarse_offset, fine_offset, coarse_gain, fine_gain;
831
832
833 devpriv->ao_range[channel] = range;
834
835
836 coarse_offset =
837 eeprom_coarse_byte(devpriv->eeprom_data
838 [offset_eeprom_address(channel, range)]);
839 fine_offset =
840 eeprom_fine_byte(devpriv->eeprom_data
841 [offset_eeprom_address(channel, range)]);
842 coarse_gain =
843 eeprom_coarse_byte(devpriv->eeprom_data
844 [gain_eeprom_address(channel, range)]);
845 fine_gain =
846 eeprom_fine_byte(devpriv->eeprom_data
847 [gain_eeprom_address(channel, range)]);
848
849
850 cb_pcidda_write_caldac(dev, caldac_number(channel),
851 coarse_offset_channel(channel), coarse_offset);
852 cb_pcidda_write_caldac(dev, caldac_number(channel),
853 fine_offset_channel(channel), fine_offset);
854 cb_pcidda_write_caldac(dev, caldac_number(channel),
855 coarse_gain_channel(channel), coarse_gain);
856 cb_pcidda_write_caldac(dev, caldac_number(channel),
857 fine_gain_channel(channel), fine_gain);
858}
859
860
861
862
863
864COMEDI_PCI_INITCLEANUP(driver_cb_pcidda, cb_pcidda_pci_table);
865