ni_at_ao.c revision 0a85b6f0ab0d2edb0d41b32697111ce0e4f43496
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 */ 154struct atao_board { 155 const char *name; 156 int n_ao_chans; 157}; 158 159static const struct atao_board atao_boards[] = { 160 { 161 .name = "ai-ao-6", 162 .n_ao_chans = 6, 163 }, 164 { 165 .name = "ai-ao-10", 166 .n_ao_chans = 10, 167 }, 168}; 169 170#define thisboard ((struct atao_board *)dev->board_ptr) 171 172struct atao_private { 173 174 unsigned short cfg1; 175 unsigned short cfg2; 176 unsigned short cfg3; 177 178 /* Used for AO readback */ 179 unsigned int ao_readback[10]; 180}; 181 182#define devpriv ((struct atao_private *)dev->private) 183 184static int atao_attach(struct comedi_device *dev, struct comedi_devconfig *it); 185static int atao_detach(struct comedi_device *dev); 186static struct comedi_driver driver_atao = { 187 .driver_name = "ni_at_ao", 188 .module = THIS_MODULE, 189 .attach = atao_attach, 190 .detach = atao_detach, 191 .board_name = &atao_boards[0].name, 192 .offset = sizeof(struct atao_board), 193 .num_names = ARRAY_SIZE(atao_boards), 194}; 195 196COMEDI_INITCLEANUP(driver_atao); 197 198static void atao_reset(struct comedi_device *dev); 199 200static int atao_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s, 201 struct comedi_insn *insn, unsigned int *data); 202static int atao_ao_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, 203 struct comedi_insn *insn, unsigned int *data); 204static int atao_dio_insn_bits(struct comedi_device *dev, 205 struct comedi_subdevice *s, 206 struct comedi_insn *insn, unsigned int *data); 207static int atao_dio_insn_config(struct comedi_device *dev, 208 struct comedi_subdevice *s, 209 struct comedi_insn *insn, unsigned int *data); 210static int atao_calib_insn_read(struct comedi_device *dev, 211 struct comedi_subdevice *s, 212 struct comedi_insn *insn, unsigned int *data); 213static int atao_calib_insn_write(struct comedi_device *dev, 214 struct comedi_subdevice *s, 215 struct comedi_insn *insn, unsigned int *data); 216 217static int atao_attach(struct comedi_device *dev, struct comedi_devconfig *it) 218{ 219 struct comedi_subdevice *s; 220 unsigned long iobase; 221 int ao_unipolar; 222 223 iobase = it->options[0]; 224 if (iobase == 0) 225 iobase = 0x1c0; 226 ao_unipolar = it->options[3]; 227 228 printk("comedi%d: ni_at_ao: 0x%04lx", dev->minor, iobase); 229 230 if (!request_region(iobase, ATAO_SIZE, "ni_at_ao")) { 231 printk(" I/O port conflict\n"); 232 return -EIO; 233 } 234 dev->iobase = iobase; 235 236 /* dev->board_ptr = atao_probe(dev); */ 237 238 dev->board_name = thisboard->name; 239 240 if (alloc_private(dev, sizeof(struct atao_private)) < 0) 241 return -ENOMEM; 242 243 if (alloc_subdevices(dev, 4) < 0) 244 return -ENOMEM; 245 246 s = dev->subdevices + 0; 247 /* analog output subdevice */ 248 s->type = COMEDI_SUBD_AO; 249 s->subdev_flags = SDF_WRITABLE; 250 s->n_chan = thisboard->n_ao_chans; 251 s->maxdata = (1 << 12) - 1; 252 if (ao_unipolar) 253 s->range_table = &range_unipolar10; 254 else 255 s->range_table = &range_bipolar10; 256 s->insn_write = &atao_ao_winsn; 257 s->insn_read = &atao_ao_rinsn; 258 259 s = dev->subdevices + 1; 260 /* digital i/o subdevice */ 261 s->type = COMEDI_SUBD_DIO; 262 s->subdev_flags = SDF_READABLE | SDF_WRITABLE; 263 s->n_chan = 8; 264 s->maxdata = 1; 265 s->range_table = &range_digital; 266 s->insn_bits = atao_dio_insn_bits; 267 s->insn_config = atao_dio_insn_config; 268 269 s = dev->subdevices + 2; 270 /* caldac subdevice */ 271 s->type = COMEDI_SUBD_CALIB; 272 s->subdev_flags = SDF_WRITABLE | SDF_INTERNAL; 273 s->n_chan = 21; 274 s->maxdata = 0xff; 275 s->insn_read = atao_calib_insn_read; 276 s->insn_write = atao_calib_insn_write; 277 278 s = dev->subdevices + 3; 279 /* eeprom subdevice */ 280 /* s->type=COMEDI_SUBD_EEPROM; */ 281 s->type = COMEDI_SUBD_UNUSED; 282 283 atao_reset(dev); 284 285 printk("\n"); 286 287 return 0; 288} 289 290static int atao_detach(struct comedi_device *dev) 291{ 292 printk("comedi%d: atao: remove\n", dev->minor); 293 294 if (dev->iobase) 295 release_region(dev->iobase, ATAO_SIZE); 296 297 return 0; 298} 299 300static void atao_reset(struct comedi_device *dev) 301{ 302 /* This is the reset sequence described in the manual */ 303 304 devpriv->cfg1 = 0; 305 outw(devpriv->cfg1, dev->iobase + ATAO_CFG1); 306 307 outb(RWSEL0 | MODESEL2, dev->iobase + ATAO_82C53_CNTRCMD); 308 outb(0x03, dev->iobase + ATAO_82C53_CNTR1); 309 outb(CNTRSEL0 | RWSEL0 | MODESEL2, dev->iobase + ATAO_82C53_CNTRCMD); 310 311 devpriv->cfg2 = 0; 312 outw(devpriv->cfg2, dev->iobase + ATAO_CFG2); 313 314 devpriv->cfg3 = 0; 315 outw(devpriv->cfg3, dev->iobase + ATAO_CFG3); 316 317 inw(dev->iobase + ATAO_FIFO_CLEAR); 318 319 devpriv->cfg1 |= GRP2WR; 320 outw(devpriv->cfg1, dev->iobase + ATAO_CFG1); 321 322 outw(0, dev->iobase + ATAO_2_INT1CLR); 323 outw(0, dev->iobase + ATAO_2_INT2CLR); 324 outw(0, dev->iobase + ATAO_2_DMATCCLR); 325 326 devpriv->cfg1 &= ~GRP2WR; 327 outw(devpriv->cfg1, dev->iobase + ATAO_CFG1); 328} 329 330static int atao_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s, 331 struct comedi_insn *insn, unsigned int *data) 332{ 333 int i; 334 int chan = CR_CHAN(insn->chanspec); 335 short bits; 336 337 for (i = 0; i < insn->n; i++) { 338 bits = data[i] - 0x800; 339 if (chan == 0) { 340 devpriv->cfg1 |= GRP2WR; 341 outw(devpriv->cfg1, dev->iobase + ATAO_CFG1); 342 } 343 outw(bits, dev->iobase + ATAO_DACn(chan)); 344 if (chan == 0) { 345 devpriv->cfg1 &= ~GRP2WR; 346 outw(devpriv->cfg1, dev->iobase + ATAO_CFG1); 347 } 348 devpriv->ao_readback[chan] = data[i]; 349 } 350 351 return i; 352} 353 354static int atao_ao_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, 355 struct comedi_insn *insn, unsigned int *data) 356{ 357 int i; 358 int chan = CR_CHAN(insn->chanspec); 359 360 for (i = 0; i < insn->n; i++) 361 data[i] = devpriv->ao_readback[chan]; 362 363 return i; 364} 365 366static int atao_dio_insn_bits(struct comedi_device *dev, 367 struct comedi_subdevice *s, 368 struct comedi_insn *insn, unsigned int *data) 369{ 370 if (insn->n != 2) 371 return -EINVAL; 372 373 if (data[0]) { 374 s->state &= ~data[0]; 375 s->state |= data[0] & data[1]; 376 outw(s->state, dev->iobase + ATAO_DOUT); 377 } 378 379 data[1] = inw(dev->iobase + ATAO_DIN); 380 381 return 2; 382} 383 384static int atao_dio_insn_config(struct comedi_device *dev, 385 struct comedi_subdevice *s, 386 struct comedi_insn *insn, unsigned int *data) 387{ 388 int chan = CR_CHAN(insn->chanspec); 389 unsigned int mask, bit; 390 391 /* The input or output configuration of each digital line is 392 * configured by a special insn_config instruction. chanspec 393 * contains the channel to be changed, and data[0] contains the 394 * value COMEDI_INPUT or COMEDI_OUTPUT. */ 395 396 mask = (chan < 4) ? 0x0f : 0xf0; 397 bit = (chan < 4) ? DOUTEN1 : DOUTEN2; 398 399 switch (data[0]) { 400 case INSN_CONFIG_DIO_OUTPUT: 401 s->io_bits |= mask; 402 devpriv->cfg3 |= bit; 403 break; 404 case INSN_CONFIG_DIO_INPUT: 405 s->io_bits &= ~mask; 406 devpriv->cfg3 &= ~bit; 407 break; 408 case INSN_CONFIG_DIO_QUERY: 409 data[1] = 410 (s->io_bits & (1 << chan)) ? COMEDI_OUTPUT : COMEDI_INPUT; 411 return insn->n; 412 break; 413 default: 414 return -EINVAL; 415 break; 416 } 417 418 outw(devpriv->cfg3, dev->iobase + ATAO_CFG3); 419 420 return 1; 421} 422 423/* 424 * Figure 2-1 in the manual shows 3 chips labeled DAC8800, which 425 * are 8-channel 8-bit DACs. These are most likely the calibration 426 * DACs. It is not explicitly stated in the manual how to access 427 * the caldacs, but we can guess. 428 */ 429static int atao_calib_insn_read(struct comedi_device *dev, 430 struct comedi_subdevice *s, 431 struct comedi_insn *insn, unsigned int *data) 432{ 433 int i; 434 for (i = 0; i < insn->n; i++) { 435 data[i] = 0; /* XXX */ 436 } 437 return insn->n; 438} 439 440static int atao_calib_insn_write(struct comedi_device *dev, 441 struct comedi_subdevice *s, 442 struct comedi_insn *insn, unsigned int *data) 443{ 444 unsigned int bitstring, bit; 445 unsigned int chan = CR_CHAN(insn->chanspec); 446 447 bitstring = ((chan & 0x7) << 8) | (data[insn->n - 1] & 0xff); 448 449 for (bit = 1 << (11 - 1); bit; bit >>= 1) { 450 outw(devpriv->cfg2 | ((bit & bitstring) ? SDATA : 0), 451 dev->iobase + ATAO_CFG2); 452 outw(devpriv->cfg2 | SCLK | ((bit & bitstring) ? SDATA : 0), 453 dev->iobase + ATAO_CFG2); 454 } 455 /* strobe the appropriate caldac */ 456 outw(devpriv->cfg2 | (((chan >> 3) + 1) << 14), 457 dev->iobase + ATAO_CFG2); 458 outw(devpriv->cfg2, dev->iobase + ATAO_CFG2); 459 460 return insn->n; 461} 462