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#include "../comedidev.h"
75#include <linux/delay.h>
76#include <linux/interrupt.h>
77
78#include "8253.h"
79#include "8255.h"
80#include "amcc_s5933.h"
81#include "comedi_fc.h"
82
83
84#define PCI_VENDOR_ID_CB 0x1307
85
86#define TIMER_BASE 100
87#define AI_BUFFER_SIZE 1024
88#define AO_BUFFER_SIZE 1024
89#define NUM_CHANNELS_8800 8
90#define NUM_CHANNELS_7376 1
91#define NUM_CHANNELS_8402 2
92#define NUM_CHANNELS_DAC08 1
93
94
95#define INT_ADCFIFO 0
96#define INT_EOS 0x1
97#define INT_FHF 0x2
98#define INT_FNE 0x3
99#define INT_MASK 0x3
100#define INTE 0x4
101#define DAHFIE 0x8
102#define EOAIE 0x10
103#define DAHFI 0x20
104#define EOAI 0x40
105#define INT 0x80
106#define EOBI 0x200
107#define ADHFI 0x400
108#define ADNEI 0x800
109#define ADNE 0x1000
110#define DAEMIE 0x1000
111#define LADFUL 0x2000
112#define DAEMI 0x4000
113
114#define ADCMUX_CONT 2
115#define BEGIN_SCAN(x) ((x) & 0xf)
116#define END_SCAN(x) (((x) & 0xf) << 4)
117#define GAIN_BITS(x) (((x) & 0x3) << 8)
118#define UNIP 0x800
119#define SE 0x400
120#define PACER_MASK 0x3000
121#define PACER_INT 0x1000
122#define PACER_EXT_FALL 0x2000
123#define PACER_EXT_RISE 0x3000
124#define EOC 0x4000
125
126#define TRIG_CONTSTAT 4
127#define SW_TRIGGER 0x1
128#define EXT_TRIGGER 0x2
129#define ANALOG_TRIGGER 0x3
130#define TRIGGER_MASK 0x3
131#define TGPOL 0x04
132#define TGSEL 0x08
133#define TGEN 0x10
134#define BURSTE 0x20
135#define XTRCL 0x80
136
137#define CALIBRATION_REG 6
138#define SELECT_8800_BIT 0x100
139#define SELECT_TRIMPOT_BIT 0x200
140#define SELECT_DAC08_BIT 0x400
141#define CAL_SRC_BITS(x) (((x) & 0x7) << 11)
142#define CAL_EN_BIT 0x4000
143#define SERIAL_DATA_IN_BIT 0x8000
144
145#define DAC_CSR 0x8
146#define DACEN 0x02
147#define DAC_MODE_UPDATE_BOTH 0x80
148
149static inline unsigned int DAC_RANGE(unsigned int channel, unsigned int range)
150{
151 return (range & 0x3) << (8 + 2 * (channel & 0x1));
152}
153
154static inline unsigned int DAC_RANGE_MASK(unsigned int channel)
155{
156 return 0x3 << (8 + 2 * (channel & 0x1));
157};
158
159
160#define DAC_EMPTY 0x1
161#define DAC_START 0x4
162#define DAC_PACER_MASK 0x18
163#define DAC_PACER_INT 0x8
164#define DAC_PACER_EXT_FALL 0x10
165#define DAC_PACER_EXT_RISE 0x18
166
167static inline unsigned int DAC_CHAN_EN(unsigned int channel)
168{
169 return 1 << (5 + (channel & 0x1));
170};
171
172
173#define ADCDATA 0
174#define ADCFIFOCLR 2
175
176
177#define ADC8254 0
178#define DIO_8255 4
179#define DAC8254 8
180
181
182static inline unsigned int DAC_DATA_REG(unsigned int channel)
183{
184 return 2 * (channel & 0x1);
185}
186
187
188#define DACDATA 0
189#define DACFIFOCLR 2
190
191#define IS_UNIPOLAR 0x4
192
193
194static const struct comedi_lrange cb_pcidas_ranges = {
195 8,
196 {
197 BIP_RANGE(10),
198 BIP_RANGE(5),
199 BIP_RANGE(2.5),
200 BIP_RANGE(1.25),
201 UNI_RANGE(10),
202 UNI_RANGE(5),
203 UNI_RANGE(2.5),
204 UNI_RANGE(1.25)
205 }
206};
207
208
209static const struct comedi_lrange cb_pcidas_alt_ranges = {
210 8,
211 {
212 BIP_RANGE(10),
213 BIP_RANGE(1),
214 BIP_RANGE(0.1),
215 BIP_RANGE(0.01),
216 UNI_RANGE(10),
217 UNI_RANGE(1),
218 UNI_RANGE(0.1),
219 UNI_RANGE(0.01)
220 }
221};
222
223
224static const struct comedi_lrange cb_pcidas_ao_ranges = {
225 4,
226 {
227 BIP_RANGE(5),
228 BIP_RANGE(10),
229 UNI_RANGE(5),
230 UNI_RANGE(10),
231 }
232};
233
234enum trimpot_model {
235 AD7376,
236 AD8402,
237};
238
239struct cb_pcidas_board {
240 const char *name;
241 unsigned short device_id;
242 int ai_nchan;
243 int ai_bits;
244 int ai_speed;
245 int ao_nchan;
246 int has_ao_fifo;
247 int ao_scan_speed;
248 int fifo_size;
249 const struct comedi_lrange *ranges;
250 enum trimpot_model trimpot;
251 unsigned has_dac08:1;
252 unsigned is_1602:1;
253};
254
255static const struct cb_pcidas_board cb_pcidas_boards[] = {
256 {
257 .name = "pci-das1602/16",
258 .device_id = 0x1,
259 .ai_nchan = 16,
260 .ai_bits = 16,
261 .ai_speed = 5000,
262 .ao_nchan = 2,
263 .has_ao_fifo = 1,
264 .ao_scan_speed = 10000,
265 .fifo_size = 512,
266 .ranges = &cb_pcidas_ranges,
267 .trimpot = AD8402,
268 .has_dac08 = 1,
269 .is_1602 = 1,
270 }, {
271 .name = "pci-das1200",
272 .device_id = 0xF,
273 .ai_nchan = 16,
274 .ai_bits = 12,
275 .ai_speed = 3200,
276 .ao_nchan = 2,
277 .fifo_size = 1024,
278 .ranges = &cb_pcidas_ranges,
279 .trimpot = AD7376,
280 }, {
281 .name = "pci-das1602/12",
282 .device_id = 0x10,
283 .ai_nchan = 16,
284 .ai_bits = 12,
285 .ai_speed = 3200,
286 .ao_nchan = 2,
287 .has_ao_fifo = 1,
288 .ao_scan_speed = 4000,
289 .fifo_size = 1024,
290 .ranges = &cb_pcidas_ranges,
291 .trimpot = AD7376,
292 .is_1602 = 1,
293 }, {
294 .name = "pci-das1200/jr",
295 .device_id = 0x19,
296 .ai_nchan = 16,
297 .ai_bits = 12,
298 .ai_speed = 3200,
299 .fifo_size = 1024,
300 .ranges = &cb_pcidas_ranges,
301 .trimpot = AD7376,
302 }, {
303 .name = "pci-das1602/16/jr",
304 .device_id = 0x1C,
305 .ai_nchan = 16,
306 .ai_bits = 16,
307 .ai_speed = 5000,
308 .fifo_size = 512,
309 .ranges = &cb_pcidas_ranges,
310 .trimpot = AD8402,
311 .has_dac08 = 1,
312 .is_1602 = 1,
313 }, {
314 .name = "pci-das1000",
315 .device_id = 0x4C,
316 .ai_nchan = 16,
317 .ai_bits = 12,
318 .ai_speed = 4000,
319 .fifo_size = 1024,
320 .ranges = &cb_pcidas_ranges,
321 .trimpot = AD7376,
322 }, {
323 .name = "pci-das1001",
324 .device_id = 0x1a,
325 .ai_nchan = 16,
326 .ai_bits = 12,
327 .ai_speed = 6800,
328 .ao_nchan = 2,
329 .fifo_size = 1024,
330 .ranges = &cb_pcidas_alt_ranges,
331 .trimpot = AD7376,
332 }, {
333 .name = "pci-das1002",
334 .device_id = 0x1b,
335 .ai_nchan = 16,
336 .ai_bits = 12,
337 .ai_speed = 6800,
338 .ao_nchan = 2,
339 .fifo_size = 1024,
340 .ranges = &cb_pcidas_ranges,
341 .trimpot = AD7376,
342 },
343};
344
345struct cb_pcidas_private {
346
347 unsigned long s5933_config;
348 unsigned long control_status;
349 unsigned long adc_fifo;
350 unsigned long pacer_counter_dio;
351 unsigned long ao_registers;
352
353 unsigned int divisor1;
354 unsigned int divisor2;
355
356 unsigned int count;
357
358 unsigned int adc_fifo_bits;
359 unsigned int s5933_intcsr_bits;
360 unsigned int ao_control_bits;
361
362 short ai_buffer[AI_BUFFER_SIZE];
363 short ao_buffer[AO_BUFFER_SIZE];
364
365 unsigned int ao_divisor1;
366 unsigned int ao_divisor2;
367
368 unsigned int ao_count;
369
370 int ao_value[2];
371 unsigned int caldac_value[NUM_CHANNELS_8800];
372 unsigned int trimpot_value[NUM_CHANNELS_8402];
373 unsigned int dac08_value;
374 unsigned int calibration_source;
375};
376
377static inline unsigned int cal_enable_bits(struct comedi_device *dev)
378{
379 struct cb_pcidas_private *devpriv = dev->private;
380
381 return CAL_EN_BIT | CAL_SRC_BITS(devpriv->calibration_source);
382}
383
384static int cb_pcidas_ai_rinsn(struct comedi_device *dev,
385 struct comedi_subdevice *s,
386 struct comedi_insn *insn, unsigned int *data)
387{
388 struct cb_pcidas_private *devpriv = dev->private;
389 unsigned int chan = CR_CHAN(insn->chanspec);
390 unsigned int range = CR_RANGE(insn->chanspec);
391 unsigned int aref = CR_AREF(insn->chanspec);
392 unsigned int bits;
393 int n, i;
394
395
396 if (insn->chanspec & CR_ALT_SOURCE) {
397 outw(cal_enable_bits(dev),
398 devpriv->control_status + CALIBRATION_REG);
399 chan = 0;
400 } else {
401 outw(0, devpriv->control_status + CALIBRATION_REG);
402 }
403
404
405 bits = BEGIN_SCAN(chan) | END_SCAN(chan) | GAIN_BITS(range);
406
407 if (range & IS_UNIPOLAR)
408 bits |= UNIP;
409
410 if (aref != AREF_DIFF)
411 bits |= SE;
412 outw(bits, devpriv->control_status + ADCMUX_CONT);
413
414
415 outw(0, devpriv->adc_fifo + ADCFIFOCLR);
416
417
418 for (n = 0; n < insn->n; n++) {
419
420 outw(0, devpriv->adc_fifo + ADCDATA);
421
422
423
424 for (i = 0; i < 10000; i++) {
425 if (inw(devpriv->control_status + ADCMUX_CONT) & EOC)
426 break;
427 }
428 if (i == 10000)
429 return -ETIMEDOUT;
430
431
432 data[n] = inw(devpriv->adc_fifo + ADCDATA);
433 }
434
435
436 return n;
437}
438
439static int ai_config_insn(struct comedi_device *dev, struct comedi_subdevice *s,
440 struct comedi_insn *insn, unsigned int *data)
441{
442 struct cb_pcidas_private *devpriv = dev->private;
443 int id = data[0];
444 unsigned int source = data[1];
445
446 switch (id) {
447 case INSN_CONFIG_ALT_SOURCE:
448 if (source >= 8) {
449 dev_err(dev->class_dev,
450 "invalid calibration source: %i\n",
451 source);
452 return -EINVAL;
453 }
454 devpriv->calibration_source = source;
455 break;
456 default:
457 return -EINVAL;
458 break;
459 }
460 return insn->n;
461}
462
463
464static int cb_pcidas_ao_nofifo_winsn(struct comedi_device *dev,
465 struct comedi_subdevice *s,
466 struct comedi_insn *insn,
467 unsigned int *data)
468{
469 struct cb_pcidas_private *devpriv = dev->private;
470 unsigned int chan = CR_CHAN(insn->chanspec);
471 unsigned int range = CR_RANGE(insn->chanspec);
472 unsigned long flags;
473
474
475 spin_lock_irqsave(&dev->spinlock, flags);
476 devpriv->ao_control_bits &= (~DAC_MODE_UPDATE_BOTH &
477 ~DAC_RANGE_MASK(chan));
478 devpriv->ao_control_bits |= (DACEN | DAC_RANGE(chan, range));
479 outw(devpriv->ao_control_bits, devpriv->control_status + DAC_CSR);
480 spin_unlock_irqrestore(&dev->spinlock, flags);
481
482
483 devpriv->ao_value[chan] = data[0];
484
485
486 outw(data[0], devpriv->ao_registers + DAC_DATA_REG(chan));
487
488 return insn->n;
489}
490
491
492static int cb_pcidas_ao_fifo_winsn(struct comedi_device *dev,
493 struct comedi_subdevice *s,
494 struct comedi_insn *insn, unsigned int *data)
495{
496 struct cb_pcidas_private *devpriv = dev->private;
497 unsigned int chan = CR_CHAN(insn->chanspec);
498 unsigned int range = CR_RANGE(insn->chanspec);
499 unsigned long flags;
500
501
502 outw(0, devpriv->ao_registers + DACFIFOCLR);
503
504
505 spin_lock_irqsave(&dev->spinlock, flags);
506 devpriv->ao_control_bits &= (~DAC_CHAN_EN(0) & ~DAC_CHAN_EN(1) &
507 ~DAC_RANGE_MASK(chan) & ~DAC_PACER_MASK);
508 devpriv->ao_control_bits |= (DACEN | DAC_RANGE(chan, range) |
509 DAC_CHAN_EN(chan) | DAC_START);
510 outw(devpriv->ao_control_bits, devpriv->control_status + DAC_CSR);
511 spin_unlock_irqrestore(&dev->spinlock, flags);
512
513
514 devpriv->ao_value[chan] = data[0];
515
516
517 outw(data[0], devpriv->ao_registers + DACDATA);
518
519 return insn->n;
520}
521
522static int cb_pcidas_ao_readback_insn(struct comedi_device *dev,
523 struct comedi_subdevice *s,
524 struct comedi_insn *insn,
525 unsigned int *data)
526{
527 struct cb_pcidas_private *devpriv = dev->private;
528
529 data[0] = devpriv->ao_value[CR_CHAN(insn->chanspec)];
530
531 return 1;
532}
533
534static int wait_for_nvram_ready(unsigned long s5933_base_addr)
535{
536 static const int timeout = 1000;
537 unsigned int i;
538
539 for (i = 0; i < timeout; i++) {
540 if ((inb(s5933_base_addr +
541 AMCC_OP_REG_MCSR_NVCMD) & MCSR_NV_BUSY)
542 == 0)
543 return 0;
544 udelay(1);
545 }
546 return -1;
547}
548
549static int nvram_read(struct comedi_device *dev, unsigned int address,
550 uint8_t *data)
551{
552 struct cb_pcidas_private *devpriv = dev->private;
553 unsigned long iobase = devpriv->s5933_config;
554
555 if (wait_for_nvram_ready(iobase) < 0)
556 return -ETIMEDOUT;
557
558 outb(MCSR_NV_ENABLE | MCSR_NV_LOAD_LOW_ADDR,
559 iobase + AMCC_OP_REG_MCSR_NVCMD);
560 outb(address & 0xff, iobase + AMCC_OP_REG_MCSR_NVDATA);
561 outb(MCSR_NV_ENABLE | MCSR_NV_LOAD_HIGH_ADDR,
562 iobase + AMCC_OP_REG_MCSR_NVCMD);
563 outb((address >> 8) & 0xff, iobase + AMCC_OP_REG_MCSR_NVDATA);
564 outb(MCSR_NV_ENABLE | MCSR_NV_READ, iobase + AMCC_OP_REG_MCSR_NVCMD);
565
566 if (wait_for_nvram_ready(iobase) < 0)
567 return -ETIMEDOUT;
568
569 *data = inb(iobase + AMCC_OP_REG_MCSR_NVDATA);
570
571 return 0;
572}
573
574static int eeprom_read_insn(struct comedi_device *dev,
575 struct comedi_subdevice *s,
576 struct comedi_insn *insn, unsigned int *data)
577{
578 uint8_t nvram_data;
579 int retval;
580
581 retval = nvram_read(dev, CR_CHAN(insn->chanspec), &nvram_data);
582 if (retval < 0)
583 return retval;
584
585 data[0] = nvram_data;
586
587 return 1;
588}
589
590static void write_calibration_bitstream(struct comedi_device *dev,
591 unsigned int register_bits,
592 unsigned int bitstream,
593 unsigned int bitstream_length)
594{
595 struct cb_pcidas_private *devpriv = dev->private;
596 static const int write_delay = 1;
597 unsigned int bit;
598
599 for (bit = 1 << (bitstream_length - 1); bit; bit >>= 1) {
600 if (bitstream & bit)
601 register_bits |= SERIAL_DATA_IN_BIT;
602 else
603 register_bits &= ~SERIAL_DATA_IN_BIT;
604 udelay(write_delay);
605 outw(register_bits, devpriv->control_status + CALIBRATION_REG);
606 }
607}
608
609static int caldac_8800_write(struct comedi_device *dev, unsigned int address,
610 uint8_t value)
611{
612 struct cb_pcidas_private *devpriv = dev->private;
613 static const int num_caldac_channels = 8;
614 static const int bitstream_length = 11;
615 unsigned int bitstream = ((address & 0x7) << 8) | value;
616 static const int caldac_8800_udelay = 1;
617
618 if (address >= num_caldac_channels) {
619 comedi_error(dev, "illegal caldac channel");
620 return -1;
621 }
622
623 if (value == devpriv->caldac_value[address])
624 return 1;
625
626 devpriv->caldac_value[address] = value;
627
628 write_calibration_bitstream(dev, cal_enable_bits(dev), bitstream,
629 bitstream_length);
630
631 udelay(caldac_8800_udelay);
632 outw(cal_enable_bits(dev) | SELECT_8800_BIT,
633 devpriv->control_status + CALIBRATION_REG);
634 udelay(caldac_8800_udelay);
635 outw(cal_enable_bits(dev), devpriv->control_status + CALIBRATION_REG);
636
637 return 1;
638}
639
640static int caldac_write_insn(struct comedi_device *dev,
641 struct comedi_subdevice *s,
642 struct comedi_insn *insn, unsigned int *data)
643{
644 const unsigned int channel = CR_CHAN(insn->chanspec);
645
646 return caldac_8800_write(dev, channel, data[0]);
647}
648
649static int caldac_read_insn(struct comedi_device *dev,
650 struct comedi_subdevice *s,
651 struct comedi_insn *insn, unsigned int *data)
652{
653 struct cb_pcidas_private *devpriv = dev->private;
654
655 data[0] = devpriv->caldac_value[CR_CHAN(insn->chanspec)];
656
657 return 1;
658}
659
660
661static void dac08_write(struct comedi_device *dev, unsigned int value)
662{
663 struct cb_pcidas_private *devpriv = dev->private;
664 unsigned long cal_reg;
665
666 if (devpriv->dac08_value != value) {
667 devpriv->dac08_value = value;
668
669 cal_reg = devpriv->control_status + CALIBRATION_REG;
670
671 value &= 0xff;
672 value |= cal_enable_bits(dev);
673
674
675 outw(value, cal_reg);
676 udelay(1);
677 outw(value | SELECT_DAC08_BIT, cal_reg);
678 udelay(1);
679 outw(value, cal_reg);
680 udelay(1);
681 }
682}
683
684static int dac08_write_insn(struct comedi_device *dev,
685 struct comedi_subdevice *s,
686 struct comedi_insn *insn, unsigned int *data)
687{
688 int i;
689
690 for (i = 0; i < insn->n; i++)
691 dac08_write(dev, data[i]);
692
693 return insn->n;
694}
695
696static int dac08_read_insn(struct comedi_device *dev,
697 struct comedi_subdevice *s, struct comedi_insn *insn,
698 unsigned int *data)
699{
700 struct cb_pcidas_private *devpriv = dev->private;
701
702 data[0] = devpriv->dac08_value;
703
704 return 1;
705}
706
707static int trimpot_7376_write(struct comedi_device *dev, uint8_t value)
708{
709 struct cb_pcidas_private *devpriv = dev->private;
710 static const int bitstream_length = 7;
711 unsigned int bitstream = value & 0x7f;
712 unsigned int register_bits;
713 static const int ad7376_udelay = 1;
714
715 register_bits = cal_enable_bits(dev) | SELECT_TRIMPOT_BIT;
716 udelay(ad7376_udelay);
717 outw(register_bits, devpriv->control_status + CALIBRATION_REG);
718
719 write_calibration_bitstream(dev, register_bits, bitstream,
720 bitstream_length);
721
722 udelay(ad7376_udelay);
723 outw(cal_enable_bits(dev), devpriv->control_status + CALIBRATION_REG);
724
725 return 0;
726}
727
728
729
730
731static int trimpot_8402_write(struct comedi_device *dev, unsigned int channel,
732 uint8_t value)
733{
734 struct cb_pcidas_private *devpriv = dev->private;
735 static const int bitstream_length = 10;
736 unsigned int bitstream = ((channel & 0x3) << 8) | (value & 0xff);
737 unsigned int register_bits;
738 static const int ad8402_udelay = 1;
739
740 register_bits = cal_enable_bits(dev) | SELECT_TRIMPOT_BIT;
741 udelay(ad8402_udelay);
742 outw(register_bits, devpriv->control_status + CALIBRATION_REG);
743
744 write_calibration_bitstream(dev, register_bits, bitstream,
745 bitstream_length);
746
747 udelay(ad8402_udelay);
748 outw(cal_enable_bits(dev), devpriv->control_status + CALIBRATION_REG);
749
750 return 0;
751}
752
753static int cb_pcidas_trimpot_write(struct comedi_device *dev,
754 unsigned int channel, unsigned int value)
755{
756 const struct cb_pcidas_board *thisboard = comedi_board(dev);
757 struct cb_pcidas_private *devpriv = dev->private;
758
759 if (devpriv->trimpot_value[channel] == value)
760 return 1;
761
762 devpriv->trimpot_value[channel] = value;
763 switch (thisboard->trimpot) {
764 case AD7376:
765 trimpot_7376_write(dev, value);
766 break;
767 case AD8402:
768 trimpot_8402_write(dev, channel, value);
769 break;
770 default:
771 comedi_error(dev, "driver bug?");
772 return -1;
773 break;
774 }
775
776 return 1;
777}
778
779static int trimpot_write_insn(struct comedi_device *dev,
780 struct comedi_subdevice *s,
781 struct comedi_insn *insn, unsigned int *data)
782{
783 unsigned int channel = CR_CHAN(insn->chanspec);
784
785 return cb_pcidas_trimpot_write(dev, channel, data[0]);
786}
787
788static int trimpot_read_insn(struct comedi_device *dev,
789 struct comedi_subdevice *s,
790 struct comedi_insn *insn, unsigned int *data)
791{
792 struct cb_pcidas_private *devpriv = dev->private;
793 unsigned int channel = CR_CHAN(insn->chanspec);
794
795 data[0] = devpriv->trimpot_value[channel];
796
797 return 1;
798}
799
800static int cb_pcidas_ai_cmdtest(struct comedi_device *dev,
801 struct comedi_subdevice *s,
802 struct comedi_cmd *cmd)
803{
804 const struct cb_pcidas_board *thisboard = comedi_board(dev);
805 struct cb_pcidas_private *devpriv = dev->private;
806 int err = 0;
807 int tmp;
808 int i, gain, start_chan;
809
810
811
812 tmp = cmd->start_src;
813 cmd->start_src &= TRIG_NOW | TRIG_EXT;
814 if (!cmd->start_src || tmp != cmd->start_src)
815 err++;
816
817 tmp = cmd->scan_begin_src;
818 cmd->scan_begin_src &= TRIG_FOLLOW | TRIG_TIMER | TRIG_EXT;
819 if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
820 err++;
821
822 tmp = cmd->convert_src;
823 cmd->convert_src &= TRIG_TIMER | TRIG_NOW | TRIG_EXT;
824 if (!cmd->convert_src || tmp != cmd->convert_src)
825 err++;
826
827 tmp = cmd->scan_end_src;
828 cmd->scan_end_src &= TRIG_COUNT;
829 if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
830 err++;
831
832 tmp = cmd->stop_src;
833 cmd->stop_src &= TRIG_COUNT | TRIG_NONE;
834 if (!cmd->stop_src || tmp != cmd->stop_src)
835 err++;
836
837 if (err)
838 return 1;
839
840
841
842 if (cmd->start_src != TRIG_NOW && cmd->start_src != TRIG_EXT)
843 err++;
844 if (cmd->scan_begin_src != TRIG_FOLLOW &&
845 cmd->scan_begin_src != TRIG_TIMER &&
846 cmd->scan_begin_src != TRIG_EXT)
847 err++;
848 if (cmd->convert_src != TRIG_TIMER &&
849 cmd->convert_src != TRIG_EXT && cmd->convert_src != TRIG_NOW)
850 err++;
851 if (cmd->stop_src != TRIG_COUNT && cmd->stop_src != TRIG_NONE)
852 err++;
853
854
855 if (cmd->scan_begin_src == TRIG_FOLLOW && cmd->convert_src == TRIG_NOW)
856 err++;
857 if (cmd->scan_begin_src != TRIG_FOLLOW && cmd->convert_src != TRIG_NOW)
858 err++;
859 if (cmd->start_src == TRIG_EXT &&
860 (cmd->convert_src == TRIG_EXT || cmd->scan_begin_src == TRIG_EXT))
861 err++;
862
863 if (err)
864 return 2;
865
866
867
868 switch (cmd->start_src) {
869 case TRIG_EXT:
870
871 if ((cmd->start_arg
872 & (CR_FLAGS_MASK & ~(CR_EDGE | CR_INVERT))) != 0) {
873 cmd->start_arg &=
874 ~(CR_FLAGS_MASK & ~(CR_EDGE | CR_INVERT));
875 err++;
876 }
877 if (!thisboard->is_1602 && (cmd->start_arg & CR_INVERT)) {
878 cmd->start_arg &= (CR_FLAGS_MASK & ~CR_INVERT);
879 err++;
880 }
881 break;
882 default:
883 if (cmd->start_arg != 0) {
884 cmd->start_arg = 0;
885 err++;
886 }
887 break;
888 }
889
890 if (cmd->scan_begin_src == TRIG_TIMER) {
891 if (cmd->scan_begin_arg <
892 thisboard->ai_speed * cmd->chanlist_len) {
893 cmd->scan_begin_arg =
894 thisboard->ai_speed * cmd->chanlist_len;
895 err++;
896 }
897 }
898 if (cmd->convert_src == TRIG_TIMER) {
899 if (cmd->convert_arg < thisboard->ai_speed) {
900 cmd->convert_arg = thisboard->ai_speed;
901 err++;
902 }
903 }
904
905 if (cmd->scan_end_arg != cmd->chanlist_len) {
906 cmd->scan_end_arg = cmd->chanlist_len;
907 err++;
908 }
909 if (cmd->stop_src == TRIG_NONE) {
910
911 if (cmd->stop_arg != 0) {
912 cmd->stop_arg = 0;
913 err++;
914 }
915 }
916
917 if (err)
918 return 3;
919
920
921
922 if (cmd->scan_begin_src == TRIG_TIMER) {
923 tmp = cmd->scan_begin_arg;
924 i8253_cascade_ns_to_timer_2div(TIMER_BASE,
925 &(devpriv->divisor1),
926 &(devpriv->divisor2),
927 &(cmd->scan_begin_arg),
928 cmd->flags & TRIG_ROUND_MASK);
929 if (tmp != cmd->scan_begin_arg)
930 err++;
931 }
932 if (cmd->convert_src == TRIG_TIMER) {
933 tmp = cmd->convert_arg;
934 i8253_cascade_ns_to_timer_2div(TIMER_BASE,
935 &(devpriv->divisor1),
936 &(devpriv->divisor2),
937 &(cmd->convert_arg),
938 cmd->flags & TRIG_ROUND_MASK);
939 if (tmp != cmd->convert_arg)
940 err++;
941 }
942
943 if (err)
944 return 4;
945
946
947 if (cmd->chanlist) {
948 gain = CR_RANGE(cmd->chanlist[0]);
949 start_chan = CR_CHAN(cmd->chanlist[0]);
950 for (i = 1; i < cmd->chanlist_len; i++) {
951 if (CR_CHAN(cmd->chanlist[i]) !=
952 (start_chan + i) % s->n_chan) {
953 comedi_error(dev,
954 "entries in chanlist must be consecutive channels, counting upwards\n");
955 err++;
956 }
957 if (CR_RANGE(cmd->chanlist[i]) != gain) {
958 comedi_error(dev,
959 "entries in chanlist must all have the same gain\n");
960 err++;
961 }
962 }
963 }
964
965 if (err)
966 return 5;
967
968 return 0;
969}
970
971static void cb_pcidas_load_counters(struct comedi_device *dev, unsigned int *ns,
972 int rounding_flags)
973{
974 struct cb_pcidas_private *devpriv = dev->private;
975
976 i8253_cascade_ns_to_timer_2div(TIMER_BASE, &(devpriv->divisor1),
977 &(devpriv->divisor2), ns,
978 rounding_flags & TRIG_ROUND_MASK);
979
980
981 i8254_load(devpriv->pacer_counter_dio + ADC8254, 0, 1,
982 devpriv->divisor1, 2);
983 i8254_load(devpriv->pacer_counter_dio + ADC8254, 0, 2,
984 devpriv->divisor2, 2);
985}
986
987static int cb_pcidas_ai_cmd(struct comedi_device *dev,
988 struct comedi_subdevice *s)
989{
990 const struct cb_pcidas_board *thisboard = comedi_board(dev);
991 struct cb_pcidas_private *devpriv = dev->private;
992 struct comedi_async *async = s->async;
993 struct comedi_cmd *cmd = &async->cmd;
994 unsigned int bits;
995 unsigned long flags;
996
997
998 outw(0, devpriv->control_status + CALIBRATION_REG);
999
1000 outw(0, devpriv->control_status + TRIG_CONTSTAT);
1001
1002 outw(0, devpriv->adc_fifo + ADCFIFOCLR);
1003
1004
1005 bits = BEGIN_SCAN(CR_CHAN(cmd->chanlist[0])) |
1006 END_SCAN(CR_CHAN(cmd->chanlist[cmd->chanlist_len - 1])) |
1007 GAIN_BITS(CR_RANGE(cmd->chanlist[0]));
1008
1009 if (CR_RANGE(cmd->chanlist[0]) & IS_UNIPOLAR)
1010 bits |= UNIP;
1011
1012 if (CR_AREF(cmd->chanlist[0]) != AREF_DIFF)
1013 bits |= SE;
1014
1015 if (cmd->convert_src == TRIG_EXT || cmd->scan_begin_src == TRIG_EXT)
1016 bits |= PACER_EXT_RISE;
1017 else
1018 bits |= PACER_INT;
1019 outw(bits, devpriv->control_status + ADCMUX_CONT);
1020
1021
1022 if (cmd->convert_src == TRIG_TIMER)
1023 cb_pcidas_load_counters(dev, &cmd->convert_arg,
1024 cmd->flags & TRIG_ROUND_MASK);
1025 else if (cmd->scan_begin_src == TRIG_TIMER)
1026 cb_pcidas_load_counters(dev, &cmd->scan_begin_arg,
1027 cmd->flags & TRIG_ROUND_MASK);
1028
1029
1030 if (cmd->stop_src == TRIG_COUNT)
1031 devpriv->count = cmd->chanlist_len * cmd->stop_arg;
1032
1033 spin_lock_irqsave(&dev->spinlock, flags);
1034 devpriv->adc_fifo_bits |= INTE;
1035 devpriv->adc_fifo_bits &= ~INT_MASK;
1036 if (cmd->flags & TRIG_WAKE_EOS) {
1037 if (cmd->convert_src == TRIG_NOW && cmd->chanlist_len > 1) {
1038
1039 devpriv->adc_fifo_bits |= INT_EOS;
1040 } else {
1041
1042 devpriv->adc_fifo_bits |= INT_FNE;
1043 }
1044 } else {
1045
1046 devpriv->adc_fifo_bits |= INT_FHF;
1047 }
1048
1049
1050 outw(devpriv->adc_fifo_bits | EOAI | INT | LADFUL,
1051 devpriv->control_status + INT_ADCFIFO);
1052 spin_unlock_irqrestore(&dev->spinlock, flags);
1053
1054
1055 bits = 0;
1056 if (cmd->start_src == TRIG_NOW)
1057 bits |= SW_TRIGGER;
1058 else if (cmd->start_src == TRIG_EXT) {
1059 bits |= EXT_TRIGGER | TGEN | XTRCL;
1060 if (thisboard->is_1602) {
1061 if (cmd->start_arg & CR_INVERT)
1062 bits |= TGPOL;
1063 if (cmd->start_arg & CR_EDGE)
1064 bits |= TGSEL;
1065 }
1066 } else {
1067 comedi_error(dev, "bug!");
1068 return -1;
1069 }
1070 if (cmd->convert_src == TRIG_NOW && cmd->chanlist_len > 1)
1071 bits |= BURSTE;
1072 outw(bits, devpriv->control_status + TRIG_CONTSTAT);
1073
1074 return 0;
1075}
1076
1077static int cb_pcidas_ao_cmdtest(struct comedi_device *dev,
1078 struct comedi_subdevice *s,
1079 struct comedi_cmd *cmd)
1080{
1081 const struct cb_pcidas_board *thisboard = comedi_board(dev);
1082 struct cb_pcidas_private *devpriv = dev->private;
1083 int err = 0;
1084 int tmp;
1085
1086
1087
1088 tmp = cmd->start_src;
1089 cmd->start_src &= TRIG_INT;
1090 if (!cmd->start_src || tmp != cmd->start_src)
1091 err++;
1092
1093 tmp = cmd->scan_begin_src;
1094 cmd->scan_begin_src &= TRIG_TIMER | TRIG_EXT;
1095 if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
1096 err++;
1097
1098 tmp = cmd->convert_src;
1099 cmd->convert_src &= TRIG_NOW;
1100 if (!cmd->convert_src || tmp != cmd->convert_src)
1101 err++;
1102
1103 tmp = cmd->scan_end_src;
1104 cmd->scan_end_src &= TRIG_COUNT;
1105 if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
1106 err++;
1107
1108 tmp = cmd->stop_src;
1109 cmd->stop_src &= TRIG_COUNT | TRIG_NONE;
1110 if (!cmd->stop_src || tmp != cmd->stop_src)
1111 err++;
1112
1113 if (err)
1114 return 1;
1115
1116
1117
1118 if (cmd->scan_begin_src != TRIG_TIMER &&
1119 cmd->scan_begin_src != TRIG_EXT)
1120 err++;
1121 if (cmd->stop_src != TRIG_COUNT && cmd->stop_src != TRIG_NONE)
1122 err++;
1123
1124 if (err)
1125 return 2;
1126
1127
1128
1129 if (cmd->start_arg != 0) {
1130 cmd->start_arg = 0;
1131 err++;
1132 }
1133
1134 if (cmd->scan_begin_src == TRIG_TIMER) {
1135 if (cmd->scan_begin_arg < thisboard->ao_scan_speed) {
1136 cmd->scan_begin_arg = thisboard->ao_scan_speed;
1137 err++;
1138 }
1139 }
1140
1141 if (cmd->scan_end_arg != cmd->chanlist_len) {
1142 cmd->scan_end_arg = cmd->chanlist_len;
1143 err++;
1144 }
1145 if (cmd->stop_src == TRIG_NONE) {
1146
1147 if (cmd->stop_arg != 0) {
1148 cmd->stop_arg = 0;
1149 err++;
1150 }
1151 }
1152
1153 if (err)
1154 return 3;
1155
1156
1157
1158 if (cmd->scan_begin_src == TRIG_TIMER) {
1159 tmp = cmd->scan_begin_arg;
1160 i8253_cascade_ns_to_timer_2div(TIMER_BASE,
1161 &(devpriv->ao_divisor1),
1162 &(devpriv->ao_divisor2),
1163 &(cmd->scan_begin_arg),
1164 cmd->flags & TRIG_ROUND_MASK);
1165 if (tmp != cmd->scan_begin_arg)
1166 err++;
1167 }
1168
1169 if (err)
1170 return 4;
1171
1172
1173 if (cmd->chanlist && cmd->chanlist_len > 1) {
1174 if (CR_CHAN(cmd->chanlist[0]) != 0 ||
1175 CR_CHAN(cmd->chanlist[1]) != 1) {
1176 comedi_error(dev,
1177 "channels must be ordered channel 0, channel 1 in chanlist\n");
1178 err++;
1179 }
1180 }
1181
1182 if (err)
1183 return 5;
1184
1185 return 0;
1186}
1187
1188
1189static int cb_pcidas_cancel(struct comedi_device *dev,
1190 struct comedi_subdevice *s)
1191{
1192 struct cb_pcidas_private *devpriv = dev->private;
1193 unsigned long flags;
1194
1195 spin_lock_irqsave(&dev->spinlock, flags);
1196
1197 devpriv->adc_fifo_bits &= ~INTE & ~EOAIE;
1198 outw(devpriv->adc_fifo_bits, devpriv->control_status + INT_ADCFIFO);
1199 spin_unlock_irqrestore(&dev->spinlock, flags);
1200
1201
1202 outw(0, devpriv->control_status + TRIG_CONTSTAT);
1203
1204 outw(0, devpriv->control_status + ADCMUX_CONT);
1205
1206 return 0;
1207}
1208
1209static int cb_pcidas_ao_inttrig(struct comedi_device *dev,
1210 struct comedi_subdevice *s,
1211 unsigned int trig_num)
1212{
1213 const struct cb_pcidas_board *thisboard = comedi_board(dev);
1214 struct cb_pcidas_private *devpriv = dev->private;
1215 unsigned int num_bytes, num_points = thisboard->fifo_size;
1216 struct comedi_async *async = s->async;
1217 struct comedi_cmd *cmd = &s->async->cmd;
1218 unsigned long flags;
1219
1220 if (trig_num != 0)
1221 return -EINVAL;
1222
1223
1224 if (cmd->stop_src == TRIG_COUNT && devpriv->ao_count < num_points)
1225 num_points = devpriv->ao_count;
1226
1227 num_bytes = cfc_read_array_from_buffer(s, devpriv->ao_buffer,
1228 num_points * sizeof(short));
1229 num_points = num_bytes / sizeof(short);
1230
1231 if (cmd->stop_src == TRIG_COUNT)
1232 devpriv->ao_count -= num_points;
1233
1234 outsw(devpriv->ao_registers + DACDATA, devpriv->ao_buffer, num_bytes);
1235
1236
1237 spin_lock_irqsave(&dev->spinlock, flags);
1238 devpriv->adc_fifo_bits |= DAEMIE | DAHFIE;
1239
1240
1241 outw(devpriv->adc_fifo_bits | DAEMI | DAHFI,
1242 devpriv->control_status + INT_ADCFIFO);
1243
1244
1245 devpriv->ao_control_bits |= DAC_START | DACEN | DAC_EMPTY;
1246 outw(devpriv->ao_control_bits, devpriv->control_status + DAC_CSR);
1247
1248 spin_unlock_irqrestore(&dev->spinlock, flags);
1249
1250 async->inttrig = NULL;
1251
1252 return 0;
1253}
1254
1255static int cb_pcidas_ao_cmd(struct comedi_device *dev,
1256 struct comedi_subdevice *s)
1257{
1258 struct cb_pcidas_private *devpriv = dev->private;
1259 struct comedi_async *async = s->async;
1260 struct comedi_cmd *cmd = &async->cmd;
1261 unsigned int i;
1262 unsigned long flags;
1263
1264
1265 spin_lock_irqsave(&dev->spinlock, flags);
1266 for (i = 0; i < cmd->chanlist_len; i++) {
1267
1268 devpriv->ao_control_bits |=
1269 DAC_CHAN_EN(CR_CHAN(cmd->chanlist[i]));
1270
1271 devpriv->ao_control_bits |= DAC_RANGE(CR_CHAN(cmd->chanlist[i]),
1272 CR_RANGE(cmd->
1273 chanlist[i]));
1274 }
1275
1276
1277 outw(devpriv->ao_control_bits, devpriv->control_status + DAC_CSR);
1278 spin_unlock_irqrestore(&dev->spinlock, flags);
1279
1280
1281 outw(0, devpriv->ao_registers + DACFIFOCLR);
1282
1283
1284 if (cmd->scan_begin_src == TRIG_TIMER) {
1285 i8253_cascade_ns_to_timer_2div(TIMER_BASE,
1286 &(devpriv->ao_divisor1),
1287 &(devpriv->ao_divisor2),
1288 &(cmd->scan_begin_arg),
1289 cmd->flags);
1290
1291
1292 i8254_load(devpriv->pacer_counter_dio + DAC8254, 0, 1,
1293 devpriv->ao_divisor1, 2);
1294 i8254_load(devpriv->pacer_counter_dio + DAC8254, 0, 2,
1295 devpriv->ao_divisor2, 2);
1296 }
1297
1298 if (cmd->stop_src == TRIG_COUNT)
1299 devpriv->ao_count = cmd->chanlist_len * cmd->stop_arg;
1300
1301 spin_lock_irqsave(&dev->spinlock, flags);
1302 switch (cmd->scan_begin_src) {
1303 case TRIG_TIMER:
1304 devpriv->ao_control_bits |= DAC_PACER_INT;
1305 break;
1306 case TRIG_EXT:
1307 devpriv->ao_control_bits |= DAC_PACER_EXT_RISE;
1308 break;
1309 default:
1310 spin_unlock_irqrestore(&dev->spinlock, flags);
1311 comedi_error(dev, "error setting dac pacer source");
1312 return -1;
1313 break;
1314 }
1315 spin_unlock_irqrestore(&dev->spinlock, flags);
1316
1317 async->inttrig = cb_pcidas_ao_inttrig;
1318
1319 return 0;
1320}
1321
1322
1323static int cb_pcidas_ao_cancel(struct comedi_device *dev,
1324 struct comedi_subdevice *s)
1325{
1326 struct cb_pcidas_private *devpriv = dev->private;
1327 unsigned long flags;
1328
1329 spin_lock_irqsave(&dev->spinlock, flags);
1330
1331 devpriv->adc_fifo_bits &= ~DAHFIE & ~DAEMIE;
1332 outw(devpriv->adc_fifo_bits, devpriv->control_status + INT_ADCFIFO);
1333
1334
1335 devpriv->ao_control_bits &= ~DACEN & ~DAC_PACER_MASK;
1336 outw(devpriv->ao_control_bits, devpriv->control_status + DAC_CSR);
1337 spin_unlock_irqrestore(&dev->spinlock, flags);
1338
1339 return 0;
1340}
1341
1342static void handle_ao_interrupt(struct comedi_device *dev, unsigned int status)
1343{
1344 const struct cb_pcidas_board *thisboard = comedi_board(dev);
1345 struct cb_pcidas_private *devpriv = dev->private;
1346 struct comedi_subdevice *s = dev->write_subdev;
1347 struct comedi_async *async = s->async;
1348 struct comedi_cmd *cmd = &async->cmd;
1349 unsigned int half_fifo = thisboard->fifo_size / 2;
1350 unsigned int num_points;
1351 unsigned long flags;
1352
1353 async->events = 0;
1354
1355 if (status & DAEMI) {
1356
1357 spin_lock_irqsave(&dev->spinlock, flags);
1358 outw(devpriv->adc_fifo_bits | DAEMI,
1359 devpriv->control_status + INT_ADCFIFO);
1360 spin_unlock_irqrestore(&dev->spinlock, flags);
1361 if (inw(devpriv->ao_registers + DAC_CSR) & DAC_EMPTY) {
1362 if (cmd->stop_src == TRIG_NONE ||
1363 (cmd->stop_src == TRIG_COUNT
1364 && devpriv->ao_count)) {
1365 comedi_error(dev, "dac fifo underflow");
1366 cb_pcidas_ao_cancel(dev, s);
1367 async->events |= COMEDI_CB_ERROR;
1368 }
1369 async->events |= COMEDI_CB_EOA;
1370 }
1371 } else if (status & DAHFI) {
1372 unsigned int num_bytes;
1373
1374
1375 num_points = half_fifo;
1376 if (cmd->stop_src == TRIG_COUNT &&
1377 devpriv->ao_count < num_points)
1378 num_points = devpriv->ao_count;
1379 num_bytes =
1380 cfc_read_array_from_buffer(s, devpriv->ao_buffer,
1381 num_points * sizeof(short));
1382 num_points = num_bytes / sizeof(short);
1383
1384 if (async->cmd.stop_src == TRIG_COUNT)
1385 devpriv->ao_count -= num_points;
1386
1387 outsw(devpriv->ao_registers + DACDATA, devpriv->ao_buffer,
1388 num_points);
1389
1390 spin_lock_irqsave(&dev->spinlock, flags);
1391 outw(devpriv->adc_fifo_bits | DAHFI,
1392 devpriv->control_status + INT_ADCFIFO);
1393 spin_unlock_irqrestore(&dev->spinlock, flags);
1394 }
1395
1396 comedi_event(dev, s);
1397}
1398
1399static irqreturn_t cb_pcidas_interrupt(int irq, void *d)
1400{
1401 struct comedi_device *dev = (struct comedi_device *)d;
1402 const struct cb_pcidas_board *thisboard = comedi_board(dev);
1403 struct cb_pcidas_private *devpriv = dev->private;
1404 struct comedi_subdevice *s = dev->read_subdev;
1405 struct comedi_async *async;
1406 int status, s5933_status;
1407 int half_fifo = thisboard->fifo_size / 2;
1408 unsigned int num_samples, i;
1409 static const int timeout = 10000;
1410 unsigned long flags;
1411
1412 if (dev->attached == 0)
1413 return IRQ_NONE;
1414
1415 async = s->async;
1416 async->events = 0;
1417
1418 s5933_status = inl(devpriv->s5933_config + AMCC_OP_REG_INTCSR);
1419
1420 if ((INTCSR_INTR_ASSERTED & s5933_status) == 0)
1421 return IRQ_NONE;
1422
1423
1424 inl_p(devpriv->s5933_config + AMCC_OP_REG_IMB4);
1425
1426 outl(devpriv->s5933_intcsr_bits | INTCSR_INBOX_INTR_STATUS,
1427 devpriv->s5933_config + AMCC_OP_REG_INTCSR);
1428
1429 status = inw(devpriv->control_status + INT_ADCFIFO);
1430
1431
1432 if (status & (DAHFI | DAEMI))
1433 handle_ao_interrupt(dev, status);
1434
1435
1436 if (status & ADHFI) {
1437
1438 num_samples = half_fifo;
1439 if (async->cmd.stop_src == TRIG_COUNT &&
1440 num_samples > devpriv->count) {
1441 num_samples = devpriv->count;
1442 }
1443 insw(devpriv->adc_fifo + ADCDATA, devpriv->ai_buffer,
1444 num_samples);
1445 cfc_write_array_to_buffer(s, devpriv->ai_buffer,
1446 num_samples * sizeof(short));
1447 devpriv->count -= num_samples;
1448 if (async->cmd.stop_src == TRIG_COUNT && devpriv->count == 0) {
1449 async->events |= COMEDI_CB_EOA;
1450 cb_pcidas_cancel(dev, s);
1451 }
1452
1453 spin_lock_irqsave(&dev->spinlock, flags);
1454 outw(devpriv->adc_fifo_bits | INT,
1455 devpriv->control_status + INT_ADCFIFO);
1456 spin_unlock_irqrestore(&dev->spinlock, flags);
1457
1458 } else if (status & (ADNEI | EOBI)) {
1459 for (i = 0; i < timeout; i++) {
1460
1461 if ((ADNE & inw(devpriv->control_status +
1462 INT_ADCFIFO)) == 0)
1463 break;
1464 cfc_write_to_buffer(s, inw(devpriv->adc_fifo));
1465 if (async->cmd.stop_src == TRIG_COUNT &&
1466 --devpriv->count == 0) {
1467
1468 cb_pcidas_cancel(dev, s);
1469 async->events |= COMEDI_CB_EOA;
1470 break;
1471 }
1472 }
1473
1474 spin_lock_irqsave(&dev->spinlock, flags);
1475 outw(devpriv->adc_fifo_bits | INT,
1476 devpriv->control_status + INT_ADCFIFO);
1477 spin_unlock_irqrestore(&dev->spinlock, flags);
1478 } else if (status & EOAI) {
1479 comedi_error(dev,
1480 "bug! encountered end of acquisition interrupt?");
1481
1482 spin_lock_irqsave(&dev->spinlock, flags);
1483 outw(devpriv->adc_fifo_bits | EOAI,
1484 devpriv->control_status + INT_ADCFIFO);
1485 spin_unlock_irqrestore(&dev->spinlock, flags);
1486 }
1487
1488 if (status & LADFUL) {
1489 comedi_error(dev, "fifo overflow");
1490
1491 spin_lock_irqsave(&dev->spinlock, flags);
1492 outw(devpriv->adc_fifo_bits | LADFUL,
1493 devpriv->control_status + INT_ADCFIFO);
1494 spin_unlock_irqrestore(&dev->spinlock, flags);
1495 cb_pcidas_cancel(dev, s);
1496 async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR;
1497 }
1498
1499 comedi_event(dev, s);
1500
1501 return IRQ_HANDLED;
1502}
1503
1504static struct pci_dev *cb_pcidas_find_pci_device(struct comedi_device *dev,
1505 struct comedi_devconfig *it)
1506{
1507 const struct cb_pcidas_board *thisboard;
1508 struct pci_dev *pcidev = NULL;
1509 int bus = it->options[0];
1510 int slot = it->options[1];
1511 int i;
1512
1513 for_each_pci_dev(pcidev) {
1514
1515 if (pcidev->vendor != PCI_VENDOR_ID_CB)
1516 continue;
1517
1518 for (i = 0; i < ARRAY_SIZE(cb_pcidas_boards); i++) {
1519 thisboard = &cb_pcidas_boards[i];
1520 if (thisboard->device_id != pcidev->device)
1521 continue;
1522
1523 if (bus || slot) {
1524
1525 if (pcidev->bus->number != bus ||
1526 PCI_SLOT(pcidev->devfn) != slot) {
1527 continue;
1528 }
1529 }
1530 dev_dbg(dev->class_dev,
1531 "Found %s on bus %i, slot %i\n",
1532 thisboard->name,
1533 pcidev->bus->number, PCI_SLOT(pcidev->devfn));
1534 dev->board_ptr = thisboard;
1535 return pcidev;
1536 }
1537 }
1538 dev_err(dev->class_dev, "No supported card found\n");
1539 return NULL;
1540}
1541
1542static int cb_pcidas_attach(struct comedi_device *dev,
1543 struct comedi_devconfig *it)
1544{
1545 const struct cb_pcidas_board *thisboard;
1546 struct cb_pcidas_private *devpriv;
1547 struct pci_dev *pcidev;
1548 struct comedi_subdevice *s;
1549 int i;
1550 int ret;
1551
1552 if (alloc_private(dev, sizeof(struct cb_pcidas_private)) < 0)
1553 return -ENOMEM;
1554 devpriv = dev->private;
1555
1556 pcidev = cb_pcidas_find_pci_device(dev, it);
1557 if (!pcidev)
1558 return -EIO;
1559 comedi_set_hw_dev(dev, &pcidev->dev);
1560 thisboard = comedi_board(dev);
1561
1562 if (comedi_pci_enable(pcidev, dev->driver->driver_name)) {
1563 dev_err(dev->class_dev,
1564 "Failed to enable PCI device and request regions\n");
1565 return -EIO;
1566 }
1567
1568 devpriv->s5933_config = pci_resource_start(pcidev, 0);
1569 devpriv->control_status = pci_resource_start(pcidev, 1);
1570 devpriv->adc_fifo = pci_resource_start(pcidev, 2);
1571 devpriv->pacer_counter_dio = pci_resource_start(pcidev, 3);
1572 if (thisboard->ao_nchan)
1573 devpriv->ao_registers = pci_resource_start(pcidev, 4);
1574
1575
1576 outl(INTCSR_INBOX_INTR_STATUS,
1577 devpriv->s5933_config + AMCC_OP_REG_INTCSR);
1578
1579 if (request_irq(pcidev->irq, cb_pcidas_interrupt,
1580 IRQF_SHARED, dev->driver->driver_name, dev)) {
1581 dev_dbg(dev->class_dev, "unable to allocate irq %d\n",
1582 pcidev->irq);
1583 return -EINVAL;
1584 }
1585 dev->irq = pcidev->irq;
1586
1587 dev->board_name = thisboard->name;
1588
1589 ret = comedi_alloc_subdevices(dev, 7);
1590 if (ret)
1591 return ret;
1592
1593 s = dev->subdevices + 0;
1594
1595 dev->read_subdev = s;
1596 s->type = COMEDI_SUBD_AI;
1597 s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_DIFF | SDF_CMD_READ;
1598
1599 s->n_chan = thisboard->ai_nchan;
1600 s->len_chanlist = thisboard->ai_nchan;
1601 s->maxdata = (1 << thisboard->ai_bits) - 1;
1602 s->range_table = thisboard->ranges;
1603 s->insn_read = cb_pcidas_ai_rinsn;
1604 s->insn_config = ai_config_insn;
1605 s->do_cmd = cb_pcidas_ai_cmd;
1606 s->do_cmdtest = cb_pcidas_ai_cmdtest;
1607 s->cancel = cb_pcidas_cancel;
1608
1609
1610 s = dev->subdevices + 1;
1611 if (thisboard->ao_nchan) {
1612 s->type = COMEDI_SUBD_AO;
1613 s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_GROUND;
1614 s->n_chan = thisboard->ao_nchan;
1615
1616
1617
1618
1619 s->maxdata = (1 << thisboard->ai_bits) - 1;
1620 s->range_table = &cb_pcidas_ao_ranges;
1621 s->insn_read = cb_pcidas_ao_readback_insn;
1622 if (thisboard->has_ao_fifo) {
1623 dev->write_subdev = s;
1624 s->subdev_flags |= SDF_CMD_WRITE;
1625 s->insn_write = cb_pcidas_ao_fifo_winsn;
1626 s->do_cmdtest = cb_pcidas_ao_cmdtest;
1627 s->do_cmd = cb_pcidas_ao_cmd;
1628 s->cancel = cb_pcidas_ao_cancel;
1629 } else {
1630 s->insn_write = cb_pcidas_ao_nofifo_winsn;
1631 }
1632 } else {
1633 s->type = COMEDI_SUBD_UNUSED;
1634 }
1635
1636
1637 s = dev->subdevices + 2;
1638 ret = subdev_8255_init(dev, s, NULL,
1639 devpriv->pacer_counter_dio + DIO_8255);
1640 if (ret)
1641 return ret;
1642
1643
1644 s = dev->subdevices + 3;
1645 s->type = COMEDI_SUBD_MEMORY;
1646 s->subdev_flags = SDF_READABLE | SDF_INTERNAL;
1647 s->n_chan = 256;
1648 s->maxdata = 0xff;
1649 s->insn_read = eeprom_read_insn;
1650
1651
1652 s = dev->subdevices + 4;
1653 s->type = COMEDI_SUBD_CALIB;
1654 s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_INTERNAL;
1655 s->n_chan = NUM_CHANNELS_8800;
1656 s->maxdata = 0xff;
1657 s->insn_read = caldac_read_insn;
1658 s->insn_write = caldac_write_insn;
1659 for (i = 0; i < s->n_chan; i++)
1660 caldac_8800_write(dev, i, s->maxdata / 2);
1661
1662
1663 s = dev->subdevices + 5;
1664 s->type = COMEDI_SUBD_CALIB;
1665 s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_INTERNAL;
1666 if (thisboard->trimpot == AD7376) {
1667 s->n_chan = NUM_CHANNELS_7376;
1668 s->maxdata = 0x7f;
1669 } else {
1670 s->n_chan = NUM_CHANNELS_8402;
1671 s->maxdata = 0xff;
1672 }
1673 s->insn_read = trimpot_read_insn;
1674 s->insn_write = trimpot_write_insn;
1675 for (i = 0; i < s->n_chan; i++)
1676 cb_pcidas_trimpot_write(dev, i, s->maxdata / 2);
1677
1678
1679 s = dev->subdevices + 6;
1680 if (thisboard->has_dac08) {
1681 s->type = COMEDI_SUBD_CALIB;
1682 s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_INTERNAL;
1683 s->n_chan = NUM_CHANNELS_DAC08;
1684 s->insn_read = dac08_read_insn;
1685 s->insn_write = dac08_write_insn;
1686 s->maxdata = 0xff;
1687 dac08_write(dev, s->maxdata / 2);
1688 } else
1689 s->type = COMEDI_SUBD_UNUSED;
1690
1691
1692 inl(devpriv->s5933_config + AMCC_OP_REG_IMB4);
1693
1694 devpriv->s5933_intcsr_bits =
1695 INTCSR_INBOX_BYTE(3) | INTCSR_INBOX_SELECT(3) |
1696 INTCSR_INBOX_FULL_INT;
1697
1698 outl(devpriv->s5933_intcsr_bits | INTCSR_INBOX_INTR_STATUS,
1699 devpriv->s5933_config + AMCC_OP_REG_INTCSR);
1700
1701 return 1;
1702}
1703
1704static void cb_pcidas_detach(struct comedi_device *dev)
1705{
1706 struct cb_pcidas_private *devpriv = dev->private;
1707 struct pci_dev *pcidev = comedi_to_pci_dev(dev);
1708
1709 if (devpriv) {
1710 if (devpriv->s5933_config) {
1711 outl(INTCSR_INBOX_INTR_STATUS,
1712 devpriv->s5933_config + AMCC_OP_REG_INTCSR);
1713 }
1714 }
1715 if (dev->irq)
1716 free_irq(dev->irq, dev);
1717 if (dev->subdevices)
1718 subdev_8255_cleanup(dev, dev->subdevices + 2);
1719 if (pcidev) {
1720 if (devpriv->s5933_config)
1721 comedi_pci_disable(pcidev);
1722 pci_dev_put(pcidev);
1723 }
1724}
1725
1726static struct comedi_driver cb_pcidas_driver = {
1727 .driver_name = "cb_pcidas",
1728 .module = THIS_MODULE,
1729 .attach = cb_pcidas_attach,
1730 .detach = cb_pcidas_detach,
1731};
1732
1733static int __devinit cb_pcidas_pci_probe(struct pci_dev *dev,
1734 const struct pci_device_id *ent)
1735{
1736 return comedi_pci_auto_config(dev, &cb_pcidas_driver);
1737}
1738
1739static void __devexit cb_pcidas_pci_remove(struct pci_dev *dev)
1740{
1741 comedi_pci_auto_unconfig(dev);
1742}
1743
1744static DEFINE_PCI_DEVICE_TABLE(cb_pcidas_pci_table) = {
1745 { PCI_DEVICE(PCI_VENDOR_ID_CB, 0x0001) },
1746 { PCI_DEVICE(PCI_VENDOR_ID_CB, 0x000f) },
1747 { PCI_DEVICE(PCI_VENDOR_ID_CB, 0x0010) },
1748 { PCI_DEVICE(PCI_VENDOR_ID_CB, 0x0019) },
1749 { PCI_DEVICE(PCI_VENDOR_ID_CB, 0x001c) },
1750 { PCI_DEVICE(PCI_VENDOR_ID_CB, 0x004c) },
1751 { PCI_DEVICE(PCI_VENDOR_ID_CB, 0x001a) },
1752 { PCI_DEVICE(PCI_VENDOR_ID_CB, 0x001b) },
1753 { 0 }
1754};
1755MODULE_DEVICE_TABLE(pci, cb_pcidas_pci_table);
1756
1757static struct pci_driver cb_pcidas_pci_driver = {
1758 .name = "cb_pcidas",
1759 .id_table = cb_pcidas_pci_table,
1760 .probe = cb_pcidas_pci_probe,
1761 .remove = __devexit_p(cb_pcidas_pci_remove)
1762};
1763module_comedi_pci_driver(cb_pcidas_driver, cb_pcidas_pci_driver);
1764
1765MODULE_AUTHOR("Comedi http://www.comedi.org");
1766MODULE_DESCRIPTION("Comedi low-level driver");
1767MODULE_LICENSE("GPL");
1768