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