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