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