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