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