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_ai_setup_dma(struct comedi_device
*dev
,
452 struct comedi_subdevice
*s
,
453 unsigned int unread_samples
)
455 struct das16_private_struct
*devpriv
= dev
->private;
456 struct comedi_isadma
*dma
= devpriv
->dma
;
457 struct comedi_isadma_desc
*desc
= &dma
->desc
[dma
->cur_dma
];
458 unsigned int max_samples
= comedi_bytes_to_samples(s
, desc
->maxsize
);
459 unsigned int nsamples
;
462 * Determine dma size based on the buffer size plus the number of
463 * unread samples and the number of samples remaining in the command.
465 nsamples
= comedi_nsamples_left(s
, max_samples
+ unread_samples
);
466 if (nsamples
> unread_samples
) {
467 nsamples
-= unread_samples
;
468 desc
->size
= comedi_samples_to_bytes(s
, nsamples
);
469 comedi_isadma_program(desc
);
473 static void das16_interrupt(struct comedi_device
*dev
)
475 struct das16_private_struct
*devpriv
= dev
->private;
476 struct comedi_subdevice
*s
= dev
->read_subdev
;
477 struct comedi_async
*async
= s
->async
;
478 struct comedi_cmd
*cmd
= &async
->cmd
;
479 struct comedi_isadma
*dma
= devpriv
->dma
;
480 struct comedi_isadma_desc
*desc
= &dma
->desc
[dma
->cur_dma
];
481 unsigned long spin_flags
;
482 unsigned int residue
;
484 unsigned int nsamples
;
486 spin_lock_irqsave(&dev
->spinlock
, spin_flags
);
487 if (!(devpriv
->ctrl_reg
& DAS16_CTRL_DMAE
)) {
488 spin_unlock_irqrestore(&dev
->spinlock
, spin_flags
);
493 * The pc104-das16jr (at least) has problems if the dma
494 * transfer is interrupted in the middle of transferring
497 residue
= comedi_isadma_disable_on_sample(desc
->chan
,
498 comedi_bytes_per_sample(s
));
500 /* figure out how many samples to read */
501 if (residue
> desc
->size
) {
502 dev_err(dev
->class_dev
, "residue > transfer size!\n");
503 async
->events
|= COMEDI_CB_ERROR
;
506 nbytes
= desc
->size
- residue
;
508 nsamples
= comedi_bytes_to_samples(s
, nbytes
);
510 /* restart DMA if more samples are needed */
512 dma
->cur_dma
= 1 - dma
->cur_dma
;
513 das16_ai_setup_dma(dev
, s
, nsamples
);
516 spin_unlock_irqrestore(&dev
->spinlock
, spin_flags
);
518 comedi_buf_write_samples(s
, desc
->virt_addr
, nsamples
);
520 if (cmd
->stop_src
== TRIG_COUNT
&& async
->scans_done
>= cmd
->stop_arg
)
521 async
->events
|= COMEDI_CB_EOA
;
523 comedi_handle_events(dev
, s
);
526 static void das16_timer_interrupt(unsigned long arg
)
528 struct comedi_device
*dev
= (struct comedi_device
*)arg
;
529 struct das16_private_struct
*devpriv
= dev
->private;
532 das16_interrupt(dev
);
534 spin_lock_irqsave(&dev
->spinlock
, flags
);
535 if (devpriv
->timer_running
)
536 mod_timer(&devpriv
->timer
, jiffies
+ timer_period());
537 spin_unlock_irqrestore(&dev
->spinlock
, flags
);
540 static void das16_ai_set_mux_range(struct comedi_device
*dev
,
541 unsigned int first_chan
,
542 unsigned int last_chan
,
545 const struct das16_board
*board
= dev
->board_ptr
;
547 /* set multiplexer */
548 outb(first_chan
| (last_chan
<< 4), dev
->iobase
+ DAS16_MUX_REG
);
550 /* some boards do not have programmable gain */
551 if (board
->ai_pg
== das16_pg_none
)
555 * Set gain (this is also burst rate register but according to
556 * computer boards manual, burst rate does nothing, even on
559 outb((das16_gainlists
[board
->ai_pg
])[range
],
560 dev
->iobase
+ DAS16_GAIN_REG
);
563 static int das16_ai_check_chanlist(struct comedi_device
*dev
,
564 struct comedi_subdevice
*s
,
565 struct comedi_cmd
*cmd
)
567 unsigned int chan0
= CR_CHAN(cmd
->chanlist
[0]);
568 unsigned int range0
= CR_RANGE(cmd
->chanlist
[0]);
571 for (i
= 1; i
< cmd
->chanlist_len
; i
++) {
572 unsigned int chan
= CR_CHAN(cmd
->chanlist
[i
]);
573 unsigned int range
= CR_RANGE(cmd
->chanlist
[i
]);
575 if (chan
!= ((chan0
+ i
) % s
->n_chan
)) {
576 dev_dbg(dev
->class_dev
,
577 "entries in chanlist must be consecutive channels, counting upwards\n");
581 if (range
!= range0
) {
582 dev_dbg(dev
->class_dev
,
583 "entries in chanlist must all have the same gain\n");
591 static int das16_cmd_test(struct comedi_device
*dev
, struct comedi_subdevice
*s
,
592 struct comedi_cmd
*cmd
)
594 const struct das16_board
*board
= dev
->board_ptr
;
595 struct das16_private_struct
*devpriv
= dev
->private;
597 unsigned int trig_mask
;
600 /* Step 1 : check if triggers are trivially valid */
602 err
|= cfc_check_trigger_src(&cmd
->start_src
, TRIG_NOW
);
604 trig_mask
= TRIG_FOLLOW
;
605 if (devpriv
->can_burst
)
606 trig_mask
|= TRIG_TIMER
| TRIG_EXT
;
607 err
|= cfc_check_trigger_src(&cmd
->scan_begin_src
, trig_mask
);
609 trig_mask
= TRIG_TIMER
| TRIG_EXT
;
610 if (devpriv
->can_burst
)
611 trig_mask
|= TRIG_NOW
;
612 err
|= cfc_check_trigger_src(&cmd
->convert_src
, trig_mask
);
614 err
|= cfc_check_trigger_src(&cmd
->scan_end_src
, TRIG_COUNT
);
615 err
|= cfc_check_trigger_src(&cmd
->stop_src
, TRIG_COUNT
| TRIG_NONE
);
620 /* Step 2a : make sure trigger sources are unique */
622 err
|= cfc_check_trigger_is_unique(cmd
->scan_begin_src
);
623 err
|= cfc_check_trigger_is_unique(cmd
->convert_src
);
624 err
|= cfc_check_trigger_is_unique(cmd
->stop_src
);
626 /* Step 2b : and mutually compatible */
628 /* make sure scan_begin_src and convert_src dont conflict */
629 if (cmd
->scan_begin_src
== TRIG_FOLLOW
&& cmd
->convert_src
== TRIG_NOW
)
631 if (cmd
->scan_begin_src
!= TRIG_FOLLOW
&& cmd
->convert_src
!= TRIG_NOW
)
637 /* Step 3: check if arguments are trivially valid */
639 err
|= cfc_check_trigger_arg_is(&cmd
->start_arg
, 0);
641 if (cmd
->scan_begin_src
== TRIG_FOLLOW
) /* internal trigger */
642 err
|= cfc_check_trigger_arg_is(&cmd
->scan_begin_arg
, 0);
644 err
|= cfc_check_trigger_arg_is(&cmd
->scan_end_arg
, cmd
->chanlist_len
);
646 /* check against maximum frequency */
647 if (cmd
->scan_begin_src
== TRIG_TIMER
)
648 err
|= cfc_check_trigger_arg_min(&cmd
->scan_begin_arg
,
649 board
->ai_speed
* cmd
->chanlist_len
);
651 if (cmd
->convert_src
== TRIG_TIMER
)
652 err
|= cfc_check_trigger_arg_min(&cmd
->convert_arg
,
655 if (cmd
->stop_src
== TRIG_COUNT
)
656 err
|= cfc_check_trigger_arg_min(&cmd
->stop_arg
, 1);
658 err
|= cfc_check_trigger_arg_is(&cmd
->stop_arg
, 0);
663 /* step 4: fix up arguments */
664 if (cmd
->scan_begin_src
== TRIG_TIMER
) {
665 arg
= cmd
->scan_begin_arg
;
666 i8253_cascade_ns_to_timer(devpriv
->clockbase
,
670 err
|= cfc_check_trigger_arg_is(&cmd
->scan_begin_arg
, arg
);
672 if (cmd
->convert_src
== TRIG_TIMER
) {
673 arg
= cmd
->convert_arg
;
674 i8253_cascade_ns_to_timer(devpriv
->clockbase
,
678 err
|= cfc_check_trigger_arg_is(&cmd
->convert_arg
, arg
);
683 /* Step 5: check channel list if it exists */
684 if (cmd
->chanlist
&& cmd
->chanlist_len
> 0)
685 err
|= das16_ai_check_chanlist(dev
, s
, cmd
);
693 static unsigned int das16_set_pacer(struct comedi_device
*dev
, unsigned int ns
,
696 struct das16_private_struct
*devpriv
= dev
->private;
697 unsigned long timer_base
= dev
->iobase
+ DAS16_TIMER_BASE_REG
;
699 i8253_cascade_ns_to_timer(devpriv
->clockbase
,
700 &devpriv
->divisor1
, &devpriv
->divisor2
,
703 i8254_set_mode(timer_base
, 0, 1, I8254_MODE2
| I8254_BINARY
);
704 i8254_set_mode(timer_base
, 0, 2, I8254_MODE2
| I8254_BINARY
);
705 i8254_write(timer_base
, 0, 1, devpriv
->divisor1
);
706 i8254_write(timer_base
, 0, 2, devpriv
->divisor2
);
711 static int das16_cmd_exec(struct comedi_device
*dev
, struct comedi_subdevice
*s
)
713 struct das16_private_struct
*devpriv
= dev
->private;
714 struct comedi_isadma
*dma
= devpriv
->dma
;
715 struct comedi_async
*async
= s
->async
;
716 struct comedi_cmd
*cmd
= &async
->cmd
;
717 unsigned int first_chan
= CR_CHAN(cmd
->chanlist
[0]);
718 unsigned int last_chan
= CR_CHAN(cmd
->chanlist
[cmd
->chanlist_len
- 1]);
719 unsigned int range
= CR_RANGE(cmd
->chanlist
[0]);
723 if (cmd
->flags
& CMDF_PRIORITY
) {
724 dev_err(dev
->class_dev
,
725 "isa dma transfers cannot be performed with CMDF_PRIORITY, aborting\n");
729 if (devpriv
->can_burst
)
730 outb(DAS1600_CONV_DISABLE
, dev
->iobase
+ DAS1600_CONV_REG
);
732 /* set mux and range for chanlist scan */
733 das16_ai_set_mux_range(dev
, first_chan
, last_chan
, range
);
735 /* set counter mode and counts */
736 cmd
->convert_arg
= das16_set_pacer(dev
, cmd
->convert_arg
, cmd
->flags
);
738 /* enable counters */
740 if (devpriv
->can_burst
) {
741 if (cmd
->convert_src
== TRIG_NOW
) {
742 outb(DAS1600_BURST_VAL
,
743 dev
->iobase
+ DAS1600_BURST_REG
);
744 /* set burst length */
745 byte
|= DAS16_PACER_BURST_LEN(cmd
->chanlist_len
- 1);
747 outb(0, dev
->iobase
+ DAS1600_BURST_REG
);
750 outb(byte
, dev
->iobase
+ DAS16_PACER_REG
);
752 /* set up dma transfer */
754 das16_ai_setup_dma(dev
, s
, 0);
757 spin_lock_irqsave(&dev
->spinlock
, flags
);
758 devpriv
->timer_running
= 1;
759 devpriv
->timer
.expires
= jiffies
+ timer_period();
760 add_timer(&devpriv
->timer
);
762 /* enable DMA interrupt with external or internal pacing */
763 devpriv
->ctrl_reg
&= ~(DAS16_CTRL_INTE
| DAS16_CTRL_PACING_MASK
);
764 devpriv
->ctrl_reg
|= DAS16_CTRL_DMAE
;
765 if (cmd
->convert_src
== TRIG_EXT
)
766 devpriv
->ctrl_reg
|= DAS16_CTRL_EXT_PACER
;
768 devpriv
->ctrl_reg
|= DAS16_CTRL_INT_PACER
;
769 outb(devpriv
->ctrl_reg
, dev
->iobase
+ DAS16_CTRL_REG
);
771 if (devpriv
->can_burst
)
772 outb(0, dev
->iobase
+ DAS1600_CONV_REG
);
773 spin_unlock_irqrestore(&dev
->spinlock
, flags
);
778 static int das16_cancel(struct comedi_device
*dev
, struct comedi_subdevice
*s
)
780 struct das16_private_struct
*devpriv
= dev
->private;
781 struct comedi_isadma
*dma
= devpriv
->dma
;
784 spin_lock_irqsave(&dev
->spinlock
, flags
);
786 /* disable interrupts, dma and pacer clocked conversions */
787 devpriv
->ctrl_reg
&= ~(DAS16_CTRL_INTE
| DAS16_CTRL_DMAE
|
788 DAS16_CTRL_PACING_MASK
);
789 outb(devpriv
->ctrl_reg
, dev
->iobase
+ DAS16_CTRL_REG
);
791 comedi_isadma_disable(dma
->chan
);
793 /* disable SW timer */
794 if (devpriv
->timer_running
) {
795 devpriv
->timer_running
= 0;
796 del_timer(&devpriv
->timer
);
799 if (devpriv
->can_burst
)
800 outb(0, dev
->iobase
+ DAS1600_BURST_REG
);
802 spin_unlock_irqrestore(&dev
->spinlock
, flags
);
807 static void das16_ai_munge(struct comedi_device
*dev
,
808 struct comedi_subdevice
*s
, void *array
,
809 unsigned int num_bytes
,
810 unsigned int start_chan_index
)
812 unsigned short *data
= array
;
813 unsigned int num_samples
= comedi_bytes_to_samples(s
, num_bytes
);
816 for (i
= 0; i
< num_samples
; i
++) {
817 data
[i
] = le16_to_cpu(data
[i
]);
818 if (s
->maxdata
== 0x0fff)
820 data
[i
] &= s
->maxdata
;
824 static int das16_ai_eoc(struct comedi_device
*dev
,
825 struct comedi_subdevice
*s
,
826 struct comedi_insn
*insn
,
827 unsigned long context
)
831 status
= inb(dev
->iobase
+ DAS16_STATUS_REG
);
832 if ((status
& DAS16_STATUS_BUSY
) == 0)
837 static int das16_ai_insn_read(struct comedi_device
*dev
,
838 struct comedi_subdevice
*s
,
839 struct comedi_insn
*insn
,
842 unsigned int chan
= CR_CHAN(insn
->chanspec
);
843 unsigned int range
= CR_RANGE(insn
->chanspec
);
848 /* set mux and range for single channel */
849 das16_ai_set_mux_range(dev
, chan
, chan
, range
);
851 for (i
= 0; i
< insn
->n
; i
++) {
852 /* trigger conversion */
853 outb_p(0, dev
->iobase
+ DAS16_TRIG_REG
);
855 ret
= comedi_timeout(dev
, s
, insn
, das16_ai_eoc
, 0);
859 val
= inb(dev
->iobase
+ DAS16_AI_MSB_REG
) << 8;
860 val
|= inb(dev
->iobase
+ DAS16_AI_LSB_REG
);
861 if (s
->maxdata
== 0x0fff)
871 static int das16_ao_insn_write(struct comedi_device
*dev
,
872 struct comedi_subdevice
*s
,
873 struct comedi_insn
*insn
,
876 unsigned int chan
= CR_CHAN(insn
->chanspec
);
879 for (i
= 0; i
< insn
->n
; i
++) {
880 unsigned int val
= data
[i
];
882 s
->readback
[chan
] = val
;
886 outb(val
& 0xff, dev
->iobase
+ DAS16_AO_LSB_REG(chan
));
887 outb((val
>> 8) & 0xff, dev
->iobase
+ DAS16_AO_MSB_REG(chan
));
893 static int das16_di_insn_bits(struct comedi_device
*dev
,
894 struct comedi_subdevice
*s
,
895 struct comedi_insn
*insn
,
898 data
[1] = inb(dev
->iobase
+ DAS16_DIO_REG
) & 0xf;
903 static int das16_do_insn_bits(struct comedi_device
*dev
,
904 struct comedi_subdevice
*s
,
905 struct comedi_insn
*insn
,
908 if (comedi_dio_update_state(s
, data
))
909 outb(s
->state
, dev
->iobase
+ DAS16_DIO_REG
);
916 static int das16_probe(struct comedi_device
*dev
, struct comedi_devconfig
*it
)
918 const struct das16_board
*board
= dev
->board_ptr
;
921 /* diobits indicates boards */
922 diobits
= inb(dev
->iobase
+ DAS16_DIO_REG
) & 0xf0;
923 if (board
->id
!= diobits
) {
924 dev_err(dev
->class_dev
,
925 "requested board's id bits are incorrect (0x%x != 0x%x)\n",
933 static void das16_reset(struct comedi_device
*dev
)
935 outb(0, dev
->iobase
+ DAS16_STATUS_REG
);
936 outb(0, dev
->iobase
+ DAS16_CTRL_REG
);
937 outb(0, dev
->iobase
+ DAS16_PACER_REG
);
938 outb(0, dev
->iobase
+ DAS16_TIMER_BASE_REG
+ i8254_control_reg
);
941 static void das16_alloc_dma(struct comedi_device
*dev
, unsigned int dma_chan
)
943 struct das16_private_struct
*devpriv
= dev
->private;
945 /* only DMA channels 3 and 1 are valid */
946 if (!(dma_chan
== 1 || dma_chan
== 3))
949 /* DMA uses two buffers */
950 devpriv
->dma
= comedi_isadma_alloc(dev
, 2, dma_chan
, dma_chan
,
951 DAS16_DMA_SIZE
, COMEDI_ISADMA_READ
);
953 init_timer(&devpriv
->timer
);
954 devpriv
->timer
.function
= das16_timer_interrupt
;
955 devpriv
->timer
.data
= (unsigned long)dev
;
959 static void das16_free_dma(struct comedi_device
*dev
)
961 struct das16_private_struct
*devpriv
= dev
->private;
964 if (devpriv
->timer
.data
)
965 del_timer_sync(&devpriv
->timer
);
966 comedi_isadma_free(devpriv
->dma
);
970 static const struct comedi_lrange
*das16_ai_range(struct comedi_device
*dev
,
971 struct comedi_subdevice
*s
,
972 struct comedi_devconfig
*it
,
973 unsigned int pg_type
,
976 unsigned int min
= it
->options
[4];
977 unsigned int max
= it
->options
[5];
979 /* get any user-defined input range */
980 if (pg_type
== das16_pg_none
&& (min
|| max
)) {
981 struct comedi_lrange
*lrange
;
982 struct comedi_krange
*krange
;
984 /* allocate single-range range table */
985 lrange
= comedi_alloc_spriv(s
,
986 sizeof(*lrange
) + sizeof(*krange
));
988 return &range_unknown
;
990 /* initialize ai range */
992 krange
= lrange
->range
;
995 krange
->flags
= UNIT_volt
;
1000 /* use software programmable range */
1001 if (status
& DAS16_STATUS_UNIPOLAR
)
1002 return das16_ai_uni_lranges
[pg_type
];
1003 return das16_ai_bip_lranges
[pg_type
];
1006 static const struct comedi_lrange
*das16_ao_range(struct comedi_device
*dev
,
1007 struct comedi_subdevice
*s
,
1008 struct comedi_devconfig
*it
)
1010 unsigned int min
= it
->options
[6];
1011 unsigned int max
= it
->options
[7];
1013 /* get any user-defined output range */
1015 struct comedi_lrange
*lrange
;
1016 struct comedi_krange
*krange
;
1018 /* allocate single-range range table */
1019 lrange
= comedi_alloc_spriv(s
,
1020 sizeof(*lrange
) + sizeof(*krange
));
1022 return &range_unknown
;
1024 /* initialize ao range */
1026 krange
= lrange
->range
;
1029 krange
->flags
= UNIT_volt
;
1034 return &range_unknown
;
1037 static int das16_attach(struct comedi_device
*dev
, struct comedi_devconfig
*it
)
1039 const struct das16_board
*board
= dev
->board_ptr
;
1040 struct das16_private_struct
*devpriv
;
1041 struct comedi_subdevice
*s
;
1042 unsigned int status
;
1045 /* check that clock setting is valid */
1046 if (it
->options
[3]) {
1047 if (it
->options
[3] != 0 &&
1048 it
->options
[3] != 1 && it
->options
[3] != 10) {
1049 dev_err(dev
->class_dev
,
1050 "Invalid option. Master clock must be set to 1 or 10 (MHz)\n");
1055 devpriv
= comedi_alloc_devpriv(dev
, sizeof(*devpriv
));
1059 if (board
->size
< 0x400) {
1060 ret
= comedi_request_region(dev
, it
->options
[0], board
->size
);
1064 ret
= comedi_request_region(dev
, it
->options
[0], 0x10);
1067 /* Request an additional region for the 8255 */
1068 ret
= __comedi_request_region(dev
, dev
->iobase
+ 0x400,
1069 board
->size
& 0x3ff);
1072 devpriv
->extra_iobase
= dev
->iobase
+ 0x400;
1073 devpriv
->can_burst
= 1;
1076 /* probe id bits to make sure they are consistent */
1077 if (das16_probe(dev
, it
))
1080 /* get master clock speed */
1081 if (devpriv
->can_burst
) {
1082 status
= inb(dev
->iobase
+ DAS1600_STATUS_REG
);
1084 if (status
& DAS1600_STATUS_CLK_10MHZ
)
1085 devpriv
->clockbase
= I8254_OSC_BASE_10MHZ
;
1087 devpriv
->clockbase
= I8254_OSC_BASE_1MHZ
;
1090 devpriv
->clockbase
= I8254_OSC_BASE_1MHZ
/
1093 devpriv
->clockbase
= I8254_OSC_BASE_1MHZ
;
1096 das16_alloc_dma(dev
, it
->options
[2]);
1098 ret
= comedi_alloc_subdevices(dev
, 4 + board
->has_8255
);
1102 status
= inb(dev
->iobase
+ DAS16_STATUS_REG
);
1104 /* Analog Input subdevice */
1105 s
= &dev
->subdevices
[0];
1106 s
->type
= COMEDI_SUBD_AI
;
1107 s
->subdev_flags
= SDF_READABLE
;
1108 if (status
& DAS16_STATUS_MUXBIT
) {
1109 s
->subdev_flags
|= SDF_GROUND
;
1112 s
->subdev_flags
|= SDF_DIFF
;
1115 s
->len_chanlist
= s
->n_chan
;
1116 s
->maxdata
= board
->ai_maxdata
;
1117 s
->range_table
= das16_ai_range(dev
, s
, it
, board
->ai_pg
, status
);
1118 s
->insn_read
= das16_ai_insn_read
;
1120 dev
->read_subdev
= s
;
1121 s
->subdev_flags
|= SDF_CMD_READ
;
1122 s
->do_cmdtest
= das16_cmd_test
;
1123 s
->do_cmd
= das16_cmd_exec
;
1124 s
->cancel
= das16_cancel
;
1125 s
->munge
= das16_ai_munge
;
1128 /* Analog Output subdevice */
1129 s
= &dev
->subdevices
[1];
1130 if (board
->has_ao
) {
1131 s
->type
= COMEDI_SUBD_AO
;
1132 s
->subdev_flags
= SDF_WRITABLE
;
1134 s
->maxdata
= 0x0fff;
1135 s
->range_table
= das16_ao_range(dev
, s
, it
);
1136 s
->insn_write
= das16_ao_insn_write
;
1138 ret
= comedi_alloc_subdev_readback(s
);
1142 s
->type
= COMEDI_SUBD_UNUSED
;
1145 /* Digital Input subdevice */
1146 s
= &dev
->subdevices
[2];
1147 s
->type
= COMEDI_SUBD_DI
;
1148 s
->subdev_flags
= SDF_READABLE
;
1151 s
->range_table
= &range_digital
;
1152 s
->insn_bits
= das16_di_insn_bits
;
1154 /* Digital Output subdevice */
1155 s
= &dev
->subdevices
[3];
1156 s
->type
= COMEDI_SUBD_DO
;
1157 s
->subdev_flags
= SDF_WRITABLE
;
1160 s
->range_table
= &range_digital
;
1161 s
->insn_bits
= das16_do_insn_bits
;
1163 /* initialize digital output lines */
1164 outb(s
->state
, dev
->iobase
+ DAS16_DIO_REG
);
1166 /* 8255 Digital I/O subdevice */
1167 if (board
->has_8255
) {
1168 s
= &dev
->subdevices
[4];
1169 ret
= subdev_8255_init(dev
, s
, NULL
, board
->i8255_offset
);
1175 /* set the interrupt level */
1176 devpriv
->ctrl_reg
= DAS16_CTRL_IRQ(dev
->irq
);
1177 outb(devpriv
->ctrl_reg
, dev
->iobase
+ DAS16_CTRL_REG
);
1179 if (devpriv
->can_burst
) {
1180 outb(DAS1600_ENABLE_VAL
, dev
->iobase
+ DAS1600_ENABLE_REG
);
1181 outb(0, dev
->iobase
+ DAS1600_CONV_REG
);
1182 outb(0, dev
->iobase
+ DAS1600_BURST_REG
);
1188 static void das16_detach(struct comedi_device
*dev
)
1190 const struct das16_board
*board
= dev
->board_ptr
;
1191 struct das16_private_struct
*devpriv
= dev
->private;
1196 das16_free_dma(dev
);
1198 if (devpriv
->extra_iobase
)
1199 release_region(devpriv
->extra_iobase
,
1200 board
->size
& 0x3ff);
1203 comedi_legacy_detach(dev
);
1206 static struct comedi_driver das16_driver
= {
1207 .driver_name
= "das16",
1208 .module
= THIS_MODULE
,
1209 .attach
= das16_attach
,
1210 .detach
= das16_detach
,
1211 .board_name
= &das16_boards
[0].name
,
1212 .num_names
= ARRAY_SIZE(das16_boards
),
1213 .offset
= sizeof(das16_boards
[0]),
1215 module_comedi_driver(das16_driver
);
1217 MODULE_AUTHOR("Comedi http://www.comedi.org");
1218 MODULE_DESCRIPTION("Comedi driver for DAS16 compatible boards");
1219 MODULE_LICENSE("GPL");