2 comedi/drivers/dt3000.c
3 Data Translation DT3000 series driver
5 COMEDI - Linux Control and Measurement Device Interface
6 Copyright (C) 1999 David A. Schleef <ds@schleef.org>
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.
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.
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.
25 Description: Data Translation DT3000 series
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
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.
38 There is code to support AI commands, but it may not work.
40 AO commands are not supported.
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
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.
62 #include <linux/interrupt.h>
63 #include "../comedidev.h"
64 #include <linux/delay.h>
66 #include "comedi_pci.h"
68 #define PCI_VENDOR_ID_DT 0x1116
70 static const struct comedi_lrange range_dt3000_ai = { 4, {
78 static const struct comedi_lrange range_dt3000_ai_pgl = { 4, {
86 struct dt3k_boardtype {
89 unsigned int device_id;
93 const struct comedi_lrange *adrange;
98 static const struct dt3k_boardtype dt3k_boardtypes[] = {
103 .adrange = &range_dt3000_ai,
108 {.name = "dt3001-pgl",
112 .adrange = &range_dt3000_ai_pgl,
121 .adrange = &range_dt3000_ai,
130 .adrange = &range_dt3000_ai,
135 {.name = "dt3003-pgl",
139 .adrange = &range_dt3000_ai_pgl,
148 .adrange = &range_dt3000_ai,
153 {.name = "dt3005", /* a.k.a. 3004-200 */
157 .adrange = &range_dt3000_ai,
164 #define n_dt3k_boards sizeof(dt3k_boardtypes)/sizeof(struct dt3k_boardtype)
165 #define this_board ((const struct dt3k_boardtype *)dev->board_ptr)
167 static DEFINE_PCI_DEVICE_TABLE(dt3k_pci_table) = {
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) },
178 MODULE_DEVICE_TABLE(pci, dt3k_pci_table);
180 #define DT3000_SIZE (4*0x1000)
182 /* dual-ported RAM location definitions */
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)
201 #define AI_FIFO_DEPTH 2003
202 #define AO_FIFO_DEPTH 2048
206 #define CMD_GETBRDINFO 0
208 #define CMD_GETCONFIG 2
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
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
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
252 #define DT3000_EXTERNAL_CLOCK 1
253 #define DT3000_RISING_EDGE 2
255 #define TMODE_MASK 0x1c
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)
263 #define DT3000_CHANNEL_MODE_SE 0
264 #define DT3000_CHANNEL_MODE_DI 1
266 struct dt3k_private {
268 struct pci_dev *pci_dev;
269 resource_size_t phys_addr;
272 unsigned int ao_readback[2];
273 unsigned int ai_front;
274 unsigned int ai_rear;
277 #define devpriv ((struct dt3k_private *)dev->private)
279 static int dt3000_attach(struct comedi_device *dev,
280 struct comedi_devconfig *it);
281 static int dt3000_detach(struct comedi_device *dev);
282 static struct comedi_driver driver_dt3000 = {
283 .driver_name = "dt3000",
284 .module = THIS_MODULE,
285 .attach = dt3000_attach,
286 .detach = dt3000_detach,
289 static int __devinit driver_dt3000_pci_probe(struct pci_dev *dev,
290 const struct pci_device_id *ent)
292 return comedi_pci_auto_config(dev, driver_dt3000.driver_name);
295 static void __devexit driver_dt3000_pci_remove(struct pci_dev *dev)
297 comedi_pci_auto_unconfig(dev);
300 static 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)
306 static int __init driver_dt3000_init_module(void)
310 retval = comedi_driver_register(&driver_dt3000);
314 driver_dt3000_pci_driver.name = (char *)driver_dt3000.driver_name;
315 return pci_register_driver(&driver_dt3000_pci_driver);
318 static void __exit driver_dt3000_cleanup_module(void)
320 pci_unregister_driver(&driver_dt3000_pci_driver);
321 comedi_driver_unregister(&driver_dt3000);
324 module_init(driver_dt3000_init_module);
325 module_exit(driver_dt3000_cleanup_module);
327 static void dt3k_ai_empty_fifo(struct comedi_device *dev,
328 struct comedi_subdevice *s);
329 static int dt3k_ns_to_timer(unsigned int timer_base, unsigned int *arg,
330 unsigned int round_mode);
331 static int dt3k_ai_cancel(struct comedi_device *dev,
332 struct comedi_subdevice *s);
334 static void debug_intr_flags(unsigned int flags);
339 static int dt3k_send_cmd(struct comedi_device *dev, unsigned int cmd)
342 unsigned int status = 0;
344 writew(cmd, devpriv->io_addr + DPR_Command_Mbx);
346 for (i = 0; i < TIMEOUT; i++) {
347 status = readw(devpriv->io_addr + DPR_Command_Mbx);
348 if ((status & DT3000_COMPLETION_MASK) != DT3000_NOTPROCESSED)
352 if ((status & DT3000_COMPLETION_MASK) == DT3000_NOERROR)
355 printk("dt3k_send_cmd() timeout/error status=0x%04x\n", status);
360 static unsigned int dt3k_readsingle(struct comedi_device *dev,
361 unsigned int subsys, unsigned int chan,
364 writew(subsys, devpriv->io_addr + DPR_SubSys);
366 writew(chan, devpriv->io_addr + DPR_Params(0));
367 writew(gain, devpriv->io_addr + DPR_Params(1));
369 dt3k_send_cmd(dev, CMD_READSINGLE);
371 return readw(devpriv->io_addr + DPR_Params(2));
374 static void dt3k_writesingle(struct comedi_device *dev, unsigned int subsys,
375 unsigned int chan, unsigned int data)
377 writew(subsys, devpriv->io_addr + DPR_SubSys);
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));
383 dt3k_send_cmd(dev, CMD_WRITESINGLE);
386 static int debug_n_ints = 0;
388 /* FIXME! Assumes shared interrupt is for this card. */
389 /* What's this debug_n_ints stuff? Obviously needs some work... */
390 static irqreturn_t dt3k_interrupt(int irq, void *d)
392 struct comedi_device *dev = d;
393 struct comedi_subdevice *s;
399 s = dev->subdevices + 0;
400 status = readw(devpriv->io_addr + DPR_Intr_Flag);
402 debug_intr_flags(status);
405 if (status & DT3000_ADFULL) {
406 dt3k_ai_empty_fifo(dev, s);
407 s->async->events |= COMEDI_CB_BLOCK;
410 if (status & (DT3000_ADSWERR | DT3000_ADHWERR))
411 s->async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
414 if (debug_n_ints >= 10) {
415 dt3k_ai_cancel(dev, s);
416 s->async->events |= COMEDI_CB_EOA;
419 comedi_event(dev, s);
424 static char *intr_flags[] = {
425 "AdFull", "AdSwError", "AdHwError", "DaEmpty",
426 "DaSwError", "DaHwError", "CtDone", "CmDone",
429 static void debug_intr_flags(unsigned int flags)
432 printk("dt3k: intr_flags:");
433 for (i = 0; i < 8; i++) {
434 if (flags & (1 << i))
435 printk(" %s", intr_flags[i]);
441 static void dt3k_ai_empty_fifo(struct comedi_device *dev,
442 struct comedi_subdevice *s)
450 front = readw(devpriv->io_addr + DPR_AD_Buf_Front);
451 count = front - devpriv->ai_front;
453 count += AI_FIFO_DEPTH;
455 printk("reading %d samples\n", count);
457 rear = devpriv->ai_rear;
459 for (i = 0; i < count; i++) {
460 data = readw(devpriv->io_addr + DPR_ADC_buffer + rear);
461 comedi_buf_put(s->async, data);
463 if (rear >= AI_FIFO_DEPTH)
467 devpriv->ai_rear = rear;
468 writew(rear, devpriv->io_addr + DPR_AD_Buf_Rear);
471 static int dt3k_ai_cmdtest(struct comedi_device *dev,
472 struct comedi_subdevice *s, struct comedi_cmd *cmd)
477 /* step 1: make sure trigger sources are trivially valid */
479 tmp = cmd->start_src;
480 cmd->start_src &= TRIG_NOW;
481 if (!cmd->start_src || tmp != cmd->start_src)
484 tmp = cmd->scan_begin_src;
485 cmd->scan_begin_src &= TRIG_TIMER;
486 if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
489 tmp = cmd->convert_src;
490 cmd->convert_src &= TRIG_TIMER;
491 if (!cmd->convert_src || tmp != cmd->convert_src)
494 tmp = cmd->scan_end_src;
495 cmd->scan_end_src &= TRIG_COUNT;
496 if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
500 cmd->stop_src &= TRIG_COUNT;
501 if (!cmd->stop_src || tmp != cmd->stop_src)
507 /* step 2: make sure trigger sources are unique and mutually compatible */
512 /* step 3: make sure arguments are trivially compatible */
514 if (cmd->start_arg != 0) {
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;
524 if (cmd->scan_begin_arg > 100 * 16 * 65535) {
525 cmd->scan_begin_arg = 100 * 16 * 65535;
531 if (cmd->convert_src == TRIG_TIMER) {
532 if (cmd->convert_arg < this_board->ai_speed) {
533 cmd->convert_arg = this_board->ai_speed;
536 if (cmd->convert_arg > 50 * 16 * 65535) {
537 cmd->convert_arg = 50 * 16 * 65535;
544 if (cmd->scan_end_arg != cmd->chanlist_len) {
545 cmd->scan_end_arg = cmd->chanlist_len;
548 if (cmd->stop_src == TRIG_COUNT) {
549 if (cmd->stop_arg > 0x00ffffff) {
550 cmd->stop_arg = 0x00ffffff;
555 if (cmd->stop_arg != 0) {
564 /* step 4: fix up any arguments */
566 if (cmd->scan_begin_src == TRIG_TIMER) {
567 tmp = cmd->scan_begin_arg;
568 dt3k_ns_to_timer(100, &cmd->scan_begin_arg,
569 cmd->flags & TRIG_ROUND_MASK);
570 if (tmp != cmd->scan_begin_arg)
575 if (cmd->convert_src == TRIG_TIMER) {
576 tmp = cmd->convert_arg;
577 dt3k_ns_to_timer(50, &cmd->convert_arg,
578 cmd->flags & TRIG_ROUND_MASK);
579 if (tmp != cmd->convert_arg)
581 if (cmd->scan_begin_src == TRIG_TIMER &&
582 cmd->scan_begin_arg <
583 cmd->convert_arg * cmd->scan_end_arg) {
584 cmd->scan_begin_arg =
585 cmd->convert_arg * cmd->scan_end_arg;
598 static int dt3k_ns_to_timer(unsigned int timer_base, unsigned int *nanosec,
599 unsigned int round_mode)
601 int divider, base, prescale;
603 /* This function needs improvment */
604 /* Don't know if divider==0 works. */
606 for (prescale = 0; prescale < 16; prescale++) {
607 base = timer_base * (prescale + 1);
608 switch (round_mode) {
609 case TRIG_ROUND_NEAREST:
611 divider = (*nanosec + base / 2) / base;
613 case TRIG_ROUND_DOWN:
614 divider = (*nanosec) / base;
617 divider = (*nanosec) / base;
620 if (divider < 65536) {
621 *nanosec = divider * base;
622 return (prescale << 16) | (divider);
627 base = timer_base * (1 << prescale);
629 *nanosec = divider * base;
630 return (prescale << 16) | (divider);
633 static int dt3k_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
635 struct comedi_cmd *cmd = &s->async->cmd;
637 unsigned int chan, range, aref;
638 unsigned int divider;
639 unsigned int tscandiv;
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]);
648 writew((range << 6) | chan,
649 devpriv->io_addr + DPR_ADC_buffer + i);
651 aref = CR_AREF(cmd->chanlist[0]);
653 writew(cmd->scan_end_arg, devpriv->io_addr + DPR_Params(0));
654 printk("param[0]=0x%04x\n", cmd->scan_end_arg);
656 if (cmd->convert_src == TRIG_TIMER) {
657 divider = dt3k_ns_to_timer(50, &cmd->convert_arg,
658 cmd->flags & TRIG_ROUND_MASK);
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);
667 if (cmd->scan_begin_src == TRIG_TIMER) {
668 tscandiv = dt3k_ns_to_timer(100, &cmd->scan_begin_arg,
669 cmd->flags & TRIG_ROUND_MASK);
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);
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);
684 writew(AI_FIFO_DEPTH / 2, devpriv->io_addr + DPR_Params(7));
685 printk("param[7]=0x%04x\n", AI_FIFO_DEPTH / 2);
687 writew(SUBS_AI, devpriv->io_addr + DPR_SubSys);
688 ret = dt3k_send_cmd(dev, CMD_CONFIG);
690 writew(DT3000_ADFULL | DT3000_ADSWERR | DT3000_ADHWERR,
691 devpriv->io_addr + DPR_Int_Mask);
695 writew(SUBS_AI, devpriv->io_addr + DPR_SubSys);
696 ret = dt3k_send_cmd(dev, CMD_START);
701 static int dt3k_ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
705 writew(SUBS_AI, devpriv->io_addr + DPR_SubSys);
706 ret = dt3k_send_cmd(dev, CMD_STOP);
708 writew(0, devpriv->io_addr + DPR_Int_Mask);
713 static int dt3k_ai_insn(struct comedi_device *dev, struct comedi_subdevice *s,
714 struct comedi_insn *insn, unsigned int *data)
717 unsigned int chan, gain, aref;
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);
724 for (i = 0; i < insn->n; i++)
725 data[i] = dt3k_readsingle(dev, SUBS_AI, chan, gain);
730 static int dt3k_ao_insn(struct comedi_device *dev, struct comedi_subdevice *s,
731 struct comedi_insn *insn, unsigned int *data)
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];
745 static int dt3k_ao_insn_read(struct comedi_device *dev,
746 struct comedi_subdevice *s,
747 struct comedi_insn *insn, unsigned int *data)
752 chan = CR_CHAN(insn->chanspec);
753 for (i = 0; i < insn->n; i++)
754 data[i] = devpriv->ao_readback[chan];
759 static void dt3k_dio_config(struct comedi_device *dev, int bits)
762 writew(SUBS_DOUT, devpriv->io_addr + DPR_SubSys);
764 writew(bits, devpriv->io_addr + DPR_Params(0));
767 writew(0, devpriv->io_addr + DPR_Params(1));
768 writew(0, devpriv->io_addr + DPR_Params(2));
771 dt3k_send_cmd(dev, CMD_CONFIG);
774 static int dt3k_dio_insn_config(struct comedi_device *dev,
775 struct comedi_subdevice *s,
776 struct comedi_insn *insn, unsigned int *data)
780 mask = (CR_CHAN(insn->chanspec) < 4) ? 0x0f : 0xf0;
783 case INSN_CONFIG_DIO_OUTPUT:
786 case INSN_CONFIG_DIO_INPUT:
789 case INSN_CONFIG_DIO_QUERY:
792 io_bits & (1 << CR_CHAN(insn->chanspec))) ? COMEDI_OUTPUT :
800 mask = (s->io_bits & 0x01) | ((s->io_bits & 0x10) >> 3);
801 dt3k_dio_config(dev, mask);
806 static int dt3k_dio_insn_bits(struct comedi_device *dev,
807 struct comedi_subdevice *s,
808 struct comedi_insn *insn, unsigned int *data)
814 s->state &= ~data[0];
815 s->state |= data[1] & data[0];
816 dt3k_writesingle(dev, SUBS_DOUT, 0, s->state);
818 data[1] = dt3k_readsingle(dev, SUBS_DIN, 0, 0);
823 static int dt3k_mem_insn_read(struct comedi_device *dev,
824 struct comedi_subdevice *s,
825 struct comedi_insn *insn, unsigned int *data)
827 unsigned int addr = CR_CHAN(insn->chanspec);
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));
835 dt3k_send_cmd(dev, CMD_READCODE);
837 data[i] = readw(devpriv->io_addr + DPR_Params(2));
843 static int dt_pci_probe(struct comedi_device *dev, int bus, int slot);
845 static int dt3000_attach(struct comedi_device *dev, struct comedi_devconfig *it)
847 struct comedi_subdevice *s;
852 bus = it->options[0];
853 slot = it->options[1];
855 ret = alloc_private(dev, sizeof(struct dt3k_private));
859 ret = dt_pci_probe(dev, bus, slot);
863 printk(" no DT board found\n");
867 dev->board_name = this_board->name;
869 if (request_irq(devpriv->pci_dev->irq, dt3k_interrupt, IRQF_SHARED,
871 printk(" unable to allocate IRQ %u\n", devpriv->pci_dev->irq);
874 dev->irq = devpriv->pci_dev->irq;
876 ret = alloc_subdevices(dev, 4);
881 dev->read_subdev = s;
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;
897 s->type = COMEDI_SUBD_AO;
898 s->subdev_flags = SDF_WRITABLE;
900 s->insn_read = dt3k_ao_insn_read;
901 s->insn_write = dt3k_ao_insn;
902 s->maxdata = (1 << this_board->dabits) - 1;
904 s->range_table = &range_bipolar10;
908 s->type = COMEDI_SUBD_DIO;
909 s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
911 s->insn_config = dt3k_dio_insn_config;
912 s->insn_bits = dt3k_dio_insn_bits;
915 s->range_table = &range_digital;
919 s->type = COMEDI_SUBD_MEMORY;
920 s->subdev_flags = SDF_READABLE;
922 s->insn_read = dt3k_mem_insn_read;
925 s->range_table = &range_unknown;
930 s->type = COMEDI_SUBD_PROC;
936 static int dt3000_detach(struct comedi_device *dev)
939 free_irq(dev->irq, dev);
942 if (devpriv->pci_dev) {
943 if (devpriv->phys_addr)
944 comedi_pci_disable(devpriv->pci_dev);
945 pci_dev_put(devpriv->pci_dev);
947 if (devpriv->io_addr)
948 iounmap(devpriv->io_addr);
955 static struct pci_dev *dt_pci_find_device(struct pci_dev *from, int *board);
956 static int setup_pci(struct comedi_device *dev);
958 static int dt_pci_probe(struct comedi_device *dev, int bus, int slot)
962 struct pci_dev *pcidev;
965 while ((pcidev = dt_pci_find_device(pcidev, &board)) != NULL) {
966 if ((bus == 0 && slot == 0) ||
967 (pcidev->bus->number == bus &&
968 PCI_SLOT(pcidev->devfn) == slot)) {
972 devpriv->pci_dev = pcidev;
975 dev->board_ptr = dt3k_boardtypes + board;
977 if (!devpriv->pci_dev)
980 ret = setup_pci(dev);
987 static int setup_pci(struct comedi_device *dev)
989 resource_size_t addr;
992 ret = comedi_pci_enable(devpriv->pci_dev, "dt3000");
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)
1002 printk("0x%08llx mapped to %p, ",
1003 (unsigned long long)devpriv->phys_addr, devpriv->io_addr);
1009 static struct pci_dev *dt_pci_find_device(struct pci_dev *from, int *board)
1013 for (from = pci_get_device(PCI_VENDOR_ID_DT, PCI_ANY_ID, from);
1015 from = pci_get_device(PCI_VENDOR_ID_DT, PCI_ANY_ID, from)) {
1016 for (i = 0; i < n_dt3k_boards; i++) {
1017 if (from->device == dt3k_boardtypes[i].device_id) {
1023 ("unknown Data Translation PCI device found with device_id=0x%04x\n",
1030 MODULE_AUTHOR("Comedi http://www.comedi.org");
1031 MODULE_DESCRIPTION("Comedi low-level driver");
1032 MODULE_LICENSE("GPL");