Merge remote-tracking branch 'lsk/v3.10/topic/coresight' into linux-linaro-lsk
[firefly-linux-kernel-4.4.55.git] / drivers / staging / comedi / drivers / das800.c
1 /*
2     comedi/drivers/das800.c
3     Driver for Keitley das800 series boards and compatibles
4     Copyright (C) 2000 Frank Mori Hess <fmhess@users.sourceforge.net>
5
6     COMEDI - Linux Control and Measurement Device Interface
7     Copyright (C) 2000 David A. Schleef <ds@schleef.org>
8
9     This program is free software; you can redistribute it and/or modify
10     it under the terms of the GNU General Public License as published by
11     the Free Software Foundation; either version 2 of the License, or
12     (at your option) any later version.
13
14     This program is distributed in the hope that it will be useful,
15     but WITHOUT ANY WARRANTY; without even the implied warranty of
16     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17     GNU General Public License for more details.
18
19     You should have received a copy of the GNU General Public License
20     along with this program; if not, write to the Free Software
21     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22
23 ************************************************************************
24 */
25 /*
26 Driver: das800
27 Description: Keithley Metrabyte DAS800 (& compatibles)
28 Author: Frank Mori Hess <fmhess@users.sourceforge.net>
29 Devices: [Keithley Metrabyte] DAS-800 (das-800), DAS-801 (das-801),
30   DAS-802 (das-802),
31   [Measurement Computing] CIO-DAS800 (cio-das800),
32   CIO-DAS801 (cio-das801), CIO-DAS802 (cio-das802),
33   CIO-DAS802/16 (cio-das802/16)
34 Status: works, cio-das802/16 untested - email me if you have tested it
35
36 Configuration options:
37   [0] - I/O port base address
38   [1] - IRQ (optional, required for timed or externally triggered conversions)
39
40 Notes:
41         IRQ can be omitted, although the cmd interface will not work without it.
42
43         All entries in the channel/gain list must use the same gain and be
44         consecutive channels counting upwards in channel number (these are
45         hardware limitations.)
46
47         I've never tested the gain setting stuff since I only have a
48         DAS-800 board with fixed gain.
49
50         The cio-das802/16 does not have a fifo-empty status bit!  Therefore
51         only fifo-half-full transfers are possible with this card.
52 */
53 /*
54
55 cmd triggers supported:
56         start_src:      TRIG_NOW | TRIG_EXT
57         scan_begin_src: TRIG_FOLLOW
58         scan_end_src:   TRIG_COUNT
59         convert_src:    TRIG_TIMER | TRIG_EXT
60         stop_src:       TRIG_NONE | TRIG_COUNT
61
62
63 */
64
65 #include <linux/interrupt.h>
66 #include "../comedidev.h"
67
68 #include <linux/ioport.h>
69 #include <linux/delay.h>
70
71 #include "8253.h"
72 #include "comedi_fc.h"
73
74 #define DAS800_SIZE           8
75 #define TIMER_BASE            1000
76 #define N_CHAN_AI             8 /*  number of analog input channels */
77
78 /* Registers for the das800 */
79
80 #define DAS800_LSB            0
81 #define   FIFO_EMPTY            0x1
82 #define   FIFO_OVF              0x2
83 #define DAS800_MSB            1
84 #define DAS800_CONTROL1       2
85 #define   CONTROL1_INTE         0x8
86 #define DAS800_CONV_CONTROL   2
87 #define   ITE                   0x1
88 #define   CASC                  0x2
89 #define   DTEN                  0x4
90 #define   IEOC                  0x8
91 #define   EACS                  0x10
92 #define   CONV_HCEN             0x80
93 #define DAS800_SCAN_LIMITS    2
94 #define DAS800_STATUS         2
95 #define   IRQ                   0x8
96 #define   BUSY                  0x80
97 #define DAS800_GAIN           3
98 #define   CIO_FFOV              0x8   /* cio-das802/16 fifo overflow */
99 #define   CIO_ENHF              0x90  /* cio-das802/16 fifo half full int ena */
100 #define   CONTROL1              0x80
101 #define   CONV_CONTROL          0xa0
102 #define   SCAN_LIMITS           0xc0
103 #define   ID                    0xe0
104 #define DAS800_8254           4
105 #define DAS800_STATUS2        7
106 #define   STATUS2_HCEN          0x80
107 #define   STATUS2_INTE          0X20
108 #define DAS800_ID             7
109
110 #define DAS802_16_HALF_FIFO_SZ  128
111
112 struct das800_board {
113         const char *name;
114         int ai_speed;
115         const struct comedi_lrange *ai_range;
116         int resolution;
117 };
118
119 static const struct comedi_lrange range_das801_ai = {
120         9, {
121                 BIP_RANGE(5),
122                 BIP_RANGE(10),
123                 UNI_RANGE(10),
124                 BIP_RANGE(0.5),
125                 UNI_RANGE(1),
126                 BIP_RANGE(0.05),
127                 UNI_RANGE(0.1),
128                 BIP_RANGE(0.01),
129                 UNI_RANGE(0.02)
130         }
131 };
132
133 static const struct comedi_lrange range_cio_das801_ai = {
134         9, {
135                 BIP_RANGE(5),
136                 BIP_RANGE(10),
137                 UNI_RANGE(10),
138                 BIP_RANGE(0.5),
139                 UNI_RANGE(1),
140                 BIP_RANGE(0.05),
141                 UNI_RANGE(0.1),
142                 BIP_RANGE(0.005),
143                 UNI_RANGE(0.01)
144         }
145 };
146
147 static const struct comedi_lrange range_das802_ai = {
148         9, {
149                 BIP_RANGE(5),
150                 BIP_RANGE(10),
151                 UNI_RANGE(10),
152                 BIP_RANGE(2.5),
153                 UNI_RANGE(5),
154                 BIP_RANGE(1.25),
155                 UNI_RANGE(2.5),
156                 BIP_RANGE(0.625),
157                 UNI_RANGE(1.25)
158         }
159 };
160
161 static const struct comedi_lrange range_das80216_ai = {
162         8, {
163                 BIP_RANGE(10),
164                 UNI_RANGE(10),
165                 BIP_RANGE(5),
166                 UNI_RANGE(5),
167                 BIP_RANGE(2.5),
168                 UNI_RANGE(2.5),
169                 BIP_RANGE(1.25),
170                 UNI_RANGE(1.25)
171         }
172 };
173
174 enum das800_boardinfo {
175         BOARD_DAS800,
176         BOARD_CIODAS800,
177         BOARD_DAS801,
178         BOARD_CIODAS801,
179         BOARD_DAS802,
180         BOARD_CIODAS802,
181         BOARD_CIODAS80216,
182 };
183
184 static const struct das800_board das800_boards[] = {
185         [BOARD_DAS800] = {
186                 .name           = "das-800",
187                 .ai_speed       = 25000,
188                 .ai_range       = &range_bipolar5,
189                 .resolution     = 12,
190         },
191         [BOARD_CIODAS800] = {
192                 .name           = "cio-das800",
193                 .ai_speed       = 20000,
194                 .ai_range       = &range_bipolar5,
195                 .resolution     = 12,
196         },
197         [BOARD_DAS801] = {
198                 .name           = "das-801",
199                 .ai_speed       = 25000,
200                 .ai_range       = &range_das801_ai,
201                 .resolution     = 12,
202         },
203         [BOARD_CIODAS801] = {
204                 .name           = "cio-das801",
205                 .ai_speed       = 20000,
206                 .ai_range       = &range_cio_das801_ai,
207                 .resolution     = 12,
208         },
209         [BOARD_DAS802] = {
210                 .name           = "das-802",
211                 .ai_speed       = 25000,
212                 .ai_range       = &range_das802_ai,
213                 .resolution     = 12,
214         },
215         [BOARD_CIODAS802] = {
216                 .name           = "cio-das802",
217                 .ai_speed       = 20000,
218                 .ai_range       = &range_das802_ai,
219                 .resolution     = 12,
220         },
221         [BOARD_CIODAS80216] = {
222                 .name           = "cio-das802/16",
223                 .ai_speed       = 10000,
224                 .ai_range       = &range_das80216_ai,
225                 .resolution     = 16,
226         },
227 };
228
229 struct das800_private {
230         unsigned int count;     /* number of data points left to be taken */
231         unsigned int divisor1;  /* counter 1 value for timed conversions */
232         unsigned int divisor2;  /* counter 2 value for timed conversions */
233         unsigned int do_bits;   /* digital output bits */
234         bool forever;           /* flag that we should take data forever */
235 };
236
237 static void das800_ind_write(struct comedi_device *dev,
238                              unsigned val, unsigned reg)
239 {
240         /*
241          * Select dev->iobase + 2 to be desired register
242          * then write to that register.
243          */
244         outb(reg, dev->iobase + DAS800_GAIN);
245         outb(val, dev->iobase + 2);
246 }
247
248 static unsigned das800_ind_read(struct comedi_device *dev, unsigned reg)
249 {
250         /*
251          * Select dev->iobase + 7 to be desired register
252          * then read from that register.
253          */
254         outb(reg, dev->iobase + DAS800_GAIN);
255         return inb(dev->iobase + 7);
256 }
257
258 static void das800_enable(struct comedi_device *dev)
259 {
260         const struct das800_board *thisboard = comedi_board(dev);
261         struct das800_private *devpriv = dev->private;
262         unsigned long irq_flags;
263
264         spin_lock_irqsave(&dev->spinlock, irq_flags);
265         /*  enable fifo-half full interrupts for cio-das802/16 */
266         if (thisboard->resolution == 16)
267                 outb(CIO_ENHF, dev->iobase + DAS800_GAIN);
268         /* enable hardware triggering */
269         das800_ind_write(dev, CONV_HCEN, CONV_CONTROL);
270         /* enable card's interrupt */
271         das800_ind_write(dev, CONTROL1_INTE | devpriv->do_bits, CONTROL1);
272         spin_unlock_irqrestore(&dev->spinlock, irq_flags);
273 }
274
275 static void das800_disable(struct comedi_device *dev)
276 {
277         unsigned long irq_flags;
278
279         spin_lock_irqsave(&dev->spinlock, irq_flags);
280         /* disable hardware triggering of conversions */
281         das800_ind_write(dev, 0x0, CONV_CONTROL);
282         spin_unlock_irqrestore(&dev->spinlock, irq_flags);
283 }
284
285 static int das800_set_frequency(struct comedi_device *dev)
286 {
287         struct das800_private *devpriv = dev->private;
288         int err = 0;
289
290         if (i8254_load(dev->iobase + DAS800_8254, 0, 1, devpriv->divisor1, 2))
291                 err++;
292         if (i8254_load(dev->iobase + DAS800_8254, 0, 2, devpriv->divisor2, 2))
293                 err++;
294         if (err)
295                 return -1;
296
297         return 0;
298 }
299
300 static int das800_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
301 {
302         struct das800_private *devpriv = dev->private;
303
304         devpriv->forever = false;
305         devpriv->count = 0;
306         das800_disable(dev);
307         return 0;
308 }
309
310 static int das800_ai_do_cmdtest(struct comedi_device *dev,
311                                 struct comedi_subdevice *s,
312                                 struct comedi_cmd *cmd)
313 {
314         const struct das800_board *thisboard = comedi_board(dev);
315         struct das800_private *devpriv = dev->private;
316         int err = 0;
317
318         /* Step 1 : check if triggers are trivially valid */
319
320         err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_EXT);
321         err |= cfc_check_trigger_src(&cmd->scan_begin_src, TRIG_FOLLOW);
322         err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_TIMER | TRIG_EXT);
323         err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
324         err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE);
325
326         if (err)
327                 return 1;
328
329         /* Step 2a : make sure trigger sources are unique */
330
331         err |= cfc_check_trigger_is_unique(cmd->start_src);
332         err |= cfc_check_trigger_is_unique(cmd->convert_src);
333         err |= cfc_check_trigger_is_unique(cmd->stop_src);
334
335         /* Step 2b : and mutually compatible */
336
337         if (err)
338                 return 2;
339
340         /* Step 3: check if arguments are trivially valid */
341
342         err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
343
344         if (cmd->convert_src == TRIG_TIMER)
345                 err |= cfc_check_trigger_arg_min(&cmd->convert_arg,
346                                                  thisboard->ai_speed);
347
348         err |= cfc_check_trigger_arg_min(&cmd->chanlist_len, 1);
349         err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
350
351         if (cmd->stop_src == TRIG_COUNT)
352                 err |= cfc_check_trigger_arg_min(&cmd->stop_arg, 1);
353         else    /* TRIG_NONE */
354                 err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
355
356         if (err)
357                 return 3;
358
359         /* step 4: fix up any arguments */
360
361         if (cmd->convert_src == TRIG_TIMER) {
362                 int tmp = cmd->convert_arg;
363
364                 /* calculate counter values that give desired timing */
365                 i8253_cascade_ns_to_timer_2div(TIMER_BASE,
366                                                &devpriv->divisor1,
367                                                &devpriv->divisor2,
368                                                &cmd->convert_arg,
369                                                cmd->flags & TRIG_ROUND_MASK);
370                 if (tmp != cmd->convert_arg)
371                         err++;
372         }
373
374         if (err)
375                 return 4;
376
377         /*  check channel/gain list against card's limitations */
378         if (cmd->chanlist) {
379                 unsigned int chan = CR_CHAN(cmd->chanlist[0]);
380                 unsigned int range = CR_RANGE(cmd->chanlist[0]);
381                 unsigned int next;
382                 int i;
383
384                 for (i = 1; i < cmd->chanlist_len; i++) {
385                         next = cmd->chanlist[i];
386                         if (CR_CHAN(next) != (chan + i) % N_CHAN_AI) {
387                                 dev_err(dev->class_dev,
388                                         "chanlist must be consecutive, counting upwards\n");
389                                 err++;
390                         }
391                         if (CR_RANGE(next) != range) {
392                                 dev_err(dev->class_dev,
393                                         "chanlist must all have the same gain\n");
394                                 err++;
395                         }
396                 }
397         }
398
399         if (err)
400                 return 5;
401
402         return 0;
403 }
404
405 static int das800_ai_do_cmd(struct comedi_device *dev,
406                             struct comedi_subdevice *s)
407 {
408         const struct das800_board *thisboard = comedi_board(dev);
409         struct das800_private *devpriv = dev->private;
410         struct comedi_async *async = s->async;
411         unsigned int gain = CR_RANGE(async->cmd.chanlist[0]);
412         unsigned int start_chan = CR_CHAN(async->cmd.chanlist[0]);
413         unsigned int end_chan = (start_chan + async->cmd.chanlist_len - 1) % 8;
414         unsigned int scan_chans = (end_chan << 3) | start_chan;
415         int conv_bits;
416         unsigned long irq_flags;
417
418         das800_disable(dev);
419
420         spin_lock_irqsave(&dev->spinlock, irq_flags);
421         /* set scan limits */
422         das800_ind_write(dev, scan_chans, SCAN_LIMITS);
423         spin_unlock_irqrestore(&dev->spinlock, irq_flags);
424
425         /* set gain */
426         if (thisboard->resolution == 12 && gain > 0)
427                 gain += 0x7;
428         gain &= 0xf;
429         outb(gain, dev->iobase + DAS800_GAIN);
430
431         switch (async->cmd.stop_src) {
432         case TRIG_COUNT:
433                 devpriv->count = async->cmd.stop_arg * async->cmd.chanlist_len;
434                 devpriv->forever = false;
435                 break;
436         case TRIG_NONE:
437                 devpriv->forever = true;
438                 devpriv->count = 0;
439                 break;
440         default:
441                 break;
442         }
443
444         /* enable auto channel scan, send interrupts on end of conversion
445          * and set clock source to internal or external
446          */
447         conv_bits = 0;
448         conv_bits |= EACS | IEOC;
449         if (async->cmd.start_src == TRIG_EXT)
450                 conv_bits |= DTEN;
451         switch (async->cmd.convert_src) {
452         case TRIG_TIMER:
453                 conv_bits |= CASC | ITE;
454                 /* set conversion frequency */
455                 if (das800_set_frequency(dev) < 0) {
456                         comedi_error(dev, "Error setting up counters");
457                         return -1;
458                 }
459                 break;
460         case TRIG_EXT:
461                 break;
462         default:
463                 break;
464         }
465
466         spin_lock_irqsave(&dev->spinlock, irq_flags);
467         das800_ind_write(dev, conv_bits, CONV_CONTROL);
468         spin_unlock_irqrestore(&dev->spinlock, irq_flags);
469
470         async->events = 0;
471         das800_enable(dev);
472         return 0;
473 }
474
475 static unsigned int das800_ai_get_sample(struct comedi_device *dev)
476 {
477         unsigned int lsb = inb(dev->iobase + DAS800_LSB);
478         unsigned int msb = inb(dev->iobase + DAS800_MSB);
479
480         return (msb << 8) | lsb;
481 }
482
483 static irqreturn_t das800_interrupt(int irq, void *d)
484 {
485         struct comedi_device *dev = d;
486         struct das800_private *devpriv = dev->private;
487         struct comedi_subdevice *s = dev->read_subdev;
488         struct comedi_async *async = s ? s->async : NULL;
489         unsigned long irq_flags;
490         unsigned int status;
491         unsigned int val;
492         bool fifo_empty;
493         bool fifo_overflow;
494         int i;
495
496         status = inb(dev->iobase + DAS800_STATUS);
497         if (!(status & IRQ))
498                 return IRQ_NONE;
499         if (!dev->attached)
500                 return IRQ_HANDLED;
501
502         spin_lock_irqsave(&dev->spinlock, irq_flags);
503         status = das800_ind_read(dev, CONTROL1) & STATUS2_HCEN;
504         /*
505          * Don't release spinlock yet since we want to make sure
506          * no one else disables hardware conversions.
507          */
508
509         /* if hardware conversions are not enabled, then quit */
510         if (status == 0) {
511                 spin_unlock_irqrestore(&dev->spinlock, irq_flags);
512                 return IRQ_HANDLED;
513         }
514
515         for (i = 0; i < DAS802_16_HALF_FIFO_SZ; i++) {
516                 val = das800_ai_get_sample(dev);
517                 if (s->maxdata == 0x0fff) {
518                         fifo_empty = !!(val & FIFO_EMPTY);
519                         fifo_overflow = !!(val & FIFO_OVF);
520                 } else {
521                         /* cio-das802/16 has no fifo empty status bit */
522                         fifo_empty = false;
523                         fifo_overflow = !!(inb(dev->iobase + DAS800_GAIN) &
524                                                 CIO_FFOV);
525                 }
526                 if (fifo_empty || fifo_overflow)
527                         break;
528
529                 if (s->maxdata == 0x0fff)
530                         val >>= 4;      /* 12-bit sample */
531
532                 /* if there are more data points to collect */
533                 if (devpriv->count > 0 || devpriv->forever) {
534                         /* write data point to buffer */
535                         cfc_write_to_buffer(s, val & s->maxdata);
536                         devpriv->count--;
537                 }
538         }
539         async->events |= COMEDI_CB_BLOCK;
540
541         if (fifo_overflow) {
542                 spin_unlock_irqrestore(&dev->spinlock, irq_flags);
543                 das800_cancel(dev, s);
544                 async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
545                 comedi_event(dev, s);
546                 async->events = 0;
547                 return IRQ_HANDLED;
548         }
549
550         if (devpriv->count > 0 || devpriv->forever) {
551                 /* Re-enable card's interrupt.
552                  * We already have spinlock, so indirect addressing is safe */
553                 das800_ind_write(dev, CONTROL1_INTE | devpriv->do_bits,
554                                  CONTROL1);
555                 spin_unlock_irqrestore(&dev->spinlock, irq_flags);
556         } else {
557                 /* otherwise, stop taking data */
558                 spin_unlock_irqrestore(&dev->spinlock, irq_flags);
559                 das800_disable(dev);
560                 async->events |= COMEDI_CB_EOA;
561         }
562         comedi_event(dev, s);
563         async->events = 0;
564         return IRQ_HANDLED;
565 }
566
567 static int das800_wait_for_conv(struct comedi_device *dev, int timeout)
568 {
569         int i;
570
571         for (i = 0; i < timeout; i++) {
572                 if (!(inb(dev->iobase + DAS800_STATUS) & BUSY))
573                         return 0;
574         }
575         return -ETIME;
576 }
577
578 static int das800_ai_insn_read(struct comedi_device *dev,
579                                struct comedi_subdevice *s,
580                                struct comedi_insn *insn,
581                                unsigned int *data)
582 {
583         struct das800_private *devpriv = dev->private;
584         unsigned int chan = CR_CHAN(insn->chanspec);
585         unsigned int range = CR_RANGE(insn->chanspec);
586         unsigned long irq_flags;
587         unsigned int val;
588         int ret;
589         int i;
590
591         das800_disable(dev);
592
593         /* set multiplexer */
594         spin_lock_irqsave(&dev->spinlock, irq_flags);
595         das800_ind_write(dev, chan | devpriv->do_bits, CONTROL1);
596         spin_unlock_irqrestore(&dev->spinlock, irq_flags);
597
598         /* set gain / range */
599         if (s->maxdata == 0x0fff && range)
600                 range += 0x7;
601         range &= 0xf;
602         outb(range, dev->iobase + DAS800_GAIN);
603
604         udelay(5);
605
606         for (i = 0; i < insn->n; i++) {
607                 /* trigger conversion */
608                 outb_p(0, dev->iobase + DAS800_MSB);
609
610                 ret = das800_wait_for_conv(dev, 1000);
611                 if (ret)
612                         return ret;
613
614                 val = das800_ai_get_sample(dev);
615                 if (s->maxdata == 0x0fff)
616                         val >>= 4;      /* 12-bit sample */
617                 data[i] = val & s->maxdata;
618         }
619
620         return insn->n;
621 }
622
623 static int das800_di_insn_bits(struct comedi_device *dev,
624                                struct comedi_subdevice *s,
625                                struct comedi_insn *insn,
626                                unsigned int *data)
627 {
628         data[1] = (inb(dev->iobase + DAS800_STATUS) >> 4) & 0x7;
629
630         return insn->n;
631 }
632
633 static int das800_do_insn_bits(struct comedi_device *dev,
634                                struct comedi_subdevice *s,
635                                struct comedi_insn *insn,
636                                unsigned int *data)
637 {
638         struct das800_private *devpriv = dev->private;
639         unsigned int mask = data[0];
640         unsigned int bits = data[1];
641         unsigned long irq_flags;
642
643         if (mask) {
644                 s->state &= ~mask;
645                 s->state |= (bits & mask);
646                 devpriv->do_bits = s->state << 4;
647
648                 spin_lock_irqsave(&dev->spinlock, irq_flags);
649                 das800_ind_write(dev, CONTROL1_INTE | devpriv->do_bits,
650                                  CONTROL1);
651                 spin_unlock_irqrestore(&dev->spinlock, irq_flags);
652         }
653
654         data[1] = s->state;
655
656         return insn->n;
657 }
658
659 static int das800_probe(struct comedi_device *dev)
660 {
661         const struct das800_board *thisboard = comedi_board(dev);
662         int board = thisboard ? thisboard - das800_boards : -EINVAL;
663         int id_bits;
664         unsigned long irq_flags;
665
666         spin_lock_irqsave(&dev->spinlock, irq_flags);
667         id_bits = das800_ind_read(dev, ID) & 0x3;
668         spin_unlock_irqrestore(&dev->spinlock, irq_flags);
669
670         switch (id_bits) {
671         case 0x0:
672                 if (board == BOARD_DAS800 || board == BOARD_CIODAS800)
673                         break;
674                 dev_dbg(dev->class_dev, "Board model (probed): DAS-800\n");
675                 board = BOARD_DAS800;
676                 break;
677         case 0x2:
678                 if (board == BOARD_DAS801 || board == BOARD_CIODAS801)
679                         break;
680                 dev_dbg(dev->class_dev, "Board model (probed): DAS-801\n");
681                 board = BOARD_DAS801;
682                 break;
683         case 0x3:
684                 if (board == BOARD_DAS802 || board == BOARD_CIODAS802 ||
685                     board == BOARD_CIODAS80216)
686                         break;
687                 dev_dbg(dev->class_dev, "Board model (probed): DAS-802\n");
688                 board = BOARD_DAS802;
689                 break;
690         default:
691                 dev_dbg(dev->class_dev, "Board model: 0x%x (unknown)\n",
692                         id_bits);
693                 board = -EINVAL;
694                 break;
695         }
696         return board;
697 }
698
699 static int das800_attach(struct comedi_device *dev, struct comedi_devconfig *it)
700 {
701         const struct das800_board *thisboard = comedi_board(dev);
702         struct das800_private *devpriv;
703         struct comedi_subdevice *s;
704         unsigned int irq = it->options[1];
705         unsigned long irq_flags;
706         int board;
707         int ret;
708
709         devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
710         if (!devpriv)
711                 return -ENOMEM;
712         dev->private = devpriv;
713
714         ret = comedi_request_region(dev, it->options[0], DAS800_SIZE);
715         if (ret)
716                 return ret;
717
718         board = das800_probe(dev);
719         if (board < 0) {
720                 dev_dbg(dev->class_dev, "unable to determine board type\n");
721                 return -ENODEV;
722         }
723         dev->board_ptr = das800_boards + board;
724         thisboard = comedi_board(dev);
725         dev->board_name = thisboard->name;
726
727         if (irq > 1 && irq <= 7) {
728                 ret = request_irq(irq, das800_interrupt, 0, dev->board_name,
729                                   dev);
730                 if (ret == 0)
731                         dev->irq = irq;
732         }
733
734         ret = comedi_alloc_subdevices(dev, 3);
735         if (ret)
736                 return ret;
737
738         /* Analog Input subdevice */
739         s = &dev->subdevices[0];
740         dev->read_subdev = s;
741         s->type         = COMEDI_SUBD_AI;
742         s->subdev_flags = SDF_READABLE | SDF_GROUND;
743         s->n_chan       = 8;
744         s->maxdata      = (1 << thisboard->resolution) - 1;
745         s->range_table  = thisboard->ai_range;
746         s->insn_read    = das800_ai_insn_read;
747         if (dev->irq) {
748                 s->subdev_flags |= SDF_CMD_READ;
749                 s->len_chanlist = 8;
750                 s->do_cmdtest   = das800_ai_do_cmdtest;
751                 s->do_cmd       = das800_ai_do_cmd;
752                 s->cancel       = das800_cancel;
753         }
754
755         /* Digital Input subdevice */
756         s = &dev->subdevices[1];
757         s->type         = COMEDI_SUBD_DI;
758         s->subdev_flags = SDF_READABLE;
759         s->n_chan       = 3;
760         s->maxdata      = 1;
761         s->range_table  = &range_digital;
762         s->insn_bits    = das800_di_insn_bits;
763
764         /* Digital Output subdevice */
765         s = &dev->subdevices[2];
766         s->type         = COMEDI_SUBD_DO;
767         s->subdev_flags = SDF_WRITABLE | SDF_READABLE;
768         s->n_chan       = 4;
769         s->maxdata      = 1;
770         s->range_table  = &range_digital;
771         s->insn_bits    = das800_do_insn_bits;
772
773         das800_disable(dev);
774
775         /* initialize digital out channels */
776         spin_lock_irqsave(&dev->spinlock, irq_flags);
777         das800_ind_write(dev, CONTROL1_INTE | devpriv->do_bits, CONTROL1);
778         spin_unlock_irqrestore(&dev->spinlock, irq_flags);
779
780         return 0;
781 };
782
783 static struct comedi_driver driver_das800 = {
784         .driver_name    = "das800",
785         .module         = THIS_MODULE,
786         .attach         = das800_attach,
787         .detach         = comedi_legacy_detach,
788         .num_names      = ARRAY_SIZE(das800_boards),
789         .board_name     = &das800_boards[0].name,
790         .offset         = sizeof(struct das800_board),
791 };
792 module_comedi_driver(driver_das800);
793
794 MODULE_AUTHOR("Comedi http://www.comedi.org");
795 MODULE_DESCRIPTION("Comedi low-level driver");
796 MODULE_LICENSE("GPL");