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 printk("comedi%d: cb_pcidas: ", dev->minor);
569
570
571
572
573 if (alloc_private(dev, sizeof(struct cb_pcidas_private)) < 0)
574 return -ENOMEM;
575
576
577
578
579 printk("\n");
580
581 for_each_pci_dev(pcidev) {
582
583 if (pcidev->vendor != PCI_VENDOR_ID_CB)
584 continue;
585
586 for (index = 0; index < ARRAY_SIZE(cb_pcidas_boards); index++) {
587 if (cb_pcidas_boards[index].device_id != pcidev->device)
588 continue;
589
590 if (it->options[0] || it->options[1]) {
591
592 if (pcidev->bus->number != it->options[0] ||
593 PCI_SLOT(pcidev->devfn) != it->options[1]) {
594 continue;
595 }
596 }
597 devpriv->pci_dev = pcidev;
598 dev->board_ptr = cb_pcidas_boards + index;
599 goto found;
600 }
601 }
602
603 printk("No supported ComputerBoards/MeasurementComputing card found on "
604 "requested position\n");
605 return -EIO;
606
607found:
608
609 printk("Found %s on bus %i, slot %i\n", cb_pcidas_boards[index].name,
610 pcidev->bus->number, PCI_SLOT(pcidev->devfn));
611
612
613
614
615 if (comedi_pci_enable(pcidev, "cb_pcidas")) {
616 printk(" Failed to enable PCI device and request regions\n");
617 return -EIO;
618 }
619
620
621
622
623 devpriv->s5933_config =
624 pci_resource_start(devpriv->pci_dev, S5933_BADRINDEX);
625 devpriv->control_status =
626 pci_resource_start(devpriv->pci_dev, CONT_STAT_BADRINDEX);
627 devpriv->adc_fifo =
628 pci_resource_start(devpriv->pci_dev, ADC_FIFO_BADRINDEX);
629 devpriv->pacer_counter_dio =
630 pci_resource_start(devpriv->pci_dev, PACER_BADRINDEX);
631 if (thisboard->ao_nchan) {
632 devpriv->ao_registers =
633 pci_resource_start(devpriv->pci_dev, AO_BADRINDEX);
634 }
635
636 outl(INTCSR_INBOX_INTR_STATUS,
637 devpriv->s5933_config + AMCC_OP_REG_INTCSR);
638
639
640 if (request_irq(devpriv->pci_dev->irq, cb_pcidas_interrupt,
641 IRQF_SHARED, "cb_pcidas", dev)) {
642 printk(" unable to allocate irq %d\n", devpriv->pci_dev->irq);
643 return -EINVAL;
644 }
645 dev->irq = devpriv->pci_dev->irq;
646
647
648 dev->board_name = thisboard->name;
649
650
651
652
653 if (alloc_subdevices(dev, 7) < 0)
654 return -ENOMEM;
655
656 s = dev->subdevices + 0;
657
658 dev->read_subdev = s;
659 s->type = COMEDI_SUBD_AI;
660 s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_DIFF | SDF_CMD_READ;
661
662 s->n_chan = thisboard->ai_se_chans;
663 s->len_chanlist = thisboard->ai_se_chans;
664 s->maxdata = (1 << thisboard->ai_bits) - 1;
665 s->range_table = thisboard->ranges;
666 s->insn_read = cb_pcidas_ai_rinsn;
667 s->insn_config = ai_config_insn;
668 s->do_cmd = cb_pcidas_ai_cmd;
669 s->do_cmdtest = cb_pcidas_ai_cmdtest;
670 s->cancel = cb_pcidas_cancel;
671
672
673 s = dev->subdevices + 1;
674 if (thisboard->ao_nchan) {
675 s->type = COMEDI_SUBD_AO;
676 s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_GROUND;
677 s->n_chan = thisboard->ao_nchan;
678
679 s->maxdata = (1 << thisboard->ai_bits) - 1;
680 s->range_table = &cb_pcidas_ao_ranges;
681 s->insn_read = cb_pcidas_ao_readback_insn;
682 if (thisboard->has_ao_fifo) {
683 dev->write_subdev = s;
684 s->subdev_flags |= SDF_CMD_WRITE;
685 s->insn_write = cb_pcidas_ao_fifo_winsn;
686 s->do_cmdtest = cb_pcidas_ao_cmdtest;
687 s->do_cmd = cb_pcidas_ao_cmd;
688 s->cancel = cb_pcidas_ao_cancel;
689 } else {
690 s->insn_write = cb_pcidas_ao_nofifo_winsn;
691 }
692 } else {
693 s->type = COMEDI_SUBD_UNUSED;
694 }
695
696
697 s = dev->subdevices + 2;
698 subdev_8255_init(dev, s, NULL, devpriv->pacer_counter_dio + DIO_8255);
699
700
701 s = dev->subdevices + 3;
702 s->type = COMEDI_SUBD_MEMORY;
703 s->subdev_flags = SDF_READABLE | SDF_INTERNAL;
704 s->n_chan = 256;
705 s->maxdata = 0xff;
706 s->insn_read = eeprom_read_insn;
707
708
709 s = dev->subdevices + 4;
710 s->type = COMEDI_SUBD_CALIB;
711 s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_INTERNAL;
712 s->n_chan = NUM_CHANNELS_8800;
713 s->maxdata = 0xff;
714 s->insn_read = caldac_read_insn;
715 s->insn_write = caldac_write_insn;
716 for (i = 0; i < s->n_chan; i++)
717 caldac_8800_write(dev, i, s->maxdata / 2);
718
719
720 s = dev->subdevices + 5;
721 s->type = COMEDI_SUBD_CALIB;
722 s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_INTERNAL;
723 if (thisboard->trimpot == AD7376) {
724 s->n_chan = NUM_CHANNELS_7376;
725 s->maxdata = 0x7f;
726 } else {
727 s->n_chan = NUM_CHANNELS_8402;
728 s->maxdata = 0xff;
729 }
730 s->insn_read = trimpot_read_insn;
731 s->insn_write = trimpot_write_insn;
732 for (i = 0; i < s->n_chan; i++)
733 cb_pcidas_trimpot_write(dev, i, s->maxdata / 2);
734
735
736 s = dev->subdevices + 6;
737 if (thisboard->has_dac08) {
738 s->type = COMEDI_SUBD_CALIB;
739 s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_INTERNAL;
740 s->n_chan = NUM_CHANNELS_DAC08;
741 s->insn_read = dac08_read_insn;
742 s->insn_write = dac08_write_insn;
743 s->maxdata = 0xff;
744 dac08_write(dev, s->maxdata / 2);
745 } else
746 s->type = COMEDI_SUBD_UNUSED;
747
748
749 inl(devpriv->s5933_config + AMCC_OP_REG_IMB4);
750
751 devpriv->s5933_intcsr_bits =
752 INTCSR_INBOX_BYTE(3) | INTCSR_INBOX_SELECT(3) |
753 INTCSR_INBOX_FULL_INT;
754
755 outl(devpriv->s5933_intcsr_bits | INTCSR_INBOX_INTR_STATUS,
756 devpriv->s5933_config + AMCC_OP_REG_INTCSR);
757
758 return 1;
759}
760
761
762
763
764
765
766
767
768
769static int cb_pcidas_detach(struct comedi_device *dev)
770{
771 printk("comedi%d: cb_pcidas: remove\n", dev->minor);
772
773 if (devpriv) {
774 if (devpriv->s5933_config) {
775
776 outl(INTCSR_INBOX_INTR_STATUS,
777 devpriv->s5933_config + AMCC_OP_REG_INTCSR);
778#ifdef CB_PCIDAS_DEBUG
779 printk("detaching, incsr is 0x%x\n",
780 inl(devpriv->s5933_config + AMCC_OP_REG_INTCSR));
781#endif
782 }
783 }
784 if (dev->irq)
785 free_irq(dev->irq, dev);
786 if (dev->subdevices)
787 subdev_8255_cleanup(dev, dev->subdevices + 2);
788 if (devpriv && devpriv->pci_dev) {
789 if (devpriv->s5933_config)
790 comedi_pci_disable(devpriv->pci_dev);
791 pci_dev_put(devpriv->pci_dev);
792 }
793
794 return 0;
795}
796
797
798
799
800
801static int cb_pcidas_ai_rinsn(struct comedi_device *dev,
802 struct comedi_subdevice *s,
803 struct comedi_insn *insn, unsigned int *data)
804{
805 int n, i;
806 unsigned int bits;
807 static const int timeout = 10000;
808 int channel;
809
810 if (insn->chanspec & CR_ALT_SOURCE) {
811 outw(cal_enable_bits(dev),
812 devpriv->control_status + CALIBRATION_REG);
813 channel = 0;
814 } else {
815 outw(0, devpriv->control_status + CALIBRATION_REG);
816 channel = CR_CHAN(insn->chanspec);
817 }
818
819 bits = BEGIN_SCAN(channel) |
820 END_SCAN(channel) | GAIN_BITS(CR_RANGE(insn->chanspec));
821
822 if (CR_RANGE(insn->chanspec) & IS_UNIPOLAR)
823 bits |= UNIP;
824
825 if (CR_AREF(insn->chanspec) != AREF_DIFF)
826 bits |= SE;
827 outw(bits, devpriv->control_status + ADCMUX_CONT);
828
829
830 outw(0, devpriv->adc_fifo + ADCFIFOCLR);
831
832
833 for (n = 0; n < insn->n; n++) {
834
835 outw(0, devpriv->adc_fifo + ADCDATA);
836
837
838
839 for (i = 0; i < timeout; i++) {
840 if (inw(devpriv->control_status + ADCMUX_CONT) & EOC)
841 break;
842 }
843 if (i == timeout)
844 return -ETIMEDOUT;
845
846
847 data[n] = inw(devpriv->adc_fifo + ADCDATA);
848 }
849
850
851 return n;
852}
853
854static int ai_config_calibration_source(struct comedi_device *dev,
855 unsigned int *data)
856{
857 static const int num_calibration_sources = 8;
858 unsigned int source = data[1];
859
860 if (source >= num_calibration_sources) {
861 printk("invalid calibration source: %i\n", source);
862 return -EINVAL;
863 }
864
865 devpriv->calibration_source = source;
866
867 return 2;
868}
869
870static int ai_config_insn(struct comedi_device *dev, struct comedi_subdevice *s,
871 struct comedi_insn *insn, unsigned int *data)
872{
873 int id = data[0];
874
875 switch (id) {
876 case INSN_CONFIG_ALT_SOURCE:
877 return ai_config_calibration_source(dev, data);
878 break;
879 default:
880 return -EINVAL;
881 break;
882 }
883 return -EINVAL;
884}
885
886
887static int cb_pcidas_ao_nofifo_winsn(struct comedi_device *dev,
888 struct comedi_subdevice *s,
889 struct comedi_insn *insn,
890 unsigned int *data)
891{
892 int channel;
893 unsigned long flags;
894
895
896 channel = CR_CHAN(insn->chanspec);
897 spin_lock_irqsave(&dev->spinlock, flags);
898 devpriv->ao_control_bits &=
899 ~DAC_MODE_UPDATE_BOTH & ~DAC_RANGE_MASK(channel);
900 devpriv->ao_control_bits |=
901 DACEN | DAC_RANGE(channel, CR_RANGE(insn->chanspec));
902 outw(devpriv->ao_control_bits, devpriv->control_status + DAC_CSR);
903 spin_unlock_irqrestore(&dev->spinlock, flags);
904
905
906 devpriv->ao_value[channel] = data[0];
907
908 outw(data[0], devpriv->ao_registers + DAC_DATA_REG(channel));
909
910 return 1;
911}
912
913
914static int cb_pcidas_ao_fifo_winsn(struct comedi_device *dev,
915 struct comedi_subdevice *s,
916 struct comedi_insn *insn, unsigned int *data)
917{
918 int channel;
919 unsigned long flags;
920
921
922 outw(0, devpriv->ao_registers + DACFIFOCLR);
923
924
925 channel = CR_CHAN(insn->chanspec);
926 spin_lock_irqsave(&dev->spinlock, flags);
927 devpriv->ao_control_bits &=
928 ~DAC_CHAN_EN(0) & ~DAC_CHAN_EN(1) & ~DAC_RANGE_MASK(channel) &
929 ~DAC_PACER_MASK;
930 devpriv->ao_control_bits |=
931 DACEN | DAC_RANGE(channel,
932 CR_RANGE(insn->
933 chanspec)) | DAC_CHAN_EN(channel) |
934 DAC_START;
935 outw(devpriv->ao_control_bits, devpriv->control_status + DAC_CSR);
936 spin_unlock_irqrestore(&dev->spinlock, flags);
937
938
939 devpriv->ao_value[channel] = data[0];
940
941 outw(data[0], devpriv->ao_registers + DACDATA);
942
943 return 1;
944}
945
946
947
948static int cb_pcidas_ao_readback_insn(struct comedi_device *dev,
949 struct comedi_subdevice *s,
950 struct comedi_insn *insn,
951 unsigned int *data)
952{
953 data[0] = devpriv->ao_value[CR_CHAN(insn->chanspec)];
954
955 return 1;
956}
957
958static int eeprom_read_insn(struct comedi_device *dev,
959 struct comedi_subdevice *s,
960 struct comedi_insn *insn, unsigned int *data)
961{
962 uint8_t nvram_data;
963 int retval;
964
965 retval = nvram_read(dev, CR_CHAN(insn->chanspec), &nvram_data);
966 if (retval < 0)
967 return retval;
968
969 data[0] = nvram_data;
970
971 return 1;
972}
973
974static int caldac_write_insn(struct comedi_device *dev,
975 struct comedi_subdevice *s,
976 struct comedi_insn *insn, unsigned int *data)
977{
978 const unsigned int channel = CR_CHAN(insn->chanspec);
979
980 return caldac_8800_write(dev, channel, data[0]);
981}
982
983static int caldac_read_insn(struct comedi_device *dev,
984 struct comedi_subdevice *s,
985 struct comedi_insn *insn, unsigned int *data)
986{
987 data[0] = devpriv->caldac_value[CR_CHAN(insn->chanspec)];
988
989 return 1;
990}
991
992
993static int dac08_write(struct comedi_device *dev, unsigned int value)
994{
995 if (devpriv->dac08_value == value)
996 return 1;
997
998 devpriv->dac08_value = value;
999
1000 outw(cal_enable_bits(dev) | (value & 0xff),
1001 devpriv->control_status + CALIBRATION_REG);
1002 udelay(1);
1003 outw(cal_enable_bits(dev) | SELECT_DAC08_BIT | (value & 0xff),
1004 devpriv->control_status + CALIBRATION_REG);
1005 udelay(1);
1006 outw(cal_enable_bits(dev) | (value & 0xff),
1007 devpriv->control_status + CALIBRATION_REG);
1008 udelay(1);
1009
1010 return 1;
1011}
1012
1013static int dac08_write_insn(struct comedi_device *dev,
1014 struct comedi_subdevice *s,
1015 struct comedi_insn *insn, unsigned int *data)
1016{
1017 return dac08_write(dev, data[0]);
1018}
1019
1020static int dac08_read_insn(struct comedi_device *dev,
1021 struct comedi_subdevice *s, struct comedi_insn *insn,
1022 unsigned int *data)
1023{
1024 data[0] = devpriv->dac08_value;
1025
1026 return 1;
1027}
1028
1029static int cb_pcidas_trimpot_write(struct comedi_device *dev,
1030 unsigned int channel, unsigned int value)
1031{
1032 if (devpriv->trimpot_value[channel] == value)
1033 return 1;
1034
1035 devpriv->trimpot_value[channel] = value;
1036 switch (thisboard->trimpot) {
1037 case AD7376:
1038 trimpot_7376_write(dev, value);
1039 break;
1040 case AD8402:
1041 trimpot_8402_write(dev, channel, value);
1042 break;
1043 default:
1044 comedi_error(dev, "driver bug?");
1045 return -1;
1046 break;
1047 }
1048
1049 return 1;
1050}
1051
1052static int trimpot_write_insn(struct comedi_device *dev,
1053 struct comedi_subdevice *s,
1054 struct comedi_insn *insn, unsigned int *data)
1055{
1056 unsigned int channel = CR_CHAN(insn->chanspec);
1057
1058 return cb_pcidas_trimpot_write(dev, channel, data[0]);
1059}
1060
1061static int trimpot_read_insn(struct comedi_device *dev,
1062 struct comedi_subdevice *s,
1063 struct comedi_insn *insn, unsigned int *data)
1064{
1065 unsigned int channel = CR_CHAN(insn->chanspec);
1066
1067 data[0] = devpriv->trimpot_value[channel];
1068
1069 return 1;
1070}
1071
1072static int cb_pcidas_ai_cmdtest(struct comedi_device *dev,
1073 struct comedi_subdevice *s,
1074 struct comedi_cmd *cmd)
1075{
1076 int err = 0;
1077 int tmp;
1078 int i, gain, start_chan;
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089 tmp = cmd->start_src;
1090 cmd->start_src &= TRIG_NOW | TRIG_EXT;
1091 if (!cmd->start_src || tmp != cmd->start_src)
1092 err++;
1093
1094 tmp = cmd->scan_begin_src;
1095 cmd->scan_begin_src &= TRIG_FOLLOW | TRIG_TIMER | TRIG_EXT;
1096 if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
1097 err++;
1098
1099 tmp = cmd->convert_src;
1100 cmd->convert_src &= TRIG_TIMER | TRIG_NOW | TRIG_EXT;
1101 if (!cmd->convert_src || tmp != cmd->convert_src)
1102 err++;
1103
1104 tmp = cmd->scan_end_src;
1105 cmd->scan_end_src &= TRIG_COUNT;
1106 if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
1107 err++;
1108
1109 tmp = cmd->stop_src;
1110 cmd->stop_src &= TRIG_COUNT | TRIG_NONE;
1111 if (!cmd->stop_src || tmp != cmd->stop_src)
1112 err++;
1113
1114 if (err)
1115 return 1;
1116
1117
1118
1119 if (cmd->start_src != TRIG_NOW && cmd->start_src != TRIG_EXT)
1120 err++;
1121 if (cmd->scan_begin_src != TRIG_FOLLOW &&
1122 cmd->scan_begin_src != TRIG_TIMER &&
1123 cmd->scan_begin_src != TRIG_EXT)
1124 err++;
1125 if (cmd->convert_src != TRIG_TIMER &&
1126 cmd->convert_src != TRIG_EXT && cmd->convert_src != TRIG_NOW)
1127 err++;
1128 if (cmd->stop_src != TRIG_COUNT && cmd->stop_src != TRIG_NONE)
1129 err++;
1130
1131
1132 if (cmd->scan_begin_src == TRIG_FOLLOW && cmd->convert_src == TRIG_NOW)
1133 err++;
1134 if (cmd->scan_begin_src != TRIG_FOLLOW && cmd->convert_src != TRIG_NOW)
1135 err++;
1136 if (cmd->start_src == TRIG_EXT &&
1137 (cmd->convert_src == TRIG_EXT || cmd->scan_begin_src == TRIG_EXT))
1138 err++;
1139
1140 if (err)
1141 return 2;
1142
1143
1144
1145 switch (cmd->start_src) {
1146 case TRIG_EXT:
1147
1148 if ((cmd->start_arg
1149 & (CR_FLAGS_MASK & ~(CR_EDGE | CR_INVERT))) != 0) {
1150 cmd->start_arg &=
1151 ~(CR_FLAGS_MASK & ~(CR_EDGE | CR_INVERT));
1152 err++;
1153 }
1154 if (!thisboard->has_ai_trig_invert &&
1155 (cmd->start_arg & CR_INVERT)) {
1156 cmd->start_arg &= (CR_FLAGS_MASK & ~CR_INVERT);
1157 err++;
1158 }
1159 break;
1160 default:
1161 if (cmd->start_arg != 0) {
1162 cmd->start_arg = 0;
1163 err++;
1164 }
1165 break;
1166 }
1167
1168 if (cmd->scan_begin_src == TRIG_TIMER) {
1169 if (cmd->scan_begin_arg <
1170 thisboard->ai_speed * cmd->chanlist_len) {
1171 cmd->scan_begin_arg =
1172 thisboard->ai_speed * cmd->chanlist_len;
1173 err++;
1174 }
1175 }
1176 if (cmd->convert_src == TRIG_TIMER) {
1177 if (cmd->convert_arg < thisboard->ai_speed) {
1178 cmd->convert_arg = thisboard->ai_speed;
1179 err++;
1180 }
1181 }
1182
1183 if (cmd->scan_end_arg != cmd->chanlist_len) {
1184 cmd->scan_end_arg = cmd->chanlist_len;
1185 err++;
1186 }
1187 if (cmd->stop_src == TRIG_NONE) {
1188
1189 if (cmd->stop_arg != 0) {
1190 cmd->stop_arg = 0;
1191 err++;
1192 }
1193 }
1194
1195 if (err)
1196 return 3;
1197
1198
1199
1200 if (cmd->scan_begin_src == TRIG_TIMER) {
1201 tmp = cmd->scan_begin_arg;
1202 i8253_cascade_ns_to_timer_2div(TIMER_BASE,
1203 &(devpriv->divisor1),
1204 &(devpriv->divisor2),
1205 &(cmd->scan_begin_arg),
1206 cmd->flags & TRIG_ROUND_MASK);
1207 if (tmp != cmd->scan_begin_arg)
1208 err++;
1209 }
1210 if (cmd->convert_src == TRIG_TIMER) {
1211 tmp = cmd->convert_arg;
1212 i8253_cascade_ns_to_timer_2div(TIMER_BASE,
1213 &(devpriv->divisor1),
1214 &(devpriv->divisor2),
1215 &(cmd->convert_arg),
1216 cmd->flags & TRIG_ROUND_MASK);
1217 if (tmp != cmd->convert_arg)
1218 err++;
1219 }
1220
1221 if (err)
1222 return 4;
1223
1224
1225 if (cmd->chanlist) {
1226 gain = CR_RANGE(cmd->chanlist[0]);
1227 start_chan = CR_CHAN(cmd->chanlist[0]);
1228 for (i = 1; i < cmd->chanlist_len; i++) {
1229 if (CR_CHAN(cmd->chanlist[i]) !=
1230 (start_chan + i) % s->n_chan) {
1231 comedi_error(dev,
1232 "entries in chanlist must be consecutive channels, counting upwards\n");
1233 err++;
1234 }
1235 if (CR_RANGE(cmd->chanlist[i]) != gain) {
1236 comedi_error(dev,
1237 "entries in chanlist must all have the same gain\n");
1238 err++;
1239 }
1240 }
1241 }
1242
1243 if (err)
1244 return 5;
1245
1246 return 0;
1247}
1248
1249static int cb_pcidas_ai_cmd(struct comedi_device *dev,
1250 struct comedi_subdevice *s)
1251{
1252 struct comedi_async *async = s->async;
1253 struct comedi_cmd *cmd = &async->cmd;
1254 unsigned int bits;
1255 unsigned long flags;
1256
1257
1258 outw(0, devpriv->control_status + CALIBRATION_REG);
1259
1260 outw(0, devpriv->control_status + TRIG_CONTSTAT);
1261
1262 outw(0, devpriv->adc_fifo + ADCFIFOCLR);
1263
1264
1265 bits = BEGIN_SCAN(CR_CHAN(cmd->chanlist[0])) |
1266 END_SCAN(CR_CHAN(cmd->chanlist[cmd->chanlist_len - 1])) |
1267 GAIN_BITS(CR_RANGE(cmd->chanlist[0]));
1268
1269 if (CR_RANGE(cmd->chanlist[0]) & IS_UNIPOLAR)
1270 bits |= UNIP;
1271
1272 if (CR_AREF(cmd->chanlist[0]) != AREF_DIFF)
1273 bits |= SE;
1274
1275 if (cmd->convert_src == TRIG_EXT || cmd->scan_begin_src == TRIG_EXT)
1276 bits |= PACER_EXT_RISE;
1277 else
1278 bits |= PACER_INT;
1279 outw(bits, devpriv->control_status + ADCMUX_CONT);
1280
1281#ifdef CB_PCIDAS_DEBUG
1282 printk("comedi: sent 0x%x to adcmux control\n", bits);
1283#endif
1284
1285
1286 if (cmd->convert_src == TRIG_TIMER)
1287 cb_pcidas_load_counters(dev, &cmd->convert_arg,
1288 cmd->flags & TRIG_ROUND_MASK);
1289 else if (cmd->scan_begin_src == TRIG_TIMER)
1290 cb_pcidas_load_counters(dev, &cmd->scan_begin_arg,
1291 cmd->flags & TRIG_ROUND_MASK);
1292
1293
1294 if (cmd->stop_src == TRIG_COUNT)
1295 devpriv->count = cmd->chanlist_len * cmd->stop_arg;
1296
1297 spin_lock_irqsave(&dev->spinlock, flags);
1298 devpriv->adc_fifo_bits |= INTE;
1299 devpriv->adc_fifo_bits &= ~INT_MASK;
1300 if (cmd->flags & TRIG_WAKE_EOS) {
1301 if (cmd->convert_src == TRIG_NOW && cmd->chanlist_len > 1)
1302 devpriv->adc_fifo_bits |= INT_EOS;
1303 else
1304 devpriv->adc_fifo_bits |= INT_FNE;
1305 } else {
1306 devpriv->adc_fifo_bits |= INT_FHF;
1307 }
1308#ifdef CB_PCIDAS_DEBUG
1309 printk("comedi: adc_fifo_bits are 0x%x\n", devpriv->adc_fifo_bits);
1310#endif
1311
1312 outw(devpriv->adc_fifo_bits | EOAI | INT | LADFUL,
1313 devpriv->control_status + INT_ADCFIFO);
1314 spin_unlock_irqrestore(&dev->spinlock, flags);
1315
1316
1317 bits = 0;
1318 if (cmd->start_src == TRIG_NOW)
1319 bits |= SW_TRIGGER;
1320 else if (cmd->start_src == TRIG_EXT) {
1321 bits |= EXT_TRIGGER | TGEN | XTRCL;
1322 if (thisboard->has_ai_trig_invert
1323 && (cmd->start_arg & CR_INVERT))
1324 bits |= TGPOL;
1325 if (thisboard->has_ai_trig_gated && (cmd->start_arg & CR_EDGE))
1326 bits |= TGSEL;
1327 } else {
1328 comedi_error(dev, "bug!");
1329 return -1;
1330 }
1331 if (cmd->convert_src == TRIG_NOW && cmd->chanlist_len > 1)
1332 bits |= BURSTE;
1333 outw(bits, devpriv->control_status + TRIG_CONTSTAT);
1334#ifdef CB_PCIDAS_DEBUG
1335 printk("comedi: sent 0x%x to trig control\n", bits);
1336#endif
1337
1338 return 0;
1339}
1340
1341static int cb_pcidas_ao_cmdtest(struct comedi_device *dev,
1342 struct comedi_subdevice *s,
1343 struct comedi_cmd *cmd)
1344{
1345 int err = 0;
1346 int tmp;
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357 tmp = cmd->start_src;
1358 cmd->start_src &= TRIG_INT;
1359 if (!cmd->start_src || tmp != cmd->start_src)
1360 err++;
1361
1362 tmp = cmd->scan_begin_src;
1363 cmd->scan_begin_src &= TRIG_TIMER | TRIG_EXT;
1364 if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
1365 err++;
1366
1367 tmp = cmd->convert_src;
1368 cmd->convert_src &= TRIG_NOW;
1369 if (!cmd->convert_src || tmp != cmd->convert_src)
1370 err++;
1371
1372 tmp = cmd->scan_end_src;
1373 cmd->scan_end_src &= TRIG_COUNT;
1374 if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
1375 err++;
1376
1377 tmp = cmd->stop_src;
1378 cmd->stop_src &= TRIG_COUNT | TRIG_NONE;
1379 if (!cmd->stop_src || tmp != cmd->stop_src)
1380 err++;
1381
1382 if (err)
1383 return 1;
1384
1385
1386
1387 if (cmd->scan_begin_src != TRIG_TIMER &&
1388 cmd->scan_begin_src != TRIG_EXT)
1389 err++;
1390 if (cmd->stop_src != TRIG_COUNT && cmd->stop_src != TRIG_NONE)
1391 err++;
1392
1393 if (err)
1394 return 2;
1395
1396
1397
1398 if (cmd->start_arg != 0) {
1399 cmd->start_arg = 0;
1400 err++;
1401 }
1402
1403 if (cmd->scan_begin_src == TRIG_TIMER) {
1404 if (cmd->scan_begin_arg < thisboard->ao_scan_speed) {
1405 cmd->scan_begin_arg = thisboard->ao_scan_speed;
1406 err++;
1407 }
1408 }
1409
1410 if (cmd->scan_end_arg != cmd->chanlist_len) {
1411 cmd->scan_end_arg = cmd->chanlist_len;
1412 err++;
1413 }
1414 if (cmd->stop_src == TRIG_NONE) {
1415
1416 if (cmd->stop_arg != 0) {
1417 cmd->stop_arg = 0;
1418 err++;
1419 }
1420 }
1421
1422 if (err)
1423 return 3;
1424
1425
1426
1427 if (cmd->scan_begin_src == TRIG_TIMER) {
1428 tmp = cmd->scan_begin_arg;
1429 i8253_cascade_ns_to_timer_2div(TIMER_BASE,
1430 &(devpriv->ao_divisor1),
1431 &(devpriv->ao_divisor2),
1432 &(cmd->scan_begin_arg),
1433 cmd->flags & TRIG_ROUND_MASK);
1434 if (tmp != cmd->scan_begin_arg)
1435 err++;
1436 }
1437
1438 if (err)
1439 return 4;
1440
1441
1442 if (cmd->chanlist && cmd->chanlist_len > 1) {
1443 if (CR_CHAN(cmd->chanlist[0]) != 0 ||
1444 CR_CHAN(cmd->chanlist[1]) != 1) {
1445 comedi_error(dev,
1446 "channels must be ordered channel 0, channel 1 in chanlist\n");
1447 err++;
1448 }
1449 }
1450
1451 if (err)
1452 return 5;
1453
1454 return 0;
1455}
1456
1457static int cb_pcidas_ao_cmd(struct comedi_device *dev,
1458 struct comedi_subdevice *s)
1459{
1460 struct comedi_async *async = s->async;
1461 struct comedi_cmd *cmd = &async->cmd;
1462 unsigned int i;
1463 unsigned long flags;
1464
1465
1466 spin_lock_irqsave(&dev->spinlock, flags);
1467 for (i = 0; i < cmd->chanlist_len; i++) {
1468
1469 devpriv->ao_control_bits |=
1470 DAC_CHAN_EN(CR_CHAN(cmd->chanlist[i]));
1471
1472 devpriv->ao_control_bits |= DAC_RANGE(CR_CHAN(cmd->chanlist[i]),
1473 CR_RANGE(cmd->
1474 chanlist[i]));
1475 }
1476
1477
1478 outw(devpriv->ao_control_bits, devpriv->control_status + DAC_CSR);
1479 spin_unlock_irqrestore(&dev->spinlock, flags);
1480
1481
1482 outw(0, devpriv->ao_registers + DACFIFOCLR);
1483
1484
1485 if (cmd->scan_begin_src == TRIG_TIMER) {
1486 i8253_cascade_ns_to_timer_2div(TIMER_BASE,
1487 &(devpriv->ao_divisor1),
1488 &(devpriv->ao_divisor2),
1489 &(cmd->scan_begin_arg),
1490 cmd->flags);
1491
1492
1493 i8254_load(devpriv->pacer_counter_dio + DAC8254, 0, 1,
1494 devpriv->ao_divisor1, 2);
1495 i8254_load(devpriv->pacer_counter_dio + DAC8254, 0, 2,
1496 devpriv->ao_divisor2, 2);
1497 }
1498
1499 if (cmd->stop_src == TRIG_COUNT)
1500 devpriv->ao_count = cmd->chanlist_len * cmd->stop_arg;
1501
1502 spin_lock_irqsave(&dev->spinlock, flags);
1503 switch (cmd->scan_begin_src) {
1504 case TRIG_TIMER:
1505 devpriv->ao_control_bits |= DAC_PACER_INT;
1506 break;
1507 case TRIG_EXT:
1508 devpriv->ao_control_bits |= DAC_PACER_EXT_RISE;
1509 break;
1510 default:
1511 spin_unlock_irqrestore(&dev->spinlock, flags);
1512 comedi_error(dev, "error setting dac pacer source");
1513 return -1;
1514 break;
1515 }
1516 spin_unlock_irqrestore(&dev->spinlock, flags);
1517
1518 async->inttrig = cb_pcidas_ao_inttrig;
1519
1520 return 0;
1521}
1522
1523static int cb_pcidas_ao_inttrig(struct comedi_device *dev,
1524 struct comedi_subdevice *s,
1525 unsigned int trig_num)
1526{
1527 unsigned int num_bytes, num_points = thisboard->fifo_size;
1528 struct comedi_async *async = s->async;
1529 struct comedi_cmd *cmd = &s->async->cmd;
1530 unsigned long flags;
1531
1532 if (trig_num != 0)
1533 return -EINVAL;
1534
1535
1536 if (cmd->stop_src == TRIG_COUNT && devpriv->ao_count < num_points)
1537 num_points = devpriv->ao_count;
1538
1539 num_bytes = cfc_read_array_from_buffer(s, devpriv->ao_buffer,
1540 num_points * sizeof(short));
1541 num_points = num_bytes / sizeof(short);
1542
1543 if (cmd->stop_src == TRIG_COUNT)
1544 devpriv->ao_count -= num_points;
1545
1546 outsw(devpriv->ao_registers + DACDATA, devpriv->ao_buffer, num_bytes);
1547
1548
1549 spin_lock_irqsave(&dev->spinlock, flags);
1550 devpriv->adc_fifo_bits |= DAEMIE | DAHFIE;
1551#ifdef CB_PCIDAS_DEBUG
1552 printk("comedi: adc_fifo_bits are 0x%x\n", 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 printk("comedi: sent 0x%x to dac control\n", devpriv->ao_control_bits);
1563#endif
1564 spin_unlock_irqrestore(&dev->spinlock, flags);
1565
1566 async->inttrig = NULL;
1567
1568 return 0;
1569}
1570
1571static irqreturn_t cb_pcidas_interrupt(int irq, void *d)
1572{
1573 struct comedi_device *dev = (struct comedi_device *)d;
1574 struct comedi_subdevice *s = dev->read_subdev;
1575 struct comedi_async *async;
1576 int status, s5933_status;
1577 int half_fifo = thisboard->fifo_size / 2;
1578 unsigned int num_samples, i;
1579 static const int timeout = 10000;
1580 unsigned long flags;
1581
1582 if (dev->attached == 0)
1583 return IRQ_NONE;
1584
1585 async = s->async;
1586 async->events = 0;
1587
1588 s5933_status = inl(devpriv->s5933_config + AMCC_OP_REG_INTCSR);
1589#ifdef CB_PCIDAS_DEBUG
1590 printk("intcsr 0x%x\n", s5933_status);
1591 printk("mbef 0x%x\n", inl(devpriv->s5933_config + AMCC_OP_REG_MBEF));
1592#endif
1593
1594 if ((INTCSR_INTR_ASSERTED & s5933_status) == 0)
1595 return IRQ_NONE;
1596
1597
1598 inl_p(devpriv->s5933_config + AMCC_OP_REG_IMB4);
1599
1600 outl(devpriv->s5933_intcsr_bits | INTCSR_INBOX_INTR_STATUS,
1601 devpriv->s5933_config + AMCC_OP_REG_INTCSR);
1602
1603 status = inw(devpriv->control_status + INT_ADCFIFO);
1604#ifdef CB_PCIDAS_DEBUG
1605 if ((status & (INT | EOAI | LADFUL | DAHFI | DAEMI)) == 0)
1606 comedi_error(dev, "spurious interrupt");
1607#endif
1608
1609
1610 if (status & (DAHFI | DAEMI))
1611 handle_ao_interrupt(dev, status);
1612
1613
1614 if (status & ADHFI) {
1615
1616 num_samples = half_fifo;
1617 if (async->cmd.stop_src == TRIG_COUNT &&
1618 num_samples > devpriv->count) {
1619 num_samples = devpriv->count;
1620 }
1621 insw(devpriv->adc_fifo + ADCDATA, devpriv->ai_buffer,
1622 num_samples);
1623 cfc_write_array_to_buffer(s, devpriv->ai_buffer,
1624 num_samples * sizeof(short));
1625 devpriv->count -= num_samples;
1626 if (async->cmd.stop_src == TRIG_COUNT && devpriv->count == 0) {
1627 async->events |= COMEDI_CB_EOA;
1628 cb_pcidas_cancel(dev, s);
1629 }
1630
1631 spin_lock_irqsave(&dev->spinlock, flags);
1632 outw(devpriv->adc_fifo_bits | INT,
1633 devpriv->control_status + INT_ADCFIFO);
1634 spin_unlock_irqrestore(&dev->spinlock, flags);
1635
1636 } else if (status & (ADNEI | EOBI)) {
1637 for (i = 0; i < timeout; i++) {
1638
1639 if ((ADNE & inw(devpriv->control_status +
1640 INT_ADCFIFO)) == 0)
1641 break;
1642 cfc_write_to_buffer(s, inw(devpriv->adc_fifo));
1643 if (async->cmd.stop_src == TRIG_COUNT && --devpriv->count == 0) {
1644 cb_pcidas_cancel(dev, s);
1645 async->events |= COMEDI_CB_EOA;
1646 break;
1647 }
1648 }
1649
1650 spin_lock_irqsave(&dev->spinlock, flags);
1651 outw(devpriv->adc_fifo_bits | INT,
1652 devpriv->control_status + INT_ADCFIFO);
1653 spin_unlock_irqrestore(&dev->spinlock, flags);
1654 } else if (status & EOAI) {
1655 comedi_error(dev,
1656 "bug! encountered end of acquisition interrupt?");
1657
1658 spin_lock_irqsave(&dev->spinlock, flags);
1659 outw(devpriv->adc_fifo_bits | EOAI,
1660 devpriv->control_status + INT_ADCFIFO);
1661 spin_unlock_irqrestore(&dev->spinlock, flags);
1662 }
1663
1664 if (status & LADFUL) {
1665 comedi_error(dev, "fifo overflow");
1666
1667 spin_lock_irqsave(&dev->spinlock, flags);
1668 outw(devpriv->adc_fifo_bits | LADFUL,
1669 devpriv->control_status + INT_ADCFIFO);
1670 spin_unlock_irqrestore(&dev->spinlock, flags);
1671 cb_pcidas_cancel(dev, s);
1672 async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR;
1673 }
1674
1675 comedi_event(dev, s);
1676
1677 return IRQ_HANDLED;
1678}
1679
1680static void handle_ao_interrupt(struct comedi_device *dev, unsigned int status)
1681{
1682 struct comedi_subdevice *s = dev->write_subdev;
1683 struct comedi_async *async = s->async;
1684 struct comedi_cmd *cmd = &async->cmd;
1685 unsigned int half_fifo = thisboard->fifo_size / 2;
1686 unsigned int num_points;
1687 unsigned long flags;
1688
1689 async->events = 0;
1690
1691 if (status & DAEMI) {
1692
1693 spin_lock_irqsave(&dev->spinlock, flags);
1694 outw(devpriv->adc_fifo_bits | DAEMI,
1695 devpriv->control_status + INT_ADCFIFO);
1696 spin_unlock_irqrestore(&dev->spinlock, flags);
1697 if (inw(devpriv->ao_registers + DAC_CSR) & DAC_EMPTY) {
1698 if (cmd->stop_src == TRIG_NONE ||
1699 (cmd->stop_src == TRIG_COUNT
1700 && devpriv->ao_count)) {
1701 comedi_error(dev, "dac fifo underflow");
1702 cb_pcidas_ao_cancel(dev, s);
1703 async->events |= COMEDI_CB_ERROR;
1704 }
1705 async->events |= COMEDI_CB_EOA;
1706 }
1707 } else if (status & DAHFI) {
1708 unsigned int num_bytes;
1709
1710
1711 num_points = half_fifo;
1712 if (cmd->stop_src == TRIG_COUNT &&
1713 devpriv->ao_count < num_points)
1714 num_points = devpriv->ao_count;
1715 num_bytes =
1716 cfc_read_array_from_buffer(s, devpriv->ao_buffer,
1717 num_points * sizeof(short));
1718 num_points = num_bytes / sizeof(short);
1719
1720 if (async->cmd.stop_src == TRIG_COUNT)
1721 devpriv->ao_count -= num_points;
1722
1723 outsw(devpriv->ao_registers + DACDATA, devpriv->ao_buffer,
1724 num_points);
1725
1726 spin_lock_irqsave(&dev->spinlock, flags);
1727 outw(devpriv->adc_fifo_bits | DAHFI,
1728 devpriv->control_status + INT_ADCFIFO);
1729 spin_unlock_irqrestore(&dev->spinlock, flags);
1730 }
1731
1732 comedi_event(dev, s);
1733}
1734
1735
1736static int cb_pcidas_cancel(struct comedi_device *dev,
1737 struct comedi_subdevice *s)
1738{
1739 unsigned long flags;
1740
1741 spin_lock_irqsave(&dev->spinlock, flags);
1742
1743 devpriv->adc_fifo_bits &= ~INTE & ~EOAIE;
1744 outw(devpriv->adc_fifo_bits, devpriv->control_status + INT_ADCFIFO);
1745 spin_unlock_irqrestore(&dev->spinlock, flags);
1746
1747
1748 outw(0, devpriv->control_status + TRIG_CONTSTAT);
1749
1750 outw(0, devpriv->control_status + ADCMUX_CONT);
1751
1752 return 0;
1753}
1754
1755
1756static int cb_pcidas_ao_cancel(struct comedi_device *dev,
1757 struct comedi_subdevice *s)
1758{
1759 unsigned long flags;
1760
1761 spin_lock_irqsave(&dev->spinlock, flags);
1762
1763 devpriv->adc_fifo_bits &= ~DAHFIE & ~DAEMIE;
1764 outw(devpriv->adc_fifo_bits, devpriv->control_status + INT_ADCFIFO);
1765
1766
1767 devpriv->ao_control_bits &= ~DACEN & ~DAC_PACER_MASK;
1768 outw(devpriv->ao_control_bits, devpriv->control_status + DAC_CSR);
1769 spin_unlock_irqrestore(&dev->spinlock, flags);
1770
1771 return 0;
1772}
1773
1774static void cb_pcidas_load_counters(struct comedi_device *dev, unsigned int *ns,
1775 int rounding_flags)
1776{
1777 i8253_cascade_ns_to_timer_2div(TIMER_BASE, &(devpriv->divisor1),
1778 &(devpriv->divisor2), ns,
1779 rounding_flags & TRIG_ROUND_MASK);
1780
1781
1782 i8254_load(devpriv->pacer_counter_dio + ADC8254, 0, 1,
1783 devpriv->divisor1, 2);
1784 i8254_load(devpriv->pacer_counter_dio + ADC8254, 0, 2,
1785 devpriv->divisor2, 2);
1786}
1787
1788static void write_calibration_bitstream(struct comedi_device *dev,
1789 unsigned int register_bits,
1790 unsigned int bitstream,
1791 unsigned int bitstream_length)
1792{
1793 static const int write_delay = 1;
1794 unsigned int bit;
1795
1796 for (bit = 1 << (bitstream_length - 1); bit; bit >>= 1) {
1797 if (bitstream & bit)
1798 register_bits |= SERIAL_DATA_IN_BIT;
1799 else
1800 register_bits &= ~SERIAL_DATA_IN_BIT;
1801 udelay(write_delay);
1802 outw(register_bits, devpriv->control_status + CALIBRATION_REG);
1803 }
1804}
1805
1806static int caldac_8800_write(struct comedi_device *dev, unsigned int address,
1807 uint8_t value)
1808{
1809 static const int num_caldac_channels = 8;
1810 static const int bitstream_length = 11;
1811 unsigned int bitstream = ((address & 0x7) << 8) | value;
1812 static const int caldac_8800_udelay = 1;
1813
1814 if (address >= num_caldac_channels) {
1815 comedi_error(dev, "illegal caldac channel");
1816 return -1;
1817 }
1818
1819 if (value == devpriv->caldac_value[address])
1820 return 1;
1821
1822 devpriv->caldac_value[address] = value;
1823
1824 write_calibration_bitstream(dev, cal_enable_bits(dev), bitstream,
1825 bitstream_length);
1826
1827 udelay(caldac_8800_udelay);
1828 outw(cal_enable_bits(dev) | SELECT_8800_BIT,
1829 devpriv->control_status + CALIBRATION_REG);
1830 udelay(caldac_8800_udelay);
1831 outw(cal_enable_bits(dev), devpriv->control_status + CALIBRATION_REG);
1832
1833 return 1;
1834}
1835
1836static int trimpot_7376_write(struct comedi_device *dev, uint8_t value)
1837{
1838 static const int bitstream_length = 7;
1839 unsigned int bitstream = value & 0x7f;
1840 unsigned int register_bits;
1841 static const int ad7376_udelay = 1;
1842
1843 register_bits = cal_enable_bits(dev) | SELECT_TRIMPOT_BIT;
1844 udelay(ad7376_udelay);
1845 outw(register_bits, devpriv->control_status + CALIBRATION_REG);
1846
1847 write_calibration_bitstream(dev, register_bits, bitstream,
1848 bitstream_length);
1849
1850 udelay(ad7376_udelay);
1851 outw(cal_enable_bits(dev), devpriv->control_status + CALIBRATION_REG);
1852
1853 return 0;
1854}
1855
1856
1857
1858
1859static int trimpot_8402_write(struct comedi_device *dev, unsigned int channel,
1860 uint8_t value)
1861{
1862 static const int bitstream_length = 10;
1863 unsigned int bitstream = ((channel & 0x3) << 8) | (value & 0xff);
1864 unsigned int register_bits;
1865 static const int ad8402_udelay = 1;
1866
1867 register_bits = cal_enable_bits(dev) | SELECT_TRIMPOT_BIT;
1868 udelay(ad8402_udelay);
1869 outw(register_bits, devpriv->control_status + CALIBRATION_REG);
1870
1871 write_calibration_bitstream(dev, register_bits, bitstream,
1872 bitstream_length);
1873
1874 udelay(ad8402_udelay);
1875 outw(cal_enable_bits(dev), devpriv->control_status + CALIBRATION_REG);
1876
1877 return 0;
1878}
1879
1880static int wait_for_nvram_ready(unsigned long s5933_base_addr)
1881{
1882 static const int timeout = 1000;
1883 unsigned int i;
1884
1885 for (i = 0; i < timeout; i++) {
1886 if ((inb(s5933_base_addr +
1887 AMCC_OP_REG_MCSR_NVCMD) & MCSR_NV_BUSY)
1888 == 0)
1889 return 0;
1890 udelay(1);
1891 }
1892 return -1;
1893}
1894
1895static int nvram_read(struct comedi_device *dev, unsigned int address,
1896 uint8_t *data)
1897{
1898 unsigned long iobase = devpriv->s5933_config;
1899
1900 if (wait_for_nvram_ready(iobase) < 0)
1901 return -ETIMEDOUT;
1902
1903 outb(MCSR_NV_ENABLE | MCSR_NV_LOAD_LOW_ADDR,
1904 iobase + AMCC_OP_REG_MCSR_NVCMD);
1905 outb(address & 0xff, iobase + AMCC_OP_REG_MCSR_NVDATA);
1906 outb(MCSR_NV_ENABLE | MCSR_NV_LOAD_HIGH_ADDR,
1907 iobase + AMCC_OP_REG_MCSR_NVCMD);
1908 outb((address >> 8) & 0xff, iobase + AMCC_OP_REG_MCSR_NVDATA);
1909 outb(MCSR_NV_ENABLE | MCSR_NV_READ, iobase + AMCC_OP_REG_MCSR_NVCMD);
1910
1911 if (wait_for_nvram_ready(iobase) < 0)
1912 return -ETIMEDOUT;
1913
1914 *data = inb(iobase + AMCC_OP_REG_MCSR_NVDATA);
1915
1916 return 0;
1917}
1918
1919
1920
1921
1922
1923static int __devinit driver_cb_pcidas_pci_probe(struct pci_dev *dev,
1924 const struct pci_device_id *ent)
1925{
1926 return comedi_pci_auto_config(dev, driver_cb_pcidas.driver_name);
1927}
1928
1929static void __devexit driver_cb_pcidas_pci_remove(struct pci_dev *dev)
1930{
1931 comedi_pci_auto_unconfig(dev);
1932}
1933
1934static struct pci_driver driver_cb_pcidas_pci_driver = {
1935 .id_table = cb_pcidas_pci_table,
1936 .probe = &driver_cb_pcidas_pci_probe,
1937 .remove = __devexit_p(&driver_cb_pcidas_pci_remove)
1938};
1939
1940static int __init driver_cb_pcidas_init_module(void)
1941{
1942 int retval;
1943
1944 retval = comedi_driver_register(&driver_cb_pcidas);
1945 if (retval < 0)
1946 return retval;
1947
1948 driver_cb_pcidas_pci_driver.name = (char *)driver_cb_pcidas.driver_name;
1949 return pci_register_driver(&driver_cb_pcidas_pci_driver);
1950}
1951
1952static void __exit driver_cb_pcidas_cleanup_module(void)
1953{
1954 pci_unregister_driver(&driver_cb_pcidas_pci_driver);
1955 comedi_driver_unregister(&driver_cb_pcidas);
1956}
1957
1958module_init(driver_cb_pcidas_init_module);
1959module_exit(driver_cb_pcidas_cleanup_module);
1960
1961MODULE_AUTHOR("Comedi http://www.comedi.org");
1962MODULE_DESCRIPTION("Comedi low-level driver");
1963MODULE_LICENSE("GPL");
1964