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