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