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#define DEBUG 1
61
62#include <linux/interrupt.h>
63#include "../comedidev.h"
64#include <linux/delay.h>
65
66#include "comedi_pci.h"
67
68#define PCI_VENDOR_ID_DT 0x1116
69
70static const struct comedi_lrange range_dt3000_ai = { 4, {
71 RANGE(-10, 10),
72 RANGE(-5, 5),
73 RANGE(-2.5, 2.5),
74 RANGE(-1.25, 1.25)
75 }
76};
77
78static const struct comedi_lrange range_dt3000_ai_pgl = { 4, {
79 RANGE(-10, 10),
80 RANGE(-1, 1),
81 RANGE(-0.1, 0.1),
82 RANGE(-0.02, 0.02)
83 }
84};
85
86struct dt3k_boardtype {
87
88 const char *name;
89 unsigned int device_id;
90 int adchan;
91 int adbits;
92 int ai_speed;
93 const struct comedi_lrange *adrange;
94 int dachan;
95 int dabits;
96};
97
98static const struct dt3k_boardtype dt3k_boardtypes[] = {
99 {.name = "dt3001",
100 .device_id = 0x22,
101 .adchan = 16,
102 .adbits = 12,
103 .adrange = &range_dt3000_ai,
104 .ai_speed = 3000,
105 .dachan = 2,
106 .dabits = 12,
107 },
108 {.name = "dt3001-pgl",
109 .device_id = 0x27,
110 .adchan = 16,
111 .adbits = 12,
112 .adrange = &range_dt3000_ai_pgl,
113 .ai_speed = 3000,
114 .dachan = 2,
115 .dabits = 12,
116 },
117 {.name = "dt3002",
118 .device_id = 0x23,
119 .adchan = 32,
120 .adbits = 12,
121 .adrange = &range_dt3000_ai,
122 .ai_speed = 3000,
123 .dachan = 0,
124 .dabits = 0,
125 },
126 {.name = "dt3003",
127 .device_id = 0x24,
128 .adchan = 64,
129 .adbits = 12,
130 .adrange = &range_dt3000_ai,
131 .ai_speed = 3000,
132 .dachan = 2,
133 .dabits = 12,
134 },
135 {.name = "dt3003-pgl",
136 .device_id = 0x28,
137 .adchan = 64,
138 .adbits = 12,
139 .adrange = &range_dt3000_ai_pgl,
140 .ai_speed = 3000,
141 .dachan = 2,
142 .dabits = 12,
143 },
144 {.name = "dt3004",
145 .device_id = 0x25,
146 .adchan = 16,
147 .adbits = 16,
148 .adrange = &range_dt3000_ai,
149 .ai_speed = 10000,
150 .dachan = 2,
151 .dabits = 12,
152 },
153 {.name = "dt3005",
154 .device_id = 0x26,
155 .adchan = 16,
156 .adbits = 16,
157 .adrange = &range_dt3000_ai,
158 .ai_speed = 5000,
159 .dachan = 2,
160 .dabits = 12,
161 },
162};
163
164#define n_dt3k_boards sizeof(dt3k_boardtypes)/sizeof(struct dt3k_boardtype)
165#define this_board ((const struct dt3k_boardtype *)dev->board_ptr)
166
167static DEFINE_PCI_DEVICE_TABLE(dt3k_pci_table) = {
168 {
169 PCI_VENDOR_ID_DT, 0x0022, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {
170 PCI_VENDOR_ID_DT, 0x0027, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {
171 PCI_VENDOR_ID_DT, 0x0023, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {
172 PCI_VENDOR_ID_DT, 0x0024, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {
173 PCI_VENDOR_ID_DT, 0x0028, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {
174 PCI_VENDOR_ID_DT, 0x0025, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {
175 PCI_VENDOR_ID_DT, 0x0026, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {
176 0}
177};
178
179MODULE_DEVICE_TABLE(pci, dt3k_pci_table);
180
181#define DT3000_SIZE (4*0x1000)
182
183
184
185#define DPR_DAC_buffer (4*0x000)
186#define DPR_ADC_buffer (4*0x800)
187#define DPR_Command (4*0xfd3)
188#define DPR_SubSys (4*0xfd3)
189#define DPR_Encode (4*0xfd4)
190#define DPR_Params(a) (4*(0xfd5+(a)))
191#define DPR_Tick_Reg_Lo (4*0xff5)
192#define DPR_Tick_Reg_Hi (4*0xff6)
193#define DPR_DA_Buf_Front (4*0xff7)
194#define DPR_DA_Buf_Rear (4*0xff8)
195#define DPR_AD_Buf_Front (4*0xff9)
196#define DPR_AD_Buf_Rear (4*0xffa)
197#define DPR_Int_Mask (4*0xffb)
198#define DPR_Intr_Flag (4*0xffc)
199#define DPR_Response_Mbx (4*0xffe)
200#define DPR_Command_Mbx (4*0xfff)
201
202#define AI_FIFO_DEPTH 2003
203#define AO_FIFO_DEPTH 2048
204
205
206
207#define CMD_GETBRDINFO 0
208#define CMD_CONFIG 1
209#define CMD_GETCONFIG 2
210#define CMD_START 3
211#define CMD_STOP 4
212#define CMD_READSINGLE 5
213#define CMD_WRITESINGLE 6
214#define CMD_CALCCLOCK 7
215#define CMD_READEVENTS 8
216#define CMD_WRITECTCTRL 16
217#define CMD_READCTCTRL 17
218#define CMD_WRITECT 18
219#define CMD_READCT 19
220#define CMD_WRITEDATA 32
221#define CMD_READDATA 33
222#define CMD_WRITEIO 34
223#define CMD_READIO 35
224#define CMD_WRITECODE 36
225#define CMD_READCODE 37
226#define CMD_EXECUTE 38
227#define CMD_HALT 48
228
229#define SUBS_AI 0
230#define SUBS_AO 1
231#define SUBS_DIN 2
232#define SUBS_DOUT 3
233#define SUBS_MEM 4
234#define SUBS_CT 5
235
236
237#define DT3000_CMDONE 0x80
238#define DT3000_CTDONE 0x40
239#define DT3000_DAHWERR 0x20
240#define DT3000_DASWERR 0x10
241#define DT3000_DAEMPTY 0x08
242#define DT3000_ADHWERR 0x04
243#define DT3000_ADSWERR 0x02
244#define DT3000_ADFULL 0x01
245
246#define DT3000_COMPLETION_MASK 0xff00
247#define DT3000_COMMAND_MASK 0x00ff
248#define DT3000_NOTPROCESSED 0x0000
249#define DT3000_NOERROR 0x5500
250#define DT3000_ERROR 0xaa00
251#define DT3000_NOTSUPPORTED 0xff00
252
253#define DT3000_EXTERNAL_CLOCK 1
254#define DT3000_RISING_EDGE 2
255
256#define TMODE_MASK 0x1c
257
258#define DT3000_AD_TRIG_INTERNAL (0<<2)
259#define DT3000_AD_TRIG_EXTERNAL (1<<2)
260#define DT3000_AD_RETRIG_INTERNAL (2<<2)
261#define DT3000_AD_RETRIG_EXTERNAL (3<<2)
262#define DT3000_AD_EXTRETRIG (4<<2)
263
264#define DT3000_CHANNEL_MODE_SE 0
265#define DT3000_CHANNEL_MODE_DI 1
266
267struct dt3k_private {
268
269 struct pci_dev *pci_dev;
270 resource_size_t phys_addr;
271 void *io_addr;
272 unsigned int lock;
273 unsigned int ao_readback[2];
274 unsigned int ai_front;
275 unsigned int ai_rear;
276};
277
278#define devpriv ((struct dt3k_private *)dev->private)
279
280static int dt3000_attach(struct comedi_device *dev,
281 struct comedi_devconfig *it);
282static int dt3000_detach(struct comedi_device *dev);
283static struct comedi_driver driver_dt3000 = {
284 .driver_name = "dt3000",
285 .module = THIS_MODULE,
286 .attach = dt3000_attach,
287 .detach = dt3000_detach,
288};
289
290COMEDI_PCI_INITCLEANUP(driver_dt3000, dt3k_pci_table);
291
292static void dt3k_ai_empty_fifo(struct comedi_device *dev,
293 struct comedi_subdevice *s);
294static int dt3k_ns_to_timer(unsigned int timer_base, unsigned int *arg,
295 unsigned int round_mode);
296static int dt3k_ai_cancel(struct comedi_device *dev,
297 struct comedi_subdevice *s);
298#ifdef DEBUG
299static void debug_intr_flags(unsigned int flags);
300#endif
301
302#define TIMEOUT 100
303
304static int dt3k_send_cmd(struct comedi_device *dev, unsigned int cmd)
305{
306 int i;
307 unsigned int status = 0;
308
309 writew(cmd, devpriv->io_addr + DPR_Command_Mbx);
310
311 for (i = 0; i < TIMEOUT; i++) {
312 status = readw(devpriv->io_addr + DPR_Command_Mbx);
313 if ((status & DT3000_COMPLETION_MASK) != DT3000_NOTPROCESSED)
314 break;
315 udelay(1);
316 }
317 if ((status & DT3000_COMPLETION_MASK) == DT3000_NOERROR) {
318 return 0;
319 }
320
321 printk("dt3k_send_cmd() timeout/error status=0x%04x\n", status);
322
323 return -ETIME;
324}
325
326static unsigned int dt3k_readsingle(struct comedi_device *dev,
327 unsigned int subsys, unsigned int chan,
328 unsigned int gain)
329{
330 writew(subsys, devpriv->io_addr + DPR_SubSys);
331
332 writew(chan, devpriv->io_addr + DPR_Params(0));
333 writew(gain, devpriv->io_addr + DPR_Params(1));
334
335 dt3k_send_cmd(dev, CMD_READSINGLE);
336
337 return readw(devpriv->io_addr + DPR_Params(2));
338}
339
340static void dt3k_writesingle(struct comedi_device *dev, unsigned int subsys,
341 unsigned int chan, unsigned int data)
342{
343 writew(subsys, devpriv->io_addr + DPR_SubSys);
344
345 writew(chan, devpriv->io_addr + DPR_Params(0));
346 writew(0, devpriv->io_addr + DPR_Params(1));
347 writew(data, devpriv->io_addr + DPR_Params(2));
348
349 dt3k_send_cmd(dev, CMD_WRITESINGLE);
350}
351
352static int debug_n_ints = 0;
353
354
355
356static irqreturn_t dt3k_interrupt(int irq, void *d)
357{
358 struct comedi_device *dev = d;
359 struct comedi_subdevice *s;
360 unsigned int status;
361
362 if (!dev->attached) {
363 return IRQ_NONE;
364 }
365
366 s = dev->subdevices + 0;
367 status = readw(devpriv->io_addr + DPR_Intr_Flag);
368#ifdef DEBUG
369 debug_intr_flags(status);
370#endif
371
372 if (status & DT3000_ADFULL) {
373 dt3k_ai_empty_fifo(dev, s);
374 s->async->events |= COMEDI_CB_BLOCK;
375 }
376
377 if (status & (DT3000_ADSWERR | DT3000_ADHWERR)) {
378 s->async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
379 }
380
381 debug_n_ints++;
382 if (debug_n_ints >= 10) {
383 dt3k_ai_cancel(dev, s);
384 s->async->events |= COMEDI_CB_EOA;
385 }
386
387 comedi_event(dev, s);
388 return IRQ_HANDLED;
389}
390
391#ifdef DEBUG
392static char *intr_flags[] = {
393 "AdFull", "AdSwError", "AdHwError", "DaEmpty",
394 "DaSwError", "DaHwError", "CtDone", "CmDone",
395};
396
397static void debug_intr_flags(unsigned int flags)
398{
399 int i;
400 printk("dt3k: intr_flags:");
401 for (i = 0; i < 8; i++) {
402 if (flags & (1 << i)) {
403 printk(" %s", intr_flags[i]);
404 }
405 }
406 printk("\n");
407}
408#endif
409
410static void dt3k_ai_empty_fifo(struct comedi_device *dev,
411 struct comedi_subdevice *s)
412{
413 int front;
414 int rear;
415 int count;
416 int i;
417 short data;
418
419 front = readw(devpriv->io_addr + DPR_AD_Buf_Front);
420 count = front - devpriv->ai_front;
421 if (count < 0)
422 count += AI_FIFO_DEPTH;
423
424 printk("reading %d samples\n", count);
425
426 rear = devpriv->ai_rear;
427
428 for (i = 0; i < count; i++) {
429 data = readw(devpriv->io_addr + DPR_ADC_buffer + rear);
430 comedi_buf_put(s->async, data);
431 rear++;
432 if (rear >= AI_FIFO_DEPTH)
433 rear = 0;
434 }
435
436 devpriv->ai_rear = rear;
437 writew(rear, devpriv->io_addr + DPR_AD_Buf_Rear);
438}
439
440static int dt3k_ai_cmdtest(struct comedi_device *dev,
441 struct comedi_subdevice *s, struct comedi_cmd *cmd)
442{
443 int err = 0;
444 int tmp;
445
446
447
448 tmp = cmd->start_src;
449 cmd->start_src &= TRIG_NOW;
450 if (!cmd->start_src || tmp != cmd->start_src)
451 err++;
452
453 tmp = cmd->scan_begin_src;
454 cmd->scan_begin_src &= TRIG_TIMER;
455 if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
456 err++;
457
458 tmp = cmd->convert_src;
459 cmd->convert_src &= TRIG_TIMER;
460 if (!cmd->convert_src || tmp != cmd->convert_src)
461 err++;
462
463 tmp = cmd->scan_end_src;
464 cmd->scan_end_src &= TRIG_COUNT;
465 if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
466 err++;
467
468 tmp = cmd->stop_src;
469 cmd->stop_src &= TRIG_COUNT;
470 if (!cmd->stop_src || tmp != cmd->stop_src)
471 err++;
472
473 if (err)
474 return 1;
475
476
477
478 if (err)
479 return 2;
480
481
482
483 if (cmd->start_arg != 0) {
484 cmd->start_arg = 0;
485 err++;
486 }
487
488 if (cmd->scan_begin_src == TRIG_TIMER) {
489 if (cmd->scan_begin_arg < this_board->ai_speed) {
490 cmd->scan_begin_arg = this_board->ai_speed;
491 err++;
492 }
493 if (cmd->scan_begin_arg > 100 * 16 * 65535) {
494 cmd->scan_begin_arg = 100 * 16 * 65535;
495 err++;
496 }
497 } else {
498
499 }
500 if (cmd->convert_src == TRIG_TIMER) {
501 if (cmd->convert_arg < this_board->ai_speed) {
502 cmd->convert_arg = this_board->ai_speed;
503 err++;
504 }
505 if (cmd->convert_arg > 50 * 16 * 65535) {
506 cmd->convert_arg = 50 * 16 * 65535;
507 err++;
508 }
509 } else {
510
511 }
512
513 if (cmd->scan_end_arg != cmd->chanlist_len) {
514 cmd->scan_end_arg = cmd->chanlist_len;
515 err++;
516 }
517 if (cmd->stop_src == TRIG_COUNT) {
518 if (cmd->stop_arg > 0x00ffffff) {
519 cmd->stop_arg = 0x00ffffff;
520 err++;
521 }
522 } else {
523
524 if (cmd->stop_arg != 0) {
525 cmd->stop_arg = 0;
526 err++;
527 }
528 }
529
530 if (err)
531 return 3;
532
533
534
535 if (cmd->scan_begin_src == TRIG_TIMER) {
536 tmp = cmd->scan_begin_arg;
537 dt3k_ns_to_timer(100, &cmd->scan_begin_arg,
538 cmd->flags & TRIG_ROUND_MASK);
539 if (tmp != cmd->scan_begin_arg)
540 err++;
541 } else {
542
543 }
544 if (cmd->convert_src == TRIG_TIMER) {
545 tmp = cmd->convert_arg;
546 dt3k_ns_to_timer(50, &cmd->convert_arg,
547 cmd->flags & TRIG_ROUND_MASK);
548 if (tmp != cmd->convert_arg)
549 err++;
550 if (cmd->scan_begin_src == TRIG_TIMER &&
551 cmd->scan_begin_arg <
552 cmd->convert_arg * cmd->scan_end_arg) {
553 cmd->scan_begin_arg =
554 cmd->convert_arg * cmd->scan_end_arg;
555 err++;
556 }
557 } else {
558
559 }
560
561 if (err)
562 return 4;
563
564 return 0;
565}
566
567static int dt3k_ns_to_timer(unsigned int timer_base, unsigned int *nanosec,
568 unsigned int round_mode)
569{
570 int divider, base, prescale;
571
572
573
574
575 for (prescale = 0; prescale < 16; prescale++) {
576 base = timer_base * (prescale + 1);
577 switch (round_mode) {
578 case TRIG_ROUND_NEAREST:
579 default:
580 divider = (*nanosec + base / 2) / base;
581 break;
582 case TRIG_ROUND_DOWN:
583 divider = (*nanosec) / base;
584 break;
585 case TRIG_ROUND_UP:
586 divider = (*nanosec) / base;
587 break;
588 }
589 if (divider < 65536) {
590 *nanosec = divider * base;
591 return (prescale << 16) | (divider);
592 }
593 }
594
595 prescale = 15;
596 base = timer_base * (1 << prescale);
597 divider = 65535;
598 *nanosec = divider * base;
599 return (prescale << 16) | (divider);
600}
601
602static int dt3k_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
603{
604 struct comedi_cmd *cmd = &s->async->cmd;
605 int i;
606 unsigned int chan, range, aref;
607 unsigned int divider;
608 unsigned int tscandiv;
609 int ret;
610 unsigned int mode;
611
612 printk("dt3k_ai_cmd:\n");
613 for (i = 0; i < cmd->chanlist_len; i++) {
614 chan = CR_CHAN(cmd->chanlist[i]);
615 range = CR_RANGE(cmd->chanlist[i]);
616
617 writew((range << 6) | chan,
618 devpriv->io_addr + DPR_ADC_buffer + i);
619 }
620 aref = CR_AREF(cmd->chanlist[0]);
621
622 writew(cmd->scan_end_arg, devpriv->io_addr + DPR_Params(0));
623 printk("param[0]=0x%04x\n", cmd->scan_end_arg);
624
625 if (cmd->convert_src == TRIG_TIMER) {
626 divider = dt3k_ns_to_timer(50, &cmd->convert_arg,
627 cmd->flags & TRIG_ROUND_MASK);
628 writew((divider >> 16), devpriv->io_addr + DPR_Params(1));
629 printk("param[1]=0x%04x\n", divider >> 16);
630 writew((divider & 0xffff), devpriv->io_addr + DPR_Params(2));
631 printk("param[2]=0x%04x\n", divider & 0xffff);
632 } else {
633
634 }
635
636 if (cmd->scan_begin_src == TRIG_TIMER) {
637 tscandiv = dt3k_ns_to_timer(100, &cmd->scan_begin_arg,
638 cmd->flags & TRIG_ROUND_MASK);
639 writew((tscandiv >> 16), devpriv->io_addr + DPR_Params(3));
640 printk("param[3]=0x%04x\n", tscandiv >> 16);
641 writew((tscandiv & 0xffff), devpriv->io_addr + DPR_Params(4));
642 printk("param[4]=0x%04x\n", tscandiv & 0xffff);
643 } else {
644
645 }
646
647 mode = DT3000_AD_RETRIG_INTERNAL | 0 | 0;
648 writew(mode, devpriv->io_addr + DPR_Params(5));
649 printk("param[5]=0x%04x\n", mode);
650 writew(aref == AREF_DIFF, devpriv->io_addr + DPR_Params(6));
651 printk("param[6]=0x%04x\n", aref == AREF_DIFF);
652
653 writew(AI_FIFO_DEPTH / 2, devpriv->io_addr + DPR_Params(7));
654 printk("param[7]=0x%04x\n", AI_FIFO_DEPTH / 2);
655
656 writew(SUBS_AI, devpriv->io_addr + DPR_SubSys);
657 ret = dt3k_send_cmd(dev, CMD_CONFIG);
658
659 writew(DT3000_ADFULL | DT3000_ADSWERR | DT3000_ADHWERR,
660 devpriv->io_addr + DPR_Int_Mask);
661
662 debug_n_ints = 0;
663
664 writew(SUBS_AI, devpriv->io_addr + DPR_SubSys);
665 ret = dt3k_send_cmd(dev, CMD_START);
666
667 return 0;
668}
669
670static int dt3k_ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
671{
672 int ret;
673
674 writew(SUBS_AI, devpriv->io_addr + DPR_SubSys);
675 ret = dt3k_send_cmd(dev, CMD_STOP);
676
677 writew(0, devpriv->io_addr + DPR_Int_Mask);
678
679 return 0;
680}
681
682static int dt3k_ai_insn(struct comedi_device *dev, struct comedi_subdevice *s,
683 struct comedi_insn *insn, unsigned int *data)
684{
685 int i;
686 unsigned int chan, gain, aref;
687
688 chan = CR_CHAN(insn->chanspec);
689 gain = CR_RANGE(insn->chanspec);
690
691 aref = CR_AREF(insn->chanspec);
692
693 for (i = 0; i < insn->n; i++) {
694 data[i] = dt3k_readsingle(dev, SUBS_AI, chan, gain);
695 }
696
697 return i;
698}
699
700static int dt3k_ao_insn(struct comedi_device *dev, struct comedi_subdevice *s,
701 struct comedi_insn *insn, unsigned int *data)
702{
703 int i;
704 unsigned int chan;
705
706 chan = CR_CHAN(insn->chanspec);
707 for (i = 0; i < insn->n; i++) {
708 dt3k_writesingle(dev, SUBS_AO, chan, data[i]);
709 devpriv->ao_readback[chan] = data[i];
710 }
711
712 return i;
713}
714
715static int dt3k_ao_insn_read(struct comedi_device *dev,
716 struct comedi_subdevice *s,
717 struct comedi_insn *insn, unsigned int *data)
718{
719 int i;
720 unsigned int chan;
721
722 chan = CR_CHAN(insn->chanspec);
723 for (i = 0; i < insn->n; i++) {
724 data[i] = devpriv->ao_readback[chan];
725 }
726
727 return i;
728}
729
730static void dt3k_dio_config(struct comedi_device *dev, int bits)
731{
732
733 writew(SUBS_DOUT, devpriv->io_addr + DPR_SubSys);
734
735 writew(bits, devpriv->io_addr + DPR_Params(0));
736#if 0
737
738 writew(0, devpriv->io_addr + DPR_Params(1));
739 writew(0, devpriv->io_addr + DPR_Params(2));
740#endif
741
742 dt3k_send_cmd(dev, CMD_CONFIG);
743}
744
745static int dt3k_dio_insn_config(struct comedi_device *dev,
746 struct comedi_subdevice *s,
747 struct comedi_insn *insn, unsigned int *data)
748{
749 int mask;
750
751 mask = (CR_CHAN(insn->chanspec) < 4) ? 0x0f : 0xf0;
752
753 switch (data[0]) {
754 case INSN_CONFIG_DIO_OUTPUT:
755 s->io_bits |= mask;
756 break;
757 case INSN_CONFIG_DIO_INPUT:
758 s->io_bits &= ~mask;
759 break;
760 case INSN_CONFIG_DIO_QUERY:
761 data[1] =
762 (s->
763 io_bits & (1 << CR_CHAN(insn->chanspec))) ? COMEDI_OUTPUT :
764 COMEDI_INPUT;
765 return insn->n;
766 break;
767 default:
768 return -EINVAL;
769 break;
770 }
771 mask = (s->io_bits & 0x01) | ((s->io_bits & 0x10) >> 3);
772 dt3k_dio_config(dev, mask);
773
774 return insn->n;
775}
776
777static int dt3k_dio_insn_bits(struct comedi_device *dev,
778 struct comedi_subdevice *s,
779 struct comedi_insn *insn, unsigned int *data)
780{
781 if (insn->n != 2)
782 return -EINVAL;
783
784 if (data[0]) {
785 s->state &= ~data[0];
786 s->state |= data[1] & data[0];
787 dt3k_writesingle(dev, SUBS_DOUT, 0, s->state);
788 }
789 data[1] = dt3k_readsingle(dev, SUBS_DIN, 0, 0);
790
791 return 2;
792}
793
794static int dt3k_mem_insn_read(struct comedi_device *dev,
795 struct comedi_subdevice *s,
796 struct comedi_insn *insn, unsigned int *data)
797{
798 unsigned int addr = CR_CHAN(insn->chanspec);
799 int i;
800
801 for (i = 0; i < insn->n; i++) {
802 writew(SUBS_MEM, devpriv->io_addr + DPR_SubSys);
803 writew(addr, devpriv->io_addr + DPR_Params(0));
804 writew(1, devpriv->io_addr + DPR_Params(1));
805
806 dt3k_send_cmd(dev, CMD_READCODE);
807
808 data[i] = readw(devpriv->io_addr + DPR_Params(2));
809 }
810
811 return i;
812}
813
814static int dt_pci_probe(struct comedi_device *dev, int bus, int slot);
815
816static int dt3000_attach(struct comedi_device *dev, struct comedi_devconfig *it)
817{
818 struct comedi_subdevice *s;
819 int bus, slot;
820 int ret = 0;
821
822 printk("dt3000:");
823 bus = it->options[0];
824 slot = it->options[1];
825
826 ret = alloc_private(dev, sizeof(struct dt3k_private));
827 if (ret < 0)
828 return ret;
829
830 ret = dt_pci_probe(dev, bus, slot);
831 if (ret < 0)
832 return ret;
833 if (ret == 0) {
834 printk(" no DT board found\n");
835 return -ENODEV;
836 }
837
838 dev->board_name = this_board->name;
839
840 if (request_irq(devpriv->pci_dev->irq, dt3k_interrupt, IRQF_SHARED,
841 "dt3000", dev)) {
842 printk(" unable to allocate IRQ %u\n", devpriv->pci_dev->irq);
843 return -EINVAL;
844 }
845 dev->irq = devpriv->pci_dev->irq;
846
847 ret = alloc_subdevices(dev, 4);
848 if (ret < 0)
849 return ret;
850
851 s = dev->subdevices;
852 dev->read_subdev = s;
853
854
855 s->type = COMEDI_SUBD_AI;
856 s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_DIFF | SDF_CMD_READ;
857 s->n_chan = this_board->adchan;
858 s->insn_read = dt3k_ai_insn;
859 s->maxdata = (1 << this_board->adbits) - 1;
860 s->len_chanlist = 512;
861 s->range_table = &range_dt3000_ai;
862 s->do_cmd = dt3k_ai_cmd;
863 s->do_cmdtest = dt3k_ai_cmdtest;
864 s->cancel = dt3k_ai_cancel;
865
866 s++;
867
868 s->type = COMEDI_SUBD_AO;
869 s->subdev_flags = SDF_WRITABLE;
870 s->n_chan = 2;
871 s->insn_read = dt3k_ao_insn_read;
872 s->insn_write = dt3k_ao_insn;
873 s->maxdata = (1 << this_board->dabits) - 1;
874 s->len_chanlist = 1;
875 s->range_table = &range_bipolar10;
876
877 s++;
878
879 s->type = COMEDI_SUBD_DIO;
880 s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
881 s->n_chan = 8;
882 s->insn_config = dt3k_dio_insn_config;
883 s->insn_bits = dt3k_dio_insn_bits;
884 s->maxdata = 1;
885 s->len_chanlist = 8;
886 s->range_table = &range_digital;
887
888 s++;
889
890 s->type = COMEDI_SUBD_MEMORY;
891 s->subdev_flags = SDF_READABLE;
892 s->n_chan = 0x1000;
893 s->insn_read = dt3k_mem_insn_read;
894 s->maxdata = 0xff;
895 s->len_chanlist = 1;
896 s->range_table = &range_unknown;
897
898#if 0
899 s++;
900
901 s->type = COMEDI_SUBD_PROC;
902#endif
903
904 return 0;
905}
906
907static int dt3000_detach(struct comedi_device *dev)
908{
909 if (dev->irq)
910 free_irq(dev->irq, dev);
911
912 if (devpriv) {
913 if (devpriv->pci_dev) {
914 if (devpriv->phys_addr) {
915 comedi_pci_disable(devpriv->pci_dev);
916 }
917 pci_dev_put(devpriv->pci_dev);
918 }
919 if (devpriv->io_addr)
920 iounmap(devpriv->io_addr);
921 }
922
923
924 return 0;
925}
926
927static struct pci_dev *dt_pci_find_device(struct pci_dev *from, int *board);
928static int setup_pci(struct comedi_device *dev);
929
930static int dt_pci_probe(struct comedi_device *dev, int bus, int slot)
931{
932 int board;
933 int ret;
934 struct pci_dev *pcidev;
935
936 pcidev = NULL;
937 while ((pcidev = dt_pci_find_device(pcidev, &board)) != NULL) {
938 if ((bus == 0 && slot == 0) ||
939 (pcidev->bus->number == bus &&
940 PCI_SLOT(pcidev->devfn) == slot)) {
941 break;
942 }
943 }
944 devpriv->pci_dev = pcidev;
945
946 if (board >= 0)
947 dev->board_ptr = dt3k_boardtypes + board;
948
949 if (!devpriv->pci_dev)
950 return 0;
951
952 ret = setup_pci(dev);
953 if (ret < 0)
954 return ret;
955
956 return 1;
957}
958
959static int setup_pci(struct comedi_device *dev)
960{
961 resource_size_t addr;
962 int ret;
963
964 ret = comedi_pci_enable(devpriv->pci_dev, "dt3000");
965 if (ret < 0)
966 return ret;
967
968 addr = pci_resource_start(devpriv->pci_dev, 0);
969 devpriv->phys_addr = addr;
970 devpriv->io_addr = ioremap(devpriv->phys_addr, DT3000_SIZE);
971 if (!devpriv->io_addr)
972 return -ENOMEM;
973#if DEBUG
974 printk("0x%08llx mapped to %p, ",
975 (unsigned long long)devpriv->phys_addr, devpriv->io_addr);
976#endif
977
978 return 0;
979}
980
981static struct pci_dev *dt_pci_find_device(struct pci_dev *from, int *board)
982{
983 int i;
984
985 for (from = pci_get_device(PCI_VENDOR_ID_DT, PCI_ANY_ID, from);
986 from != NULL;
987 from = pci_get_device(PCI_VENDOR_ID_DT, PCI_ANY_ID, from)) {
988 for (i = 0; i < n_dt3k_boards; i++) {
989 if (from->device == dt3k_boardtypes[i].device_id) {
990 *board = i;
991 return from;
992 }
993 }
994 printk
995 ("unknown Data Translation PCI device found with device_id=0x%04x\n",
996 from->device);
997 }
998 *board = -1;
999 return from;
1000}
1001