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