5 * COMEDI - Linux Control and Measurement Device Interface
6 * Copyright (C) 2000 David A. Schleef <ds@schleef.org>
7 * Copyright (C) 2000 Chris R. Baugher <baugher@enteract.com>
8 * Copyright (C) 2001,2002 Frank Mori Hess <fmhess@users.sourceforge.net>
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
23 * Description: DAS16 compatible boards
24 * Author: Sam Moore, Warren Jasper, ds, Chris Baugher, Frank Hess, Roman Fietze
25 * Devices: [Keithley Metrabyte] DAS-16 (das-16), DAS-16G (das-16g),
26 * DAS-16F (das-16f), DAS-1201 (das-1201), DAS-1202 (das-1202),
27 * DAS-1401 (das-1401), DAS-1402 (das-1402), DAS-1601 (das-1601),
28 * DAS-1602 (das-1602),
29 * [ComputerBoards] PC104-DAS16/JR (pc104-das16jr),
30 * PC104-DAS16JR/16 (pc104-das16jr/16), CIO-DAS16 (cio-das16),
31 * CIO-DAS16F (cio-das16/f), CIO-DAS16/JR (cio-das16/jr),
32 * CIO-DAS16JR/16 (cio-das16jr/16), CIO-DAS1401/12 (cio-das1401/12),
33 * CIO-DAS1402/12 (cio-das1402/12), CIO-DAS1402/16 (cio-das1402/16),
34 * CIO-DAS1601/12 (cio-das1601/12), CIO-DAS1602/12 (cio-das1602/12),
35 * CIO-DAS1602/16 (cio-das1602/16), CIO-DAS16/330 (cio-das16/330)
39 * A rewrite of the das16 and das1600 drivers.
42 * [0] - base io address
43 * [1] - irq (does nothing, irq is not used anymore)
44 * [2] - dma channel (optional, required for comedi_command support)
45 * [3] - master clock speed in MHz (optional, 1 or 10, ignored if
46 * board can probe clock, defaults to 1)
47 * [4] - analog input range lowest voltage in microvolts (optional,
48 * only useful if your board does not have software
50 * [5] - analog input range highest voltage in microvolts (optional,
51 * only useful if board does not have software programmable
53 * [6] - analog output range lowest voltage in microvolts (optional)
54 * [7] - analog output range highest voltage in microvolts (optional)
56 * Passing a zero for an option is the same as leaving it unspecified.
60 * Testing and debugging help provided by Daniel Koch.
64 * 4919.PDF (das1400, 1600)
66 * 4923.PDF (das1200, 1400, 1600)
68 * Computer boards manuals also available from their website
69 * www.measurementcomputing.com
72 #include <linux/module.h>
73 #include <linux/slab.h>
74 #include <linux/interrupt.h>
76 #include "../comedidev.h"
78 #include "comedi_isadma.h"
79 #include "comedi_fc.h"
83 #define DAS16_DMA_SIZE 0xff00 /* size in bytes of allocated dma buffer */
88 #define DAS16_TRIG_REG 0x00
89 #define DAS16_AI_LSB_REG 0x00
90 #define DAS16_AI_MSB_REG 0x01
91 #define DAS16_MUX_REG 0x02
92 #define DAS16_DIO_REG 0x03
93 #define DAS16_AO_LSB_REG(x) ((x) ? 0x06 : 0x04)
94 #define DAS16_AO_MSB_REG(x) ((x) ? 0x07 : 0x05)
95 #define DAS16_STATUS_REG 0x08
96 #define DAS16_STATUS_BUSY (1 << 7)
97 #define DAS16_STATUS_UNIPOLAR (1 << 6)
98 #define DAS16_STATUS_MUXBIT (1 << 5)
99 #define DAS16_STATUS_INT (1 << 4)
100 #define DAS16_CTRL_REG 0x09
101 #define DAS16_CTRL_INTE (1 << 7)
102 #define DAS16_CTRL_IRQ(x) (((x) & 0x7) << 4)
103 #define DAS16_CTRL_DMAE (1 << 2)
104 #define DAS16_CTRL_PACING_MASK (3 << 0)
105 #define DAS16_CTRL_INT_PACER (3 << 0)
106 #define DAS16_CTRL_EXT_PACER (2 << 0)
107 #define DAS16_CTRL_SOFT_PACER (0 << 0)
108 #define DAS16_PACER_REG 0x0a
109 #define DAS16_PACER_BURST_LEN(x) (((x) & 0xf) << 4)
110 #define DAS16_PACER_CTR0 (1 << 1)
111 #define DAS16_PACER_TRIG0 (1 << 0)
112 #define DAS16_GAIN_REG 0x0b
113 #define DAS16_TIMER_BASE_REG 0x0c /* to 0x0f */
115 #define DAS1600_CONV_REG 0x404
116 #define DAS1600_CONV_DISABLE (1 << 6)
117 #define DAS1600_BURST_REG 0x405
118 #define DAS1600_BURST_VAL (1 << 6)
119 #define DAS1600_ENABLE_REG 0x406
120 #define DAS1600_ENABLE_VAL (1 << 6)
121 #define DAS1600_STATUS_REG 0x407
122 #define DAS1600_STATUS_BME (1 << 6)
123 #define DAS1600_STATUS_ME (1 << 5)
124 #define DAS1600_STATUS_CD (1 << 4)
125 #define DAS1600_STATUS_WS (1 << 1)
126 #define DAS1600_STATUS_CLK_10MHZ (1 << 0)
128 static const struct comedi_lrange range_das1x01_bip
= {
137 static const struct comedi_lrange range_das1x01_unip
= {
146 static const struct comedi_lrange range_das1x02_bip
= {
155 static const struct comedi_lrange range_das1x02_unip
= {
164 static const struct comedi_lrange range_das16jr
= {
178 static const struct comedi_lrange range_das16jr_16
= {
191 static const int das16jr_gainlist
[] = { 8, 0, 1, 2, 3, 4, 5, 6, 7 };
192 static const int das16jr_16_gainlist
[] = { 0, 1, 2, 3, 4, 5, 6, 7 };
193 static const int das1600_gainlist
[] = { 0, 1, 2, 3 };
202 static const int *const das16_gainlists
[] = {
210 static const struct comedi_lrange
*const das16_ai_uni_lranges
[] = {
218 static const struct comedi_lrange
*const das16_ai_bip_lranges
[] = {
228 unsigned int ai_maxdata
;
229 unsigned int ai_speed
; /* max conversion speed in nanosec */
231 unsigned int has_ao
:1;
232 unsigned int has_8255
:1;
234 unsigned int i8255_offset
;
240 static const struct das16_board das16_boards
[] = {
243 .ai_maxdata
= 0x0fff,
245 .ai_pg
= das16_pg_none
,
248 .i8255_offset
= 0x10,
253 .ai_maxdata
= 0x0fff,
255 .ai_pg
= das16_pg_none
,
258 .i8255_offset
= 0x10,
263 .ai_maxdata
= 0x0fff,
265 .ai_pg
= das16_pg_none
,
268 .i8255_offset
= 0x10,
273 .ai_maxdata
= 0x0fff,
275 .ai_pg
= das16_pg_none
,
278 .i8255_offset
= 0x10,
282 .name
= "cio-das16/f",
283 .ai_maxdata
= 0x0fff,
285 .ai_pg
= das16_pg_none
,
288 .i8255_offset
= 0x10,
292 .name
= "cio-das16/jr",
293 .ai_maxdata
= 0x0fff,
295 .ai_pg
= das16_pg_16jr
,
299 .name
= "pc104-das16jr",
300 .ai_maxdata
= 0x0fff,
302 .ai_pg
= das16_pg_16jr
,
306 .name
= "cio-das16jr/16",
307 .ai_maxdata
= 0xffff,
309 .ai_pg
= das16_pg_16jr_16
,
313 .name
= "pc104-das16jr/16",
314 .ai_maxdata
= 0xffff,
316 .ai_pg
= das16_pg_16jr_16
,
321 .ai_maxdata
= 0x0fff,
323 .ai_pg
= das16_pg_none
,
325 .i8255_offset
= 0x400,
330 .ai_maxdata
= 0x0fff,
332 .ai_pg
= das16_pg_none
,
334 .i8255_offset
= 0x400,
339 .ai_maxdata
= 0x0fff,
341 .ai_pg
= das16_pg_1601
,
346 .ai_maxdata
= 0x0fff,
348 .ai_pg
= das16_pg_1602
,
353 .ai_maxdata
= 0x0fff,
355 .ai_pg
= das16_pg_1601
,
358 .i8255_offset
= 0x400,
363 .ai_maxdata
= 0x0fff,
365 .ai_pg
= das16_pg_1602
,
368 .i8255_offset
= 0x400,
372 .name
= "cio-das1401/12",
373 .ai_maxdata
= 0x0fff,
375 .ai_pg
= das16_pg_1601
,
379 .name
= "cio-das1402/12",
380 .ai_maxdata
= 0x0fff,
382 .ai_pg
= das16_pg_1602
,
386 .name
= "cio-das1402/16",
387 .ai_maxdata
= 0xffff,
389 .ai_pg
= das16_pg_1602
,
393 .name
= "cio-das1601/12",
394 .ai_maxdata
= 0x0fff,
396 .ai_pg
= das16_pg_1601
,
399 .i8255_offset
= 0x400,
403 .name
= "cio-das1602/12",
404 .ai_maxdata
= 0x0fff,
406 .ai_pg
= das16_pg_1602
,
409 .i8255_offset
= 0x400,
413 .name
= "cio-das1602/16",
414 .ai_maxdata
= 0xffff,
416 .ai_pg
= das16_pg_1602
,
419 .i8255_offset
= 0x400,
423 .name
= "cio-das16/330",
424 .ai_maxdata
= 0x0fff,
426 .ai_pg
= das16_pg_16jr
,
432 /* Period for timer interrupt in jiffies. It's a function
433 * to deal with possibility of dynamic HZ patches */
434 static inline int timer_period(void)
439 struct das16_private_struct
{
440 struct comedi_isadma
*dma
;
441 unsigned int clockbase
;
442 unsigned int ctrl_reg
;
443 unsigned int divisor1
;
444 unsigned int divisor2
;
445 struct timer_list timer
;
446 unsigned long extra_iobase
;
447 unsigned int can_burst
:1;
448 unsigned int timer_running
:1;
451 static void das16_interrupt(struct comedi_device
*dev
)
453 struct das16_private_struct
*devpriv
= dev
->private;
454 struct comedi_subdevice
*s
= dev
->read_subdev
;
455 struct comedi_async
*async
= s
->async
;
456 struct comedi_cmd
*cmd
= &async
->cmd
;
457 struct comedi_isadma
*dma
= devpriv
->dma
;
458 struct comedi_isadma_desc
*desc
= &dma
->desc
[dma
->cur_dma
];
459 unsigned long spin_flags
;
460 unsigned int residue
;
462 unsigned int nsamples
;
464 spin_lock_irqsave(&dev
->spinlock
, spin_flags
);
465 if (!(devpriv
->ctrl_reg
& DAS16_CTRL_DMAE
)) {
466 spin_unlock_irqrestore(&dev
->spinlock
, spin_flags
);
471 * The pc104-das16jr (at least) has problems if the dma
472 * transfer is interrupted in the middle of transferring
475 residue
= comedi_isadma_disable_on_sample(desc
->chan
,
476 comedi_bytes_per_sample(s
));
478 /* figure out how many samples to read */
479 if (residue
> desc
->size
) {
480 dev_err(dev
->class_dev
, "residue > transfer size!\n");
481 async
->events
|= COMEDI_CB_ERROR
;
484 nbytes
= desc
->size
- residue
;
486 nsamples
= comedi_bytes_to_samples(s
, nbytes
);
488 /* restart DMA if more samples are needed */
489 if (nsamples
&& nsamples
< comedi_nsamples_left(s
, nsamples
+ 1)) {
490 struct comedi_isadma_desc
*nxt_desc
;
492 dma
->cur_dma
= 1 - dma
->cur_dma
;
493 nxt_desc
= &dma
->desc
[dma
->cur_dma
];
494 nxt_desc
->size
= nxt_desc
->maxsize
;
495 comedi_isadma_program(nxt_desc
);
498 spin_unlock_irqrestore(&dev
->spinlock
, spin_flags
);
500 comedi_buf_write_samples(s
, desc
->virt_addr
, nsamples
);
502 if (cmd
->stop_src
== TRIG_COUNT
&& async
->scans_done
>= cmd
->stop_arg
)
503 async
->events
|= COMEDI_CB_EOA
;
505 comedi_handle_events(dev
, s
);
508 static void das16_timer_interrupt(unsigned long arg
)
510 struct comedi_device
*dev
= (struct comedi_device
*)arg
;
511 struct das16_private_struct
*devpriv
= dev
->private;
514 das16_interrupt(dev
);
516 spin_lock_irqsave(&dev
->spinlock
, flags
);
517 if (devpriv
->timer_running
)
518 mod_timer(&devpriv
->timer
, jiffies
+ timer_period());
519 spin_unlock_irqrestore(&dev
->spinlock
, flags
);
522 static int das16_ai_check_chanlist(struct comedi_device
*dev
,
523 struct comedi_subdevice
*s
,
524 struct comedi_cmd
*cmd
)
526 unsigned int chan0
= CR_CHAN(cmd
->chanlist
[0]);
527 unsigned int range0
= CR_RANGE(cmd
->chanlist
[0]);
530 for (i
= 1; i
< cmd
->chanlist_len
; i
++) {
531 unsigned int chan
= CR_CHAN(cmd
->chanlist
[i
]);
532 unsigned int range
= CR_RANGE(cmd
->chanlist
[i
]);
534 if (chan
!= ((chan0
+ i
) % s
->n_chan
)) {
535 dev_dbg(dev
->class_dev
,
536 "entries in chanlist must be consecutive channels, counting upwards\n");
540 if (range
!= range0
) {
541 dev_dbg(dev
->class_dev
,
542 "entries in chanlist must all have the same gain\n");
550 static int das16_cmd_test(struct comedi_device
*dev
, struct comedi_subdevice
*s
,
551 struct comedi_cmd
*cmd
)
553 const struct das16_board
*board
= dev
->board_ptr
;
554 struct das16_private_struct
*devpriv
= dev
->private;
556 unsigned int trig_mask
;
559 /* Step 1 : check if triggers are trivially valid */
561 err
|= cfc_check_trigger_src(&cmd
->start_src
, TRIG_NOW
);
563 trig_mask
= TRIG_FOLLOW
;
564 if (devpriv
->can_burst
)
565 trig_mask
|= TRIG_TIMER
| TRIG_EXT
;
566 err
|= cfc_check_trigger_src(&cmd
->scan_begin_src
, trig_mask
);
568 trig_mask
= TRIG_TIMER
| TRIG_EXT
;
569 if (devpriv
->can_burst
)
570 trig_mask
|= TRIG_NOW
;
571 err
|= cfc_check_trigger_src(&cmd
->convert_src
, trig_mask
);
573 err
|= cfc_check_trigger_src(&cmd
->scan_end_src
, TRIG_COUNT
);
574 err
|= cfc_check_trigger_src(&cmd
->stop_src
, TRIG_COUNT
| TRIG_NONE
);
579 /* Step 2a : make sure trigger sources are unique */
581 err
|= cfc_check_trigger_is_unique(cmd
->scan_begin_src
);
582 err
|= cfc_check_trigger_is_unique(cmd
->convert_src
);
583 err
|= cfc_check_trigger_is_unique(cmd
->stop_src
);
585 /* Step 2b : and mutually compatible */
587 /* make sure scan_begin_src and convert_src dont conflict */
588 if (cmd
->scan_begin_src
== TRIG_FOLLOW
&& cmd
->convert_src
== TRIG_NOW
)
590 if (cmd
->scan_begin_src
!= TRIG_FOLLOW
&& cmd
->convert_src
!= TRIG_NOW
)
596 /* Step 3: check if arguments are trivially valid */
598 err
|= cfc_check_trigger_arg_is(&cmd
->start_arg
, 0);
600 if (cmd
->scan_begin_src
== TRIG_FOLLOW
) /* internal trigger */
601 err
|= cfc_check_trigger_arg_is(&cmd
->scan_begin_arg
, 0);
603 err
|= cfc_check_trigger_arg_is(&cmd
->scan_end_arg
, cmd
->chanlist_len
);
605 /* check against maximum frequency */
606 if (cmd
->scan_begin_src
== TRIG_TIMER
)
607 err
|= cfc_check_trigger_arg_min(&cmd
->scan_begin_arg
,
608 board
->ai_speed
* cmd
->chanlist_len
);
610 if (cmd
->convert_src
== TRIG_TIMER
)
611 err
|= cfc_check_trigger_arg_min(&cmd
->convert_arg
,
614 if (cmd
->stop_src
== TRIG_COUNT
)
615 err
|= cfc_check_trigger_arg_min(&cmd
->stop_arg
, 1);
617 err
|= cfc_check_trigger_arg_is(&cmd
->stop_arg
, 0);
622 /* step 4: fix up arguments */
623 if (cmd
->scan_begin_src
== TRIG_TIMER
) {
624 arg
= cmd
->scan_begin_arg
;
625 i8253_cascade_ns_to_timer(devpriv
->clockbase
,
629 err
|= cfc_check_trigger_arg_is(&cmd
->scan_begin_arg
, arg
);
631 if (cmd
->convert_src
== TRIG_TIMER
) {
632 arg
= cmd
->convert_arg
;
633 i8253_cascade_ns_to_timer(devpriv
->clockbase
,
637 err
|= cfc_check_trigger_arg_is(&cmd
->convert_arg
, arg
);
642 /* Step 5: check channel list if it exists */
643 if (cmd
->chanlist
&& cmd
->chanlist_len
> 0)
644 err
|= das16_ai_check_chanlist(dev
, s
, cmd
);
652 static unsigned int das16_set_pacer(struct comedi_device
*dev
, unsigned int ns
,
655 struct das16_private_struct
*devpriv
= dev
->private;
656 unsigned long timer_base
= dev
->iobase
+ DAS16_TIMER_BASE_REG
;
658 i8253_cascade_ns_to_timer(devpriv
->clockbase
,
659 &devpriv
->divisor1
, &devpriv
->divisor2
,
662 i8254_set_mode(timer_base
, 0, 1, I8254_MODE2
| I8254_BINARY
);
663 i8254_set_mode(timer_base
, 0, 2, I8254_MODE2
| I8254_BINARY
);
664 i8254_write(timer_base
, 0, 1, devpriv
->divisor1
);
665 i8254_write(timer_base
, 0, 2, devpriv
->divisor2
);
670 static int das16_cmd_exec(struct comedi_device
*dev
, struct comedi_subdevice
*s
)
672 const struct das16_board
*board
= dev
->board_ptr
;
673 struct das16_private_struct
*devpriv
= dev
->private;
674 struct comedi_isadma
*dma
= devpriv
->dma
;
675 struct comedi_isadma_desc
*desc
= &dma
->desc
[0];
676 struct comedi_async
*async
= s
->async
;
677 struct comedi_cmd
*cmd
= &async
->cmd
;
682 if (cmd
->flags
& CMDF_PRIORITY
) {
683 dev_err(dev
->class_dev
,
684 "isa dma transfers cannot be performed with CMDF_PRIORITY, aborting\n");
688 if (devpriv
->can_burst
)
689 outb(DAS1600_CONV_DISABLE
, dev
->iobase
+ DAS1600_CONV_REG
);
691 /* set scan limits */
692 byte
= CR_CHAN(cmd
->chanlist
[0]);
693 byte
|= CR_CHAN(cmd
->chanlist
[cmd
->chanlist_len
- 1]) << 4;
694 outb(byte
, dev
->iobase
+ DAS16_MUX_REG
);
696 /* set gain (this is also burst rate register but according to
697 * computer boards manual, burst rate does nothing, even on
699 if (board
->ai_pg
!= das16_pg_none
) {
700 range
= CR_RANGE(cmd
->chanlist
[0]);
701 outb((das16_gainlists
[board
->ai_pg
])[range
],
702 dev
->iobase
+ DAS16_GAIN_REG
);
705 /* set counter mode and counts */
706 cmd
->convert_arg
= das16_set_pacer(dev
, cmd
->convert_arg
, cmd
->flags
);
708 /* enable counters */
710 if (devpriv
->can_burst
) {
711 if (cmd
->convert_src
== TRIG_NOW
) {
712 outb(DAS1600_BURST_VAL
,
713 dev
->iobase
+ DAS1600_BURST_REG
);
714 /* set burst length */
715 byte
|= DAS16_PACER_BURST_LEN(cmd
->chanlist_len
- 1);
717 outb(0, dev
->iobase
+ DAS1600_BURST_REG
);
720 outb(byte
, dev
->iobase
+ DAS16_PACER_REG
);
722 /* set up dma transfer */
724 desc
->size
= desc
->maxsize
;
725 comedi_isadma_program(desc
);
728 spin_lock_irqsave(&dev
->spinlock
, flags
);
729 devpriv
->timer_running
= 1;
730 devpriv
->timer
.expires
= jiffies
+ timer_period();
731 add_timer(&devpriv
->timer
);
733 /* enable DMA interrupt with external or internal pacing */
734 devpriv
->ctrl_reg
&= ~(DAS16_CTRL_INTE
| DAS16_CTRL_PACING_MASK
);
735 devpriv
->ctrl_reg
|= DAS16_CTRL_DMAE
;
736 if (cmd
->convert_src
== TRIG_EXT
)
737 devpriv
->ctrl_reg
|= DAS16_CTRL_EXT_PACER
;
739 devpriv
->ctrl_reg
|= DAS16_CTRL_INT_PACER
;
740 outb(devpriv
->ctrl_reg
, dev
->iobase
+ DAS16_CTRL_REG
);
742 if (devpriv
->can_burst
)
743 outb(0, dev
->iobase
+ DAS1600_CONV_REG
);
744 spin_unlock_irqrestore(&dev
->spinlock
, flags
);
749 static int das16_cancel(struct comedi_device
*dev
, struct comedi_subdevice
*s
)
751 struct das16_private_struct
*devpriv
= dev
->private;
752 struct comedi_isadma
*dma
= devpriv
->dma
;
755 spin_lock_irqsave(&dev
->spinlock
, flags
);
757 /* disable interrupts, dma and pacer clocked conversions */
758 devpriv
->ctrl_reg
&= ~(DAS16_CTRL_INTE
| DAS16_CTRL_DMAE
|
759 DAS16_CTRL_PACING_MASK
);
760 outb(devpriv
->ctrl_reg
, dev
->iobase
+ DAS16_CTRL_REG
);
762 comedi_isadma_disable(dma
->chan
);
764 /* disable SW timer */
765 if (devpriv
->timer_running
) {
766 devpriv
->timer_running
= 0;
767 del_timer(&devpriv
->timer
);
770 if (devpriv
->can_burst
)
771 outb(0, dev
->iobase
+ DAS1600_BURST_REG
);
773 spin_unlock_irqrestore(&dev
->spinlock
, flags
);
778 static void das16_ai_munge(struct comedi_device
*dev
,
779 struct comedi_subdevice
*s
, void *array
,
780 unsigned int num_bytes
,
781 unsigned int start_chan_index
)
783 unsigned short *data
= array
;
784 unsigned int num_samples
= comedi_bytes_to_samples(s
, num_bytes
);
787 for (i
= 0; i
< num_samples
; i
++) {
788 data
[i
] = le16_to_cpu(data
[i
]);
789 if (s
->maxdata
== 0x0fff)
791 data
[i
] &= s
->maxdata
;
795 static int das16_ai_eoc(struct comedi_device
*dev
,
796 struct comedi_subdevice
*s
,
797 struct comedi_insn
*insn
,
798 unsigned long context
)
802 status
= inb(dev
->iobase
+ DAS16_STATUS_REG
);
803 if ((status
& DAS16_STATUS_BUSY
) == 0)
808 static int das16_ai_insn_read(struct comedi_device
*dev
,
809 struct comedi_subdevice
*s
,
810 struct comedi_insn
*insn
,
813 const struct das16_board
*board
= dev
->board_ptr
;
814 unsigned int chan
= CR_CHAN(insn
->chanspec
);
815 unsigned int range
= CR_RANGE(insn
->chanspec
);
820 /* set multiplexer */
821 outb(chan
| (chan
<< 4), dev
->iobase
+ DAS16_MUX_REG
);
824 if (board
->ai_pg
!= das16_pg_none
) {
825 outb((das16_gainlists
[board
->ai_pg
])[range
],
826 dev
->iobase
+ DAS16_GAIN_REG
);
829 for (i
= 0; i
< insn
->n
; i
++) {
830 /* trigger conversion */
831 outb_p(0, dev
->iobase
+ DAS16_TRIG_REG
);
833 ret
= comedi_timeout(dev
, s
, insn
, das16_ai_eoc
, 0);
837 val
= inb(dev
->iobase
+ DAS16_AI_MSB_REG
) << 8;
838 val
|= inb(dev
->iobase
+ DAS16_AI_LSB_REG
);
839 if (s
->maxdata
== 0x0fff)
849 static int das16_ao_insn_write(struct comedi_device
*dev
,
850 struct comedi_subdevice
*s
,
851 struct comedi_insn
*insn
,
854 unsigned int chan
= CR_CHAN(insn
->chanspec
);
857 for (i
= 0; i
< insn
->n
; i
++) {
858 unsigned int val
= data
[i
];
860 s
->readback
[chan
] = val
;
864 outb(val
& 0xff, dev
->iobase
+ DAS16_AO_LSB_REG(chan
));
865 outb((val
>> 8) & 0xff, dev
->iobase
+ DAS16_AO_MSB_REG(chan
));
871 static int das16_di_insn_bits(struct comedi_device
*dev
,
872 struct comedi_subdevice
*s
,
873 struct comedi_insn
*insn
,
876 data
[1] = inb(dev
->iobase
+ DAS16_DIO_REG
) & 0xf;
881 static int das16_do_insn_bits(struct comedi_device
*dev
,
882 struct comedi_subdevice
*s
,
883 struct comedi_insn
*insn
,
886 if (comedi_dio_update_state(s
, data
))
887 outb(s
->state
, dev
->iobase
+ DAS16_DIO_REG
);
894 static int das16_probe(struct comedi_device
*dev
, struct comedi_devconfig
*it
)
896 const struct das16_board
*board
= dev
->board_ptr
;
899 /* diobits indicates boards */
900 diobits
= inb(dev
->iobase
+ DAS16_DIO_REG
) & 0xf0;
901 if (board
->id
!= diobits
) {
902 dev_err(dev
->class_dev
,
903 "requested board's id bits are incorrect (0x%x != 0x%x)\n",
911 static void das16_reset(struct comedi_device
*dev
)
913 outb(0, dev
->iobase
+ DAS16_STATUS_REG
);
914 outb(0, dev
->iobase
+ DAS16_CTRL_REG
);
915 outb(0, dev
->iobase
+ DAS16_PACER_REG
);
916 outb(0, dev
->iobase
+ DAS16_TIMER_BASE_REG
+ i8254_control_reg
);
919 static void das16_alloc_dma(struct comedi_device
*dev
, unsigned int dma_chan
)
921 struct das16_private_struct
*devpriv
= dev
->private;
923 /* only DMA channels 3 and 1 are valid */
924 if (!(dma_chan
== 1 || dma_chan
== 3))
927 /* DMA uses two buffers */
928 devpriv
->dma
= comedi_isadma_alloc(dev
, 2, dma_chan
, dma_chan
,
929 DAS16_DMA_SIZE
, COMEDI_ISADMA_READ
);
931 init_timer(&devpriv
->timer
);
932 devpriv
->timer
.function
= das16_timer_interrupt
;
933 devpriv
->timer
.data
= (unsigned long)dev
;
937 static void das16_free_dma(struct comedi_device
*dev
)
939 struct das16_private_struct
*devpriv
= dev
->private;
942 if (devpriv
->timer
.data
)
943 del_timer_sync(&devpriv
->timer
);
944 comedi_isadma_free(devpriv
->dma
);
948 static const struct comedi_lrange
*das16_ai_range(struct comedi_device
*dev
,
949 struct comedi_subdevice
*s
,
950 struct comedi_devconfig
*it
,
951 unsigned int pg_type
,
954 unsigned int min
= it
->options
[4];
955 unsigned int max
= it
->options
[5];
957 /* get any user-defined input range */
958 if (pg_type
== das16_pg_none
&& (min
|| max
)) {
959 struct comedi_lrange
*lrange
;
960 struct comedi_krange
*krange
;
962 /* allocate single-range range table */
963 lrange
= comedi_alloc_spriv(s
,
964 sizeof(*lrange
) + sizeof(*krange
));
966 return &range_unknown
;
968 /* initialize ai range */
970 krange
= lrange
->range
;
973 krange
->flags
= UNIT_volt
;
978 /* use software programmable range */
979 if (status
& DAS16_STATUS_UNIPOLAR
)
980 return das16_ai_uni_lranges
[pg_type
];
981 return das16_ai_bip_lranges
[pg_type
];
984 static const struct comedi_lrange
*das16_ao_range(struct comedi_device
*dev
,
985 struct comedi_subdevice
*s
,
986 struct comedi_devconfig
*it
)
988 unsigned int min
= it
->options
[6];
989 unsigned int max
= it
->options
[7];
991 /* get any user-defined output range */
993 struct comedi_lrange
*lrange
;
994 struct comedi_krange
*krange
;
996 /* allocate single-range range table */
997 lrange
= comedi_alloc_spriv(s
,
998 sizeof(*lrange
) + sizeof(*krange
));
1000 return &range_unknown
;
1002 /* initialize ao range */
1004 krange
= lrange
->range
;
1007 krange
->flags
= UNIT_volt
;
1012 return &range_unknown
;
1015 static int das16_attach(struct comedi_device
*dev
, struct comedi_devconfig
*it
)
1017 const struct das16_board
*board
= dev
->board_ptr
;
1018 struct das16_private_struct
*devpriv
;
1019 struct comedi_subdevice
*s
;
1020 unsigned int status
;
1023 /* check that clock setting is valid */
1024 if (it
->options
[3]) {
1025 if (it
->options
[3] != 0 &&
1026 it
->options
[3] != 1 && it
->options
[3] != 10) {
1027 dev_err(dev
->class_dev
,
1028 "Invalid option. Master clock must be set to 1 or 10 (MHz)\n");
1033 devpriv
= comedi_alloc_devpriv(dev
, sizeof(*devpriv
));
1037 if (board
->size
< 0x400) {
1038 ret
= comedi_request_region(dev
, it
->options
[0], board
->size
);
1042 ret
= comedi_request_region(dev
, it
->options
[0], 0x10);
1045 /* Request an additional region for the 8255 */
1046 ret
= __comedi_request_region(dev
, dev
->iobase
+ 0x400,
1047 board
->size
& 0x3ff);
1050 devpriv
->extra_iobase
= dev
->iobase
+ 0x400;
1051 devpriv
->can_burst
= 1;
1054 /* probe id bits to make sure they are consistent */
1055 if (das16_probe(dev
, it
))
1058 /* get master clock speed */
1059 if (devpriv
->can_burst
) {
1060 status
= inb(dev
->iobase
+ DAS1600_STATUS_REG
);
1062 if (status
& DAS1600_STATUS_CLK_10MHZ
)
1063 devpriv
->clockbase
= I8254_OSC_BASE_10MHZ
;
1065 devpriv
->clockbase
= I8254_OSC_BASE_1MHZ
;
1068 devpriv
->clockbase
= I8254_OSC_BASE_1MHZ
/
1071 devpriv
->clockbase
= I8254_OSC_BASE_1MHZ
;
1074 das16_alloc_dma(dev
, it
->options
[2]);
1076 ret
= comedi_alloc_subdevices(dev
, 4 + board
->has_8255
);
1080 status
= inb(dev
->iobase
+ DAS16_STATUS_REG
);
1082 /* Analog Input subdevice */
1083 s
= &dev
->subdevices
[0];
1084 s
->type
= COMEDI_SUBD_AI
;
1085 s
->subdev_flags
= SDF_READABLE
;
1086 if (status
& DAS16_STATUS_MUXBIT
) {
1087 s
->subdev_flags
|= SDF_GROUND
;
1090 s
->subdev_flags
|= SDF_DIFF
;
1093 s
->len_chanlist
= s
->n_chan
;
1094 s
->maxdata
= board
->ai_maxdata
;
1095 s
->range_table
= das16_ai_range(dev
, s
, it
, board
->ai_pg
, status
);
1096 s
->insn_read
= das16_ai_insn_read
;
1098 dev
->read_subdev
= s
;
1099 s
->subdev_flags
|= SDF_CMD_READ
;
1100 s
->do_cmdtest
= das16_cmd_test
;
1101 s
->do_cmd
= das16_cmd_exec
;
1102 s
->cancel
= das16_cancel
;
1103 s
->munge
= das16_ai_munge
;
1106 /* Analog Output subdevice */
1107 s
= &dev
->subdevices
[1];
1108 if (board
->has_ao
) {
1109 s
->type
= COMEDI_SUBD_AO
;
1110 s
->subdev_flags
= SDF_WRITABLE
;
1112 s
->maxdata
= 0x0fff;
1113 s
->range_table
= das16_ao_range(dev
, s
, it
);
1114 s
->insn_write
= das16_ao_insn_write
;
1116 ret
= comedi_alloc_subdev_readback(s
);
1120 s
->type
= COMEDI_SUBD_UNUSED
;
1123 /* Digital Input subdevice */
1124 s
= &dev
->subdevices
[2];
1125 s
->type
= COMEDI_SUBD_DI
;
1126 s
->subdev_flags
= SDF_READABLE
;
1129 s
->range_table
= &range_digital
;
1130 s
->insn_bits
= das16_di_insn_bits
;
1132 /* Digital Output subdevice */
1133 s
= &dev
->subdevices
[3];
1134 s
->type
= COMEDI_SUBD_DO
;
1135 s
->subdev_flags
= SDF_WRITABLE
;
1138 s
->range_table
= &range_digital
;
1139 s
->insn_bits
= das16_do_insn_bits
;
1141 /* initialize digital output lines */
1142 outb(s
->state
, dev
->iobase
+ DAS16_DIO_REG
);
1144 /* 8255 Digital I/O subdevice */
1145 if (board
->has_8255
) {
1146 s
= &dev
->subdevices
[4];
1147 ret
= subdev_8255_init(dev
, s
, NULL
, board
->i8255_offset
);
1153 /* set the interrupt level */
1154 devpriv
->ctrl_reg
= DAS16_CTRL_IRQ(dev
->irq
);
1155 outb(devpriv
->ctrl_reg
, dev
->iobase
+ DAS16_CTRL_REG
);
1157 if (devpriv
->can_burst
) {
1158 outb(DAS1600_ENABLE_VAL
, dev
->iobase
+ DAS1600_ENABLE_REG
);
1159 outb(0, dev
->iobase
+ DAS1600_CONV_REG
);
1160 outb(0, dev
->iobase
+ DAS1600_BURST_REG
);
1166 static void das16_detach(struct comedi_device
*dev
)
1168 const struct das16_board
*board
= dev
->board_ptr
;
1169 struct das16_private_struct
*devpriv
= dev
->private;
1174 das16_free_dma(dev
);
1176 if (devpriv
->extra_iobase
)
1177 release_region(devpriv
->extra_iobase
,
1178 board
->size
& 0x3ff);
1181 comedi_legacy_detach(dev
);
1184 static struct comedi_driver das16_driver
= {
1185 .driver_name
= "das16",
1186 .module
= THIS_MODULE
,
1187 .attach
= das16_attach
,
1188 .detach
= das16_detach
,
1189 .board_name
= &das16_boards
[0].name
,
1190 .num_names
= ARRAY_SIZE(das16_boards
),
1191 .offset
= sizeof(das16_boards
[0]),
1193 module_comedi_driver(das16_driver
);
1195 MODULE_AUTHOR("Comedi http://www.comedi.org");
1196 MODULE_DESCRIPTION("Comedi driver for DAS16 compatible boards");
1197 MODULE_LICENSE("GPL");