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