Merge tag 'iio-for-3.8a' of git://git.kernel.org/pub/scm/linux/kernel/git/jic23/iio...
[deliverable/linux.git] / drivers / staging / comedi / drivers / dt3000.c
1 /*
2 comedi/drivers/dt3000.c
3 Data Translation DT3000 series driver
4
5 COMEDI - Linux Control and Measurement Device Interface
6 Copyright (C) 1999 David A. Schleef <ds@schleef.org>
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21
22 */
23 /*
24 Driver: dt3000
25 Description: Data Translation DT3000 series
26 Author: ds
27 Devices: [Data Translation] DT3001 (dt3000), DT3001-PGL, DT3002, DT3003,
28 DT3003-PGL, DT3004, DT3005, DT3004-200
29 Updated: Mon, 14 Apr 2008 15:41:24 +0100
30 Status: works
31
32 Configuration Options:
33 [0] - PCI bus of device (optional)
34 [1] - PCI slot of device (optional)
35 If bus/slot is not specified, the first supported
36 PCI device found will be used.
37
38 There is code to support AI commands, but it may not work.
39
40 AO commands are not supported.
41 */
42
43 /*
44 The DT3000 series is Data Translation's attempt to make a PCI
45 data acquisition board. The design of this series is very nice,
46 since each board has an on-board DSP (Texas Instruments TMS320C52).
47 However, a few details are a little annoying. The boards lack
48 bus-mastering DMA, which eliminates them from serious work.
49 They also are not capable of autocalibration, which is a common
50 feature in modern hardware. The default firmware is pretty bad,
51 making it nearly impossible to write an RT compatible driver.
52 It would make an interesting project to write a decent firmware
53 for these boards.
54
55 Data Translation originally wanted an NDA for the documentation
56 for the 3k series. However, if you ask nicely, they might send
57 you the docs without one, also.
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_fc.h"
67
68 #define PCI_VENDOR_ID_DT 0x1116
69
70 static 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
78 static 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
86 struct 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
98 static 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", /* a.k.a. 3004-200 */
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 this_board ((const struct dt3k_boardtype *)dev->board_ptr)
165
166 #define DT3000_SIZE (4*0x1000)
167
168 /* dual-ported RAM location definitions */
169
170 #define DPR_DAC_buffer (4*0x000)
171 #define DPR_ADC_buffer (4*0x800)
172 #define DPR_Command (4*0xfd3)
173 #define DPR_SubSys (4*0xfd3)
174 #define DPR_Encode (4*0xfd4)
175 #define DPR_Params(a) (4*(0xfd5+(a)))
176 #define DPR_Tick_Reg_Lo (4*0xff5)
177 #define DPR_Tick_Reg_Hi (4*0xff6)
178 #define DPR_DA_Buf_Front (4*0xff7)
179 #define DPR_DA_Buf_Rear (4*0xff8)
180 #define DPR_AD_Buf_Front (4*0xff9)
181 #define DPR_AD_Buf_Rear (4*0xffa)
182 #define DPR_Int_Mask (4*0xffb)
183 #define DPR_Intr_Flag (4*0xffc)
184 #define DPR_Response_Mbx (4*0xffe)
185 #define DPR_Command_Mbx (4*0xfff)
186
187 #define AI_FIFO_DEPTH 2003
188 #define AO_FIFO_DEPTH 2048
189
190 /* command list */
191
192 #define CMD_GETBRDINFO 0
193 #define CMD_CONFIG 1
194 #define CMD_GETCONFIG 2
195 #define CMD_START 3
196 #define CMD_STOP 4
197 #define CMD_READSINGLE 5
198 #define CMD_WRITESINGLE 6
199 #define CMD_CALCCLOCK 7
200 #define CMD_READEVENTS 8
201 #define CMD_WRITECTCTRL 16
202 #define CMD_READCTCTRL 17
203 #define CMD_WRITECT 18
204 #define CMD_READCT 19
205 #define CMD_WRITEDATA 32
206 #define CMD_READDATA 33
207 #define CMD_WRITEIO 34
208 #define CMD_READIO 35
209 #define CMD_WRITECODE 36
210 #define CMD_READCODE 37
211 #define CMD_EXECUTE 38
212 #define CMD_HALT 48
213
214 #define SUBS_AI 0
215 #define SUBS_AO 1
216 #define SUBS_DIN 2
217 #define SUBS_DOUT 3
218 #define SUBS_MEM 4
219 #define SUBS_CT 5
220
221 /* interrupt flags */
222 #define DT3000_CMDONE 0x80
223 #define DT3000_CTDONE 0x40
224 #define DT3000_DAHWERR 0x20
225 #define DT3000_DASWERR 0x10
226 #define DT3000_DAEMPTY 0x08
227 #define DT3000_ADHWERR 0x04
228 #define DT3000_ADSWERR 0x02
229 #define DT3000_ADFULL 0x01
230
231 #define DT3000_COMPLETION_MASK 0xff00
232 #define DT3000_COMMAND_MASK 0x00ff
233 #define DT3000_NOTPROCESSED 0x0000
234 #define DT3000_NOERROR 0x5500
235 #define DT3000_ERROR 0xaa00
236 #define DT3000_NOTSUPPORTED 0xff00
237
238 #define DT3000_EXTERNAL_CLOCK 1
239 #define DT3000_RISING_EDGE 2
240
241 #define TMODE_MASK 0x1c
242
243 #define DT3000_AD_TRIG_INTERNAL (0<<2)
244 #define DT3000_AD_TRIG_EXTERNAL (1<<2)
245 #define DT3000_AD_RETRIG_INTERNAL (2<<2)
246 #define DT3000_AD_RETRIG_EXTERNAL (3<<2)
247 #define DT3000_AD_EXTRETRIG (4<<2)
248
249 #define DT3000_CHANNEL_MODE_SE 0
250 #define DT3000_CHANNEL_MODE_DI 1
251
252 struct dt3k_private {
253 void __iomem *io_addr;
254 unsigned int lock;
255 unsigned int ao_readback[2];
256 unsigned int ai_front;
257 unsigned int ai_rear;
258 };
259
260 static void dt3k_ai_empty_fifo(struct comedi_device *dev,
261 struct comedi_subdevice *s);
262 static int dt3k_ns_to_timer(unsigned int timer_base, unsigned int *arg,
263 unsigned int round_mode);
264 static int dt3k_ai_cancel(struct comedi_device *dev,
265 struct comedi_subdevice *s);
266 #ifdef DEBUG
267 static void debug_intr_flags(unsigned int flags);
268 #endif
269
270 #define TIMEOUT 100
271
272 static int dt3k_send_cmd(struct comedi_device *dev, unsigned int cmd)
273 {
274 struct dt3k_private *devpriv = dev->private;
275 int i;
276 unsigned int status = 0;
277
278 writew(cmd, devpriv->io_addr + DPR_Command_Mbx);
279
280 for (i = 0; i < TIMEOUT; i++) {
281 status = readw(devpriv->io_addr + DPR_Command_Mbx);
282 if ((status & DT3000_COMPLETION_MASK) != DT3000_NOTPROCESSED)
283 break;
284 udelay(1);
285 }
286 if ((status & DT3000_COMPLETION_MASK) == DT3000_NOERROR)
287 return 0;
288
289 dev_dbg(dev->class_dev, "dt3k_send_cmd() timeout/error status=0x%04x\n",
290 status);
291
292 return -ETIME;
293 }
294
295 static unsigned int dt3k_readsingle(struct comedi_device *dev,
296 unsigned int subsys, unsigned int chan,
297 unsigned int gain)
298 {
299 struct dt3k_private *devpriv = dev->private;
300
301 writew(subsys, devpriv->io_addr + DPR_SubSys);
302
303 writew(chan, devpriv->io_addr + DPR_Params(0));
304 writew(gain, devpriv->io_addr + DPR_Params(1));
305
306 dt3k_send_cmd(dev, CMD_READSINGLE);
307
308 return readw(devpriv->io_addr + DPR_Params(2));
309 }
310
311 static void dt3k_writesingle(struct comedi_device *dev, unsigned int subsys,
312 unsigned int chan, unsigned int data)
313 {
314 struct dt3k_private *devpriv = dev->private;
315
316 writew(subsys, devpriv->io_addr + DPR_SubSys);
317
318 writew(chan, devpriv->io_addr + DPR_Params(0));
319 writew(0, devpriv->io_addr + DPR_Params(1));
320 writew(data, devpriv->io_addr + DPR_Params(2));
321
322 dt3k_send_cmd(dev, CMD_WRITESINGLE);
323 }
324
325 static int debug_n_ints;
326
327 /* FIXME! Assumes shared interrupt is for this card. */
328 /* What's this debug_n_ints stuff? Obviously needs some work... */
329 static irqreturn_t dt3k_interrupt(int irq, void *d)
330 {
331 struct comedi_device *dev = d;
332 struct dt3k_private *devpriv = dev->private;
333 struct comedi_subdevice *s;
334 unsigned int status;
335
336 if (!dev->attached)
337 return IRQ_NONE;
338
339 s = &dev->subdevices[0];
340 status = readw(devpriv->io_addr + DPR_Intr_Flag);
341 #ifdef DEBUG
342 debug_intr_flags(status);
343 #endif
344
345 if (status & DT3000_ADFULL) {
346 dt3k_ai_empty_fifo(dev, s);
347 s->async->events |= COMEDI_CB_BLOCK;
348 }
349
350 if (status & (DT3000_ADSWERR | DT3000_ADHWERR))
351 s->async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
352
353 debug_n_ints++;
354 if (debug_n_ints >= 10) {
355 dt3k_ai_cancel(dev, s);
356 s->async->events |= COMEDI_CB_EOA;
357 }
358
359 comedi_event(dev, s);
360 return IRQ_HANDLED;
361 }
362
363 #ifdef DEBUG
364 static char *intr_flags[] = {
365 "AdFull", "AdSwError", "AdHwError", "DaEmpty",
366 "DaSwError", "DaHwError", "CtDone", "CmDone",
367 };
368
369 static void debug_intr_flags(unsigned int flags)
370 {
371 int i;
372 printk(KERN_DEBUG "dt3k: intr_flags:");
373 for (i = 0; i < 8; i++) {
374 if (flags & (1 << i))
375 printk(KERN_CONT " %s", intr_flags[i]);
376 }
377 printk(KERN_CONT "\n");
378 }
379 #endif
380
381 static void dt3k_ai_empty_fifo(struct comedi_device *dev,
382 struct comedi_subdevice *s)
383 {
384 struct dt3k_private *devpriv = dev->private;
385 int front;
386 int rear;
387 int count;
388 int i;
389 short data;
390
391 front = readw(devpriv->io_addr + DPR_AD_Buf_Front);
392 count = front - devpriv->ai_front;
393 if (count < 0)
394 count += AI_FIFO_DEPTH;
395
396 dev_dbg(dev->class_dev, "reading %d samples\n", count);
397
398 rear = devpriv->ai_rear;
399
400 for (i = 0; i < count; i++) {
401 data = readw(devpriv->io_addr + DPR_ADC_buffer + rear);
402 comedi_buf_put(s->async, data);
403 rear++;
404 if (rear >= AI_FIFO_DEPTH)
405 rear = 0;
406 }
407
408 devpriv->ai_rear = rear;
409 writew(rear, devpriv->io_addr + DPR_AD_Buf_Rear);
410 }
411
412 static int dt3k_ai_cmdtest(struct comedi_device *dev,
413 struct comedi_subdevice *s, struct comedi_cmd *cmd)
414 {
415 int err = 0;
416 int tmp;
417
418 /* Step 1 : check if triggers are trivially valid */
419
420 err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW);
421 err |= cfc_check_trigger_src(&cmd->scan_begin_src, TRIG_TIMER);
422 err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_TIMER);
423 err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
424 err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT);
425
426 if (err)
427 return 1;
428
429 /* Step 2a : make sure trigger sources are unique */
430 /* Step 2b : and mutually compatible */
431
432 if (err)
433 return 2;
434
435 /* step 3: make sure arguments are trivially compatible */
436
437 if (cmd->start_arg != 0) {
438 cmd->start_arg = 0;
439 err++;
440 }
441
442 if (cmd->scan_begin_src == TRIG_TIMER) {
443 if (cmd->scan_begin_arg < this_board->ai_speed) {
444 cmd->scan_begin_arg = this_board->ai_speed;
445 err++;
446 }
447 if (cmd->scan_begin_arg > 100 * 16 * 65535) {
448 cmd->scan_begin_arg = 100 * 16 * 65535;
449 err++;
450 }
451 } else {
452 /* not supported */
453 }
454 if (cmd->convert_src == TRIG_TIMER) {
455 if (cmd->convert_arg < this_board->ai_speed) {
456 cmd->convert_arg = this_board->ai_speed;
457 err++;
458 }
459 if (cmd->convert_arg > 50 * 16 * 65535) {
460 cmd->convert_arg = 50 * 16 * 65535;
461 err++;
462 }
463 } else {
464 /* not supported */
465 }
466
467 if (cmd->scan_end_arg != cmd->chanlist_len) {
468 cmd->scan_end_arg = cmd->chanlist_len;
469 err++;
470 }
471 if (cmd->stop_src == TRIG_COUNT) {
472 if (cmd->stop_arg > 0x00ffffff) {
473 cmd->stop_arg = 0x00ffffff;
474 err++;
475 }
476 } else {
477 /* TRIG_NONE */
478 if (cmd->stop_arg != 0) {
479 cmd->stop_arg = 0;
480 err++;
481 }
482 }
483
484 if (err)
485 return 3;
486
487 /* step 4: fix up any arguments */
488
489 if (cmd->scan_begin_src == TRIG_TIMER) {
490 tmp = cmd->scan_begin_arg;
491 dt3k_ns_to_timer(100, &cmd->scan_begin_arg,
492 cmd->flags & TRIG_ROUND_MASK);
493 if (tmp != cmd->scan_begin_arg)
494 err++;
495 } else {
496 /* not supported */
497 }
498 if (cmd->convert_src == TRIG_TIMER) {
499 tmp = cmd->convert_arg;
500 dt3k_ns_to_timer(50, &cmd->convert_arg,
501 cmd->flags & TRIG_ROUND_MASK);
502 if (tmp != cmd->convert_arg)
503 err++;
504 if (cmd->scan_begin_src == TRIG_TIMER &&
505 cmd->scan_begin_arg <
506 cmd->convert_arg * cmd->scan_end_arg) {
507 cmd->scan_begin_arg =
508 cmd->convert_arg * cmd->scan_end_arg;
509 err++;
510 }
511 } else {
512 /* not supported */
513 }
514
515 if (err)
516 return 4;
517
518 return 0;
519 }
520
521 static int dt3k_ns_to_timer(unsigned int timer_base, unsigned int *nanosec,
522 unsigned int round_mode)
523 {
524 int divider, base, prescale;
525
526 /* This function needs improvment */
527 /* Don't know if divider==0 works. */
528
529 for (prescale = 0; prescale < 16; prescale++) {
530 base = timer_base * (prescale + 1);
531 switch (round_mode) {
532 case TRIG_ROUND_NEAREST:
533 default:
534 divider = (*nanosec + base / 2) / base;
535 break;
536 case TRIG_ROUND_DOWN:
537 divider = (*nanosec) / base;
538 break;
539 case TRIG_ROUND_UP:
540 divider = (*nanosec) / base;
541 break;
542 }
543 if (divider < 65536) {
544 *nanosec = divider * base;
545 return (prescale << 16) | (divider);
546 }
547 }
548
549 prescale = 15;
550 base = timer_base * (1 << prescale);
551 divider = 65535;
552 *nanosec = divider * base;
553 return (prescale << 16) | (divider);
554 }
555
556 static int dt3k_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
557 {
558 struct dt3k_private *devpriv = dev->private;
559 struct comedi_cmd *cmd = &s->async->cmd;
560 int i;
561 unsigned int chan, range, aref;
562 unsigned int divider;
563 unsigned int tscandiv;
564 int ret;
565 unsigned int mode;
566
567 dev_dbg(dev->class_dev, "dt3k_ai_cmd:\n");
568 for (i = 0; i < cmd->chanlist_len; i++) {
569 chan = CR_CHAN(cmd->chanlist[i]);
570 range = CR_RANGE(cmd->chanlist[i]);
571
572 writew((range << 6) | chan,
573 devpriv->io_addr + DPR_ADC_buffer + i);
574 }
575 aref = CR_AREF(cmd->chanlist[0]);
576
577 writew(cmd->scan_end_arg, devpriv->io_addr + DPR_Params(0));
578 dev_dbg(dev->class_dev, "param[0]=0x%04x\n", cmd->scan_end_arg);
579
580 if (cmd->convert_src == TRIG_TIMER) {
581 divider = dt3k_ns_to_timer(50, &cmd->convert_arg,
582 cmd->flags & TRIG_ROUND_MASK);
583 writew((divider >> 16), devpriv->io_addr + DPR_Params(1));
584 dev_dbg(dev->class_dev, "param[1]=0x%04x\n", divider >> 16);
585 writew((divider & 0xffff), devpriv->io_addr + DPR_Params(2));
586 dev_dbg(dev->class_dev, "param[2]=0x%04x\n", divider & 0xffff);
587 } else {
588 /* not supported */
589 }
590
591 if (cmd->scan_begin_src == TRIG_TIMER) {
592 tscandiv = dt3k_ns_to_timer(100, &cmd->scan_begin_arg,
593 cmd->flags & TRIG_ROUND_MASK);
594 writew((tscandiv >> 16), devpriv->io_addr + DPR_Params(3));
595 dev_dbg(dev->class_dev, "param[3]=0x%04x\n", tscandiv >> 16);
596 writew((tscandiv & 0xffff), devpriv->io_addr + DPR_Params(4));
597 dev_dbg(dev->class_dev, "param[4]=0x%04x\n", tscandiv & 0xffff);
598 } else {
599 /* not supported */
600 }
601
602 mode = DT3000_AD_RETRIG_INTERNAL | 0 | 0;
603 writew(mode, devpriv->io_addr + DPR_Params(5));
604 dev_dbg(dev->class_dev, "param[5]=0x%04x\n", mode);
605 writew(aref == AREF_DIFF, devpriv->io_addr + DPR_Params(6));
606 dev_dbg(dev->class_dev, "param[6]=0x%04x\n", aref == AREF_DIFF);
607
608 writew(AI_FIFO_DEPTH / 2, devpriv->io_addr + DPR_Params(7));
609 dev_dbg(dev->class_dev, "param[7]=0x%04x\n", AI_FIFO_DEPTH / 2);
610
611 writew(SUBS_AI, devpriv->io_addr + DPR_SubSys);
612 ret = dt3k_send_cmd(dev, CMD_CONFIG);
613
614 writew(DT3000_ADFULL | DT3000_ADSWERR | DT3000_ADHWERR,
615 devpriv->io_addr + DPR_Int_Mask);
616
617 debug_n_ints = 0;
618
619 writew(SUBS_AI, devpriv->io_addr + DPR_SubSys);
620 ret = dt3k_send_cmd(dev, CMD_START);
621
622 return 0;
623 }
624
625 static int dt3k_ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
626 {
627 struct dt3k_private *devpriv = dev->private;
628 int ret;
629
630 writew(SUBS_AI, devpriv->io_addr + DPR_SubSys);
631 ret = dt3k_send_cmd(dev, CMD_STOP);
632
633 writew(0, devpriv->io_addr + DPR_Int_Mask);
634
635 return 0;
636 }
637
638 static int dt3k_ai_insn(struct comedi_device *dev, struct comedi_subdevice *s,
639 struct comedi_insn *insn, unsigned int *data)
640 {
641 int i;
642 unsigned int chan, gain, aref;
643
644 chan = CR_CHAN(insn->chanspec);
645 gain = CR_RANGE(insn->chanspec);
646 /* XXX docs don't explain how to select aref */
647 aref = CR_AREF(insn->chanspec);
648
649 for (i = 0; i < insn->n; i++)
650 data[i] = dt3k_readsingle(dev, SUBS_AI, chan, gain);
651
652 return i;
653 }
654
655 static int dt3k_ao_insn(struct comedi_device *dev, struct comedi_subdevice *s,
656 struct comedi_insn *insn, unsigned int *data)
657 {
658 struct dt3k_private *devpriv = dev->private;
659 int i;
660 unsigned int chan;
661
662 chan = CR_CHAN(insn->chanspec);
663 for (i = 0; i < insn->n; i++) {
664 dt3k_writesingle(dev, SUBS_AO, chan, data[i]);
665 devpriv->ao_readback[chan] = data[i];
666 }
667
668 return i;
669 }
670
671 static int dt3k_ao_insn_read(struct comedi_device *dev,
672 struct comedi_subdevice *s,
673 struct comedi_insn *insn, unsigned int *data)
674 {
675 struct dt3k_private *devpriv = dev->private;
676 int i;
677 unsigned int chan;
678
679 chan = CR_CHAN(insn->chanspec);
680 for (i = 0; i < insn->n; i++)
681 data[i] = devpriv->ao_readback[chan];
682
683 return i;
684 }
685
686 static void dt3k_dio_config(struct comedi_device *dev, int bits)
687 {
688 struct dt3k_private *devpriv = dev->private;
689
690 /* XXX */
691 writew(SUBS_DOUT, devpriv->io_addr + DPR_SubSys);
692
693 writew(bits, devpriv->io_addr + DPR_Params(0));
694 #if 0
695 /* don't know */
696 writew(0, devpriv->io_addr + DPR_Params(1));
697 writew(0, devpriv->io_addr + DPR_Params(2));
698 #endif
699
700 dt3k_send_cmd(dev, CMD_CONFIG);
701 }
702
703 static int dt3k_dio_insn_config(struct comedi_device *dev,
704 struct comedi_subdevice *s,
705 struct comedi_insn *insn, unsigned int *data)
706 {
707 int mask;
708
709 mask = (CR_CHAN(insn->chanspec) < 4) ? 0x0f : 0xf0;
710
711 switch (data[0]) {
712 case INSN_CONFIG_DIO_OUTPUT:
713 s->io_bits |= mask;
714 break;
715 case INSN_CONFIG_DIO_INPUT:
716 s->io_bits &= ~mask;
717 break;
718 case INSN_CONFIG_DIO_QUERY:
719 data[1] =
720 (s->
721 io_bits & (1 << CR_CHAN(insn->chanspec))) ? COMEDI_OUTPUT :
722 COMEDI_INPUT;
723 return insn->n;
724 break;
725 default:
726 return -EINVAL;
727 break;
728 }
729 mask = (s->io_bits & 0x01) | ((s->io_bits & 0x10) >> 3);
730 dt3k_dio_config(dev, mask);
731
732 return insn->n;
733 }
734
735 static int dt3k_dio_insn_bits(struct comedi_device *dev,
736 struct comedi_subdevice *s,
737 struct comedi_insn *insn, unsigned int *data)
738 {
739 if (data[0]) {
740 s->state &= ~data[0];
741 s->state |= data[1] & data[0];
742 dt3k_writesingle(dev, SUBS_DOUT, 0, s->state);
743 }
744 data[1] = dt3k_readsingle(dev, SUBS_DIN, 0, 0);
745
746 return insn->n;
747 }
748
749 static int dt3k_mem_insn_read(struct comedi_device *dev,
750 struct comedi_subdevice *s,
751 struct comedi_insn *insn, unsigned int *data)
752 {
753 struct dt3k_private *devpriv = dev->private;
754 unsigned int addr = CR_CHAN(insn->chanspec);
755 int i;
756
757 for (i = 0; i < insn->n; i++) {
758 writew(SUBS_MEM, devpriv->io_addr + DPR_SubSys);
759 writew(addr, devpriv->io_addr + DPR_Params(0));
760 writew(1, devpriv->io_addr + DPR_Params(1));
761
762 dt3k_send_cmd(dev, CMD_READCODE);
763
764 data[i] = readw(devpriv->io_addr + DPR_Params(2));
765 }
766
767 return i;
768 }
769
770 static struct pci_dev *dt3000_find_pci_dev(struct comedi_device *dev,
771 struct comedi_devconfig *it)
772 {
773 struct pci_dev *pcidev = NULL;
774 int bus = it->options[0];
775 int slot = it->options[1];
776 int i;
777
778 for_each_pci_dev(pcidev) {
779 if (bus || slot) {
780 if (bus != pcidev->bus->number ||
781 slot != PCI_SLOT(pcidev->devfn))
782 continue;
783 }
784 if (pcidev->vendor != PCI_VENDOR_ID_DT)
785 continue;
786 for (i = 0; i < ARRAY_SIZE(dt3k_boardtypes); i++) {
787 if (dt3k_boardtypes[i].device_id != pcidev->device)
788 continue;
789 dev->board_ptr = dt3k_boardtypes + i;
790 return pcidev;
791 }
792 }
793 dev_err(dev->class_dev,
794 "No supported board found! (req. bus %d, slot %d)\n",
795 bus, slot);
796 return NULL;
797 }
798
799 static int dt3000_attach(struct comedi_device *dev, struct comedi_devconfig *it)
800 {
801 struct dt3k_private *devpriv;
802 struct pci_dev *pcidev;
803 struct comedi_subdevice *s;
804 resource_size_t pci_base;
805 int ret = 0;
806
807 dev_dbg(dev->class_dev, "dt3000:\n");
808
809 ret = alloc_private(dev, sizeof(*devpriv));
810 if (ret)
811 return ret;
812 devpriv = dev->private;
813
814 pcidev = dt3000_find_pci_dev(dev, it);
815 if (!pcidev)
816 return -EIO;
817 comedi_set_hw_dev(dev, &pcidev->dev);
818
819 ret = comedi_pci_enable(pcidev, "dt3000");
820 if (ret < 0)
821 return ret;
822 dev->iobase = 1; /* the "detach" needs this */
823
824 pci_base = pci_resource_start(pcidev, 0);
825 devpriv->io_addr = ioremap(pci_base, DT3000_SIZE);
826 if (!devpriv->io_addr)
827 return -ENOMEM;
828
829 dev->board_name = this_board->name;
830
831 if (request_irq(pcidev->irq, dt3k_interrupt, IRQF_SHARED,
832 "dt3000", dev)) {
833 dev_err(dev->class_dev, "unable to allocate IRQ %u\n",
834 pcidev->irq);
835 return -EINVAL;
836 }
837 dev->irq = pcidev->irq;
838
839 ret = comedi_alloc_subdevices(dev, 4);
840 if (ret)
841 return ret;
842
843 s = &dev->subdevices[0];
844 dev->read_subdev = s;
845
846 /* ai subdevice */
847 s->type = COMEDI_SUBD_AI;
848 s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_DIFF | SDF_CMD_READ;
849 s->n_chan = this_board->adchan;
850 s->insn_read = dt3k_ai_insn;
851 s->maxdata = (1 << this_board->adbits) - 1;
852 s->len_chanlist = 512;
853 s->range_table = &range_dt3000_ai; /* XXX */
854 s->do_cmd = dt3k_ai_cmd;
855 s->do_cmdtest = dt3k_ai_cmdtest;
856 s->cancel = dt3k_ai_cancel;
857
858 s = &dev->subdevices[1];
859 /* ao subsystem */
860 s->type = COMEDI_SUBD_AO;
861 s->subdev_flags = SDF_WRITABLE;
862 s->n_chan = 2;
863 s->insn_read = dt3k_ao_insn_read;
864 s->insn_write = dt3k_ao_insn;
865 s->maxdata = (1 << this_board->dabits) - 1;
866 s->len_chanlist = 1;
867 s->range_table = &range_bipolar10;
868
869 s = &dev->subdevices[2];
870 /* dio subsystem */
871 s->type = COMEDI_SUBD_DIO;
872 s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
873 s->n_chan = 8;
874 s->insn_config = dt3k_dio_insn_config;
875 s->insn_bits = dt3k_dio_insn_bits;
876 s->maxdata = 1;
877 s->len_chanlist = 8;
878 s->range_table = &range_digital;
879
880 s = &dev->subdevices[3];
881 /* mem subsystem */
882 s->type = COMEDI_SUBD_MEMORY;
883 s->subdev_flags = SDF_READABLE;
884 s->n_chan = 0x1000;
885 s->insn_read = dt3k_mem_insn_read;
886 s->maxdata = 0xff;
887 s->len_chanlist = 1;
888 s->range_table = &range_unknown;
889
890 #if 0
891 s = &dev->subdevices[4];
892 /* proc subsystem */
893 s->type = COMEDI_SUBD_PROC;
894 #endif
895
896 return 0;
897 }
898
899 static void dt3000_detach(struct comedi_device *dev)
900 {
901 struct pci_dev *pcidev = comedi_to_pci_dev(dev);
902 struct dt3k_private *devpriv = dev->private;
903
904 if (dev->irq)
905 free_irq(dev->irq, dev);
906 if (devpriv) {
907 if (devpriv->io_addr)
908 iounmap(devpriv->io_addr);
909 }
910 if (pcidev) {
911 if (dev->iobase)
912 comedi_pci_disable(pcidev);
913 pci_dev_put(pcidev);
914 }
915 }
916
917 static struct comedi_driver dt3000_driver = {
918 .driver_name = "dt3000",
919 .module = THIS_MODULE,
920 .attach = dt3000_attach,
921 .detach = dt3000_detach,
922 };
923
924 static int __devinit dt3000_pci_probe(struct pci_dev *dev,
925 const struct pci_device_id *ent)
926 {
927 return comedi_pci_auto_config(dev, &dt3000_driver);
928 }
929
930 static void __devexit dt3000_pci_remove(struct pci_dev *dev)
931 {
932 comedi_pci_auto_unconfig(dev);
933 }
934
935 static DEFINE_PCI_DEVICE_TABLE(dt3000_pci_table) = {
936 { PCI_DEVICE(PCI_VENDOR_ID_DT, 0x0022) },
937 { PCI_DEVICE(PCI_VENDOR_ID_DT, 0x0027) },
938 { PCI_DEVICE(PCI_VENDOR_ID_DT, 0x0023) },
939 { PCI_DEVICE(PCI_VENDOR_ID_DT, 0x0024) },
940 { PCI_DEVICE(PCI_VENDOR_ID_DT, 0x0028) },
941 { PCI_DEVICE(PCI_VENDOR_ID_DT, 0x0025) },
942 { PCI_DEVICE(PCI_VENDOR_ID_DT, 0x0026) },
943 { 0 }
944 };
945 MODULE_DEVICE_TABLE(pci, dt3000_pci_table);
946
947 static struct pci_driver dt3000_pci_driver = {
948 .name = "dt3000",
949 .id_table = dt3000_pci_table,
950 .probe = dt3000_pci_probe,
951 .remove = __devexit_p(dt3000_pci_remove),
952 };
953 module_comedi_pci_driver(dt3000_driver, dt3000_pci_driver);
954
955 MODULE_AUTHOR("Comedi http://www.comedi.org");
956 MODULE_DESCRIPTION("Comedi low-level driver");
957 MODULE_LICENSE("GPL");
This page took 0.055481 seconds and 6 git commands to generate.