ni_at_ao.c revision 75b807393272fcfcf54d1188c667dc0fccd1fb69
1/* 2 comedi/drivers/ni_at_ao.c 3 Driver for NI AT-AO-6/10 boards 4 5 COMEDI - Linux Control and Measurement Device Interface 6 Copyright (C) 2000,2002 David A. Schleef <ds@schleef.org> 7 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. 12 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. 17 18 You should have received a copy of the GNU General Public License 19 along with this program; if not, write to the Free Software 20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 21 22*/ 23/* 24Driver: ni_at_ao 25Description: National Instruments AT-AO-6/10 26Devices: [National Instruments] AT-AO-6 (at-ao-6), AT-AO-10 (at-ao-10) 27Status: should work 28Author: ds 29Updated: Sun Dec 26 12:26:28 EST 2004 30 31Configuration options: 32 [0] - I/O port base address 33 [1] - IRQ (unused) 34 [2] - DMA (unused) 35 [3] - analog output range, set by jumpers on hardware (0 for -10 to 10V bipolar, 1 for 0V to 10V unipolar) 36 37*/ 38/* 39 * Register-level programming information can be found in NI 40 * document 320379.pdf. 41 */ 42 43#include "../comedidev.h" 44 45#include <linux/ioport.h> 46 47/* board egisters */ 48/* registers with _2_ are accessed when GRP2WR is set in CFG1 */ 49 50#define ATAO_SIZE 0x20 51 52#define ATAO_2_DMATCCLR 0x00 /* W 16 */ 53#define ATAO_DIN 0x00 /* R 16 */ 54#define ATAO_DOUT 0x00 /* W 16 */ 55 56#define ATAO_CFG2 0x02 /* W 16 */ 57#define CALLD1 0x8000 58#define CALLD0 0x4000 59#define FFRTEN 0x2000 60#define DAC2S8 0x1000 61#define DAC2S6 0x0800 62#define DAC2S4 0x0400 63#define DAC2S2 0x0200 64#define DAC2S0 0x0100 65#define LDAC8 0x0080 66#define LDAC6 0x0040 67#define LDAC4 0x0020 68#define LDAC2 0x0010 69#define LDAC0 0x0008 70#define PROMEN 0x0004 71#define SCLK 0x0002 72#define SDATA 0x0001 73 74#define ATAO_2_INT1CLR 0x02 /* W 16 */ 75 76#define ATAO_CFG3 0x04 /* W 16 */ 77#define DMAMODE 0x0040 78#define CLKOUT 0x0020 79#define RCLKEN 0x0010 80#define DOUTEN2 0x0008 81#define DOUTEN1 0x0004 82#define EN2_5V 0x0002 83#define SCANEN 0x0001 84 85#define ATAO_2_INT2CLR 0x04 /* W 16 */ 86 87#define ATAO_82C53_BASE 0x06 /* RW 8 */ 88 89#define ATAO_82C53_CNTR1 0x06 /* RW 8 */ 90#define ATAO_82C53_CNTR2 0x07 /* RW 8 */ 91#define ATAO_82C53_CNTR3 0x08 /* RW 8 */ 92#define ATAO_82C53_CNTRCMD 0x09 /* W 8 */ 93#define CNTRSEL1 0x80 94#define CNTRSEL0 0x40 95#define RWSEL1 0x20 96#define RWSEL0 0x10 97#define MODESEL2 0x08 98#define MODESEL1 0x04 99#define MODESEL0 0x02 100#define BCDSEL 0x01 101 /* read-back command */ 102#define COUNT 0x20 103#define STATUS 0x10 104#define CNTR3 0x08 105#define CNTR2 0x04 106#define CNTR1 0x02 107 /* status */ 108#define OUT 0x80 109#define _NULL 0x40 110#define RW1 0x20 111#define RW0 0x10 112#define MODE2 0x08 113#define MODE1 0x04 114#define MODE0 0x02 115#define BCD 0x01 116 117#define ATAO_2_RTSISHFT 0x06 /* W 8 */ 118#define RSI 0x01 119 120#define ATAO_2_RTSISTRB 0x07 /* W 8 */ 121 122#define ATAO_CFG1 0x0a /* W 16 */ 123#define EXTINT2EN 0x8000 124#define EXTINT1EN 0x4000 125#define CNTINT2EN 0x2000 126#define CNTINT1EN 0x1000 127#define TCINTEN 0x0800 128#define CNT1SRC 0x0400 129#define CNT2SRC 0x0200 130#define FIFOEN 0x0100 131#define GRP2WR 0x0080 132#define EXTUPDEN 0x0040 133#define DMARQ 0x0020 134#define DMAEN 0x0010 135#define CH_mask 0x000f 136#define ATAO_STATUS 0x0a /* R 16 */ 137#define FH 0x0040 138#define FE 0x0020 139#define FF 0x0010 140#define INT2 0x0008 141#define INT1 0x0004 142#define TCINT 0x0002 143#define PROMOUT 0x0001 144 145#define ATAO_FIFO_WRITE 0x0c /* W 16 */ 146#define ATAO_FIFO_CLEAR 0x0c /* R 16 */ 147#define ATAO_DACn(x) (0x0c + 2*(x)) /* W */ 148 149/* 150 * Board descriptions for two imaginary boards. Describing the 151 * boards in this way is optional, and completely driver-dependent. 152 * Some drivers use arrays such as this, other do not. 153 */ 154typedef struct atao_board_struct { 155 const char *name; 156 int n_ao_chans; 157} atao_board; 158static const atao_board atao_boards[] = { 159 { 160 name: "ai-ao-6", 161 n_ao_chans:6, 162 }, 163 { 164 name: "ai-ao-10", 165 n_ao_chans:10, 166 }, 167}; 168 169#define thisboard ((atao_board *)dev->board_ptr) 170 171struct atao_private { 172 173 unsigned short cfg1; 174 unsigned short cfg2; 175 unsigned short cfg3; 176 177 /* Used for AO readback */ 178 unsigned int ao_readback[10]; 179}; 180 181#define devpriv ((struct atao_private *)dev->private) 182 183static int atao_attach(struct comedi_device * dev, struct comedi_devconfig * it); 184static int atao_detach(struct comedi_device * dev); 185static struct comedi_driver driver_atao = { 186 driver_name:"ni_at_ao", 187 module:THIS_MODULE, 188 attach:atao_attach, 189 detach:atao_detach, 190 board_name:&atao_boards[0].name, 191 offset:sizeof(atao_board), 192 num_names:sizeof(atao_boards) / sizeof(atao_board), 193}; 194 195COMEDI_INITCLEANUP(driver_atao); 196 197static void atao_reset(struct comedi_device * dev); 198 199static int atao_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s, 200 struct comedi_insn * insn, unsigned int * data); 201static int atao_ao_rinsn(struct comedi_device * dev, struct comedi_subdevice * s, 202 struct comedi_insn * insn, unsigned int * data); 203static int atao_dio_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s, 204 struct comedi_insn * insn, unsigned int * data); 205static int atao_dio_insn_config(struct comedi_device * dev, struct comedi_subdevice * s, 206 struct comedi_insn * insn, unsigned int * data); 207static int atao_calib_insn_read(struct comedi_device * dev, struct comedi_subdevice * s, 208 struct comedi_insn * insn, unsigned int * data); 209static int atao_calib_insn_write(struct comedi_device * dev, struct comedi_subdevice * s, 210 struct comedi_insn * insn, unsigned int * data); 211 212static int atao_attach(struct comedi_device * dev, struct comedi_devconfig * it) 213{ 214 struct comedi_subdevice *s; 215 unsigned long iobase; 216 int ao_unipolar; 217 218 iobase = it->options[0]; 219 if (iobase == 0) 220 iobase = 0x1c0; 221 ao_unipolar = it->options[3]; 222 223 printk("comedi%d: ni_at_ao: 0x%04lx", dev->minor, iobase); 224 225 if (!request_region(iobase, ATAO_SIZE, "ni_at_ao")) { 226 printk(" I/O port conflict\n"); 227 return -EIO; 228 } 229 dev->iobase = iobase; 230 231 //dev->board_ptr = atao_probe(dev); 232 233 dev->board_name = thisboard->name; 234 235 if (alloc_private(dev, sizeof(struct atao_private)) < 0) 236 return -ENOMEM; 237 238 if (alloc_subdevices(dev, 4) < 0) 239 return -ENOMEM; 240 241 s = dev->subdevices + 0; 242 /* analog output subdevice */ 243 s->type = COMEDI_SUBD_AO; 244 s->subdev_flags = SDF_WRITABLE; 245 s->n_chan = thisboard->n_ao_chans; 246 s->maxdata = (1 << 12) - 1; 247 if (ao_unipolar) 248 s->range_table = &range_unipolar10; 249 else 250 s->range_table = &range_bipolar10; 251 s->insn_write = &atao_ao_winsn; 252 s->insn_read = &atao_ao_rinsn; 253 254 s = dev->subdevices + 1; 255 /* digital i/o subdevice */ 256 s->type = COMEDI_SUBD_DIO; 257 s->subdev_flags = SDF_READABLE | SDF_WRITABLE; 258 s->n_chan = 8; 259 s->maxdata = 1; 260 s->range_table = &range_digital; 261 s->insn_bits = atao_dio_insn_bits; 262 s->insn_config = atao_dio_insn_config; 263 264 s = dev->subdevices + 2; 265 /* caldac subdevice */ 266 s->type = COMEDI_SUBD_CALIB; 267 s->subdev_flags = SDF_WRITABLE | SDF_INTERNAL; 268 s->n_chan = 21; 269 s->maxdata = 0xff; 270 s->insn_read = atao_calib_insn_read; 271 s->insn_write = atao_calib_insn_write; 272 273 s = dev->subdevices + 3; 274 /* eeprom subdevice */ 275 //s->type=COMEDI_SUBD_EEPROM; 276 s->type = COMEDI_SUBD_UNUSED; 277 278 atao_reset(dev); 279 280 printk("\n"); 281 282 return 0; 283} 284 285static int atao_detach(struct comedi_device * dev) 286{ 287 printk("comedi%d: atao: remove\n", dev->minor); 288 289 if (dev->iobase) 290 release_region(dev->iobase, ATAO_SIZE); 291 292 return 0; 293} 294 295static void atao_reset(struct comedi_device * dev) 296{ 297 /* This is the reset sequence described in the manual */ 298 299 devpriv->cfg1 = 0; 300 outw(devpriv->cfg1, dev->iobase + ATAO_CFG1); 301 302 outb(RWSEL0 | MODESEL2, dev->iobase + ATAO_82C53_CNTRCMD); 303 outb(0x03, dev->iobase + ATAO_82C53_CNTR1); 304 outb(CNTRSEL0 | RWSEL0 | MODESEL2, dev->iobase + ATAO_82C53_CNTRCMD); 305 306 devpriv->cfg2 = 0; 307 outw(devpriv->cfg2, dev->iobase + ATAO_CFG2); 308 309 devpriv->cfg3 = 0; 310 outw(devpriv->cfg3, dev->iobase + ATAO_CFG3); 311 312 inw(dev->iobase + ATAO_FIFO_CLEAR); 313 314 devpriv->cfg1 |= GRP2WR; 315 outw(devpriv->cfg1, dev->iobase + ATAO_CFG1); 316 317 outw(0, dev->iobase + ATAO_2_INT1CLR); 318 outw(0, dev->iobase + ATAO_2_INT2CLR); 319 outw(0, dev->iobase + ATAO_2_DMATCCLR); 320 321 devpriv->cfg1 &= ~GRP2WR; 322 outw(devpriv->cfg1, dev->iobase + ATAO_CFG1); 323} 324 325static int atao_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s, 326 struct comedi_insn * insn, unsigned int * data) 327{ 328 int i; 329 int chan = CR_CHAN(insn->chanspec); 330 short bits; 331 332 for (i = 0; i < insn->n; i++) { 333 bits = data[i] - 0x800; 334 if (chan == 0) { 335 devpriv->cfg1 |= GRP2WR; 336 outw(devpriv->cfg1, dev->iobase + ATAO_CFG1); 337 } 338 outw(bits, dev->iobase + ATAO_DACn(chan)); 339 if (chan == 0) { 340 devpriv->cfg1 &= ~GRP2WR; 341 outw(devpriv->cfg1, dev->iobase + ATAO_CFG1); 342 } 343 devpriv->ao_readback[chan] = data[i]; 344 } 345 346 return i; 347} 348 349static int atao_ao_rinsn(struct comedi_device * dev, struct comedi_subdevice * s, 350 struct comedi_insn * insn, unsigned int * data) 351{ 352 int i; 353 int chan = CR_CHAN(insn->chanspec); 354 355 for (i = 0; i < insn->n; i++) 356 data[i] = devpriv->ao_readback[chan]; 357 358 return i; 359} 360 361static int atao_dio_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s, 362 struct comedi_insn * insn, unsigned int * data) 363{ 364 if (insn->n != 2) 365 return -EINVAL; 366 367 if (data[0]) { 368 s->state &= ~data[0]; 369 s->state |= data[0] & data[1]; 370 outw(s->state, dev->iobase + ATAO_DOUT); 371 } 372 373 data[1] = inw(dev->iobase + ATAO_DIN); 374 375 return 2; 376} 377 378static int atao_dio_insn_config(struct comedi_device * dev, struct comedi_subdevice * s, 379 struct comedi_insn * insn, unsigned int * data) 380{ 381 int chan = CR_CHAN(insn->chanspec); 382 unsigned int mask, bit; 383 384 /* The input or output configuration of each digital line is 385 * configured by a special insn_config instruction. chanspec 386 * contains the channel to be changed, and data[0] contains the 387 * value COMEDI_INPUT or COMEDI_OUTPUT. */ 388 389 mask = (chan < 4) ? 0x0f : 0xf0; 390 bit = (chan < 4) ? DOUTEN1 : DOUTEN2; 391 392 switch (data[0]) { 393 case INSN_CONFIG_DIO_OUTPUT: 394 s->io_bits |= mask; 395 devpriv->cfg3 |= bit; 396 break; 397 case INSN_CONFIG_DIO_INPUT: 398 s->io_bits &= ~mask; 399 devpriv->cfg3 &= ~bit; 400 break; 401 case INSN_CONFIG_DIO_QUERY: 402 data[1] = 403 (s-> 404 io_bits & (1 << chan)) ? COMEDI_OUTPUT : COMEDI_INPUT; 405 return insn->n; 406 break; 407 default: 408 return -EINVAL; 409 break; 410 } 411 412 outw(devpriv->cfg3, dev->iobase + ATAO_CFG3); 413 414 return 1; 415} 416 417/* 418 * Figure 2-1 in the manual shows 3 chips labeled DAC8800, which 419 * are 8-channel 8-bit DACs. These are most likely the calibration 420 * DACs. It is not explicitly stated in the manual how to access 421 * the caldacs, but we can guess. 422 */ 423static int atao_calib_insn_read(struct comedi_device * dev, struct comedi_subdevice * s, 424 struct comedi_insn * insn, unsigned int * data) 425{ 426 int i; 427 for (i = 0; i < insn->n; i++) { 428 data[i] = 0; /* XXX */ 429 } 430 return insn->n; 431} 432 433static int atao_calib_insn_write(struct comedi_device * dev, struct comedi_subdevice * s, 434 struct comedi_insn * insn, unsigned int * data) 435{ 436 unsigned int bitstring, bit; 437 unsigned int chan = CR_CHAN(insn->chanspec); 438 439 bitstring = ((chan & 0x7) << 8) | (data[insn->n - 1] & 0xff); 440 441 for (bit = 1 << (11 - 1); bit; bit >>= 1) { 442 outw(devpriv->cfg2 | ((bit & bitstring) ? SDATA : 0), 443 dev->iobase + ATAO_CFG2); 444 outw(devpriv->cfg2 | SCLK | ((bit & bitstring) ? SDATA : 0), 445 dev->iobase + ATAO_CFG2); 446 } 447 /* strobe the appropriate caldac */ 448 outw(devpriv->cfg2 | (((chan >> 3) + 1) << 14), 449 dev->iobase + ATAO_CFG2); 450 outw(devpriv->cfg2, dev->iobase + ATAO_CFG2); 451 452 return insn->n; 453} 454