2 comedi/drivers/ni_at_ao.c
3 Driver for NI AT-AO-6/10 boards
5 COMEDI - Linux Control and Measurement Device Interface
6 Copyright (C) 2000,2002 David A. Schleef <ds@schleef.org>
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
20 Description: National Instruments AT-AO-6/10
21 Devices: [National Instruments] AT-AO-6 (at-ao-6), AT-AO-10 (at-ao-10)
24 Updated: Sun Dec 26 12:26:28 EST 2004
26 Configuration options:
27 [0] - I/O port base address
30 [3] - analog output range, set by jumpers on hardware (0 for -10 to 10V
31 bipolar, 1 for 0V to 10V unipolar)
35 * Register-level programming information can be found in NI
36 * document 320379.pdf.
39 #include "../comedidev.h"
41 #include <linux/ioport.h>
44 /* registers with _2_ are accessed when GRP2WR is set in CFG1 */
46 #define ATAO_SIZE 0x20
48 #define ATAO_2_DMATCCLR 0x00 /* W 16 */
49 #define ATAO_DIN 0x00 /* R 16 */
50 #define ATAO_DOUT 0x00 /* W 16 */
52 #define ATAO_CFG2 0x02 /* W 16 */
70 #define ATAO_2_INT1CLR 0x02 /* W 16 */
72 #define ATAO_CFG3 0x04 /* W 16 */
73 #define DMAMODE 0x0040
76 #define DOUTEN2 0x0008
77 #define DOUTEN1 0x0004
81 #define ATAO_2_INT2CLR 0x04 /* W 16 */
83 #define ATAO_82C53_BASE 0x06 /* RW 8 */
85 #define ATAO_82C53_CNTR1 0x06 /* RW 8 */
86 #define ATAO_82C53_CNTR2 0x07 /* RW 8 */
87 #define ATAO_82C53_CNTR3 0x08 /* RW 8 */
88 #define ATAO_82C53_CNTRCMD 0x09 /* W 8 */
97 /* read-back command */
113 #define ATAO_2_RTSISHFT 0x06 /* W 8 */
116 #define ATAO_2_RTSISTRB 0x07 /* W 8 */
118 #define ATAO_CFG1 0x0a /* W 16 */
119 #define EXTINT2EN 0x8000
120 #define EXTINT1EN 0x4000
121 #define CNTINT2EN 0x2000
122 #define CNTINT1EN 0x1000
123 #define TCINTEN 0x0800
124 #define CNT1SRC 0x0400
125 #define CNT2SRC 0x0200
126 #define FIFOEN 0x0100
127 #define GRP2WR 0x0080
128 #define EXTUPDEN 0x0040
131 #define CH_mask 0x000f
132 #define ATAO_STATUS 0x0a /* R 16 */
139 #define PROMOUT 0x0001
141 #define ATAO_FIFO_WRITE 0x0c /* W 16 */
142 #define ATAO_FIFO_CLEAR 0x0c /* R 16 */
143 #define ATAO_DACn(x) (0x0c + 2*(x)) /* W */
146 * Board descriptions for two imaginary boards. Describing the
147 * boards in this way is optional, and completely driver-dependent.
148 * Some drivers use arrays such as this, other do not.
155 struct atao_private
{
161 /* Used for AO readback */
162 unsigned int ao_readback
[10];
165 static void atao_reset(struct comedi_device
*dev
)
167 struct atao_private
*devpriv
= dev
->private;
169 /* This is the reset sequence described in the manual */
172 outw(devpriv
->cfg1
, dev
->iobase
+ ATAO_CFG1
);
174 outb(RWSEL0
| MODESEL2
, dev
->iobase
+ ATAO_82C53_CNTRCMD
);
175 outb(0x03, dev
->iobase
+ ATAO_82C53_CNTR1
);
176 outb(CNTRSEL0
| RWSEL0
| MODESEL2
, dev
->iobase
+ ATAO_82C53_CNTRCMD
);
179 outw(devpriv
->cfg2
, dev
->iobase
+ ATAO_CFG2
);
182 outw(devpriv
->cfg3
, dev
->iobase
+ ATAO_CFG3
);
184 inw(dev
->iobase
+ ATAO_FIFO_CLEAR
);
186 devpriv
->cfg1
|= GRP2WR
;
187 outw(devpriv
->cfg1
, dev
->iobase
+ ATAO_CFG1
);
189 outw(0, dev
->iobase
+ ATAO_2_INT1CLR
);
190 outw(0, dev
->iobase
+ ATAO_2_INT2CLR
);
191 outw(0, dev
->iobase
+ ATAO_2_DMATCCLR
);
193 devpriv
->cfg1
&= ~GRP2WR
;
194 outw(devpriv
->cfg1
, dev
->iobase
+ ATAO_CFG1
);
197 static int atao_ao_winsn(struct comedi_device
*dev
, struct comedi_subdevice
*s
,
198 struct comedi_insn
*insn
, unsigned int *data
)
200 struct atao_private
*devpriv
= dev
->private;
202 int chan
= CR_CHAN(insn
->chanspec
);
205 for (i
= 0; i
< insn
->n
; i
++) {
206 bits
= data
[i
] - 0x800;
208 devpriv
->cfg1
|= GRP2WR
;
209 outw(devpriv
->cfg1
, dev
->iobase
+ ATAO_CFG1
);
211 outw(bits
, dev
->iobase
+ ATAO_DACn(chan
));
213 devpriv
->cfg1
&= ~GRP2WR
;
214 outw(devpriv
->cfg1
, dev
->iobase
+ ATAO_CFG1
);
216 devpriv
->ao_readback
[chan
] = data
[i
];
222 static int atao_ao_rinsn(struct comedi_device
*dev
, struct comedi_subdevice
*s
,
223 struct comedi_insn
*insn
, unsigned int *data
)
225 struct atao_private
*devpriv
= dev
->private;
227 int chan
= CR_CHAN(insn
->chanspec
);
229 for (i
= 0; i
< insn
->n
; i
++)
230 data
[i
] = devpriv
->ao_readback
[chan
];
235 static int atao_dio_insn_bits(struct comedi_device
*dev
,
236 struct comedi_subdevice
*s
,
237 struct comedi_insn
*insn
, unsigned int *data
)
240 s
->state
&= ~data
[0];
241 s
->state
|= data
[0] & data
[1];
242 outw(s
->state
, dev
->iobase
+ ATAO_DOUT
);
245 data
[1] = inw(dev
->iobase
+ ATAO_DIN
);
250 static int atao_dio_insn_config(struct comedi_device
*dev
,
251 struct comedi_subdevice
*s
,
252 struct comedi_insn
*insn
, unsigned int *data
)
254 struct atao_private
*devpriv
= dev
->private;
255 int chan
= CR_CHAN(insn
->chanspec
);
256 unsigned int mask
, bit
;
258 /* The input or output configuration of each digital line is
259 * configured by a special insn_config instruction. chanspec
260 * contains the channel to be changed, and data[0] contains the
261 * value COMEDI_INPUT or COMEDI_OUTPUT. */
263 mask
= (chan
< 4) ? 0x0f : 0xf0;
264 bit
= (chan
< 4) ? DOUTEN1
: DOUTEN2
;
267 case INSN_CONFIG_DIO_OUTPUT
:
269 devpriv
->cfg3
|= bit
;
271 case INSN_CONFIG_DIO_INPUT
:
273 devpriv
->cfg3
&= ~bit
;
275 case INSN_CONFIG_DIO_QUERY
:
277 (s
->io_bits
& (1 << chan
)) ? COMEDI_OUTPUT
: COMEDI_INPUT
;
285 outw(devpriv
->cfg3
, dev
->iobase
+ ATAO_CFG3
);
291 * Figure 2-1 in the manual shows 3 chips labeled DAC8800, which
292 * are 8-channel 8-bit DACs. These are most likely the calibration
293 * DACs. It is not explicitly stated in the manual how to access
294 * the caldacs, but we can guess.
296 static int atao_calib_insn_read(struct comedi_device
*dev
,
297 struct comedi_subdevice
*s
,
298 struct comedi_insn
*insn
, unsigned int *data
)
301 for (i
= 0; i
< insn
->n
; i
++)
302 data
[i
] = 0; /* XXX */
306 static int atao_calib_insn_write(struct comedi_device
*dev
,
307 struct comedi_subdevice
*s
,
308 struct comedi_insn
*insn
, unsigned int *data
)
310 struct atao_private
*devpriv
= dev
->private;
311 unsigned int bitstring
, bit
;
312 unsigned int chan
= CR_CHAN(insn
->chanspec
);
314 bitstring
= ((chan
& 0x7) << 8) | (data
[insn
->n
- 1] & 0xff);
316 for (bit
= 1 << (11 - 1); bit
; bit
>>= 1) {
317 outw(devpriv
->cfg2
| ((bit
& bitstring
) ? SDATA
: 0),
318 dev
->iobase
+ ATAO_CFG2
);
319 outw(devpriv
->cfg2
| SCLK
| ((bit
& bitstring
) ? SDATA
: 0),
320 dev
->iobase
+ ATAO_CFG2
);
322 /* strobe the appropriate caldac */
323 outw(devpriv
->cfg2
| (((chan
>> 3) + 1) << 14),
324 dev
->iobase
+ ATAO_CFG2
);
325 outw(devpriv
->cfg2
, dev
->iobase
+ ATAO_CFG2
);
330 static int atao_attach(struct comedi_device
*dev
, struct comedi_devconfig
*it
)
332 const struct atao_board
*board
= comedi_board(dev
);
333 struct atao_private
*devpriv
;
334 struct comedi_subdevice
*s
;
338 ao_unipolar
= it
->options
[3];
340 ret
= comedi_request_region(dev
, it
->options
[0], ATAO_SIZE
);
344 devpriv
= kzalloc(sizeof(*devpriv
), GFP_KERNEL
);
347 dev
->private = devpriv
;
349 ret
= comedi_alloc_subdevices(dev
, 4);
353 s
= &dev
->subdevices
[0];
354 /* analog output subdevice */
355 s
->type
= COMEDI_SUBD_AO
;
356 s
->subdev_flags
= SDF_WRITABLE
;
357 s
->n_chan
= board
->n_ao_chans
;
358 s
->maxdata
= (1 << 12) - 1;
360 s
->range_table
= &range_unipolar10
;
362 s
->range_table
= &range_bipolar10
;
363 s
->insn_write
= &atao_ao_winsn
;
364 s
->insn_read
= &atao_ao_rinsn
;
366 s
= &dev
->subdevices
[1];
367 /* digital i/o subdevice */
368 s
->type
= COMEDI_SUBD_DIO
;
369 s
->subdev_flags
= SDF_READABLE
| SDF_WRITABLE
;
372 s
->range_table
= &range_digital
;
373 s
->insn_bits
= atao_dio_insn_bits
;
374 s
->insn_config
= atao_dio_insn_config
;
376 s
= &dev
->subdevices
[2];
377 /* caldac subdevice */
378 s
->type
= COMEDI_SUBD_CALIB
;
379 s
->subdev_flags
= SDF_WRITABLE
| SDF_INTERNAL
;
382 s
->insn_read
= atao_calib_insn_read
;
383 s
->insn_write
= atao_calib_insn_write
;
385 s
= &dev
->subdevices
[3];
386 /* eeprom subdevice */
387 /* s->type=COMEDI_SUBD_EEPROM; */
388 s
->type
= COMEDI_SUBD_UNUSED
;
392 printk(KERN_INFO
"\n");
397 static const struct atao_board atao_boards
[] = {
407 static struct comedi_driver ni_at_ao_driver
= {
408 .driver_name
= "ni_at_ao",
409 .module
= THIS_MODULE
,
410 .attach
= atao_attach
,
411 .detach
= comedi_legacy_detach
,
412 .board_name
= &atao_boards
[0].name
,
413 .offset
= sizeof(struct atao_board
),
414 .num_names
= ARRAY_SIZE(atao_boards
),
416 module_comedi_driver(ni_at_ao_driver
);
418 MODULE_AUTHOR("Comedi http://www.comedi.org");
419 MODULE_DESCRIPTION("Comedi low-level driver");
420 MODULE_LICENSE("GPL");