Merge tag 'for-v3.13/clock-fixes-a' of git://git.kernel.org/pub/scm/linux/kernel...
[cascardo/linux.git] / drivers / staging / comedi / drivers / dt3000.c
1 /*
2     comedi/drivers/dt3000.c
3     Data Translation DT3000 series driver
4
5     COMEDI - Linux Control and Measurement Device Interface
6     Copyright (C) 1999 David A. Schleef <ds@schleef.org>
7
8     This program is free software; you can redistribute it and/or modify
9     it under the terms of the GNU General Public License as published by
10     the Free Software Foundation; either version 2 of the License, or
11     (at your option) any later version.
12
13     This program is distributed in the hope that it will be useful,
14     but WITHOUT ANY WARRANTY; without even the implied warranty of
15     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16     GNU General Public License for more details.
17 */
18 /*
19 Driver: dt3000
20 Description: Data Translation DT3000 series
21 Author: ds
22 Devices: [Data Translation] DT3001 (dt3000), DT3001-PGL, DT3002, DT3003,
23   DT3003-PGL, DT3004, DT3005, DT3004-200
24 Updated: Mon, 14 Apr 2008 15:41:24 +0100
25 Status: works
26
27 Configuration Options: not applicable, uses PCI auto config
28
29 There is code to support AI commands, but it may not work.
30
31 AO commands are not supported.
32 */
33
34 /*
35    The DT3000 series is Data Translation's attempt to make a PCI
36    data acquisition board.  The design of this series is very nice,
37    since each board has an on-board DSP (Texas Instruments TMS320C52).
38    However, a few details are a little annoying.  The boards lack
39    bus-mastering DMA, which eliminates them from serious work.
40    They also are not capable of autocalibration, which is a common
41    feature in modern hardware.  The default firmware is pretty bad,
42    making it nearly impossible to write an RT compatible driver.
43    It would make an interesting project to write a decent firmware
44    for these boards.
45
46    Data Translation originally wanted an NDA for the documentation
47    for the 3k series.  However, if you ask nicely, they might send
48    you the docs without one, also.
49 */
50
51 #define DEBUG 1
52
53 #include <linux/module.h>
54 #include <linux/pci.h>
55 #include <linux/delay.h>
56 #include <linux/interrupt.h>
57
58 #include "../comedidev.h"
59
60 #include "comedi_fc.h"
61
62 static const struct comedi_lrange range_dt3000_ai = {
63         4, {
64                 BIP_RANGE(10),
65                 BIP_RANGE(5),
66                 BIP_RANGE(2.5),
67                 BIP_RANGE(1.25)
68         }
69 };
70
71 static const struct comedi_lrange range_dt3000_ai_pgl = {
72         4, {
73                 BIP_RANGE(10),
74                 BIP_RANGE(1),
75                 BIP_RANGE(0.1),
76                 BIP_RANGE(0.02)
77         }
78 };
79
80 enum dt3k_boardid {
81         BOARD_DT3001,
82         BOARD_DT3001_PGL,
83         BOARD_DT3002,
84         BOARD_DT3003,
85         BOARD_DT3003_PGL,
86         BOARD_DT3004,
87         BOARD_DT3005,
88 };
89
90 struct dt3k_boardtype {
91         const char *name;
92         int adchan;
93         int adbits;
94         int ai_speed;
95         const struct comedi_lrange *adrange;
96         int dachan;
97         int dabits;
98 };
99
100 static const struct dt3k_boardtype dt3k_boardtypes[] = {
101         [BOARD_DT3001] = {
102                 .name           = "dt3001",
103                 .adchan         = 16,
104                 .adbits         = 12,
105                 .adrange        = &range_dt3000_ai,
106                 .ai_speed       = 3000,
107                 .dachan         = 2,
108                 .dabits         = 12,
109         },
110         [BOARD_DT3001_PGL] = {
111                 .name           = "dt3001-pgl",
112                 .adchan         = 16,
113                 .adbits         = 12,
114                 .adrange        = &range_dt3000_ai_pgl,
115                 .ai_speed       = 3000,
116                 .dachan         = 2,
117                 .dabits         = 12,
118         },
119         [BOARD_DT3002] = {
120                 .name           = "dt3002",
121                 .adchan         = 32,
122                 .adbits         = 12,
123                 .adrange        = &range_dt3000_ai,
124                 .ai_speed       = 3000,
125         },
126         [BOARD_DT3003] = {
127                 .name           = "dt3003",
128                 .adchan         = 64,
129                 .adbits         = 12,
130                 .adrange        = &range_dt3000_ai,
131                 .ai_speed       = 3000,
132                 .dachan         = 2,
133                 .dabits         = 12,
134         },
135         [BOARD_DT3003_PGL] = {
136                 .name           = "dt3003-pgl",
137                 .adchan         = 64,
138                 .adbits         = 12,
139                 .adrange        = &range_dt3000_ai_pgl,
140                 .ai_speed       = 3000,
141                 .dachan         = 2,
142                 .dabits         = 12,
143         },
144         [BOARD_DT3004] = {
145                 .name           = "dt3004",
146                 .adchan         = 16,
147                 .adbits         = 16,
148                 .adrange        = &range_dt3000_ai,
149                 .ai_speed       = 10000,
150                 .dachan         = 2,
151                 .dabits         = 12,
152         },
153         [BOARD_DT3005] = {
154                 .name           = "dt3005",     /* a.k.a. 3004-200 */
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 /* dual-ported RAM location definitions */
165
166 #define DPR_DAC_buffer          (4*0x000)
167 #define DPR_ADC_buffer          (4*0x800)
168 #define DPR_Command             (4*0xfd3)
169 #define DPR_SubSys              (4*0xfd3)
170 #define DPR_Encode              (4*0xfd4)
171 #define DPR_Params(a)           (4*(0xfd5+(a)))
172 #define DPR_Tick_Reg_Lo         (4*0xff5)
173 #define DPR_Tick_Reg_Hi         (4*0xff6)
174 #define DPR_DA_Buf_Front        (4*0xff7)
175 #define DPR_DA_Buf_Rear         (4*0xff8)
176 #define DPR_AD_Buf_Front        (4*0xff9)
177 #define DPR_AD_Buf_Rear         (4*0xffa)
178 #define DPR_Int_Mask            (4*0xffb)
179 #define DPR_Intr_Flag           (4*0xffc)
180 #define DPR_Response_Mbx        (4*0xffe)
181 #define DPR_Command_Mbx         (4*0xfff)
182
183 #define AI_FIFO_DEPTH   2003
184 #define AO_FIFO_DEPTH   2048
185
186 /* command list */
187
188 #define CMD_GETBRDINFO          0
189 #define CMD_CONFIG              1
190 #define CMD_GETCONFIG           2
191 #define CMD_START               3
192 #define CMD_STOP                4
193 #define CMD_READSINGLE          5
194 #define CMD_WRITESINGLE         6
195 #define CMD_CALCCLOCK           7
196 #define CMD_READEVENTS          8
197 #define CMD_WRITECTCTRL         16
198 #define CMD_READCTCTRL          17
199 #define CMD_WRITECT             18
200 #define CMD_READCT              19
201 #define CMD_WRITEDATA           32
202 #define CMD_READDATA            33
203 #define CMD_WRITEIO             34
204 #define CMD_READIO              35
205 #define CMD_WRITECODE           36
206 #define CMD_READCODE            37
207 #define CMD_EXECUTE             38
208 #define CMD_HALT                48
209
210 #define SUBS_AI         0
211 #define SUBS_AO         1
212 #define SUBS_DIN        2
213 #define SUBS_DOUT       3
214 #define SUBS_MEM        4
215 #define SUBS_CT         5
216
217 /* interrupt flags */
218 #define DT3000_CMDONE           0x80
219 #define DT3000_CTDONE           0x40
220 #define DT3000_DAHWERR          0x20
221 #define DT3000_DASWERR          0x10
222 #define DT3000_DAEMPTY          0x08
223 #define DT3000_ADHWERR          0x04
224 #define DT3000_ADSWERR          0x02
225 #define DT3000_ADFULL           0x01
226
227 #define DT3000_COMPLETION_MASK  0xff00
228 #define DT3000_COMMAND_MASK     0x00ff
229 #define DT3000_NOTPROCESSED     0x0000
230 #define DT3000_NOERROR          0x5500
231 #define DT3000_ERROR            0xaa00
232 #define DT3000_NOTSUPPORTED     0xff00
233
234 #define DT3000_EXTERNAL_CLOCK   1
235 #define DT3000_RISING_EDGE      2
236
237 #define TMODE_MASK              0x1c
238
239 #define DT3000_AD_TRIG_INTERNAL         (0<<2)
240 #define DT3000_AD_TRIG_EXTERNAL         (1<<2)
241 #define DT3000_AD_RETRIG_INTERNAL       (2<<2)
242 #define DT3000_AD_RETRIG_EXTERNAL       (3<<2)
243 #define DT3000_AD_EXTRETRIG             (4<<2)
244
245 #define DT3000_CHANNEL_MODE_SE          0
246 #define DT3000_CHANNEL_MODE_DI          1
247
248 struct dt3k_private {
249         void __iomem *io_addr;
250         unsigned int lock;
251         unsigned int ao_readback[2];
252         unsigned int ai_front;
253         unsigned int ai_rear;
254 };
255
256 #ifdef DEBUG
257 static char *intr_flags[] = {
258         "AdFull", "AdSwError", "AdHwError", "DaEmpty",
259         "DaSwError", "DaHwError", "CtDone", "CmDone",
260 };
261
262 static void debug_intr_flags(unsigned int flags)
263 {
264         int i;
265         printk(KERN_DEBUG "dt3k: intr_flags:");
266         for (i = 0; i < 8; i++) {
267                 if (flags & (1 << i))
268                         printk(KERN_CONT " %s", intr_flags[i]);
269         }
270         printk(KERN_CONT "\n");
271 }
272 #endif
273
274 #define TIMEOUT 100
275
276 static void dt3k_send_cmd(struct comedi_device *dev, unsigned int cmd)
277 {
278         struct dt3k_private *devpriv = dev->private;
279         int i;
280         unsigned int status = 0;
281
282         writew(cmd, devpriv->io_addr + DPR_Command_Mbx);
283
284         for (i = 0; i < TIMEOUT; i++) {
285                 status = readw(devpriv->io_addr + DPR_Command_Mbx);
286                 if ((status & DT3000_COMPLETION_MASK) != DT3000_NOTPROCESSED)
287                         break;
288                 udelay(1);
289         }
290
291         if ((status & DT3000_COMPLETION_MASK) != DT3000_NOERROR)
292                 dev_dbg(dev->class_dev, "%s: timeout/error status=0x%04x\n",
293                         __func__, status);
294 }
295
296 static unsigned int dt3k_readsingle(struct comedi_device *dev,
297                                     unsigned int subsys, unsigned int chan,
298                                     unsigned int gain)
299 {
300         struct dt3k_private *devpriv = dev->private;
301
302         writew(subsys, devpriv->io_addr + DPR_SubSys);
303
304         writew(chan, devpriv->io_addr + DPR_Params(0));
305         writew(gain, devpriv->io_addr + DPR_Params(1));
306
307         dt3k_send_cmd(dev, CMD_READSINGLE);
308
309         return readw(devpriv->io_addr + DPR_Params(2));
310 }
311
312 static void dt3k_writesingle(struct comedi_device *dev, unsigned int subsys,
313                              unsigned int chan, unsigned int data)
314 {
315         struct dt3k_private *devpriv = dev->private;
316
317         writew(subsys, devpriv->io_addr + DPR_SubSys);
318
319         writew(chan, devpriv->io_addr + DPR_Params(0));
320         writew(0, devpriv->io_addr + DPR_Params(1));
321         writew(data, devpriv->io_addr + DPR_Params(2));
322
323         dt3k_send_cmd(dev, CMD_WRITESINGLE);
324 }
325
326 static void dt3k_ai_empty_fifo(struct comedi_device *dev,
327                                struct comedi_subdevice *s)
328 {
329         struct dt3k_private *devpriv = dev->private;
330         int front;
331         int rear;
332         int count;
333         int i;
334         unsigned short data;
335
336         front = readw(devpriv->io_addr + DPR_AD_Buf_Front);
337         count = front - devpriv->ai_front;
338         if (count < 0)
339                 count += AI_FIFO_DEPTH;
340
341         rear = devpriv->ai_rear;
342
343         for (i = 0; i < count; i++) {
344                 data = readw(devpriv->io_addr + DPR_ADC_buffer + rear);
345                 comedi_buf_put(s->async, data);
346                 rear++;
347                 if (rear >= AI_FIFO_DEPTH)
348                         rear = 0;
349         }
350
351         devpriv->ai_rear = rear;
352         writew(rear, devpriv->io_addr + DPR_AD_Buf_Rear);
353 }
354
355 static int dt3k_ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
356 {
357         struct dt3k_private *devpriv = dev->private;
358
359         writew(SUBS_AI, devpriv->io_addr + DPR_SubSys);
360         dt3k_send_cmd(dev, CMD_STOP);
361
362         writew(0, devpriv->io_addr + DPR_Int_Mask);
363
364         return 0;
365 }
366
367 static int debug_n_ints;
368
369 /* FIXME! Assumes shared interrupt is for this card. */
370 /* What's this debug_n_ints stuff? Obviously needs some work... */
371 static irqreturn_t dt3k_interrupt(int irq, void *d)
372 {
373         struct comedi_device *dev = d;
374         struct dt3k_private *devpriv = dev->private;
375         struct comedi_subdevice *s;
376         unsigned int status;
377
378         if (!dev->attached)
379                 return IRQ_NONE;
380
381         s = &dev->subdevices[0];
382         status = readw(devpriv->io_addr + DPR_Intr_Flag);
383 #ifdef DEBUG
384         debug_intr_flags(status);
385 #endif
386
387         if (status & DT3000_ADFULL) {
388                 dt3k_ai_empty_fifo(dev, s);
389                 s->async->events |= COMEDI_CB_BLOCK;
390         }
391
392         if (status & (DT3000_ADSWERR | DT3000_ADHWERR))
393                 s->async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
394
395         debug_n_ints++;
396         if (debug_n_ints >= 10) {
397                 dt3k_ai_cancel(dev, s);
398                 s->async->events |= COMEDI_CB_EOA;
399         }
400
401         comedi_event(dev, s);
402         return IRQ_HANDLED;
403 }
404
405 static int dt3k_ns_to_timer(unsigned int timer_base, unsigned int *nanosec,
406                             unsigned int round_mode)
407 {
408         int divider, base, prescale;
409
410         /* This function needs improvment */
411         /* Don't know if divider==0 works. */
412
413         for (prescale = 0; prescale < 16; prescale++) {
414                 base = timer_base * (prescale + 1);
415                 switch (round_mode) {
416                 case TRIG_ROUND_NEAREST:
417                 default:
418                         divider = (*nanosec + base / 2) / base;
419                         break;
420                 case TRIG_ROUND_DOWN:
421                         divider = (*nanosec) / base;
422                         break;
423                 case TRIG_ROUND_UP:
424                         divider = (*nanosec) / base;
425                         break;
426                 }
427                 if (divider < 65536) {
428                         *nanosec = divider * base;
429                         return (prescale << 16) | (divider);
430                 }
431         }
432
433         prescale = 15;
434         base = timer_base * (1 << prescale);
435         divider = 65535;
436         *nanosec = divider * base;
437         return (prescale << 16) | (divider);
438 }
439
440 static int dt3k_ai_cmdtest(struct comedi_device *dev,
441                            struct comedi_subdevice *s, struct comedi_cmd *cmd)
442 {
443         const struct dt3k_boardtype *this_board = comedi_board(dev);
444         int err = 0;
445         int tmp;
446
447         /* Step 1 : check if triggers are trivially valid */
448
449         err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW);
450         err |= cfc_check_trigger_src(&cmd->scan_begin_src, TRIG_TIMER);
451         err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_TIMER);
452         err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
453         err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT);
454
455         if (err)
456                 return 1;
457
458         /* Step 2a : make sure trigger sources are unique */
459         /* Step 2b : and mutually compatible */
460
461         if (err)
462                 return 2;
463
464         /* Step 3: check if arguments are trivially valid */
465
466         err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
467
468         if (cmd->scan_begin_src == TRIG_TIMER) {
469                 err |= cfc_check_trigger_arg_min(&cmd->scan_begin_arg,
470                                                  this_board->ai_speed);
471                 err |= cfc_check_trigger_arg_max(&cmd->scan_begin_arg,
472                                                  100 * 16 * 65535);
473         }
474
475         if (cmd->convert_src == TRIG_TIMER) {
476                 err |= cfc_check_trigger_arg_min(&cmd->convert_arg,
477                                                  this_board->ai_speed);
478                 err |= cfc_check_trigger_arg_max(&cmd->convert_arg,
479                                                  50 * 16 * 65535);
480         }
481
482         err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
483
484         if (cmd->stop_src == TRIG_COUNT)
485                 err |= cfc_check_trigger_arg_max(&cmd->stop_arg, 0x00ffffff);
486         else    /* TRIG_NONE */
487                 err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
488
489         if (err)
490                 return 3;
491
492         /* step 4: fix up any arguments */
493
494         if (cmd->scan_begin_src == TRIG_TIMER) {
495                 tmp = cmd->scan_begin_arg;
496                 dt3k_ns_to_timer(100, &cmd->scan_begin_arg,
497                                  cmd->flags & TRIG_ROUND_MASK);
498                 if (tmp != cmd->scan_begin_arg)
499                         err++;
500         }
501
502         if (cmd->convert_src == TRIG_TIMER) {
503                 tmp = cmd->convert_arg;
504                 dt3k_ns_to_timer(50, &cmd->convert_arg,
505                                  cmd->flags & TRIG_ROUND_MASK);
506                 if (tmp != cmd->convert_arg)
507                         err++;
508                 if (cmd->scan_begin_src == TRIG_TIMER &&
509                     cmd->scan_begin_arg <
510                     cmd->convert_arg * cmd->scan_end_arg) {
511                         cmd->scan_begin_arg =
512                             cmd->convert_arg * cmd->scan_end_arg;
513                         err++;
514                 }
515         }
516
517         if (err)
518                 return 4;
519
520         return 0;
521 }
522
523 static int dt3k_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
524 {
525         struct dt3k_private *devpriv = dev->private;
526         struct comedi_cmd *cmd = &s->async->cmd;
527         int i;
528         unsigned int chan, range, aref;
529         unsigned int divider;
530         unsigned int tscandiv;
531         unsigned int mode;
532
533         for (i = 0; i < cmd->chanlist_len; i++) {
534                 chan = CR_CHAN(cmd->chanlist[i]);
535                 range = CR_RANGE(cmd->chanlist[i]);
536
537                 writew((range << 6) | chan,
538                        devpriv->io_addr + DPR_ADC_buffer + i);
539         }
540         aref = CR_AREF(cmd->chanlist[0]);
541
542         writew(cmd->scan_end_arg, devpriv->io_addr + DPR_Params(0));
543
544         if (cmd->convert_src == TRIG_TIMER) {
545                 divider = dt3k_ns_to_timer(50, &cmd->convert_arg,
546                                            cmd->flags & TRIG_ROUND_MASK);
547                 writew((divider >> 16), devpriv->io_addr + DPR_Params(1));
548                 writew((divider & 0xffff), devpriv->io_addr + DPR_Params(2));
549         }
550
551         if (cmd->scan_begin_src == TRIG_TIMER) {
552                 tscandiv = dt3k_ns_to_timer(100, &cmd->scan_begin_arg,
553                                             cmd->flags & TRIG_ROUND_MASK);
554                 writew((tscandiv >> 16), devpriv->io_addr + DPR_Params(3));
555                 writew((tscandiv & 0xffff), devpriv->io_addr + DPR_Params(4));
556         }
557
558         mode = DT3000_AD_RETRIG_INTERNAL | 0 | 0;
559         writew(mode, devpriv->io_addr + DPR_Params(5));
560         writew(aref == AREF_DIFF, devpriv->io_addr + DPR_Params(6));
561
562         writew(AI_FIFO_DEPTH / 2, devpriv->io_addr + DPR_Params(7));
563
564         writew(SUBS_AI, devpriv->io_addr + DPR_SubSys);
565         dt3k_send_cmd(dev, CMD_CONFIG);
566
567         writew(DT3000_ADFULL | DT3000_ADSWERR | DT3000_ADHWERR,
568                devpriv->io_addr + DPR_Int_Mask);
569
570         debug_n_ints = 0;
571
572         writew(SUBS_AI, devpriv->io_addr + DPR_SubSys);
573         dt3k_send_cmd(dev, CMD_START);
574
575         return 0;
576 }
577
578 static int dt3k_ai_insn(struct comedi_device *dev, struct comedi_subdevice *s,
579                         struct comedi_insn *insn, unsigned int *data)
580 {
581         int i;
582         unsigned int chan, gain, aref;
583
584         chan = CR_CHAN(insn->chanspec);
585         gain = CR_RANGE(insn->chanspec);
586         /* XXX docs don't explain how to select aref */
587         aref = CR_AREF(insn->chanspec);
588
589         for (i = 0; i < insn->n; i++)
590                 data[i] = dt3k_readsingle(dev, SUBS_AI, chan, gain);
591
592         return i;
593 }
594
595 static int dt3k_ao_insn(struct comedi_device *dev, struct comedi_subdevice *s,
596                         struct comedi_insn *insn, unsigned int *data)
597 {
598         struct dt3k_private *devpriv = dev->private;
599         int i;
600         unsigned int chan;
601
602         chan = CR_CHAN(insn->chanspec);
603         for (i = 0; i < insn->n; i++) {
604                 dt3k_writesingle(dev, SUBS_AO, chan, data[i]);
605                 devpriv->ao_readback[chan] = data[i];
606         }
607
608         return i;
609 }
610
611 static int dt3k_ao_insn_read(struct comedi_device *dev,
612                              struct comedi_subdevice *s,
613                              struct comedi_insn *insn, unsigned int *data)
614 {
615         struct dt3k_private *devpriv = dev->private;
616         int i;
617         unsigned int chan;
618
619         chan = CR_CHAN(insn->chanspec);
620         for (i = 0; i < insn->n; i++)
621                 data[i] = devpriv->ao_readback[chan];
622
623         return i;
624 }
625
626 static void dt3k_dio_config(struct comedi_device *dev, int bits)
627 {
628         struct dt3k_private *devpriv = dev->private;
629
630         /* XXX */
631         writew(SUBS_DOUT, devpriv->io_addr + DPR_SubSys);
632
633         writew(bits, devpriv->io_addr + DPR_Params(0));
634 #if 0
635         /* don't know */
636         writew(0, devpriv->io_addr + DPR_Params(1));
637         writew(0, devpriv->io_addr + DPR_Params(2));
638 #endif
639
640         dt3k_send_cmd(dev, CMD_CONFIG);
641 }
642
643 static int dt3k_dio_insn_config(struct comedi_device *dev,
644                                 struct comedi_subdevice *s,
645                                 struct comedi_insn *insn,
646                                 unsigned int *data)
647 {
648         unsigned int chan = CR_CHAN(insn->chanspec);
649         unsigned int mask;
650         int ret;
651
652         if (chan < 4)
653                 mask = 0x0f;
654         else
655                 mask = 0xf0;
656
657         ret = comedi_dio_insn_config(dev, s, insn, data, mask);
658         if (ret)
659                 return ret;
660
661         dt3k_dio_config(dev, (s->io_bits & 0x01) | ((s->io_bits & 0x10) >> 3));
662
663         return insn->n;
664 }
665
666 static int dt3k_dio_insn_bits(struct comedi_device *dev,
667                               struct comedi_subdevice *s,
668                               struct comedi_insn *insn,
669                               unsigned int *data)
670 {
671         if (comedi_dio_update_state(s, data))
672                 dt3k_writesingle(dev, SUBS_DOUT, 0, s->state);
673
674         data[1] = dt3k_readsingle(dev, SUBS_DIN, 0, 0);
675
676         return insn->n;
677 }
678
679 static int dt3k_mem_insn_read(struct comedi_device *dev,
680                               struct comedi_subdevice *s,
681                               struct comedi_insn *insn, unsigned int *data)
682 {
683         struct dt3k_private *devpriv = dev->private;
684         unsigned int addr = CR_CHAN(insn->chanspec);
685         int i;
686
687         for (i = 0; i < insn->n; i++) {
688                 writew(SUBS_MEM, devpriv->io_addr + DPR_SubSys);
689                 writew(addr, devpriv->io_addr + DPR_Params(0));
690                 writew(1, devpriv->io_addr + DPR_Params(1));
691
692                 dt3k_send_cmd(dev, CMD_READCODE);
693
694                 data[i] = readw(devpriv->io_addr + DPR_Params(2));
695         }
696
697         return i;
698 }
699
700 static int dt3000_auto_attach(struct comedi_device *dev,
701                               unsigned long context)
702 {
703         struct pci_dev *pcidev = comedi_to_pci_dev(dev);
704         const struct dt3k_boardtype *this_board = NULL;
705         struct dt3k_private *devpriv;
706         struct comedi_subdevice *s;
707         int ret = 0;
708
709         if (context < ARRAY_SIZE(dt3k_boardtypes))
710                 this_board = &dt3k_boardtypes[context];
711         if (!this_board)
712                 return -ENODEV;
713         dev->board_ptr = this_board;
714         dev->board_name = this_board->name;
715
716         devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
717         if (!devpriv)
718                 return -ENOMEM;
719
720         ret = comedi_pci_enable(dev);
721         if (ret < 0)
722                 return ret;
723
724         devpriv->io_addr = pci_ioremap_bar(pcidev, 0);
725         if (!devpriv->io_addr)
726                 return -ENOMEM;
727
728         ret = request_irq(pcidev->irq, dt3k_interrupt, IRQF_SHARED,
729                           dev->board_name, dev);
730         if (ret)
731                 return ret;
732         dev->irq = pcidev->irq;
733
734         ret = comedi_alloc_subdevices(dev, 4);
735         if (ret)
736                 return ret;
737
738         s = &dev->subdevices[0];
739         dev->read_subdev = s;
740         /* ai subdevice */
741         s->type         = COMEDI_SUBD_AI;
742         s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_DIFF | SDF_CMD_READ;
743         s->n_chan       = this_board->adchan;
744         s->insn_read    = dt3k_ai_insn;
745         s->maxdata      = (1 << this_board->adbits) - 1;
746         s->len_chanlist = 512;
747         s->range_table  = &range_dt3000_ai;     /* XXX */
748         s->do_cmd       = dt3k_ai_cmd;
749         s->do_cmdtest   = dt3k_ai_cmdtest;
750         s->cancel       = dt3k_ai_cancel;
751
752         s = &dev->subdevices[1];
753         /* ao subsystem */
754         s->type         = COMEDI_SUBD_AO;
755         s->subdev_flags = SDF_WRITABLE;
756         s->n_chan       = 2;
757         s->insn_read    = dt3k_ao_insn_read;
758         s->insn_write   = dt3k_ao_insn;
759         s->maxdata      = (1 << this_board->dabits) - 1;
760         s->len_chanlist = 1;
761         s->range_table  = &range_bipolar10;
762
763         s = &dev->subdevices[2];
764         /* dio subsystem */
765         s->type         = COMEDI_SUBD_DIO;
766         s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
767         s->n_chan       = 8;
768         s->insn_config  = dt3k_dio_insn_config;
769         s->insn_bits    = dt3k_dio_insn_bits;
770         s->maxdata      = 1;
771         s->len_chanlist = 8;
772         s->range_table  = &range_digital;
773
774         s = &dev->subdevices[3];
775         /* mem subsystem */
776         s->type         = COMEDI_SUBD_MEMORY;
777         s->subdev_flags = SDF_READABLE;
778         s->n_chan       = 0x1000;
779         s->insn_read    = dt3k_mem_insn_read;
780         s->maxdata      = 0xff;
781         s->len_chanlist = 1;
782         s->range_table  = &range_unknown;
783
784 #if 0
785         s = &dev->subdevices[4];
786         /* proc subsystem */
787         s->type = COMEDI_SUBD_PROC;
788 #endif
789
790         dev_info(dev->class_dev, "%s attached\n", dev->board_name);
791
792         return 0;
793 }
794
795 static void dt3000_detach(struct comedi_device *dev)
796 {
797         struct dt3k_private *devpriv = dev->private;
798
799         if (dev->irq)
800                 free_irq(dev->irq, dev);
801         if (devpriv) {
802                 if (devpriv->io_addr)
803                         iounmap(devpriv->io_addr);
804         }
805         comedi_pci_disable(dev);
806 }
807
808 static struct comedi_driver dt3000_driver = {
809         .driver_name    = "dt3000",
810         .module         = THIS_MODULE,
811         .auto_attach    = dt3000_auto_attach,
812         .detach         = dt3000_detach,
813 };
814
815 static int dt3000_pci_probe(struct pci_dev *dev,
816                             const struct pci_device_id *id)
817 {
818         return comedi_pci_auto_config(dev, &dt3000_driver, id->driver_data);
819 }
820
821 static DEFINE_PCI_DEVICE_TABLE(dt3000_pci_table) = {
822         { PCI_VDEVICE(DT, 0x0022), BOARD_DT3001 },
823         { PCI_VDEVICE(DT, 0x0023), BOARD_DT3002 },
824         { PCI_VDEVICE(DT, 0x0024), BOARD_DT3003 },
825         { PCI_VDEVICE(DT, 0x0025), BOARD_DT3004 },
826         { PCI_VDEVICE(DT, 0x0026), BOARD_DT3005 },
827         { PCI_VDEVICE(DT, 0x0027), BOARD_DT3001_PGL },
828         { PCI_VDEVICE(DT, 0x0028), BOARD_DT3003_PGL },
829         { 0 }
830 };
831 MODULE_DEVICE_TABLE(pci, dt3000_pci_table);
832
833 static struct pci_driver dt3000_pci_driver = {
834         .name           = "dt3000",
835         .id_table       = dt3000_pci_table,
836         .probe          = dt3000_pci_probe,
837         .remove         = comedi_pci_auto_unconfig,
838 };
839 module_comedi_pci_driver(dt3000_driver, dt3000_pci_driver);
840
841 MODULE_AUTHOR("Comedi http://www.comedi.org");
842 MODULE_DESCRIPTION("Comedi low-level driver");
843 MODULE_LICENSE("GPL");