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