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