staging/comedi/addi: Convert pci_table entries to PCI_DEVICE (if PCI_ANY_ID is used)
[cascardo/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_pci.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 n_dt3k_boards sizeof(dt3k_boardtypes)/sizeof(struct dt3k_boardtype)
165 #define this_board ((const struct dt3k_boardtype *)dev->board_ptr)
166
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) },
175         { 0 }
176 };
177
178 MODULE_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
266 struct dt3k_private {
267
268         struct pci_dev *pci_dev;
269         resource_size_t phys_addr;
270         void *io_addr;
271         unsigned int lock;
272         unsigned int ao_readback[2];
273         unsigned int ai_front;
274         unsigned int ai_rear;
275 };
276
277 #define devpriv ((struct dt3k_private *)dev->private)
278
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,
287 };
288
289 static 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
295 static void __devexit driver_dt3000_pci_remove(struct pci_dev *dev)
296 {
297         comedi_pci_auto_unconfig(dev);
298 }
299
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)
304 };
305
306 static 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
318 static void __exit driver_dt3000_cleanup_module(void)
319 {
320         pci_unregister_driver(&driver_dt3000_pci_driver);
321         comedi_driver_unregister(&driver_dt3000);
322 }
323
324 module_init(driver_dt3000_init_module);
325 module_exit(driver_dt3000_cleanup_module);
326
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);
333 #ifdef DEBUG
334 static void debug_intr_flags(unsigned int flags);
335 #endif
336
337 #define TIMEOUT 100
338
339 static int dt3k_send_cmd(struct comedi_device *dev, unsigned int cmd)
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;
350                 udelay(1);
351         }
352         if ((status & DT3000_COMPLETION_MASK) == DT3000_NOERROR)
353                 return 0;
354
355         printk("dt3k_send_cmd() timeout/error status=0x%04x\n", status);
356
357         return -ETIME;
358 }
359
360 static unsigned int dt3k_readsingle(struct comedi_device *dev,
361                                     unsigned int subsys, unsigned int chan,
362                                     unsigned int gain)
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
374 static void dt3k_writesingle(struct comedi_device *dev, unsigned int subsys,
375                              unsigned int chan, unsigned int data)
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
386 static int debug_n_ints = 0;
387
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)
391 {
392         struct comedi_device *dev = d;
393         struct comedi_subdevice *s;
394         unsigned int status;
395
396         if (!dev->attached)
397                 return IRQ_NONE;
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
410         if (status & (DT3000_ADSWERR | DT3000_ADHWERR))
411                 s->async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
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
424 static char *intr_flags[] = {
425         "AdFull", "AdSwError", "AdHwError", "DaEmpty",
426         "DaSwError", "DaHwError", "CtDone", "CmDone",
427 };
428
429 static void debug_intr_flags(unsigned int flags)
430 {
431         int i;
432         printk("dt3k: intr_flags:");
433         for (i = 0; i < 8; i++) {
434                 if (flags & (1 << i))
435                         printk(" %s", intr_flags[i]);
436         }
437         printk("\n");
438 }
439 #endif
440
441 static void dt3k_ai_empty_fifo(struct comedi_device *dev,
442                                struct comedi_subdevice *s)
443 {
444         int front;
445         int rear;
446         int count;
447         int i;
448         short data;
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
471 static int dt3k_ai_cmdtest(struct comedi_device *dev,
472                            struct comedi_subdevice *s, struct comedi_cmd *cmd)
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,
569                                  cmd->flags & TRIG_ROUND_MASK);
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,
578                                  cmd->flags & TRIG_ROUND_MASK);
579                 if (tmp != cmd->convert_arg)
580                         err++;
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;
586                         err++;
587                 }
588         } else {
589                 /* not supported */
590         }
591
592         if (err)
593                 return 4;
594
595         return 0;
596 }
597
598 static int dt3k_ns_to_timer(unsigned int timer_base, unsigned int *nanosec,
599                             unsigned int round_mode)
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
633 static int dt3k_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
634 {
635         struct comedi_cmd *cmd = &s->async->cmd;
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,
649                        devpriv->io_addr + DPR_ADC_buffer + i);
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,
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);
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,
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);
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,
691                devpriv->io_addr + DPR_Int_Mask);
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
701 static int dt3k_ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
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
713 static int dt3k_ai_insn(struct comedi_device *dev, struct comedi_subdevice *s,
714                         struct comedi_insn *insn, unsigned int *data)
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
724         for (i = 0; i < insn->n; i++)
725                 data[i] = dt3k_readsingle(dev, SUBS_AI, chan, gain);
726
727         return i;
728 }
729
730 static int dt3k_ao_insn(struct comedi_device *dev, struct comedi_subdevice *s,
731                         struct comedi_insn *insn, unsigned int *data)
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
745 static int dt3k_ao_insn_read(struct comedi_device *dev,
746                              struct comedi_subdevice *s,
747                              struct comedi_insn *insn, unsigned int *data)
748 {
749         int i;
750         unsigned int chan;
751
752         chan = CR_CHAN(insn->chanspec);
753         for (i = 0; i < insn->n; i++)
754                 data[i] = devpriv->ao_readback[chan];
755
756         return i;
757 }
758
759 static void dt3k_dio_config(struct comedi_device *dev, int bits)
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
774 static int dt3k_dio_insn_config(struct comedi_device *dev,
775                                 struct comedi_subdevice *s,
776                                 struct comedi_insn *insn, unsigned int *data)
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] =
791                     (s->
792                      io_bits & (1 << CR_CHAN(insn->chanspec))) ? COMEDI_OUTPUT :
793                     COMEDI_INPUT;
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
806 static int dt3k_dio_insn_bits(struct comedi_device *dev,
807                               struct comedi_subdevice *s,
808                               struct comedi_insn *insn, unsigned int *data)
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
823 static int dt3k_mem_insn_read(struct comedi_device *dev,
824                               struct comedi_subdevice *s,
825                               struct comedi_insn *insn, unsigned int *data)
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
843 static int dt_pci_probe(struct comedi_device *dev, int bus, int slot);
844
845 static int dt3000_attach(struct comedi_device *dev, struct comedi_devconfig *it)
846 {
847         struct comedi_subdevice *s;
848         int bus, slot;
849         int ret = 0;
850
851         printk("dt3000:");
852         bus = it->options[0];
853         slot = it->options[1];
854
855         ret = alloc_private(dev, sizeof(struct dt3k_private));
856         if (ret < 0)
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
869         if (request_irq(devpriv->pci_dev->irq, dt3k_interrupt, IRQF_SHARED,
870                         "dt3000", dev)) {
871                 printk(" unable to allocate IRQ %u\n", devpriv->pci_dev->irq);
872                 return -EINVAL;
873         }
874         dev->irq = devpriv->pci_dev->irq;
875
876         ret = alloc_subdevices(dev, 4);
877         if (ret < 0)
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
936 static int dt3000_detach(struct comedi_device *dev)
937 {
938         if (dev->irq)
939                 free_irq(dev->irq, dev);
940
941         if (devpriv) {
942                 if (devpriv->pci_dev) {
943                         if (devpriv->phys_addr)
944                                 comedi_pci_disable(devpriv->pci_dev);
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
955 static struct pci_dev *dt_pci_find_device(struct pci_dev *from, int *board);
956 static int setup_pci(struct comedi_device *dev);
957
958 static int dt_pci_probe(struct comedi_device *dev, int bus, int slot)
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) ||
967                     (pcidev->bus->number == bus &&
968                      PCI_SLOT(pcidev->devfn) == slot)) {
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
980         ret = setup_pci(dev);
981         if (ret < 0)
982                 return ret;
983
984         return 1;
985 }
986
987 static int setup_pci(struct comedi_device *dev)
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, ",
1003                (unsigned long long)devpriv->phys_addr, devpriv->io_addr);
1004 #endif
1005
1006         return 0;
1007 }
1008
1009 static 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);
1014              from != NULL;
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) {
1018                                 *board = i;
1019                                 return from;
1020                         }
1021                 }
1022                 printk
1023                     ("unknown Data Translation PCI device found with device_id=0x%04x\n",
1024                      from->device);
1025         }
1026         *board = -1;
1027         return from;
1028 }
1029
1030 MODULE_AUTHOR("Comedi http://www.comedi.org");
1031 MODULE_DESCRIPTION("Comedi low-level driver");
1032 MODULE_LICENSE("GPL");