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