- patches.arch/x86_mce_intel_decode_physical_address.patch:
[linux-flexiantxendom0-3.2.10.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 COMEDI_PCI_INITCLEANUP(driver_dt3000, dt3k_pci_table);
291
292 static void dt3k_ai_empty_fifo(struct comedi_device *dev,
293                                struct comedi_subdevice *s);
294 static int dt3k_ns_to_timer(unsigned int timer_base, unsigned int *arg,
295                             unsigned int round_mode);
296 static int dt3k_ai_cancel(struct comedi_device *dev,
297                           struct comedi_subdevice *s);
298 #ifdef DEBUG
299 static void debug_intr_flags(unsigned int flags);
300 #endif
301
302 #define TIMEOUT 100
303
304 static int dt3k_send_cmd(struct comedi_device *dev, unsigned int cmd)
305 {
306         int i;
307         unsigned int status = 0;
308
309         writew(cmd, devpriv->io_addr + DPR_Command_Mbx);
310
311         for (i = 0; i < TIMEOUT; i++) {
312                 status = readw(devpriv->io_addr + DPR_Command_Mbx);
313                 if ((status & DT3000_COMPLETION_MASK) != DT3000_NOTPROCESSED)
314                         break;
315                 udelay(1);
316         }
317         if ((status & DT3000_COMPLETION_MASK) == DT3000_NOERROR)
318                 return 0;
319
320         printk("dt3k_send_cmd() timeout/error status=0x%04x\n", status);
321
322         return -ETIME;
323 }
324
325 static unsigned int dt3k_readsingle(struct comedi_device *dev,
326                                     unsigned int subsys, unsigned int chan,
327                                     unsigned int gain)
328 {
329         writew(subsys, devpriv->io_addr + DPR_SubSys);
330
331         writew(chan, devpriv->io_addr + DPR_Params(0));
332         writew(gain, devpriv->io_addr + DPR_Params(1));
333
334         dt3k_send_cmd(dev, CMD_READSINGLE);
335
336         return readw(devpriv->io_addr + DPR_Params(2));
337 }
338
339 static void dt3k_writesingle(struct comedi_device *dev, unsigned int subsys,
340                              unsigned int chan, unsigned int data)
341 {
342         writew(subsys, devpriv->io_addr + DPR_SubSys);
343
344         writew(chan, devpriv->io_addr + DPR_Params(0));
345         writew(0, devpriv->io_addr + DPR_Params(1));
346         writew(data, devpriv->io_addr + DPR_Params(2));
347
348         dt3k_send_cmd(dev, CMD_WRITESINGLE);
349 }
350
351 static int debug_n_ints = 0;
352
353 /* FIXME! Assumes shared interrupt is for this card. */
354 /* What's this debug_n_ints stuff? Obviously needs some work... */
355 static irqreturn_t dt3k_interrupt(int irq, void *d)
356 {
357         struct comedi_device *dev = d;
358         struct comedi_subdevice *s;
359         unsigned int status;
360
361         if (!dev->attached)
362                 return IRQ_NONE;
363
364         s = dev->subdevices + 0;
365         status = readw(devpriv->io_addr + DPR_Intr_Flag);
366 #ifdef DEBUG
367         debug_intr_flags(status);
368 #endif
369
370         if (status & DT3000_ADFULL) {
371                 dt3k_ai_empty_fifo(dev, s);
372                 s->async->events |= COMEDI_CB_BLOCK;
373         }
374
375         if (status & (DT3000_ADSWERR | DT3000_ADHWERR))
376                 s->async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
377
378         debug_n_ints++;
379         if (debug_n_ints >= 10) {
380                 dt3k_ai_cancel(dev, s);
381                 s->async->events |= COMEDI_CB_EOA;
382         }
383
384         comedi_event(dev, s);
385         return IRQ_HANDLED;
386 }
387
388 #ifdef DEBUG
389 static char *intr_flags[] = {
390         "AdFull", "AdSwError", "AdHwError", "DaEmpty",
391         "DaSwError", "DaHwError", "CtDone", "CmDone",
392 };
393
394 static void debug_intr_flags(unsigned int flags)
395 {
396         int i;
397         printk("dt3k: intr_flags:");
398         for (i = 0; i < 8; i++) {
399                 if (flags & (1 << i))
400                         printk(" %s", intr_flags[i]);
401         }
402         printk("\n");
403 }
404 #endif
405
406 static void dt3k_ai_empty_fifo(struct comedi_device *dev,
407                                struct comedi_subdevice *s)
408 {
409         int front;
410         int rear;
411         int count;
412         int i;
413         short data;
414
415         front = readw(devpriv->io_addr + DPR_AD_Buf_Front);
416         count = front - devpriv->ai_front;
417         if (count < 0)
418                 count += AI_FIFO_DEPTH;
419
420         printk("reading %d samples\n", count);
421
422         rear = devpriv->ai_rear;
423
424         for (i = 0; i < count; i++) {
425                 data = readw(devpriv->io_addr + DPR_ADC_buffer + rear);
426                 comedi_buf_put(s->async, data);
427                 rear++;
428                 if (rear >= AI_FIFO_DEPTH)
429                         rear = 0;
430         }
431
432         devpriv->ai_rear = rear;
433         writew(rear, devpriv->io_addr + DPR_AD_Buf_Rear);
434 }
435
436 static int dt3k_ai_cmdtest(struct comedi_device *dev,
437                            struct comedi_subdevice *s, struct comedi_cmd *cmd)
438 {
439         int err = 0;
440         int tmp;
441
442         /* step 1: make sure trigger sources are trivially valid */
443
444         tmp = cmd->start_src;
445         cmd->start_src &= TRIG_NOW;
446         if (!cmd->start_src || tmp != cmd->start_src)
447                 err++;
448
449         tmp = cmd->scan_begin_src;
450         cmd->scan_begin_src &= TRIG_TIMER;
451         if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
452                 err++;
453
454         tmp = cmd->convert_src;
455         cmd->convert_src &= TRIG_TIMER;
456         if (!cmd->convert_src || tmp != cmd->convert_src)
457                 err++;
458
459         tmp = cmd->scan_end_src;
460         cmd->scan_end_src &= TRIG_COUNT;
461         if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
462                 err++;
463
464         tmp = cmd->stop_src;
465         cmd->stop_src &= TRIG_COUNT;
466         if (!cmd->stop_src || tmp != cmd->stop_src)
467                 err++;
468
469         if (err)
470                 return 1;
471
472         /* step 2: make sure trigger sources are unique and mutually compatible */
473
474         if (err)
475                 return 2;
476
477         /* step 3: make sure arguments are trivially compatible */
478
479         if (cmd->start_arg != 0) {
480                 cmd->start_arg = 0;
481                 err++;
482         }
483
484         if (cmd->scan_begin_src == TRIG_TIMER) {
485                 if (cmd->scan_begin_arg < this_board->ai_speed) {
486                         cmd->scan_begin_arg = this_board->ai_speed;
487                         err++;
488                 }
489                 if (cmd->scan_begin_arg > 100 * 16 * 65535) {
490                         cmd->scan_begin_arg = 100 * 16 * 65535;
491                         err++;
492                 }
493         } else {
494                 /* not supported */
495         }
496         if (cmd->convert_src == TRIG_TIMER) {
497                 if (cmd->convert_arg < this_board->ai_speed) {
498                         cmd->convert_arg = this_board->ai_speed;
499                         err++;
500                 }
501                 if (cmd->convert_arg > 50 * 16 * 65535) {
502                         cmd->convert_arg = 50 * 16 * 65535;
503                         err++;
504                 }
505         } else {
506                 /* not supported */
507         }
508
509         if (cmd->scan_end_arg != cmd->chanlist_len) {
510                 cmd->scan_end_arg = cmd->chanlist_len;
511                 err++;
512         }
513         if (cmd->stop_src == TRIG_COUNT) {
514                 if (cmd->stop_arg > 0x00ffffff) {
515                         cmd->stop_arg = 0x00ffffff;
516                         err++;
517                 }
518         } else {
519                 /* TRIG_NONE */
520                 if (cmd->stop_arg != 0) {
521                         cmd->stop_arg = 0;
522                         err++;
523                 }
524         }
525
526         if (err)
527                 return 3;
528
529         /* step 4: fix up any arguments */
530
531         if (cmd->scan_begin_src == TRIG_TIMER) {
532                 tmp = cmd->scan_begin_arg;
533                 dt3k_ns_to_timer(100, &cmd->scan_begin_arg,
534                                  cmd->flags & TRIG_ROUND_MASK);
535                 if (tmp != cmd->scan_begin_arg)
536                         err++;
537         } else {
538                 /* not supported */
539         }
540         if (cmd->convert_src == TRIG_TIMER) {
541                 tmp = cmd->convert_arg;
542                 dt3k_ns_to_timer(50, &cmd->convert_arg,
543                                  cmd->flags & TRIG_ROUND_MASK);
544                 if (tmp != cmd->convert_arg)
545                         err++;
546                 if (cmd->scan_begin_src == TRIG_TIMER &&
547                     cmd->scan_begin_arg <
548                     cmd->convert_arg * cmd->scan_end_arg) {
549                         cmd->scan_begin_arg =
550                             cmd->convert_arg * cmd->scan_end_arg;
551                         err++;
552                 }
553         } else {
554                 /* not supported */
555         }
556
557         if (err)
558                 return 4;
559
560         return 0;
561 }
562
563 static int dt3k_ns_to_timer(unsigned int timer_base, unsigned int *nanosec,
564                             unsigned int round_mode)
565 {
566         int divider, base, prescale;
567
568         /* This function needs improvment */
569         /* Don't know if divider==0 works. */
570
571         for (prescale = 0; prescale < 16; prescale++) {
572                 base = timer_base * (prescale + 1);
573                 switch (round_mode) {
574                 case TRIG_ROUND_NEAREST:
575                 default:
576                         divider = (*nanosec + base / 2) / base;
577                         break;
578                 case TRIG_ROUND_DOWN:
579                         divider = (*nanosec) / base;
580                         break;
581                 case TRIG_ROUND_UP:
582                         divider = (*nanosec) / base;
583                         break;
584                 }
585                 if (divider < 65536) {
586                         *nanosec = divider * base;
587                         return (prescale << 16) | (divider);
588                 }
589         }
590
591         prescale = 15;
592         base = timer_base * (1 << prescale);
593         divider = 65535;
594         *nanosec = divider * base;
595         return (prescale << 16) | (divider);
596 }
597
598 static int dt3k_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
599 {
600         struct comedi_cmd *cmd = &s->async->cmd;
601         int i;
602         unsigned int chan, range, aref;
603         unsigned int divider;
604         unsigned int tscandiv;
605         int ret;
606         unsigned int mode;
607
608         printk("dt3k_ai_cmd:\n");
609         for (i = 0; i < cmd->chanlist_len; i++) {
610                 chan = CR_CHAN(cmd->chanlist[i]);
611                 range = CR_RANGE(cmd->chanlist[i]);
612
613                 writew((range << 6) | chan,
614                        devpriv->io_addr + DPR_ADC_buffer + i);
615         }
616         aref = CR_AREF(cmd->chanlist[0]);
617
618         writew(cmd->scan_end_arg, devpriv->io_addr + DPR_Params(0));
619         printk("param[0]=0x%04x\n", cmd->scan_end_arg);
620
621         if (cmd->convert_src == TRIG_TIMER) {
622                 divider = dt3k_ns_to_timer(50, &cmd->convert_arg,
623                                            cmd->flags & TRIG_ROUND_MASK);
624                 writew((divider >> 16), devpriv->io_addr + DPR_Params(1));
625                 printk("param[1]=0x%04x\n", divider >> 16);
626                 writew((divider & 0xffff), devpriv->io_addr + DPR_Params(2));
627                 printk("param[2]=0x%04x\n", divider & 0xffff);
628         } else {
629                 /* not supported */
630         }
631
632         if (cmd->scan_begin_src == TRIG_TIMER) {
633                 tscandiv = dt3k_ns_to_timer(100, &cmd->scan_begin_arg,
634                                             cmd->flags & TRIG_ROUND_MASK);
635                 writew((tscandiv >> 16), devpriv->io_addr + DPR_Params(3));
636                 printk("param[3]=0x%04x\n", tscandiv >> 16);
637                 writew((tscandiv & 0xffff), devpriv->io_addr + DPR_Params(4));
638                 printk("param[4]=0x%04x\n", tscandiv & 0xffff);
639         } else {
640                 /* not supported */
641         }
642
643         mode = DT3000_AD_RETRIG_INTERNAL | 0 | 0;
644         writew(mode, devpriv->io_addr + DPR_Params(5));
645         printk("param[5]=0x%04x\n", mode);
646         writew(aref == AREF_DIFF, devpriv->io_addr + DPR_Params(6));
647         printk("param[6]=0x%04x\n", aref == AREF_DIFF);
648
649         writew(AI_FIFO_DEPTH / 2, devpriv->io_addr + DPR_Params(7));
650         printk("param[7]=0x%04x\n", AI_FIFO_DEPTH / 2);
651
652         writew(SUBS_AI, devpriv->io_addr + DPR_SubSys);
653         ret = dt3k_send_cmd(dev, CMD_CONFIG);
654
655         writew(DT3000_ADFULL | DT3000_ADSWERR | DT3000_ADHWERR,
656                devpriv->io_addr + DPR_Int_Mask);
657
658         debug_n_ints = 0;
659
660         writew(SUBS_AI, devpriv->io_addr + DPR_SubSys);
661         ret = dt3k_send_cmd(dev, CMD_START);
662
663         return 0;
664 }
665
666 static int dt3k_ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
667 {
668         int ret;
669
670         writew(SUBS_AI, devpriv->io_addr + DPR_SubSys);
671         ret = dt3k_send_cmd(dev, CMD_STOP);
672
673         writew(0, devpriv->io_addr + DPR_Int_Mask);
674
675         return 0;
676 }
677
678 static int dt3k_ai_insn(struct comedi_device *dev, struct comedi_subdevice *s,
679                         struct comedi_insn *insn, unsigned int *data)
680 {
681         int i;
682         unsigned int chan, gain, aref;
683
684         chan = CR_CHAN(insn->chanspec);
685         gain = CR_RANGE(insn->chanspec);
686         /* XXX docs don't explain how to select aref */
687         aref = CR_AREF(insn->chanspec);
688
689         for (i = 0; i < insn->n; i++)
690                 data[i] = dt3k_readsingle(dev, SUBS_AI, chan, gain);
691
692         return i;
693 }
694
695 static int dt3k_ao_insn(struct comedi_device *dev, struct comedi_subdevice *s,
696                         struct comedi_insn *insn, unsigned int *data)
697 {
698         int i;
699         unsigned int chan;
700
701         chan = CR_CHAN(insn->chanspec);
702         for (i = 0; i < insn->n; i++) {
703                 dt3k_writesingle(dev, SUBS_AO, chan, data[i]);
704                 devpriv->ao_readback[chan] = data[i];
705         }
706
707         return i;
708 }
709
710 static int dt3k_ao_insn_read(struct comedi_device *dev,
711                              struct comedi_subdevice *s,
712                              struct comedi_insn *insn, unsigned int *data)
713 {
714         int i;
715         unsigned int chan;
716
717         chan = CR_CHAN(insn->chanspec);
718         for (i = 0; i < insn->n; i++)
719                 data[i] = devpriv->ao_readback[chan];
720
721         return i;
722 }
723
724 static void dt3k_dio_config(struct comedi_device *dev, int bits)
725 {
726         /* XXX */
727         writew(SUBS_DOUT, devpriv->io_addr + DPR_SubSys);
728
729         writew(bits, devpriv->io_addr + DPR_Params(0));
730 #if 0
731         /* don't know */
732         writew(0, devpriv->io_addr + DPR_Params(1));
733         writew(0, devpriv->io_addr + DPR_Params(2));
734 #endif
735
736         dt3k_send_cmd(dev, CMD_CONFIG);
737 }
738
739 static int dt3k_dio_insn_config(struct comedi_device *dev,
740                                 struct comedi_subdevice *s,
741                                 struct comedi_insn *insn, unsigned int *data)
742 {
743         int mask;
744
745         mask = (CR_CHAN(insn->chanspec) < 4) ? 0x0f : 0xf0;
746
747         switch (data[0]) {
748         case INSN_CONFIG_DIO_OUTPUT:
749                 s->io_bits |= mask;
750                 break;
751         case INSN_CONFIG_DIO_INPUT:
752                 s->io_bits &= ~mask;
753                 break;
754         case INSN_CONFIG_DIO_QUERY:
755                 data[1] =
756                     (s->
757                      io_bits & (1 << CR_CHAN(insn->chanspec))) ? COMEDI_OUTPUT :
758                     COMEDI_INPUT;
759                 return insn->n;
760                 break;
761         default:
762                 return -EINVAL;
763                 break;
764         }
765         mask = (s->io_bits & 0x01) | ((s->io_bits & 0x10) >> 3);
766         dt3k_dio_config(dev, mask);
767
768         return insn->n;
769 }
770
771 static int dt3k_dio_insn_bits(struct comedi_device *dev,
772                               struct comedi_subdevice *s,
773                               struct comedi_insn *insn, unsigned int *data)
774 {
775         if (insn->n != 2)
776                 return -EINVAL;
777
778         if (data[0]) {
779                 s->state &= ~data[0];
780                 s->state |= data[1] & data[0];
781                 dt3k_writesingle(dev, SUBS_DOUT, 0, s->state);
782         }
783         data[1] = dt3k_readsingle(dev, SUBS_DIN, 0, 0);
784
785         return 2;
786 }
787
788 static int dt3k_mem_insn_read(struct comedi_device *dev,
789                               struct comedi_subdevice *s,
790                               struct comedi_insn *insn, unsigned int *data)
791 {
792         unsigned int addr = CR_CHAN(insn->chanspec);
793         int i;
794
795         for (i = 0; i < insn->n; i++) {
796                 writew(SUBS_MEM, devpriv->io_addr + DPR_SubSys);
797                 writew(addr, devpriv->io_addr + DPR_Params(0));
798                 writew(1, devpriv->io_addr + DPR_Params(1));
799
800                 dt3k_send_cmd(dev, CMD_READCODE);
801
802                 data[i] = readw(devpriv->io_addr + DPR_Params(2));
803         }
804
805         return i;
806 }
807
808 static int dt_pci_probe(struct comedi_device *dev, int bus, int slot);
809
810 static int dt3000_attach(struct comedi_device *dev, struct comedi_devconfig *it)
811 {
812         struct comedi_subdevice *s;
813         int bus, slot;
814         int ret = 0;
815
816         printk("dt3000:");
817         bus = it->options[0];
818         slot = it->options[1];
819
820         ret = alloc_private(dev, sizeof(struct dt3k_private));
821         if (ret < 0)
822                 return ret;
823
824         ret = dt_pci_probe(dev, bus, slot);
825         if (ret < 0)
826                 return ret;
827         if (ret == 0) {
828                 printk(" no DT board found\n");
829                 return -ENODEV;
830         }
831
832         dev->board_name = this_board->name;
833
834         if (request_irq(devpriv->pci_dev->irq, dt3k_interrupt, IRQF_SHARED,
835                         "dt3000", dev)) {
836                 printk(" unable to allocate IRQ %u\n", devpriv->pci_dev->irq);
837                 return -EINVAL;
838         }
839         dev->irq = devpriv->pci_dev->irq;
840
841         ret = alloc_subdevices(dev, 4);
842         if (ret < 0)
843                 return ret;
844
845         s = dev->subdevices;
846         dev->read_subdev = s;
847
848         /* ai subdevice */
849         s->type = COMEDI_SUBD_AI;
850         s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_DIFF | SDF_CMD_READ;
851         s->n_chan = this_board->adchan;
852         s->insn_read = dt3k_ai_insn;
853         s->maxdata = (1 << this_board->adbits) - 1;
854         s->len_chanlist = 512;
855         s->range_table = &range_dt3000_ai;      /* XXX */
856         s->do_cmd = dt3k_ai_cmd;
857         s->do_cmdtest = dt3k_ai_cmdtest;
858         s->cancel = dt3k_ai_cancel;
859
860         s++;
861         /* ao subsystem */
862         s->type = COMEDI_SUBD_AO;
863         s->subdev_flags = SDF_WRITABLE;
864         s->n_chan = 2;
865         s->insn_read = dt3k_ao_insn_read;
866         s->insn_write = dt3k_ao_insn;
867         s->maxdata = (1 << this_board->dabits) - 1;
868         s->len_chanlist = 1;
869         s->range_table = &range_bipolar10;
870
871         s++;
872         /* dio subsystem */
873         s->type = COMEDI_SUBD_DIO;
874         s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
875         s->n_chan = 8;
876         s->insn_config = dt3k_dio_insn_config;
877         s->insn_bits = dt3k_dio_insn_bits;
878         s->maxdata = 1;
879         s->len_chanlist = 8;
880         s->range_table = &range_digital;
881
882         s++;
883         /* mem subsystem */
884         s->type = COMEDI_SUBD_MEMORY;
885         s->subdev_flags = SDF_READABLE;
886         s->n_chan = 0x1000;
887         s->insn_read = dt3k_mem_insn_read;
888         s->maxdata = 0xff;
889         s->len_chanlist = 1;
890         s->range_table = &range_unknown;
891
892 #if 0
893         s++;
894         /* proc subsystem */
895         s->type = COMEDI_SUBD_PROC;
896 #endif
897
898         return 0;
899 }
900
901 static int dt3000_detach(struct comedi_device *dev)
902 {
903         if (dev->irq)
904                 free_irq(dev->irq, dev);
905
906         if (devpriv) {
907                 if (devpriv->pci_dev) {
908                         if (devpriv->phys_addr)
909                                 comedi_pci_disable(devpriv->pci_dev);
910                         pci_dev_put(devpriv->pci_dev);
911                 }
912                 if (devpriv->io_addr)
913                         iounmap(devpriv->io_addr);
914         }
915         /* XXX */
916
917         return 0;
918 }
919
920 static struct pci_dev *dt_pci_find_device(struct pci_dev *from, int *board);
921 static int setup_pci(struct comedi_device *dev);
922
923 static int dt_pci_probe(struct comedi_device *dev, int bus, int slot)
924 {
925         int board;
926         int ret;
927         struct pci_dev *pcidev;
928
929         pcidev = NULL;
930         while ((pcidev = dt_pci_find_device(pcidev, &board)) != NULL) {
931                 if ((bus == 0 && slot == 0) ||
932                     (pcidev->bus->number == bus &&
933                      PCI_SLOT(pcidev->devfn) == slot)) {
934                         break;
935                 }
936         }
937         devpriv->pci_dev = pcidev;
938
939         if (board >= 0)
940                 dev->board_ptr = dt3k_boardtypes + board;
941
942         if (!devpriv->pci_dev)
943                 return 0;
944
945         ret = setup_pci(dev);
946         if (ret < 0)
947                 return ret;
948
949         return 1;
950 }
951
952 static int setup_pci(struct comedi_device *dev)
953 {
954         resource_size_t addr;
955         int ret;
956
957         ret = comedi_pci_enable(devpriv->pci_dev, "dt3000");
958         if (ret < 0)
959                 return ret;
960
961         addr = pci_resource_start(devpriv->pci_dev, 0);
962         devpriv->phys_addr = addr;
963         devpriv->io_addr = ioremap(devpriv->phys_addr, DT3000_SIZE);
964         if (!devpriv->io_addr)
965                 return -ENOMEM;
966 #if DEBUG
967         printk("0x%08llx mapped to %p, ",
968                (unsigned long long)devpriv->phys_addr, devpriv->io_addr);
969 #endif
970
971         return 0;
972 }
973
974 static struct pci_dev *dt_pci_find_device(struct pci_dev *from, int *board)
975 {
976         int i;
977
978         for (from = pci_get_device(PCI_VENDOR_ID_DT, PCI_ANY_ID, from);
979              from != NULL;
980              from = pci_get_device(PCI_VENDOR_ID_DT, PCI_ANY_ID, from)) {
981                 for (i = 0; i < n_dt3k_boards; i++) {
982                         if (from->device == dt3k_boardtypes[i].device_id) {
983                                 *board = i;
984                                 return from;
985                         }
986                 }
987                 printk
988                     ("unknown Data Translation PCI device found with device_id=0x%04x\n",
989                      from->device);
990         }
991         *board = -1;
992         return from;
993 }