das1800.c revision a351ecf3081f94796cf915dba820f9f5e62c43cf
1/* 2 comedi/drivers/das1800.c 3 Driver for Keitley das1700/das1800 series boards 4 Copyright (C) 2000 Frank Mori Hess <fmhess@users.sourceforge.net> 5 6 COMEDI - Linux Control and Measurement Device Interface 7 Copyright (C) 2000 David A. Schleef <ds@schleef.org> 8 9 This program is free software; you can redistribute it and/or modify 10 it under the terms of the GNU General Public License as published by 11 the Free Software Foundation; either version 2 of the License, or 12 (at your option) any later version. 13 14 This program is distributed in the hope that it will be useful, 15 but WITHOUT ANY WARRANTY; without even the implied warranty of 16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 GNU General Public License for more details. 18 19 You should have received a copy of the GNU General Public License 20 along with this program; if not, write to the Free Software 21 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 22 23************************************************************************ 24*/ 25/* 26Driver: das1800 27Description: Keithley Metrabyte DAS1800 (& compatibles) 28Author: Frank Mori Hess <fmhess@users.sourceforge.net> 29Devices: [Keithley Metrabyte] DAS-1701ST (das-1701st), 30 DAS-1701ST-DA (das-1701st-da), DAS-1701/AO (das-1701ao), 31 DAS-1702ST (das-1702st), DAS-1702ST-DA (das-1702st-da), 32 DAS-1702HR (das-1702hr), DAS-1702HR-DA (das-1702hr-da), 33 DAS-1702/AO (das-1702ao), DAS-1801ST (das-1801st), 34 DAS-1801ST-DA (das-1801st-da), DAS-1801HC (das-1801hc), 35 DAS-1801AO (das-1801ao), DAS-1802ST (das-1802st), 36 DAS-1802ST-DA (das-1802st-da), DAS-1802HR (das-1802hr), 37 DAS-1802HR-DA (das-1802hr-da), DAS-1802HC (das-1802hc), 38 DAS-1802AO (das-1802ao) 39Status: works 40 41The waveform analog output on the 'ao' cards is not supported. 42If you need it, send me (Frank Hess) an email. 43 44Configuration options: 45 [0] - I/O port base address 46 [1] - IRQ (optional, required for timed or externally triggered conversions) 47 [2] - DMA0 (optional, requires irq) 48 [3] - DMA1 (optional, requires irq and dma0) 49*/ 50/* 51 52This driver supports the following Keithley boards: 53 54das-1701st 55das-1701st-da 56das-1701ao 57das-1702st 58das-1702st-da 59das-1702hr 60das-1702hr-da 61das-1702ao 62das-1801st 63das-1801st-da 64das-1801hc 65das-1801ao 66das-1802st 67das-1802st-da 68das-1802hr 69das-1802hr-da 70das-1802hc 71das-1802ao 72 73Options: 74 [0] - base io address 75 [1] - irq (optional, required for timed or externally triggered conversions) 76 [2] - dma0 (optional, requires irq) 77 [3] - dma1 (optional, requires irq and dma0) 78 79irq can be omitted, although the cmd interface will not work without it. 80 81analog input cmd triggers supported: 82 start_src: TRIG_NOW | TRIG_EXT 83 scan_begin_src: TRIG_FOLLOW | TRIG_TIMER | TRIG_EXT 84 scan_end_src: TRIG_COUNT 85 convert_src: TRIG_TIMER | TRIG_EXT (TRIG_EXT requires scan_begin_src == TRIG_FOLLOW) 86 stop_src: TRIG_COUNT | TRIG_EXT | TRIG_NONE 87 88scan_begin_src triggers TRIG_TIMER and TRIG_EXT use the card's 89'burst mode' which limits the valid conversion time to 64 microseconds 90(convert_arg <= 64000). This limitation does not apply if scan_begin_src 91is TRIG_FOLLOW. 92 93NOTES: 94Only the DAS-1801ST has been tested by me. 95Unipolar and bipolar ranges cannot be mixed in the channel/gain list. 96 97TODO: 98 Make it automatically allocate irq and dma channels if they are not specified 99 Add support for analog out on 'ao' cards 100 read insn for analog out 101*/ 102 103#include "../comedidev.h" 104 105#include <linux/ioport.h> 106#include <asm/dma.h> 107 108#include "8253.h" 109#include "comedi_fc.h" 110 111/* misc. defines */ 112#define DAS1800_SIZE 16 /* uses 16 io addresses */ 113#define FIFO_SIZE 1024 /* 1024 sample fifo */ 114#define TIMER_BASE 200 /* 5 Mhz master clock */ 115#define UNIPOLAR 0x4 /* bit that determines whether input range is uni/bipolar */ 116#define DMA_BUF_SIZE 0x1ff00 /* size in bytes of dma buffers */ 117 118/* Registers for the das1800 */ 119#define DAS1800_FIFO 0x0 120#define DAS1800_QRAM 0x0 121#define DAS1800_DAC 0x0 122#define DAS1800_SELECT 0x2 123#define ADC 0x0 124#define QRAM 0x1 125#define DAC(a) (0x2 + a) 126#define DAS1800_DIGITAL 0x3 127#define DAS1800_CONTROL_A 0x4 128#define FFEN 0x1 129#define CGEN 0x4 130#define CGSL 0x8 131#define TGEN 0x10 132#define TGSL 0x20 133#define ATEN 0x80 134#define DAS1800_CONTROL_B 0x5 135#define DMA_CH5 0x1 136#define DMA_CH6 0x2 137#define DMA_CH7 0x3 138#define DMA_CH5_CH6 0x5 139#define DMA_CH6_CH7 0x6 140#define DMA_CH7_CH5 0x7 141#define DMA_ENABLED 0x3 /* mask used to determine if dma is enabled */ 142#define DMA_DUAL 0x4 143#define IRQ3 0x8 144#define IRQ5 0x10 145#define IRQ7 0x18 146#define IRQ10 0x28 147#define IRQ11 0x30 148#define IRQ15 0x38 149#define FIMD 0x40 150#define DAS1800_CONTROL_C 0X6 151#define IPCLK 0x1 152#define XPCLK 0x3 153#define BMDE 0x4 154#define CMEN 0x8 155#define UQEN 0x10 156#define SD 0x40 157#define UB 0x80 158#define DAS1800_STATUS 0x7 159/* bits that prevent interrupt status bits (and CVEN) from being cleared on write */ 160#define CLEAR_INTR_MASK (CVEN_MASK | 0x1f) 161#define INT 0x1 162#define DMATC 0x2 163#define CT0TC 0x8 164#define OVF 0x10 165#define FHF 0x20 166#define FNE 0x40 167#define CVEN_MASK 0x40 /* masks CVEN on write */ 168#define CVEN 0x80 169#define DAS1800_BURST_LENGTH 0x8 170#define DAS1800_BURST_RATE 0x9 171#define DAS1800_QRAM_ADDRESS 0xa 172#define DAS1800_COUNTER 0xc 173 174#define IOBASE2 0x400 /* offset of additional ioports used on 'ao' cards */ 175 176enum { 177 das1701st, das1701st_da, das1702st, das1702st_da, das1702hr, 178 das1702hr_da, 179 das1701ao, das1702ao, das1801st, das1801st_da, das1802st, das1802st_da, 180 das1802hr, das1802hr_da, das1801hc, das1802hc, das1801ao, das1802ao 181}; 182 183static int das1800_attach(struct comedi_device * dev, struct comedi_devconfig * it); 184static int das1800_detach(struct comedi_device * dev); 185static int das1800_probe(struct comedi_device * dev); 186static int das1800_cancel(struct comedi_device * dev, struct comedi_subdevice * s); 187static irqreturn_t das1800_interrupt(int irq, void *d PT_REGS_ARG); 188static int das1800_ai_poll(struct comedi_device * dev, struct comedi_subdevice * s); 189static void das1800_ai_handler(struct comedi_device * dev); 190static void das1800_handle_dma(struct comedi_device * dev, struct comedi_subdevice * s, 191 unsigned int status); 192static void das1800_flush_dma(struct comedi_device * dev, struct comedi_subdevice * s); 193static void das1800_flush_dma_channel(struct comedi_device * dev, struct comedi_subdevice * s, 194 unsigned int channel, uint16_t * buffer); 195static void das1800_handle_fifo_half_full(struct comedi_device * dev, 196 struct comedi_subdevice * s); 197static void das1800_handle_fifo_not_empty(struct comedi_device * dev, 198 struct comedi_subdevice * s); 199static int das1800_ai_do_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s, 200 struct comedi_cmd * cmd); 201static int das1800_ai_do_cmd(struct comedi_device * dev, struct comedi_subdevice * s); 202static int das1800_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s, 203 struct comedi_insn * insn, unsigned int * data); 204static int das1800_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s, 205 struct comedi_insn * insn, unsigned int * data); 206static int das1800_di_rbits(struct comedi_device * dev, struct comedi_subdevice * s, 207 struct comedi_insn * insn, unsigned int * data); 208static int das1800_do_wbits(struct comedi_device * dev, struct comedi_subdevice * s, 209 struct comedi_insn * insn, unsigned int * data); 210 211static int das1800_set_frequency(struct comedi_device * dev); 212static unsigned int burst_convert_arg(unsigned int convert_arg, int round_mode); 213static unsigned int suggest_transfer_size(struct comedi_cmd * cmd); 214 215/* analog input ranges */ 216static const struct comedi_lrange range_ai_das1801 = { 217 8, 218 { 219 RANGE(-5, 5), 220 RANGE(-1, 1), 221 RANGE(-0.1, 0.1), 222 RANGE(-0.02, 0.02), 223 RANGE(0, 5), 224 RANGE(0, 1), 225 RANGE(0, 0.1), 226 RANGE(0, 0.02), 227 } 228}; 229 230static const struct comedi_lrange range_ai_das1802 = { 231 8, 232 { 233 RANGE(-10, 10), 234 RANGE(-5, 5), 235 RANGE(-2.5, 2.5), 236 RANGE(-1.25, 1.25), 237 RANGE(0, 10), 238 RANGE(0, 5), 239 RANGE(0, 2.5), 240 RANGE(0, 1.25), 241 } 242}; 243 244struct das1800_board { 245 const char *name; 246 int ai_speed; /* max conversion period in nanoseconds */ 247 int resolution; /* bits of ai resolution */ 248 int qram_len; /* length of card's channel / gain queue */ 249 int common; /* supports AREF_COMMON flag */ 250 int do_n_chan; /* number of digital output channels */ 251 int ao_ability; /* 0 == no analog out, 1 == basic analog out, 2 == waveform analog out */ 252 int ao_n_chan; /* number of analog out channels */ 253 const struct comedi_lrange *range_ai; /* available input ranges */ 254}; 255 256/* Warning: the maximum conversion speeds listed below are 257 * not always achievable depending on board setup (see 258 * user manual.) 259 */ 260static const struct das1800_board das1800_boards[] = { 261 { 262 name: "das-1701st", 263 ai_speed:6250, 264 resolution:12, 265 qram_len:256, 266 common: 1, 267 do_n_chan:4, 268 ao_ability:0, 269 ao_n_chan:0, 270 range_ai:&range_ai_das1801, 271 }, 272 { 273 name: "das-1701st-da", 274 ai_speed:6250, 275 resolution:12, 276 qram_len:256, 277 common: 1, 278 do_n_chan:4, 279 ao_ability:1, 280 ao_n_chan:4, 281 range_ai:&range_ai_das1801, 282 }, 283 { 284 name: "das-1702st", 285 ai_speed:6250, 286 resolution:12, 287 qram_len:256, 288 common: 1, 289 do_n_chan:4, 290 ao_ability:0, 291 ao_n_chan:0, 292 range_ai:&range_ai_das1802, 293 }, 294 { 295 name: "das-1702st-da", 296 ai_speed:6250, 297 resolution:12, 298 qram_len:256, 299 common: 1, 300 do_n_chan:4, 301 ao_ability:1, 302 ao_n_chan:4, 303 range_ai:&range_ai_das1802, 304 }, 305 { 306 name: "das-1702hr", 307 ai_speed:20000, 308 resolution:16, 309 qram_len:256, 310 common: 1, 311 do_n_chan:4, 312 ao_ability:0, 313 ao_n_chan:0, 314 range_ai:&range_ai_das1802, 315 }, 316 { 317 name: "das-1702hr-da", 318 ai_speed:20000, 319 resolution:16, 320 qram_len:256, 321 common: 1, 322 do_n_chan:4, 323 ao_ability:1, 324 ao_n_chan:2, 325 range_ai:&range_ai_das1802, 326 }, 327 { 328 name: "das-1701ao", 329 ai_speed:6250, 330 resolution:12, 331 qram_len:256, 332 common: 1, 333 do_n_chan:4, 334 ao_ability:2, 335 ao_n_chan:2, 336 range_ai:&range_ai_das1801, 337 }, 338 { 339 name: "das-1702ao", 340 ai_speed:6250, 341 resolution:12, 342 qram_len:256, 343 common: 1, 344 do_n_chan:4, 345 ao_ability:2, 346 ao_n_chan:2, 347 range_ai:&range_ai_das1802, 348 }, 349 { 350 name: "das-1801st", 351 ai_speed:3000, 352 resolution:12, 353 qram_len:256, 354 common: 1, 355 do_n_chan:4, 356 ao_ability:0, 357 ao_n_chan:0, 358 range_ai:&range_ai_das1801, 359 }, 360 { 361 name: "das-1801st-da", 362 ai_speed:3000, 363 resolution:12, 364 qram_len:256, 365 common: 1, 366 do_n_chan:4, 367 ao_ability:0, 368 ao_n_chan:4, 369 range_ai:&range_ai_das1801, 370 }, 371 { 372 name: "das-1802st", 373 ai_speed:3000, 374 resolution:12, 375 qram_len:256, 376 common: 1, 377 do_n_chan:4, 378 ao_ability:0, 379 ao_n_chan:0, 380 range_ai:&range_ai_das1802, 381 }, 382 { 383 name: "das-1802st-da", 384 ai_speed:3000, 385 resolution:12, 386 qram_len:256, 387 common: 1, 388 do_n_chan:4, 389 ao_ability:1, 390 ao_n_chan:4, 391 range_ai:&range_ai_das1802, 392 }, 393 { 394 name: "das-1802hr", 395 ai_speed:10000, 396 resolution:16, 397 qram_len:256, 398 common: 1, 399 do_n_chan:4, 400 ao_ability:0, 401 ao_n_chan:0, 402 range_ai:&range_ai_das1802, 403 }, 404 { 405 name: "das-1802hr-da", 406 ai_speed:10000, 407 resolution:16, 408 qram_len:256, 409 common: 1, 410 do_n_chan:4, 411 ao_ability:1, 412 ao_n_chan:2, 413 range_ai:&range_ai_das1802, 414 }, 415 { 416 name: "das-1801hc", 417 ai_speed:3000, 418 resolution:12, 419 qram_len:64, 420 common: 0, 421 do_n_chan:8, 422 ao_ability:1, 423 ao_n_chan:2, 424 range_ai:&range_ai_das1801, 425 }, 426 { 427 name: "das-1802hc", 428 ai_speed:3000, 429 resolution:12, 430 qram_len:64, 431 common: 0, 432 do_n_chan:8, 433 ao_ability:1, 434 ao_n_chan:2, 435 range_ai:&range_ai_das1802, 436 }, 437 { 438 name: "das-1801ao", 439 ai_speed:3000, 440 resolution:12, 441 qram_len:256, 442 common: 1, 443 do_n_chan:4, 444 ao_ability:2, 445 ao_n_chan:2, 446 range_ai:&range_ai_das1801, 447 }, 448 { 449 name: "das-1802ao", 450 ai_speed:3000, 451 resolution:12, 452 qram_len:256, 453 common: 1, 454 do_n_chan:4, 455 ao_ability:2, 456 ao_n_chan:2, 457 range_ai:&range_ai_das1802, 458 }, 459}; 460 461/* 462 * Useful for shorthand access to the particular board structure 463 */ 464#define thisboard ((const struct das1800_board *)dev->board_ptr) 465 466struct das1800_private { 467 volatile unsigned int count; /* number of data points left to be taken */ 468 unsigned int divisor1; /* value to load into board's counter 1 for timed conversions */ 469 unsigned int divisor2; /* value to load into board's counter 2 for timed conversions */ 470 int do_bits; /* digital output bits */ 471 int irq_dma_bits; /* bits for control register b */ 472 /* dma bits for control register b, stored so that dma can be 473 * turned on and off */ 474 int dma_bits; 475 unsigned int dma0; /* dma channels used */ 476 unsigned int dma1; 477 volatile unsigned int dma_current; /* dma channel currently in use */ 478 uint16_t *ai_buf0; /* pointers to dma buffers */ 479 uint16_t *ai_buf1; 480 uint16_t *dma_current_buf; /* pointer to dma buffer currently being used */ 481 unsigned int dma_transfer_size; /* size of transfer currently used, in bytes */ 482 unsigned long iobase2; /* secondary io address used for analog out on 'ao' boards */ 483 short ao_update_bits; /* remembers the last write to the 'update' dac */ 484}; 485 486#define devpriv ((struct das1800_private *)dev->private) 487 488/* analog out range for boards with basic analog out */ 489static const struct comedi_lrange range_ao_1 = { 490 1, 491 { 492 RANGE(-10, 10), 493 } 494}; 495 496/* analog out range for 'ao' boards */ 497/* 498static const struct comedi_lrange range_ao_2 = { 499 2, 500 { 501 RANGE(-10, 10), 502 RANGE(-5, 5), 503 } 504}; 505*/ 506 507static struct comedi_driver driver_das1800 = { 508 driver_name:"das1800", 509 module:THIS_MODULE, 510 attach:das1800_attach, 511 detach:das1800_detach, 512 num_names:sizeof(das1800_boards) / sizeof(struct das1800_board), 513 board_name:&das1800_boards[0].name, 514 offset:sizeof(struct das1800_board), 515}; 516 517/* 518 * A convenient macro that defines init_module() and cleanup_module(), 519 * as necessary. 520 */ 521COMEDI_INITCLEANUP(driver_das1800); 522 523static int das1800_init_dma(struct comedi_device * dev, unsigned int dma0, 524 unsigned int dma1) 525{ 526 unsigned long flags; 527 528 /* need an irq to do dma */ 529 if (dev->irq && dma0) { 530 /* encode dma0 and dma1 into 2 digit hexadecimal for switch */ 531 switch ((dma0 & 0x7) | (dma1 << 4)) { 532 case 0x5: /* dma0 == 5 */ 533 devpriv->dma_bits |= DMA_CH5; 534 break; 535 case 0x6: /* dma0 == 6 */ 536 devpriv->dma_bits |= DMA_CH6; 537 break; 538 case 0x7: /* dma0 == 7 */ 539 devpriv->dma_bits |= DMA_CH7; 540 break; 541 case 0x65: /* dma0 == 5, dma1 == 6 */ 542 devpriv->dma_bits |= DMA_CH5_CH6; 543 break; 544 case 0x76: /* dma0 == 6, dma1 == 7 */ 545 devpriv->dma_bits |= DMA_CH6_CH7; 546 break; 547 case 0x57: /* dma0 == 7, dma1 == 5 */ 548 devpriv->dma_bits |= DMA_CH7_CH5; 549 break; 550 default: 551 printk(" only supports dma channels 5 through 7\n" 552 " Dual dma only allows the following combinations:\n" 553 " dma 5,6 / 6,7 / or 7,5\n"); 554 return -EINVAL; 555 break; 556 } 557 if (request_dma(dma0, driver_das1800.driver_name)) { 558 printk(" failed to allocate dma channel %i\n", dma0); 559 return -EINVAL; 560 } 561 devpriv->dma0 = dma0; 562 devpriv->dma_current = dma0; 563 if (dma1) { 564 if (request_dma(dma1, driver_das1800.driver_name)) { 565 printk(" failed to allocate dma channel %i\n", 566 dma1); 567 return -EINVAL; 568 } 569 devpriv->dma1 = dma1; 570 } 571 devpriv->ai_buf0 = kmalloc(DMA_BUF_SIZE, GFP_KERNEL | GFP_DMA); 572 if (devpriv->ai_buf0 == NULL) 573 return -ENOMEM; 574 devpriv->dma_current_buf = devpriv->ai_buf0; 575 if (dma1) { 576 devpriv->ai_buf1 = 577 kmalloc(DMA_BUF_SIZE, GFP_KERNEL | GFP_DMA); 578 if (devpriv->ai_buf1 == NULL) 579 return -ENOMEM; 580 } 581 flags = claim_dma_lock(); 582 disable_dma(devpriv->dma0); 583 set_dma_mode(devpriv->dma0, DMA_MODE_READ); 584 if (dma1) { 585 disable_dma(devpriv->dma1); 586 set_dma_mode(devpriv->dma1, DMA_MODE_READ); 587 } 588 release_dma_lock(flags); 589 } 590 return 0; 591} 592 593static int das1800_attach(struct comedi_device * dev, struct comedi_devconfig * it) 594{ 595 struct comedi_subdevice *s; 596 unsigned long iobase = it->options[0]; 597 unsigned int irq = it->options[1]; 598 unsigned int dma0 = it->options[2]; 599 unsigned int dma1 = it->options[3]; 600 unsigned long iobase2; 601 int board; 602 int retval; 603 604 /* allocate and initialize dev->private */ 605 if (alloc_private(dev, sizeof(struct das1800_private)) < 0) 606 return -ENOMEM; 607 608 printk("comedi%d: %s: io 0x%lx", dev->minor, driver_das1800.driver_name, 609 iobase); 610 if (irq) { 611 printk(", irq %u", irq); 612 if (dma0) { 613 printk(", dma %u", dma0); 614 if (dma1) 615 printk(" and %u", dma1); 616 } 617 } 618 printk("\n"); 619 620 if (iobase == 0) { 621 printk(" io base address required\n"); 622 return -EINVAL; 623 } 624 625 /* check if io addresses are available */ 626 if (!request_region(iobase, DAS1800_SIZE, driver_das1800.driver_name)) { 627 printk(" I/O port conflict: failed to allocate ports 0x%lx to 0x%lx\n", iobase, iobase + DAS1800_SIZE - 1); 628 return -EIO; 629 } 630 dev->iobase = iobase; 631 632 board = das1800_probe(dev); 633 if (board < 0) { 634 printk(" unable to determine board type\n"); 635 return -ENODEV; 636 } 637 638 dev->board_ptr = das1800_boards + board; 639 dev->board_name = thisboard->name; 640 641 /* if it is an 'ao' board with fancy analog out then we need extra io ports */ 642 if (thisboard->ao_ability == 2) { 643 iobase2 = iobase + IOBASE2; 644 if (!request_region(iobase2, DAS1800_SIZE, 645 driver_das1800.driver_name)) { 646 printk(" I/O port conflict: failed to allocate ports 0x%lx to 0x%lx\n", iobase2, iobase2 + DAS1800_SIZE - 1); 647 return -EIO; 648 } 649 devpriv->iobase2 = iobase2; 650 } 651 652 /* grab our IRQ */ 653 if (irq) { 654 if (comedi_request_irq(irq, das1800_interrupt, 0, 655 driver_das1800.driver_name, dev)) { 656 printk(" unable to allocate irq %u\n", irq); 657 return -EINVAL; 658 } 659 } 660 dev->irq = irq; 661 662 /* set bits that tell card which irq to use */ 663 switch (irq) { 664 case 0: 665 break; 666 case 3: 667 devpriv->irq_dma_bits |= 0x8; 668 break; 669 case 5: 670 devpriv->irq_dma_bits |= 0x10; 671 break; 672 case 7: 673 devpriv->irq_dma_bits |= 0x18; 674 break; 675 case 10: 676 devpriv->irq_dma_bits |= 0x28; 677 break; 678 case 11: 679 devpriv->irq_dma_bits |= 0x30; 680 break; 681 case 15: 682 devpriv->irq_dma_bits |= 0x38; 683 break; 684 default: 685 printk(" irq out of range\n"); 686 return -EINVAL; 687 break; 688 } 689 690 retval = das1800_init_dma(dev, dma0, dma1); 691 if (retval < 0) 692 return retval; 693 694 if (devpriv->ai_buf0 == NULL) { 695 devpriv->ai_buf0 = 696 kmalloc(FIFO_SIZE * sizeof(uint16_t), GFP_KERNEL); 697 if (devpriv->ai_buf0 == NULL) 698 return -ENOMEM; 699 } 700 701 if (alloc_subdevices(dev, 4) < 0) 702 return -ENOMEM; 703 704 /* analog input subdevice */ 705 s = dev->subdevices + 0; 706 dev->read_subdev = s; 707 s->type = COMEDI_SUBD_AI; 708 s->subdev_flags = SDF_READABLE | SDF_DIFF | SDF_GROUND | SDF_CMD_READ; 709 if (thisboard->common) 710 s->subdev_flags |= SDF_COMMON; 711 s->n_chan = thisboard->qram_len; 712 s->len_chanlist = thisboard->qram_len; 713 s->maxdata = (1 << thisboard->resolution) - 1; 714 s->range_table = thisboard->range_ai; 715 s->do_cmd = das1800_ai_do_cmd; 716 s->do_cmdtest = das1800_ai_do_cmdtest; 717 s->insn_read = das1800_ai_rinsn; 718 s->poll = das1800_ai_poll; 719 s->cancel = das1800_cancel; 720 721 /* analog out */ 722 s = dev->subdevices + 1; 723 if (thisboard->ao_ability == 1) { 724 s->type = COMEDI_SUBD_AO; 725 s->subdev_flags = SDF_WRITABLE; 726 s->n_chan = thisboard->ao_n_chan; 727 s->maxdata = (1 << thisboard->resolution) - 1; 728 s->range_table = &range_ao_1; 729 s->insn_write = das1800_ao_winsn; 730 } else { 731 s->type = COMEDI_SUBD_UNUSED; 732 } 733 734 /* di */ 735 s = dev->subdevices + 2; 736 s->type = COMEDI_SUBD_DI; 737 s->subdev_flags = SDF_READABLE; 738 s->n_chan = 4; 739 s->maxdata = 1; 740 s->range_table = &range_digital; 741 s->insn_bits = das1800_di_rbits; 742 743 /* do */ 744 s = dev->subdevices + 3; 745 s->type = COMEDI_SUBD_DO; 746 s->subdev_flags = SDF_WRITABLE | SDF_READABLE; 747 s->n_chan = thisboard->do_n_chan; 748 s->maxdata = 1; 749 s->range_table = &range_digital; 750 s->insn_bits = das1800_do_wbits; 751 752 das1800_cancel(dev, dev->read_subdev); 753 754 /* initialize digital out channels */ 755 outb(devpriv->do_bits, dev->iobase + DAS1800_DIGITAL); 756 757 /* initialize analog out channels */ 758 if (thisboard->ao_ability == 1) { 759 /* select 'update' dac channel for baseAddress + 0x0 */ 760 outb(DAC(thisboard->ao_n_chan - 1), 761 dev->iobase + DAS1800_SELECT); 762 outw(devpriv->ao_update_bits, dev->iobase + DAS1800_DAC); 763 } 764 765 return 0; 766}; 767 768static int das1800_detach(struct comedi_device * dev) 769{ 770 /* only free stuff if it has been allocated by _attach */ 771 if (dev->iobase) 772 release_region(dev->iobase, DAS1800_SIZE); 773 if (dev->irq) 774 comedi_free_irq(dev->irq, dev); 775 if (dev->private) { 776 if (devpriv->iobase2) 777 release_region(devpriv->iobase2, DAS1800_SIZE); 778 if (devpriv->dma0) 779 free_dma(devpriv->dma0); 780 if (devpriv->dma1) 781 free_dma(devpriv->dma1); 782 if (devpriv->ai_buf0) 783 kfree(devpriv->ai_buf0); 784 if (devpriv->ai_buf1) 785 kfree(devpriv->ai_buf1); 786 } 787 788 printk("comedi%d: %s: remove\n", dev->minor, 789 driver_das1800.driver_name); 790 791 return 0; 792}; 793 794/* probes and checks das-1800 series board type 795 */ 796static int das1800_probe(struct comedi_device * dev) 797{ 798 int id; 799 int board; 800 801 id = (inb(dev->iobase + DAS1800_DIGITAL) >> 4) & 0xf; /* get id bits */ 802 board = ((struct das1800_board *) dev->board_ptr) - das1800_boards; 803 804 switch (id) { 805 case 0x3: 806 if (board == das1801st_da || board == das1802st_da || 807 board == das1701st_da || board == das1702st_da) { 808 printk(" Board model: %s\n", 809 das1800_boards[board].name); 810 return board; 811 } 812 printk(" Board model (probed, not recommended): das-1800st-da series\n"); 813 return das1801st; 814 break; 815 case 0x4: 816 if (board == das1802hr_da || board == das1702hr_da) { 817 printk(" Board model: %s\n", 818 das1800_boards[board].name); 819 return board; 820 } 821 printk(" Board model (probed, not recommended): das-1802hr-da\n"); 822 return das1802hr; 823 break; 824 case 0x5: 825 if (board == das1801ao || board == das1802ao || 826 board == das1701ao || board == das1702ao) { 827 printk(" Board model: %s\n", 828 das1800_boards[board].name); 829 return board; 830 } 831 printk(" Board model (probed, not recommended): das-1800ao series\n"); 832 return das1801ao; 833 break; 834 case 0x6: 835 if (board == das1802hr || board == das1702hr) { 836 printk(" Board model: %s\n", 837 das1800_boards[board].name); 838 return board; 839 } 840 printk(" Board model (probed, not recommended): das-1802hr\n"); 841 return das1802hr; 842 break; 843 case 0x7: 844 if (board == das1801st || board == das1802st || 845 board == das1701st || board == das1702st) { 846 printk(" Board model: %s\n", 847 das1800_boards[board].name); 848 return board; 849 } 850 printk(" Board model (probed, not recommended): das-1800st series\n"); 851 return das1801st; 852 break; 853 case 0x8: 854 if (board == das1801hc || board == das1802hc) { 855 printk(" Board model: %s\n", 856 das1800_boards[board].name); 857 return board; 858 } 859 printk(" Board model (probed, not recommended): das-1800hc series\n"); 860 return das1801hc; 861 break; 862 default: 863 printk(" Board model: probe returned 0x%x (unknown, please report)\n", id); 864 return board; 865 break; 866 } 867 return -1; 868} 869 870static int das1800_ai_poll(struct comedi_device * dev, struct comedi_subdevice * s) 871{ 872 unsigned long flags; 873 874 /* prevent race with interrupt handler */ 875 comedi_spin_lock_irqsave(&dev->spinlock, flags); 876 das1800_ai_handler(dev); 877 comedi_spin_unlock_irqrestore(&dev->spinlock, flags); 878 879 return s->async->buf_write_count - s->async->buf_read_count; 880} 881 882static irqreturn_t das1800_interrupt(int irq, void *d PT_REGS_ARG) 883{ 884 struct comedi_device *dev = d; 885 unsigned int status; 886 887 if (dev->attached == 0) { 888 comedi_error(dev, "premature interrupt"); 889 return IRQ_HANDLED; 890 } 891 892 /* Prevent race with das1800_ai_poll() on multi processor systems. 893 * Also protects indirect addressing in das1800_ai_handler */ 894 spin_lock(&dev->spinlock); 895 status = inb(dev->iobase + DAS1800_STATUS); 896 897 /* if interrupt was not caused by das-1800 */ 898 if (!(status & INT)) { 899 spin_unlock(&dev->spinlock); 900 return IRQ_NONE; 901 } 902 /* clear the interrupt status bit INT */ 903 outb(CLEAR_INTR_MASK & ~INT, dev->iobase + DAS1800_STATUS); 904 /* handle interrupt */ 905 das1800_ai_handler(dev); 906 907 spin_unlock(&dev->spinlock); 908 return IRQ_HANDLED; 909} 910 911/* the guts of the interrupt handler, that is shared with das1800_ai_poll */ 912static void das1800_ai_handler(struct comedi_device * dev) 913{ 914 struct comedi_subdevice *s = dev->subdevices + 0; /* analog input subdevice */ 915 struct comedi_async *async = s->async; 916 struct comedi_cmd *cmd = &async->cmd; 917 unsigned int status = inb(dev->iobase + DAS1800_STATUS); 918 919 async->events = 0; 920 /* select adc for base address + 0 */ 921 outb(ADC, dev->iobase + DAS1800_SELECT); 922 /* dma buffer full */ 923 if (devpriv->irq_dma_bits & DMA_ENABLED) { 924 /* look for data from dma transfer even if dma terminal count hasn't happened yet */ 925 das1800_handle_dma(dev, s, status); 926 } else if (status & FHF) { /* if fifo half full */ 927 das1800_handle_fifo_half_full(dev, s); 928 } else if (status & FNE) { /* if fifo not empty */ 929 das1800_handle_fifo_not_empty(dev, s); 930 } 931 932 async->events |= COMEDI_CB_BLOCK; 933 /* if the card's fifo has overflowed */ 934 if (status & OVF) { 935 /* clear OVF interrupt bit */ 936 outb(CLEAR_INTR_MASK & ~OVF, dev->iobase + DAS1800_STATUS); 937 comedi_error(dev, "DAS1800 FIFO overflow"); 938 das1800_cancel(dev, s); 939 async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA; 940 comedi_event(dev, s); 941 return; 942 } 943 /* stop taking data if appropriate */ 944 /* stop_src TRIG_EXT */ 945 if (status & CT0TC) { 946 /* clear CT0TC interrupt bit */ 947 outb(CLEAR_INTR_MASK & ~CT0TC, dev->iobase + DAS1800_STATUS); 948 /* make sure we get all remaining data from board before quitting */ 949 if (devpriv->irq_dma_bits & DMA_ENABLED) 950 das1800_flush_dma(dev, s); 951 else 952 das1800_handle_fifo_not_empty(dev, s); 953 das1800_cancel(dev, s); /* disable hardware conversions */ 954 async->events |= COMEDI_CB_EOA; 955 } else if (cmd->stop_src == TRIG_COUNT && devpriv->count == 0) { /* stop_src TRIG_COUNT */ 956 das1800_cancel(dev, s); /* disable hardware conversions */ 957 async->events |= COMEDI_CB_EOA; 958 } 959 960 comedi_event(dev, s); 961 962 return; 963} 964 965static void das1800_handle_dma(struct comedi_device * dev, struct comedi_subdevice * s, 966 unsigned int status) 967{ 968 unsigned long flags; 969 const int dual_dma = devpriv->irq_dma_bits & DMA_DUAL; 970 971 flags = claim_dma_lock(); 972 das1800_flush_dma_channel(dev, s, devpriv->dma_current, 973 devpriv->dma_current_buf); 974 /* re-enable dma channel */ 975 set_dma_addr(devpriv->dma_current, 976 virt_to_bus(devpriv->dma_current_buf)); 977 set_dma_count(devpriv->dma_current, devpriv->dma_transfer_size); 978 enable_dma(devpriv->dma_current); 979 release_dma_lock(flags); 980 981 if (status & DMATC) { 982 /* clear DMATC interrupt bit */ 983 outb(CLEAR_INTR_MASK & ~DMATC, dev->iobase + DAS1800_STATUS); 984 /* switch dma channels for next time, if appropriate */ 985 if (dual_dma) { 986 /* read data from the other channel next time */ 987 if (devpriv->dma_current == devpriv->dma0) { 988 devpriv->dma_current = devpriv->dma1; 989 devpriv->dma_current_buf = devpriv->ai_buf1; 990 } else { 991 devpriv->dma_current = devpriv->dma0; 992 devpriv->dma_current_buf = devpriv->ai_buf0; 993 } 994 } 995 } 996 997 return; 998} 999 1000static inline uint16_t munge_bipolar_sample(const struct comedi_device * dev, 1001 uint16_t sample) 1002{ 1003 sample += 1 << (thisboard->resolution - 1); 1004 return sample; 1005} 1006 1007static void munge_data(struct comedi_device * dev, uint16_t * array, 1008 unsigned int num_elements) 1009{ 1010 unsigned int i; 1011 int unipolar; 1012 1013 /* see if card is using a unipolar or bipolar range so we can munge data correctly */ 1014 unipolar = inb(dev->iobase + DAS1800_CONTROL_C) & UB; 1015 1016 /* convert to unsigned type if we are in a bipolar mode */ 1017 if (!unipolar) { 1018 for (i = 0; i < num_elements; i++) { 1019 array[i] = munge_bipolar_sample(dev, array[i]); 1020 } 1021 } 1022} 1023 1024/* Utility function used by das1800_flush_dma() and das1800_handle_dma(). 1025 * Assumes dma lock is held */ 1026static void das1800_flush_dma_channel(struct comedi_device * dev, struct comedi_subdevice * s, 1027 unsigned int channel, uint16_t * buffer) 1028{ 1029 unsigned int num_bytes, num_samples; 1030 struct comedi_cmd *cmd = &s->async->cmd; 1031 1032 disable_dma(channel); 1033 1034 /* clear flip-flop to make sure 2-byte registers 1035 * get set correctly */ 1036 clear_dma_ff(channel); 1037 1038 /* figure out how many points to read */ 1039 num_bytes = devpriv->dma_transfer_size - get_dma_residue(channel); 1040 num_samples = num_bytes / sizeof(short); 1041 1042 /* if we only need some of the points */ 1043 if (cmd->stop_src == TRIG_COUNT && devpriv->count < num_samples) 1044 num_samples = devpriv->count; 1045 1046 munge_data(dev, buffer, num_samples); 1047 cfc_write_array_to_buffer(s, buffer, num_bytes); 1048 if (s->async->cmd.stop_src == TRIG_COUNT) 1049 devpriv->count -= num_samples; 1050 1051 return; 1052} 1053 1054/* flushes remaining data from board when external trigger has stopped aquisition 1055 * and we are using dma transfers */ 1056static void das1800_flush_dma(struct comedi_device * dev, struct comedi_subdevice * s) 1057{ 1058 unsigned long flags; 1059 const int dual_dma = devpriv->irq_dma_bits & DMA_DUAL; 1060 1061 flags = claim_dma_lock(); 1062 das1800_flush_dma_channel(dev, s, devpriv->dma_current, 1063 devpriv->dma_current_buf); 1064 1065 if (dual_dma) { 1066 /* switch to other channel and flush it */ 1067 if (devpriv->dma_current == devpriv->dma0) { 1068 devpriv->dma_current = devpriv->dma1; 1069 devpriv->dma_current_buf = devpriv->ai_buf1; 1070 } else { 1071 devpriv->dma_current = devpriv->dma0; 1072 devpriv->dma_current_buf = devpriv->ai_buf0; 1073 } 1074 das1800_flush_dma_channel(dev, s, devpriv->dma_current, 1075 devpriv->dma_current_buf); 1076 } 1077 1078 release_dma_lock(flags); 1079 1080 /* get any remaining samples in fifo */ 1081 das1800_handle_fifo_not_empty(dev, s); 1082 1083 return; 1084} 1085 1086static void das1800_handle_fifo_half_full(struct comedi_device * dev, 1087 struct comedi_subdevice * s) 1088{ 1089 int numPoints = 0; /* number of points to read */ 1090 struct comedi_cmd *cmd = &s->async->cmd; 1091 1092 numPoints = FIFO_SIZE / 2; 1093 /* if we only need some of the points */ 1094 if (cmd->stop_src == TRIG_COUNT && devpriv->count < numPoints) 1095 numPoints = devpriv->count; 1096 insw(dev->iobase + DAS1800_FIFO, devpriv->ai_buf0, numPoints); 1097 munge_data(dev, devpriv->ai_buf0, numPoints); 1098 cfc_write_array_to_buffer(s, devpriv->ai_buf0, 1099 numPoints * sizeof(devpriv->ai_buf0[0])); 1100 if (cmd->stop_src == TRIG_COUNT) 1101 devpriv->count -= numPoints; 1102 return; 1103} 1104 1105static void das1800_handle_fifo_not_empty(struct comedi_device * dev, 1106 struct comedi_subdevice * s) 1107{ 1108 short dpnt; 1109 int unipolar; 1110 struct comedi_cmd *cmd = &s->async->cmd; 1111 1112 unipolar = inb(dev->iobase + DAS1800_CONTROL_C) & UB; 1113 1114 while (inb(dev->iobase + DAS1800_STATUS) & FNE) { 1115 if (cmd->stop_src == TRIG_COUNT && devpriv->count == 0) 1116 break; 1117 dpnt = inw(dev->iobase + DAS1800_FIFO); 1118 /* convert to unsigned type if we are in a bipolar mode */ 1119 if (!unipolar) ; 1120 dpnt = munge_bipolar_sample(dev, dpnt); 1121 cfc_write_to_buffer(s, dpnt); 1122 if (cmd->stop_src == TRIG_COUNT) 1123 devpriv->count--; 1124 } 1125 1126 return; 1127} 1128 1129static int das1800_cancel(struct comedi_device * dev, struct comedi_subdevice * s) 1130{ 1131 outb(0x0, dev->iobase + DAS1800_STATUS); /* disable conversions */ 1132 outb(0x0, dev->iobase + DAS1800_CONTROL_B); /* disable interrupts and dma */ 1133 outb(0x0, dev->iobase + DAS1800_CONTROL_A); /* disable and clear fifo and stop triggering */ 1134 if (devpriv->dma0) 1135 disable_dma(devpriv->dma0); 1136 if (devpriv->dma1) 1137 disable_dma(devpriv->dma1); 1138 return 0; 1139} 1140 1141/* test analog input cmd */ 1142static int das1800_ai_do_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s, 1143 struct comedi_cmd * cmd) 1144{ 1145 int err = 0; 1146 int tmp; 1147 unsigned int tmp_arg; 1148 int i; 1149 int unipolar; 1150 1151 /* step 1: make sure trigger sources are trivially valid */ 1152 1153 tmp = cmd->start_src; 1154 cmd->start_src &= TRIG_NOW | TRIG_EXT; 1155 if (!cmd->start_src || tmp != cmd->start_src) 1156 err++; 1157 1158 tmp = cmd->scan_begin_src; 1159 cmd->scan_begin_src &= TRIG_FOLLOW | TRIG_TIMER | TRIG_EXT; 1160 if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src) 1161 err++; 1162 1163 tmp = cmd->convert_src; 1164 cmd->convert_src &= TRIG_TIMER | TRIG_EXT; 1165 if (!cmd->convert_src || tmp != cmd->convert_src) 1166 err++; 1167 1168 tmp = cmd->scan_end_src; 1169 cmd->scan_end_src &= TRIG_COUNT; 1170 if (!cmd->scan_end_src || tmp != cmd->scan_end_src) 1171 err++; 1172 1173 tmp = cmd->stop_src; 1174 cmd->stop_src &= TRIG_COUNT | TRIG_EXT | TRIG_NONE; 1175 if (!cmd->stop_src || tmp != cmd->stop_src) 1176 err++; 1177 1178 if (err) 1179 return 1; 1180 1181 /* step 2: make sure trigger sources are unique and mutually compatible */ 1182 1183 /* uniqueness check */ 1184 if (cmd->start_src != TRIG_NOW && cmd->start_src != TRIG_EXT) 1185 err++; 1186 if (cmd->scan_begin_src != TRIG_FOLLOW && 1187 cmd->scan_begin_src != TRIG_TIMER && 1188 cmd->scan_begin_src != TRIG_EXT) 1189 err++; 1190 if (cmd->convert_src != TRIG_TIMER && cmd->convert_src != TRIG_EXT) 1191 err++; 1192 if (cmd->stop_src != TRIG_COUNT && 1193 cmd->stop_src != TRIG_NONE && cmd->stop_src != TRIG_EXT) 1194 err++; 1195 /* compatibility check */ 1196 if (cmd->scan_begin_src != TRIG_FOLLOW && 1197 cmd->convert_src != TRIG_TIMER) 1198 err++; 1199 1200 if (err) 1201 return 2; 1202 1203 /* step 3: make sure arguments are trivially compatible */ 1204 1205 if (cmd->start_arg != 0) { 1206 cmd->start_arg = 0; 1207 err++; 1208 } 1209 if (cmd->convert_src == TRIG_TIMER) { 1210 if (cmd->convert_arg < thisboard->ai_speed) { 1211 cmd->convert_arg = thisboard->ai_speed; 1212 err++; 1213 } 1214 } 1215 if (!cmd->chanlist_len) { 1216 cmd->chanlist_len = 1; 1217 err++; 1218 } 1219 if (cmd->scan_end_arg != cmd->chanlist_len) { 1220 cmd->scan_end_arg = cmd->chanlist_len; 1221 err++; 1222 } 1223 1224 switch (cmd->stop_src) { 1225 case TRIG_COUNT: 1226 if (!cmd->stop_arg) { 1227 cmd->stop_arg = 1; 1228 err++; 1229 } 1230 break; 1231 case TRIG_NONE: 1232 if (cmd->stop_arg != 0) { 1233 cmd->stop_arg = 0; 1234 err++; 1235 } 1236 break; 1237 default: 1238 break; 1239 } 1240 1241 if (err) 1242 return 3; 1243 1244 /* step 4: fix up any arguments */ 1245 1246 if (cmd->convert_src == TRIG_TIMER) { 1247 /* if we are not in burst mode */ 1248 if (cmd->scan_begin_src == TRIG_FOLLOW) { 1249 tmp_arg = cmd->convert_arg; 1250 /* calculate counter values that give desired timing */ 1251 i8253_cascade_ns_to_timer_2div(TIMER_BASE, 1252 &(devpriv->divisor1), &(devpriv->divisor2), 1253 &(cmd->convert_arg), 1254 cmd->flags & TRIG_ROUND_MASK); 1255 if (tmp_arg != cmd->convert_arg) 1256 err++; 1257 } 1258 /* if we are in burst mode */ 1259 else { 1260 /* check that convert_arg is compatible */ 1261 tmp_arg = cmd->convert_arg; 1262 cmd->convert_arg = 1263 burst_convert_arg(cmd->convert_arg, 1264 cmd->flags & TRIG_ROUND_MASK); 1265 if (tmp_arg != cmd->convert_arg) 1266 err++; 1267 1268 if (cmd->scan_begin_src == TRIG_TIMER) { 1269 /* if scans are timed faster than conversion rate allows */ 1270 if (cmd->convert_arg * cmd->chanlist_len > 1271 cmd->scan_begin_arg) { 1272 cmd->scan_begin_arg = 1273 cmd->convert_arg * 1274 cmd->chanlist_len; 1275 err++; 1276 } 1277 tmp_arg = cmd->scan_begin_arg; 1278 /* calculate counter values that give desired timing */ 1279 i8253_cascade_ns_to_timer_2div(TIMER_BASE, 1280 &(devpriv->divisor1), 1281 &(devpriv->divisor2), 1282 &(cmd->scan_begin_arg), 1283 cmd->flags & TRIG_ROUND_MASK); 1284 if (tmp_arg != cmd->scan_begin_arg) 1285 err++; 1286 } 1287 } 1288 } 1289 1290 if (err) 1291 return 4; 1292 1293 /* make sure user is not trying to mix unipolar and bipolar ranges */ 1294 if (cmd->chanlist) { 1295 unipolar = CR_RANGE(cmd->chanlist[0]) & UNIPOLAR; 1296 for (i = 1; i < cmd->chanlist_len; i++) { 1297 if (unipolar != (CR_RANGE(cmd->chanlist[i]) & UNIPOLAR)) { 1298 comedi_error(dev, 1299 "unipolar and bipolar ranges cannot be mixed in the chanlist"); 1300 err++; 1301 break; 1302 } 1303 } 1304 } 1305 1306 if (err) 1307 return 5; 1308 1309 return 0; 1310} 1311 1312/* analog input cmd interface */ 1313 1314/* first, some utility functions used in the main ai_do_cmd() */ 1315 1316/* returns appropriate bits for control register a, depending on command */ 1317static int control_a_bits(struct comedi_cmd cmd) 1318{ 1319 int control_a; 1320 1321 control_a = FFEN; /* enable fifo */ 1322 if (cmd.stop_src == TRIG_EXT) { 1323 control_a |= ATEN; 1324 } 1325 switch (cmd.start_src) { 1326 case TRIG_EXT: 1327 control_a |= TGEN | CGSL; 1328 break; 1329 case TRIG_NOW: 1330 control_a |= CGEN; 1331 break; 1332 default: 1333 break; 1334 } 1335 1336 return control_a; 1337} 1338 1339/* returns appropriate bits for control register c, depending on command */ 1340static int control_c_bits(struct comedi_cmd cmd) 1341{ 1342 int control_c; 1343 int aref; 1344 1345 /* set clock source to internal or external, select analog reference, 1346 * select unipolar / bipolar 1347 */ 1348 aref = CR_AREF(cmd.chanlist[0]); 1349 control_c = UQEN; /* enable upper qram addresses */ 1350 if (aref != AREF_DIFF) 1351 control_c |= SD; 1352 if (aref == AREF_COMMON) 1353 control_c |= CMEN; 1354 /* if a unipolar range was selected */ 1355 if (CR_RANGE(cmd.chanlist[0]) & UNIPOLAR) 1356 control_c |= UB; 1357 switch (cmd.scan_begin_src) { 1358 case TRIG_FOLLOW: /* not in burst mode */ 1359 switch (cmd.convert_src) { 1360 case TRIG_TIMER: 1361 /* trig on cascaded counters */ 1362 control_c |= IPCLK; 1363 break; 1364 case TRIG_EXT: 1365 /* trig on falling edge of external trigger */ 1366 control_c |= XPCLK; 1367 break; 1368 default: 1369 break; 1370 } 1371 break; 1372 case TRIG_TIMER: 1373 /* burst mode with internal pacer clock */ 1374 control_c |= BMDE | IPCLK; 1375 break; 1376 case TRIG_EXT: 1377 /* burst mode with external trigger */ 1378 control_c |= BMDE | XPCLK; 1379 break; 1380 default: 1381 break; 1382 } 1383 1384 return control_c; 1385} 1386 1387/* sets up counters */ 1388static int setup_counters(struct comedi_device * dev, struct comedi_cmd cmd) 1389{ 1390 /* setup cascaded counters for conversion/scan frequency */ 1391 switch (cmd.scan_begin_src) { 1392 case TRIG_FOLLOW: /* not in burst mode */ 1393 if (cmd.convert_src == TRIG_TIMER) { 1394 /* set conversion frequency */ 1395 i8253_cascade_ns_to_timer_2div(TIMER_BASE, 1396 &(devpriv->divisor1), &(devpriv->divisor2), 1397 &(cmd.convert_arg), 1398 cmd.flags & TRIG_ROUND_MASK); 1399 if (das1800_set_frequency(dev) < 0) { 1400 return -1; 1401 } 1402 } 1403 break; 1404 case TRIG_TIMER: /* in burst mode */ 1405 /* set scan frequency */ 1406 i8253_cascade_ns_to_timer_2div(TIMER_BASE, &(devpriv->divisor1), 1407 &(devpriv->divisor2), &(cmd.scan_begin_arg), 1408 cmd.flags & TRIG_ROUND_MASK); 1409 if (das1800_set_frequency(dev) < 0) { 1410 return -1; 1411 } 1412 break; 1413 default: 1414 break; 1415 } 1416 1417 /* setup counter 0 for 'about triggering' */ 1418 if (cmd.stop_src == TRIG_EXT) { 1419 /* load counter 0 in mode 0 */ 1420 i8254_load(dev->iobase + DAS1800_COUNTER, 0, 0, 1, 0); 1421 } 1422 1423 return 0; 1424} 1425 1426/* sets up dma */ 1427static void setup_dma(struct comedi_device * dev, struct comedi_cmd cmd) 1428{ 1429 unsigned long lock_flags; 1430 const int dual_dma = devpriv->irq_dma_bits & DMA_DUAL; 1431 1432 if ((devpriv->irq_dma_bits & DMA_ENABLED) == 0) 1433 return; 1434 1435 /* determine a reasonable dma transfer size */ 1436 devpriv->dma_transfer_size = suggest_transfer_size(&cmd); 1437 lock_flags = claim_dma_lock(); 1438 disable_dma(devpriv->dma0); 1439 /* clear flip-flop to make sure 2-byte registers for 1440 * count and address get set correctly */ 1441 clear_dma_ff(devpriv->dma0); 1442 set_dma_addr(devpriv->dma0, virt_to_bus(devpriv->ai_buf0)); 1443 /* set appropriate size of transfer */ 1444 set_dma_count(devpriv->dma0, devpriv->dma_transfer_size); 1445 devpriv->dma_current = devpriv->dma0; 1446 devpriv->dma_current_buf = devpriv->ai_buf0; 1447 enable_dma(devpriv->dma0); 1448 /* set up dual dma if appropriate */ 1449 if (dual_dma) { 1450 disable_dma(devpriv->dma1); 1451 /* clear flip-flop to make sure 2-byte registers for 1452 * count and address get set correctly */ 1453 clear_dma_ff(devpriv->dma1); 1454 set_dma_addr(devpriv->dma1, virt_to_bus(devpriv->ai_buf1)); 1455 /* set appropriate size of transfer */ 1456 set_dma_count(devpriv->dma1, devpriv->dma_transfer_size); 1457 enable_dma(devpriv->dma1); 1458 } 1459 release_dma_lock(lock_flags); 1460 1461 return; 1462} 1463 1464/* programs channel/gain list into card */ 1465static void program_chanlist(struct comedi_device * dev, struct comedi_cmd cmd) 1466{ 1467 int i, n, chan_range; 1468 unsigned long irq_flags; 1469 const int range_mask = 0x3; /* masks unipolar/bipolar bit off range */ 1470 const int range_bitshift = 8; 1471 1472 n = cmd.chanlist_len; 1473 /* spinlock protects indirect addressing */ 1474 comedi_spin_lock_irqsave(&dev->spinlock, irq_flags); 1475 outb(QRAM, dev->iobase + DAS1800_SELECT); /* select QRAM for baseAddress + 0x0 */ 1476 outb(n - 1, dev->iobase + DAS1800_QRAM_ADDRESS); /*set QRAM address start */ 1477 /* make channel / gain list */ 1478 for (i = 0; i < n; i++) { 1479 chan_range = 1480 CR_CHAN(cmd.chanlist[i]) | ((CR_RANGE(cmd. 1481 chanlist[i]) & range_mask) << 1482 range_bitshift); 1483 outw(chan_range, dev->iobase + DAS1800_QRAM); 1484 } 1485 outb(n - 1, dev->iobase + DAS1800_QRAM_ADDRESS); /*finish write to QRAM */ 1486 comedi_spin_unlock_irqrestore(&dev->spinlock, irq_flags); 1487 1488 return; 1489} 1490 1491/* analog input do_cmd */ 1492static int das1800_ai_do_cmd(struct comedi_device * dev, struct comedi_subdevice * s) 1493{ 1494 int ret; 1495 int control_a, control_c; 1496 struct comedi_async *async = s->async; 1497 struct comedi_cmd cmd = async->cmd; 1498 1499 if (!dev->irq) { 1500 comedi_error(dev, 1501 "no irq assigned for das-1800, cannot do hardware conversions"); 1502 return -1; 1503 } 1504 1505 /* disable dma on TRIG_WAKE_EOS, or TRIG_RT 1506 * (because dma in handler is unsafe at hard real-time priority) */ 1507 if (cmd.flags & (TRIG_WAKE_EOS | TRIG_RT)) { 1508 devpriv->irq_dma_bits &= ~DMA_ENABLED; 1509 } else { 1510 devpriv->irq_dma_bits |= devpriv->dma_bits; 1511 } 1512 /* interrupt on end of conversion for TRIG_WAKE_EOS */ 1513 if (cmd.flags & TRIG_WAKE_EOS) { 1514 /* interrupt fifo not empty */ 1515 devpriv->irq_dma_bits &= ~FIMD; 1516 } else { 1517 /* interrupt fifo half full */ 1518 devpriv->irq_dma_bits |= FIMD; 1519 } 1520 /* determine how many conversions we need */ 1521 if (cmd.stop_src == TRIG_COUNT) { 1522 devpriv->count = cmd.stop_arg * cmd.chanlist_len; 1523 } 1524 1525 das1800_cancel(dev, s); 1526 1527 /* determine proper bits for control registers */ 1528 control_a = control_a_bits(cmd); 1529 control_c = control_c_bits(cmd); 1530 1531 /* setup card and start */ 1532 program_chanlist(dev, cmd); 1533 ret = setup_counters(dev, cmd); 1534 if (ret < 0) { 1535 comedi_error(dev, "Error setting up counters"); 1536 return ret; 1537 } 1538 setup_dma(dev, cmd); 1539 outb(control_c, dev->iobase + DAS1800_CONTROL_C); 1540 /* set conversion rate and length for burst mode */ 1541 if (control_c & BMDE) { 1542 /* program conversion period with number of microseconds minus 1 */ 1543 outb(cmd.convert_arg / 1000 - 1, 1544 dev->iobase + DAS1800_BURST_RATE); 1545 outb(cmd.chanlist_len - 1, dev->iobase + DAS1800_BURST_LENGTH); 1546 } 1547 outb(devpriv->irq_dma_bits, dev->iobase + DAS1800_CONTROL_B); /* enable irq/dma */ 1548 outb(control_a, dev->iobase + DAS1800_CONTROL_A); /* enable fifo and triggering */ 1549 outb(CVEN, dev->iobase + DAS1800_STATUS); /* enable conversions */ 1550 1551 return 0; 1552} 1553 1554/* read analog input */ 1555static int das1800_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s, 1556 struct comedi_insn * insn, unsigned int * data) 1557{ 1558 int i, n; 1559 int chan, range, aref, chan_range; 1560 int timeout = 1000; 1561 short dpnt; 1562 int conv_flags = 0; 1563 unsigned long irq_flags; 1564 1565 /* set up analog reference and unipolar / bipolar mode */ 1566 aref = CR_AREF(insn->chanspec); 1567 conv_flags |= UQEN; 1568 if (aref != AREF_DIFF) 1569 conv_flags |= SD; 1570 if (aref == AREF_COMMON) 1571 conv_flags |= CMEN; 1572 /* if a unipolar range was selected */ 1573 if (CR_RANGE(insn->chanspec) & UNIPOLAR) 1574 conv_flags |= UB; 1575 1576 outb(conv_flags, dev->iobase + DAS1800_CONTROL_C); /* software conversion enabled */ 1577 outb(CVEN, dev->iobase + DAS1800_STATUS); /* enable conversions */ 1578 outb(0x0, dev->iobase + DAS1800_CONTROL_A); /* reset fifo */ 1579 outb(FFEN, dev->iobase + DAS1800_CONTROL_A); 1580 1581 chan = CR_CHAN(insn->chanspec); 1582 /* mask of unipolar/bipolar bit from range */ 1583 range = CR_RANGE(insn->chanspec) & 0x3; 1584 chan_range = chan | (range << 8); 1585 comedi_spin_lock_irqsave(&dev->spinlock, irq_flags); 1586 outb(QRAM, dev->iobase + DAS1800_SELECT); /* select QRAM for baseAddress + 0x0 */ 1587 outb(0x0, dev->iobase + DAS1800_QRAM_ADDRESS); /* set QRAM address start */ 1588 outw(chan_range, dev->iobase + DAS1800_QRAM); 1589 outb(0x0, dev->iobase + DAS1800_QRAM_ADDRESS); /*finish write to QRAM */ 1590 outb(ADC, dev->iobase + DAS1800_SELECT); /* select ADC for baseAddress + 0x0 */ 1591 1592 for (n = 0; n < insn->n; n++) { 1593 /* trigger conversion */ 1594 outb(0, dev->iobase + DAS1800_FIFO); 1595 for (i = 0; i < timeout; i++) { 1596 if (inb(dev->iobase + DAS1800_STATUS) & FNE) 1597 break; 1598 } 1599 if (i == timeout) { 1600 comedi_error(dev, "timeout"); 1601 return -ETIME; 1602 } 1603 dpnt = inw(dev->iobase + DAS1800_FIFO); 1604 /* shift data to offset binary for bipolar ranges */ 1605 if ((conv_flags & UB) == 0) 1606 dpnt += 1 << (thisboard->resolution - 1); 1607 data[n] = dpnt; 1608 } 1609 comedi_spin_unlock_irqrestore(&dev->spinlock, irq_flags); 1610 1611 return n; 1612} 1613 1614/* writes to an analog output channel */ 1615static int das1800_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s, 1616 struct comedi_insn * insn, unsigned int * data) 1617{ 1618 int chan = CR_CHAN(insn->chanspec); 1619/* int range = CR_RANGE(insn->chanspec); */ 1620 int update_chan = thisboard->ao_n_chan - 1; 1621 short output; 1622 unsigned long irq_flags; 1623 1624 /* card expects two's complement data */ 1625 output = data[0] - (1 << (thisboard->resolution - 1)); 1626 /* if the write is to the 'update' channel, we need to remember its value */ 1627 if (chan == update_chan) 1628 devpriv->ao_update_bits = output; 1629 /* write to channel */ 1630 comedi_spin_lock_irqsave(&dev->spinlock, irq_flags); 1631 outb(DAC(chan), dev->iobase + DAS1800_SELECT); /* select dac channel for baseAddress + 0x0 */ 1632 outw(output, dev->iobase + DAS1800_DAC); 1633 /* now we need to write to 'update' channel to update all dac channels */ 1634 if (chan != update_chan) { 1635 outb(DAC(update_chan), dev->iobase + DAS1800_SELECT); /* select 'update' channel for baseAddress + 0x0 */ 1636 outw(devpriv->ao_update_bits, dev->iobase + DAS1800_DAC); 1637 } 1638 comedi_spin_unlock_irqrestore(&dev->spinlock, irq_flags); 1639 1640 return 1; 1641} 1642 1643/* reads from digital input channels */ 1644static int das1800_di_rbits(struct comedi_device * dev, struct comedi_subdevice * s, 1645 struct comedi_insn * insn, unsigned int * data) 1646{ 1647 1648 data[1] = inb(dev->iobase + DAS1800_DIGITAL) & 0xf; 1649 data[0] = 0; 1650 1651 return 2; 1652} 1653 1654/* writes to digital output channels */ 1655static int das1800_do_wbits(struct comedi_device * dev, struct comedi_subdevice * s, 1656 struct comedi_insn * insn, unsigned int * data) 1657{ 1658 unsigned int wbits; 1659 1660 /* only set bits that have been masked */ 1661 data[0] &= (1 << s->n_chan) - 1; 1662 wbits = devpriv->do_bits; 1663 wbits &= ~data[0]; 1664 wbits |= data[0] & data[1]; 1665 devpriv->do_bits = wbits; 1666 1667 outb(devpriv->do_bits, dev->iobase + DAS1800_DIGITAL); 1668 1669 data[1] = devpriv->do_bits; 1670 1671 return 2; 1672} 1673 1674/* loads counters with divisor1, divisor2 from private structure */ 1675static int das1800_set_frequency(struct comedi_device * dev) 1676{ 1677 int err = 0; 1678 1679 /* counter 1, mode 2 */ 1680 if (i8254_load(dev->iobase + DAS1800_COUNTER, 0, 1, devpriv->divisor1, 1681 2)) 1682 err++; 1683 /* counter 2, mode 2 */ 1684 if (i8254_load(dev->iobase + DAS1800_COUNTER, 0, 2, devpriv->divisor2, 1685 2)) 1686 err++; 1687 if (err) 1688 return -1; 1689 1690 return 0; 1691} 1692 1693/* converts requested conversion timing to timing compatible with 1694 * hardware, used only when card is in 'burst mode' 1695 */ 1696static unsigned int burst_convert_arg(unsigned int convert_arg, int round_mode) 1697{ 1698 unsigned int micro_sec; 1699 1700 /* in burst mode, the maximum conversion time is 64 microseconds */ 1701 if (convert_arg > 64000) 1702 convert_arg = 64000; 1703 1704 /* the conversion time must be an integral number of microseconds */ 1705 switch (round_mode) { 1706 case TRIG_ROUND_NEAREST: 1707 default: 1708 micro_sec = (convert_arg + 500) / 1000; 1709 break; 1710 case TRIG_ROUND_DOWN: 1711 micro_sec = convert_arg / 1000; 1712 break; 1713 case TRIG_ROUND_UP: 1714 micro_sec = (convert_arg - 1) / 1000 + 1; 1715 break; 1716 } 1717 1718 /* return number of nanoseconds */ 1719 return micro_sec * 1000; 1720} 1721 1722/* utility function that suggests a dma transfer size based on the conversion period 'ns' */ 1723static unsigned int suggest_transfer_size(struct comedi_cmd * cmd) 1724{ 1725 unsigned int size = DMA_BUF_SIZE; 1726 static const int sample_size = 2; /* size in bytes of one sample from board */ 1727 unsigned int fill_time = 300000000; /* target time in nanoseconds for filling dma buffer */ 1728 unsigned int max_size; /* maximum size we will allow for a transfer */ 1729 1730 /* make dma buffer fill in 0.3 seconds for timed modes */ 1731 switch (cmd->scan_begin_src) { 1732 case TRIG_FOLLOW: /* not in burst mode */ 1733 if (cmd->convert_src == TRIG_TIMER) 1734 size = (fill_time / cmd->convert_arg) * sample_size; 1735 break; 1736 case TRIG_TIMER: 1737 size = (fill_time / (cmd->scan_begin_arg * cmd->chanlist_len)) * 1738 sample_size; 1739 break; 1740 default: 1741 size = DMA_BUF_SIZE; 1742 break; 1743 } 1744 1745 /* set a minimum and maximum size allowed */ 1746 max_size = DMA_BUF_SIZE; 1747 /* if we are taking limited number of conversions, limit transfer size to that */ 1748 if (cmd->stop_src == TRIG_COUNT && 1749 cmd->stop_arg * cmd->chanlist_len * sample_size < max_size) 1750 max_size = cmd->stop_arg * cmd->chanlist_len * sample_size; 1751 1752 if (size > max_size) 1753 size = max_size; 1754 if (size < sample_size) 1755 size = sample_size; 1756 1757 return size; 1758} 1759