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