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 long adc_byte_count
;
444 unsigned int divisor1
;
445 unsigned int divisor2
;
446 struct comedi_lrange
*user_ai_range_table
;
447 struct comedi_lrange
*user_ao_range_table
;
448 struct timer_list timer
;
450 unsigned long extra_iobase
;
451 unsigned int can_burst
:1;
454 static void das16_interrupt(struct comedi_device
*dev
)
456 struct das16_private_struct
*devpriv
= dev
->private;
457 struct comedi_subdevice
*s
= dev
->read_subdev
;
458 struct comedi_async
*async
= s
->async
;
459 struct comedi_cmd
*cmd
= &async
->cmd
;
460 struct comedi_isadma
*dma
= devpriv
->dma
;
461 struct comedi_isadma_desc
*desc
= &dma
->desc
[dma
->cur_dma
];
462 unsigned long spin_flags
;
463 unsigned int nsamples
;
464 int num_bytes
, residue
;
466 spin_lock_irqsave(&dev
->spinlock
, spin_flags
);
467 if (!(devpriv
->ctrl_reg
& DAS16_CTRL_DMAE
)) {
468 spin_unlock_irqrestore(&dev
->spinlock
, spin_flags
);
473 * The pc104-das16jr (at least) has problems if the dma
474 * transfer is interrupted in the middle of transferring
477 residue
= comedi_isadma_disable_on_sample(desc
->chan
,
478 comedi_bytes_per_sample(s
));
480 /* figure out how many points to read */
481 if (residue
> desc
->size
) {
482 dev_err(dev
->class_dev
, "residue > transfer size!\n");
483 async
->events
|= COMEDI_CB_ERROR
| COMEDI_CB_EOA
;
486 num_bytes
= desc
->size
- residue
;
488 if (cmd
->stop_src
== TRIG_COUNT
&&
489 num_bytes
>= devpriv
->adc_byte_count
) {
490 num_bytes
= devpriv
->adc_byte_count
;
491 async
->events
|= COMEDI_CB_EOA
;
494 dma
->cur_dma
= 1 - dma
->cur_dma
;
495 devpriv
->adc_byte_count
-= num_bytes
;
498 if (!(async
->events
& COMEDI_CB_CANCEL_MASK
)) {
499 struct comedi_isadma_desc
*nxt_desc
= &dma
->desc
[dma
->cur_dma
];
501 nxt_desc
->size
= nxt_desc
->maxsize
;
502 comedi_isadma_program(nxt_desc
);
505 spin_unlock_irqrestore(&dev
->spinlock
, spin_flags
);
507 nsamples
= comedi_bytes_to_samples(s
, num_bytes
);
508 comedi_buf_write_samples(s
, desc
->virt_addr
, nsamples
);
510 comedi_handle_events(dev
, s
);
513 static void das16_timer_interrupt(unsigned long arg
)
515 struct comedi_device
*dev
= (struct comedi_device
*)arg
;
516 struct das16_private_struct
*devpriv
= dev
->private;
519 das16_interrupt(dev
);
521 spin_lock_irqsave(&dev
->spinlock
, flags
);
522 if (devpriv
->timer_running
)
523 mod_timer(&devpriv
->timer
, jiffies
+ timer_period());
524 spin_unlock_irqrestore(&dev
->spinlock
, flags
);
527 static int das16_ai_check_chanlist(struct comedi_device
*dev
,
528 struct comedi_subdevice
*s
,
529 struct comedi_cmd
*cmd
)
531 unsigned int chan0
= CR_CHAN(cmd
->chanlist
[0]);
532 unsigned int range0
= CR_RANGE(cmd
->chanlist
[0]);
535 for (i
= 1; i
< cmd
->chanlist_len
; i
++) {
536 unsigned int chan
= CR_CHAN(cmd
->chanlist
[i
]);
537 unsigned int range
= CR_RANGE(cmd
->chanlist
[i
]);
539 if (chan
!= ((chan0
+ i
) % s
->n_chan
)) {
540 dev_dbg(dev
->class_dev
,
541 "entries in chanlist must be consecutive channels, counting upwards\n");
545 if (range
!= range0
) {
546 dev_dbg(dev
->class_dev
,
547 "entries in chanlist must all have the same gain\n");
555 static int das16_cmd_test(struct comedi_device
*dev
, struct comedi_subdevice
*s
,
556 struct comedi_cmd
*cmd
)
558 const struct das16_board
*board
= dev
->board_ptr
;
559 struct das16_private_struct
*devpriv
= dev
->private;
561 unsigned int trig_mask
;
564 /* Step 1 : check if triggers are trivially valid */
566 err
|= cfc_check_trigger_src(&cmd
->start_src
, TRIG_NOW
);
568 trig_mask
= TRIG_FOLLOW
;
569 if (devpriv
->can_burst
)
570 trig_mask
|= TRIG_TIMER
| TRIG_EXT
;
571 err
|= cfc_check_trigger_src(&cmd
->scan_begin_src
, trig_mask
);
573 trig_mask
= TRIG_TIMER
| TRIG_EXT
;
574 if (devpriv
->can_burst
)
575 trig_mask
|= TRIG_NOW
;
576 err
|= cfc_check_trigger_src(&cmd
->convert_src
, trig_mask
);
578 err
|= cfc_check_trigger_src(&cmd
->scan_end_src
, TRIG_COUNT
);
579 err
|= cfc_check_trigger_src(&cmd
->stop_src
, TRIG_COUNT
| TRIG_NONE
);
584 /* Step 2a : make sure trigger sources are unique */
586 err
|= cfc_check_trigger_is_unique(cmd
->scan_begin_src
);
587 err
|= cfc_check_trigger_is_unique(cmd
->convert_src
);
588 err
|= cfc_check_trigger_is_unique(cmd
->stop_src
);
590 /* Step 2b : and mutually compatible */
592 /* make sure scan_begin_src and convert_src dont conflict */
593 if (cmd
->scan_begin_src
== TRIG_FOLLOW
&& cmd
->convert_src
== TRIG_NOW
)
595 if (cmd
->scan_begin_src
!= TRIG_FOLLOW
&& cmd
->convert_src
!= TRIG_NOW
)
601 /* Step 3: check if arguments are trivially valid */
603 err
|= cfc_check_trigger_arg_is(&cmd
->start_arg
, 0);
605 if (cmd
->scan_begin_src
== TRIG_FOLLOW
) /* internal trigger */
606 err
|= cfc_check_trigger_arg_is(&cmd
->scan_begin_arg
, 0);
608 err
|= cfc_check_trigger_arg_is(&cmd
->scan_end_arg
, cmd
->chanlist_len
);
610 /* check against maximum frequency */
611 if (cmd
->scan_begin_src
== TRIG_TIMER
)
612 err
|= cfc_check_trigger_arg_min(&cmd
->scan_begin_arg
,
613 board
->ai_speed
* cmd
->chanlist_len
);
615 if (cmd
->convert_src
== TRIG_TIMER
)
616 err
|= cfc_check_trigger_arg_min(&cmd
->convert_arg
,
619 if (cmd
->stop_src
== TRIG_COUNT
)
620 err
|= cfc_check_trigger_arg_min(&cmd
->stop_arg
, 1);
622 err
|= cfc_check_trigger_arg_is(&cmd
->stop_arg
, 0);
627 /* step 4: fix up arguments */
628 if (cmd
->scan_begin_src
== TRIG_TIMER
) {
629 arg
= cmd
->scan_begin_arg
;
630 i8253_cascade_ns_to_timer(devpriv
->clockbase
,
634 err
|= cfc_check_trigger_arg_is(&cmd
->scan_begin_arg
, arg
);
636 if (cmd
->convert_src
== TRIG_TIMER
) {
637 arg
= cmd
->convert_arg
;
638 i8253_cascade_ns_to_timer(devpriv
->clockbase
,
642 err
|= cfc_check_trigger_arg_is(&cmd
->convert_arg
, arg
);
647 /* Step 5: check channel list if it exists */
648 if (cmd
->chanlist
&& cmd
->chanlist_len
> 0)
649 err
|= das16_ai_check_chanlist(dev
, s
, cmd
);
657 static unsigned int das16_set_pacer(struct comedi_device
*dev
, unsigned int ns
,
660 struct das16_private_struct
*devpriv
= dev
->private;
661 unsigned long timer_base
= dev
->iobase
+ DAS16_TIMER_BASE_REG
;
663 i8253_cascade_ns_to_timer(devpriv
->clockbase
,
664 &devpriv
->divisor1
, &devpriv
->divisor2
,
667 i8254_set_mode(timer_base
, 0, 1, I8254_MODE2
| I8254_BINARY
);
668 i8254_set_mode(timer_base
, 0, 2, I8254_MODE2
| I8254_BINARY
);
669 i8254_write(timer_base
, 0, 1, devpriv
->divisor1
);
670 i8254_write(timer_base
, 0, 2, devpriv
->divisor2
);
675 static int das16_cmd_exec(struct comedi_device
*dev
, struct comedi_subdevice
*s
)
677 const struct das16_board
*board
= dev
->board_ptr
;
678 struct das16_private_struct
*devpriv
= dev
->private;
679 struct comedi_isadma
*dma
= devpriv
->dma
;
680 struct comedi_isadma_desc
*desc
= &dma
->desc
[0];
681 struct comedi_async
*async
= s
->async
;
682 struct comedi_cmd
*cmd
= &async
->cmd
;
687 if (cmd
->flags
& CMDF_PRIORITY
) {
688 dev_err(dev
->class_dev
,
689 "isa dma transfers cannot be performed with CMDF_PRIORITY, aborting\n");
693 devpriv
->adc_byte_count
= cmd
->stop_arg
* comedi_bytes_per_scan(s
);
695 if (devpriv
->can_burst
)
696 outb(DAS1600_CONV_DISABLE
, dev
->iobase
+ DAS1600_CONV_REG
);
698 /* set scan limits */
699 byte
= CR_CHAN(cmd
->chanlist
[0]);
700 byte
|= CR_CHAN(cmd
->chanlist
[cmd
->chanlist_len
- 1]) << 4;
701 outb(byte
, dev
->iobase
+ DAS16_MUX_REG
);
703 /* set gain (this is also burst rate register but according to
704 * computer boards manual, burst rate does nothing, even on
706 if (board
->ai_pg
!= das16_pg_none
) {
707 range
= CR_RANGE(cmd
->chanlist
[0]);
708 outb((das16_gainlists
[board
->ai_pg
])[range
],
709 dev
->iobase
+ DAS16_GAIN_REG
);
712 /* set counter mode and counts */
713 cmd
->convert_arg
= das16_set_pacer(dev
, cmd
->convert_arg
, cmd
->flags
);
715 /* enable counters */
717 if (devpriv
->can_burst
) {
718 if (cmd
->convert_src
== TRIG_NOW
) {
719 outb(DAS1600_BURST_VAL
,
720 dev
->iobase
+ DAS1600_BURST_REG
);
721 /* set burst length */
722 byte
|= DAS16_PACER_BURST_LEN(cmd
->chanlist_len
- 1);
724 outb(0, dev
->iobase
+ DAS1600_BURST_REG
);
727 outb(byte
, dev
->iobase
+ DAS16_PACER_REG
);
729 /* set up dma transfer */
731 desc
->size
= desc
->maxsize
;
732 comedi_isadma_program(desc
);
735 spin_lock_irqsave(&dev
->spinlock
, flags
);
736 devpriv
->timer_running
= 1;
737 devpriv
->timer
.expires
= jiffies
+ timer_period();
738 add_timer(&devpriv
->timer
);
740 /* enable DMA interrupt with external or internal pacing */
741 devpriv
->ctrl_reg
&= ~(DAS16_CTRL_INTE
| DAS16_CTRL_PACING_MASK
);
742 devpriv
->ctrl_reg
|= DAS16_CTRL_DMAE
;
743 if (cmd
->convert_src
== TRIG_EXT
)
744 devpriv
->ctrl_reg
|= DAS16_CTRL_EXT_PACER
;
746 devpriv
->ctrl_reg
|= DAS16_CTRL_INT_PACER
;
747 outb(devpriv
->ctrl_reg
, dev
->iobase
+ DAS16_CTRL_REG
);
749 if (devpriv
->can_burst
)
750 outb(0, dev
->iobase
+ DAS1600_CONV_REG
);
751 spin_unlock_irqrestore(&dev
->spinlock
, flags
);
756 static int das16_cancel(struct comedi_device
*dev
, struct comedi_subdevice
*s
)
758 struct das16_private_struct
*devpriv
= dev
->private;
759 struct comedi_isadma
*dma
= devpriv
->dma
;
762 spin_lock_irqsave(&dev
->spinlock
, flags
);
764 /* disable interrupts, dma and pacer clocked conversions */
765 devpriv
->ctrl_reg
&= ~(DAS16_CTRL_INTE
| DAS16_CTRL_DMAE
|
766 DAS16_CTRL_PACING_MASK
);
767 outb(devpriv
->ctrl_reg
, dev
->iobase
+ DAS16_CTRL_REG
);
769 comedi_isadma_disable(dma
->chan
);
771 /* disable SW timer */
772 if (devpriv
->timer_running
) {
773 devpriv
->timer_running
= 0;
774 del_timer(&devpriv
->timer
);
777 if (devpriv
->can_burst
)
778 outb(0, dev
->iobase
+ DAS1600_BURST_REG
);
780 spin_unlock_irqrestore(&dev
->spinlock
, flags
);
785 static void das16_ai_munge(struct comedi_device
*dev
,
786 struct comedi_subdevice
*s
, void *array
,
787 unsigned int num_bytes
,
788 unsigned int start_chan_index
)
790 unsigned short *data
= array
;
791 unsigned int num_samples
= comedi_bytes_to_samples(s
, num_bytes
);
794 for (i
= 0; i
< num_samples
; i
++) {
795 data
[i
] = le16_to_cpu(data
[i
]);
796 if (s
->maxdata
== 0x0fff)
798 data
[i
] &= s
->maxdata
;
802 static int das16_ai_eoc(struct comedi_device
*dev
,
803 struct comedi_subdevice
*s
,
804 struct comedi_insn
*insn
,
805 unsigned long context
)
809 status
= inb(dev
->iobase
+ DAS16_STATUS_REG
);
810 if ((status
& DAS16_STATUS_BUSY
) == 0)
815 static int das16_ai_insn_read(struct comedi_device
*dev
,
816 struct comedi_subdevice
*s
,
817 struct comedi_insn
*insn
,
820 const struct das16_board
*board
= dev
->board_ptr
;
821 unsigned int chan
= CR_CHAN(insn
->chanspec
);
822 unsigned int range
= CR_RANGE(insn
->chanspec
);
827 /* set multiplexer */
828 outb(chan
| (chan
<< 4), dev
->iobase
+ DAS16_MUX_REG
);
831 if (board
->ai_pg
!= das16_pg_none
) {
832 outb((das16_gainlists
[board
->ai_pg
])[range
],
833 dev
->iobase
+ DAS16_GAIN_REG
);
836 for (i
= 0; i
< insn
->n
; i
++) {
837 /* trigger conversion */
838 outb_p(0, dev
->iobase
+ DAS16_TRIG_REG
);
840 ret
= comedi_timeout(dev
, s
, insn
, das16_ai_eoc
, 0);
844 val
= inb(dev
->iobase
+ DAS16_AI_MSB_REG
) << 8;
845 val
|= inb(dev
->iobase
+ DAS16_AI_LSB_REG
);
846 if (s
->maxdata
== 0x0fff)
856 static int das16_ao_insn_write(struct comedi_device
*dev
,
857 struct comedi_subdevice
*s
,
858 struct comedi_insn
*insn
,
861 unsigned int chan
= CR_CHAN(insn
->chanspec
);
864 for (i
= 0; i
< insn
->n
; i
++) {
865 unsigned int val
= data
[i
];
867 s
->readback
[chan
] = val
;
871 outb(val
& 0xff, dev
->iobase
+ DAS16_AO_LSB_REG(chan
));
872 outb((val
>> 8) & 0xff, dev
->iobase
+ DAS16_AO_MSB_REG(chan
));
878 static int das16_di_insn_bits(struct comedi_device
*dev
,
879 struct comedi_subdevice
*s
,
880 struct comedi_insn
*insn
,
883 data
[1] = inb(dev
->iobase
+ DAS16_DIO_REG
) & 0xf;
888 static int das16_do_insn_bits(struct comedi_device
*dev
,
889 struct comedi_subdevice
*s
,
890 struct comedi_insn
*insn
,
893 if (comedi_dio_update_state(s
, data
))
894 outb(s
->state
, dev
->iobase
+ DAS16_DIO_REG
);
901 static int das16_probe(struct comedi_device
*dev
, struct comedi_devconfig
*it
)
903 const struct das16_board
*board
= dev
->board_ptr
;
906 /* diobits indicates boards */
907 diobits
= inb(dev
->iobase
+ DAS16_DIO_REG
) & 0xf0;
908 if (board
->id
!= diobits
) {
909 dev_err(dev
->class_dev
,
910 "requested board's id bits are incorrect (0x%x != 0x%x)\n",
918 static void das16_reset(struct comedi_device
*dev
)
920 outb(0, dev
->iobase
+ DAS16_STATUS_REG
);
921 outb(0, dev
->iobase
+ DAS16_CTRL_REG
);
922 outb(0, dev
->iobase
+ DAS16_PACER_REG
);
923 outb(0, dev
->iobase
+ DAS16_TIMER_BASE_REG
+ i8254_control_reg
);
926 static void das16_alloc_dma(struct comedi_device
*dev
, unsigned int dma_chan
)
928 struct das16_private_struct
*devpriv
= dev
->private;
930 /* only DMA channels 3 and 1 are valid */
931 if (!(dma_chan
== 1 || dma_chan
== 3))
934 /* DMA uses two buffers */
935 devpriv
->dma
= comedi_isadma_alloc(dev
, 2, dma_chan
, dma_chan
,
936 DAS16_DMA_SIZE
, COMEDI_ISADMA_READ
);
938 init_timer(&devpriv
->timer
);
939 devpriv
->timer
.function
= das16_timer_interrupt
;
940 devpriv
->timer
.data
= (unsigned long)dev
;
944 static void das16_free_dma(struct comedi_device
*dev
)
946 struct das16_private_struct
*devpriv
= dev
->private;
949 if (devpriv
->timer
.data
)
950 del_timer_sync(&devpriv
->timer
);
951 comedi_isadma_free(devpriv
->dma
);
955 static int das16_attach(struct comedi_device
*dev
, struct comedi_devconfig
*it
)
957 const struct das16_board
*board
= dev
->board_ptr
;
958 struct das16_private_struct
*devpriv
;
959 struct comedi_subdevice
*s
;
960 struct comedi_lrange
*lrange
;
961 struct comedi_krange
*krange
;
965 /* check that clock setting is valid */
966 if (it
->options
[3]) {
967 if (it
->options
[3] != 0 &&
968 it
->options
[3] != 1 && it
->options
[3] != 10) {
969 dev_err(dev
->class_dev
,
970 "Invalid option. Master clock must be set to 1 or 10 (MHz)\n");
975 devpriv
= comedi_alloc_devpriv(dev
, sizeof(*devpriv
));
979 if (board
->size
< 0x400) {
980 ret
= comedi_request_region(dev
, it
->options
[0], board
->size
);
984 ret
= comedi_request_region(dev
, it
->options
[0], 0x10);
987 /* Request an additional region for the 8255 */
988 ret
= __comedi_request_region(dev
, dev
->iobase
+ 0x400,
989 board
->size
& 0x3ff);
992 devpriv
->extra_iobase
= dev
->iobase
+ 0x400;
993 devpriv
->can_burst
= 1;
996 /* probe id bits to make sure they are consistent */
997 if (das16_probe(dev
, it
))
1000 /* get master clock speed */
1001 if (devpriv
->can_burst
) {
1002 status
= inb(dev
->iobase
+ DAS1600_STATUS_REG
);
1004 if (status
& DAS1600_STATUS_CLK_10MHZ
)
1005 devpriv
->clockbase
= I8254_OSC_BASE_10MHZ
;
1007 devpriv
->clockbase
= I8254_OSC_BASE_1MHZ
;
1010 devpriv
->clockbase
= I8254_OSC_BASE_1MHZ
/
1013 devpriv
->clockbase
= I8254_OSC_BASE_1MHZ
;
1016 das16_alloc_dma(dev
, it
->options
[2]);
1018 /* get any user-defined input range */
1019 if (board
->ai_pg
== das16_pg_none
&&
1020 (it
->options
[4] || it
->options
[5])) {
1021 /* allocate single-range range table */
1022 lrange
= kzalloc(sizeof(*lrange
) + sizeof(*krange
), GFP_KERNEL
);
1026 /* initialize ai range */
1027 devpriv
->user_ai_range_table
= lrange
;
1029 krange
= devpriv
->user_ai_range_table
->range
;
1030 krange
->min
= it
->options
[4];
1031 krange
->max
= it
->options
[5];
1032 krange
->flags
= UNIT_volt
;
1035 /* get any user-defined output range */
1036 if (it
->options
[6] || it
->options
[7]) {
1037 /* allocate single-range range table */
1038 lrange
= kzalloc(sizeof(*lrange
) + sizeof(*krange
), GFP_KERNEL
);
1042 /* initialize ao range */
1043 devpriv
->user_ao_range_table
= lrange
;
1045 krange
= devpriv
->user_ao_range_table
->range
;
1046 krange
->min
= it
->options
[6];
1047 krange
->max
= it
->options
[7];
1048 krange
->flags
= UNIT_volt
;
1051 ret
= comedi_alloc_subdevices(dev
, 4 + board
->has_8255
);
1055 status
= inb(dev
->iobase
+ DAS16_STATUS_REG
);
1057 /* Analog Input subdevice */
1058 s
= &dev
->subdevices
[0];
1059 s
->type
= COMEDI_SUBD_AI
;
1060 s
->subdev_flags
= SDF_READABLE
;
1061 if (status
& DAS16_STATUS_MUXBIT
) {
1062 s
->subdev_flags
|= SDF_GROUND
;
1065 s
->subdev_flags
|= SDF_DIFF
;
1068 s
->len_chanlist
= s
->n_chan
;
1069 s
->maxdata
= board
->ai_maxdata
;
1070 if (devpriv
->user_ai_range_table
) { /* user defined ai range */
1071 s
->range_table
= devpriv
->user_ai_range_table
;
1072 } else if (status
& DAS16_STATUS_UNIPOLAR
) {
1073 s
->range_table
= das16_ai_uni_lranges
[board
->ai_pg
];
1075 s
->range_table
= das16_ai_bip_lranges
[board
->ai_pg
];
1077 s
->insn_read
= das16_ai_insn_read
;
1079 dev
->read_subdev
= s
;
1080 s
->subdev_flags
|= SDF_CMD_READ
;
1081 s
->do_cmdtest
= das16_cmd_test
;
1082 s
->do_cmd
= das16_cmd_exec
;
1083 s
->cancel
= das16_cancel
;
1084 s
->munge
= das16_ai_munge
;
1087 /* Analog Output subdevice */
1088 s
= &dev
->subdevices
[1];
1089 if (board
->has_ao
) {
1090 s
->type
= COMEDI_SUBD_AO
;
1091 s
->subdev_flags
= SDF_WRITABLE
;
1093 s
->maxdata
= 0x0fff;
1094 s
->range_table
= devpriv
->user_ao_range_table
;
1095 s
->insn_write
= das16_ao_insn_write
;
1097 ret
= comedi_alloc_subdev_readback(s
);
1101 s
->type
= COMEDI_SUBD_UNUSED
;
1104 /* Digital Input subdevice */
1105 s
= &dev
->subdevices
[2];
1106 s
->type
= COMEDI_SUBD_DI
;
1107 s
->subdev_flags
= SDF_READABLE
;
1110 s
->range_table
= &range_digital
;
1111 s
->insn_bits
= das16_di_insn_bits
;
1113 /* Digital Output subdevice */
1114 s
= &dev
->subdevices
[3];
1115 s
->type
= COMEDI_SUBD_DO
;
1116 s
->subdev_flags
= SDF_WRITABLE
;
1119 s
->range_table
= &range_digital
;
1120 s
->insn_bits
= das16_do_insn_bits
;
1122 /* initialize digital output lines */
1123 outb(s
->state
, dev
->iobase
+ DAS16_DIO_REG
);
1125 /* 8255 Digital I/O subdevice */
1126 if (board
->has_8255
) {
1127 s
= &dev
->subdevices
[4];
1128 ret
= subdev_8255_init(dev
, s
, NULL
, board
->i8255_offset
);
1134 /* set the interrupt level */
1135 devpriv
->ctrl_reg
= DAS16_CTRL_IRQ(dev
->irq
);
1136 outb(devpriv
->ctrl_reg
, dev
->iobase
+ DAS16_CTRL_REG
);
1138 if (devpriv
->can_burst
) {
1139 outb(DAS1600_ENABLE_VAL
, dev
->iobase
+ DAS1600_ENABLE_REG
);
1140 outb(0, dev
->iobase
+ DAS1600_CONV_REG
);
1141 outb(0, dev
->iobase
+ DAS1600_BURST_REG
);
1147 static void das16_detach(struct comedi_device
*dev
)
1149 const struct das16_board
*board
= dev
->board_ptr
;
1150 struct das16_private_struct
*devpriv
= dev
->private;
1155 das16_free_dma(dev
);
1156 kfree(devpriv
->user_ai_range_table
);
1157 kfree(devpriv
->user_ao_range_table
);
1159 if (devpriv
->extra_iobase
)
1160 release_region(devpriv
->extra_iobase
,
1161 board
->size
& 0x3ff);
1164 comedi_legacy_detach(dev
);
1167 static struct comedi_driver das16_driver
= {
1168 .driver_name
= "das16",
1169 .module
= THIS_MODULE
,
1170 .attach
= das16_attach
,
1171 .detach
= das16_detach
,
1172 .board_name
= &das16_boards
[0].name
,
1173 .num_names
= ARRAY_SIZE(das16_boards
),
1174 .offset
= sizeof(das16_boards
[0]),
1176 module_comedi_driver(das16_driver
);
1178 MODULE_AUTHOR("Comedi http://www.comedi.org");
1179 MODULE_DESCRIPTION("Comedi driver for DAS16 compatible boards");
1180 MODULE_LICENSE("GPL");