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