1// SPDX-License-Identifier: GPL-2.0+ 2/* 3 * Comedi driver for Keithley DAS-1700/DAS-1800 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 10/* 11 * Driver: das1800 12 * Description: Keithley Metrabyte DAS1800 (& compatibles) 13 * Author: Frank Mori Hess <fmhess@users.sourceforge.net> 14 * Devices: [Keithley Metrabyte] DAS-1701ST (das-1701st), 15 * DAS-1701ST-DA (das-1701st-da), DAS-1701/AO (das-1701ao), 16 * DAS-1702ST (das-1702st), DAS-1702ST-DA (das-1702st-da), 17 * DAS-1702HR (das-1702hr), DAS-1702HR-DA (das-1702hr-da), 18 * DAS-1702/AO (das-1702ao), DAS-1801ST (das-1801st), 19 * DAS-1801ST-DA (das-1801st-da), DAS-1801HC (das-1801hc), 20 * DAS-1801AO (das-1801ao), DAS-1802ST (das-1802st), 21 * DAS-1802ST-DA (das-1802st-da), DAS-1802HR (das-1802hr), 22 * DAS-1802HR-DA (das-1802hr-da), DAS-1802HC (das-1802hc), 23 * DAS-1802AO (das-1802ao) 24 * Status: works 25 * 26 * Configuration options: 27 * [0] - I/O port base address 28 * [1] - IRQ (optional, required for analog input cmd support) 29 * [2] - DMA0 (optional, requires irq) 30 * [3] - DMA1 (optional, requires irq and dma0) 31 * 32 * analog input cmd triggers supported: 33 * 34 * start_src TRIG_NOW command starts immediately 35 * TRIG_EXT command starts on external pin TGIN 36 * 37 * scan_begin_src TRIG_FOLLOW paced/external scans start immediately 38 * TRIG_TIMER burst scans start periodically 39 * TRIG_EXT burst scans start on external pin XPCLK 40 * 41 * scan_end_src TRIG_COUNT scan ends after last channel 42 * 43 * convert_src TRIG_TIMER paced/burst conversions are timed 44 * TRIG_EXT conversions on external pin XPCLK 45 * (requires scan_begin_src == TRIG_FOLLOW) 46 * 47 * stop_src TRIG_COUNT command stops after stop_arg scans 48 * TRIG_EXT command stops on external pin TGIN 49 * TRIG_NONE command runs until canceled 50 * 51 * If TRIG_EXT is used for both the start_src and stop_src, the first TGIN 52 * trigger starts the command, and the second trigger will stop it. If only 53 * one is TRIG_EXT, the first trigger will either stop or start the command. 54 * The external pin TGIN is normally set for negative edge triggering. It 55 * can be set to positive edge with the CR_INVERT flag. If TRIG_EXT is used 56 * for both the start_src and stop_src they must have the same polarity. 57 * 58 * Minimum conversion speed is limited to 64 microseconds (convert_arg <= 64000) 59 * for 'burst' scans. This limitation does not apply for 'paced' scans. The 60 * maximum conversion speed is limited by the board (convert_arg >= ai_speed). 61 * Maximum conversion speeds are not always achievable depending on the 62 * board setup (see user manual). 63 * 64 * NOTES: 65 * Only the DAS-1801ST has been tested by me. 66 * Unipolar and bipolar ranges cannot be mixed in the channel/gain list. 67 * 68 * The waveform analog output on the 'ao' cards is not supported. 69 * If you need it, send me (Frank Hess) an email. 70 */ 71 72#include <linux/module.h> 73#include <linux/interrupt.h> 74#include <linux/slab.h> 75#include <linux/io.h> 76#include <linux/comedi/comedidev.h> 77#include <linux/comedi/comedi_8254.h> 78#include <linux/comedi/comedi_isadma.h> 79 80/* misc. defines */ 81#define DAS1800_SIZE 16 /* uses 16 io addresses */ 82#define FIFO_SIZE 1024 /* 1024 sample fifo */ 83#define DMA_BUF_SIZE 0x1ff00 /* size in bytes of dma buffers */ 84 85/* Registers for the das1800 */ 86#define DAS1800_FIFO 0x0 87#define DAS1800_QRAM 0x0 88#define DAS1800_DAC 0x0 89#define DAS1800_SELECT 0x2 90#define ADC 0x0 91#define QRAM 0x1 92#define DAC(a) (0x2 + a) 93#define DAS1800_DIGITAL 0x3 94#define DAS1800_CONTROL_A 0x4 95#define FFEN 0x1 96#define CGEN 0x4 97#define CGSL 0x8 98#define TGEN 0x10 99#define TGSL 0x20 100#define TGPL 0x40 101#define ATEN 0x80 102#define DAS1800_CONTROL_B 0x5 103#define DMA_CH5 0x1 104#define DMA_CH6 0x2 105#define DMA_CH7 0x3 106#define DMA_CH5_CH6 0x5 107#define DMA_CH6_CH7 0x6 108#define DMA_CH7_CH5 0x7 109#define DMA_ENABLED 0x3 110#define DMA_DUAL 0x4 111#define IRQ3 0x8 112#define IRQ5 0x10 113#define IRQ7 0x18 114#define IRQ10 0x28 115#define IRQ11 0x30 116#define IRQ15 0x38 117#define FIMD 0x40 118#define DAS1800_CONTROL_C 0X6 119#define IPCLK 0x1 120#define XPCLK 0x3 121#define BMDE 0x4 122#define CMEN 0x8 123#define UQEN 0x10 124#define SD 0x40 125#define UB 0x80 126#define DAS1800_STATUS 0x7 127#define INT 0x1 128#define DMATC 0x2 129#define CT0TC 0x8 130#define OVF 0x10 131#define FHF 0x20 132#define FNE 0x40 133#define CVEN 0x80 134#define CVEN_MASK 0x40 135#define CLEAR_INTR_MASK (CVEN_MASK | 0x1f) 136#define DAS1800_BURST_LENGTH 0x8 137#define DAS1800_BURST_RATE 0x9 138#define DAS1800_QRAM_ADDRESS 0xa 139#define DAS1800_COUNTER 0xc 140 141#define IOBASE2 0x400 142 143static const struct comedi_lrange das1801_ai_range = { 144 8, { 145 BIP_RANGE(5), /* bipolar gain = 1 */ 146 BIP_RANGE(1), /* bipolar gain = 10 */ 147 BIP_RANGE(0.1), /* bipolar gain = 50 */ 148 BIP_RANGE(0.02), /* bipolar gain = 250 */ 149 UNI_RANGE(5), /* unipolar gain = 1 */ 150 UNI_RANGE(1), /* unipolar gain = 10 */ 151 UNI_RANGE(0.1), /* unipolar gain = 50 */ 152 UNI_RANGE(0.02) /* unipolar gain = 250 */ 153 } 154}; 155 156static const struct comedi_lrange das1802_ai_range = { 157 8, { 158 BIP_RANGE(10), /* bipolar gain = 1 */ 159 BIP_RANGE(5), /* bipolar gain = 2 */ 160 BIP_RANGE(2.5), /* bipolar gain = 4 */ 161 BIP_RANGE(1.25), /* bipolar gain = 8 */ 162 UNI_RANGE(10), /* unipolar gain = 1 */ 163 UNI_RANGE(5), /* unipolar gain = 2 */ 164 UNI_RANGE(2.5), /* unipolar gain = 4 */ 165 UNI_RANGE(1.25) /* unipolar gain = 8 */ 166 } 167}; 168 169/* 170 * The waveform analog outputs on the 'ao' boards are not currently 171 * supported. They have a comedi_lrange of: 172 * { 2, { BIP_RANGE(10), BIP_RANGE(5) } } 173 */ 174 175enum das1800_boardid { 176 BOARD_DAS1701ST, 177 BOARD_DAS1701ST_DA, 178 BOARD_DAS1702ST, 179 BOARD_DAS1702ST_DA, 180 BOARD_DAS1702HR, 181 BOARD_DAS1702HR_DA, 182 BOARD_DAS1701AO, 183 BOARD_DAS1702AO, 184 BOARD_DAS1801ST, 185 BOARD_DAS1801ST_DA, 186 BOARD_DAS1802ST, 187 BOARD_DAS1802ST_DA, 188 BOARD_DAS1802HR, 189 BOARD_DAS1802HR_DA, 190 BOARD_DAS1801HC, 191 BOARD_DAS1802HC, 192 BOARD_DAS1801AO, 193 BOARD_DAS1802AO 194}; 195 196/* board probe id values (hi byte of the digital input register) */ 197#define DAS1800_ID_ST_DA 0x3 198#define DAS1800_ID_HR_DA 0x4 199#define DAS1800_ID_AO 0x5 200#define DAS1800_ID_HR 0x6 201#define DAS1800_ID_ST 0x7 202#define DAS1800_ID_HC 0x8 203 204struct das1800_board { 205 const char *name; 206 unsigned char id; 207 unsigned int ai_speed; 208 unsigned int is_01_series:1; 209}; 210 211static const struct das1800_board das1800_boards[] = { 212 [BOARD_DAS1701ST] = { 213 .name = "das-1701st", 214 .id = DAS1800_ID_ST, 215 .ai_speed = 6250, 216 .is_01_series = 1, 217 }, 218 [BOARD_DAS1701ST_DA] = { 219 .name = "das-1701st-da", 220 .id = DAS1800_ID_ST_DA, 221 .ai_speed = 6250, 222 .is_01_series = 1, 223 }, 224 [BOARD_DAS1702ST] = { 225 .name = "das-1702st", 226 .id = DAS1800_ID_ST, 227 .ai_speed = 6250, 228 }, 229 [BOARD_DAS1702ST_DA] = { 230 .name = "das-1702st-da", 231 .id = DAS1800_ID_ST_DA, 232 .ai_speed = 6250, 233 }, 234 [BOARD_DAS1702HR] = { 235 .name = "das-1702hr", 236 .id = DAS1800_ID_HR, 237 .ai_speed = 20000, 238 }, 239 [BOARD_DAS1702HR_DA] = { 240 .name = "das-1702hr-da", 241 .id = DAS1800_ID_HR_DA, 242 .ai_speed = 20000, 243 }, 244 [BOARD_DAS1701AO] = { 245 .name = "das-1701ao", 246 .id = DAS1800_ID_AO, 247 .ai_speed = 6250, 248 .is_01_series = 1, 249 }, 250 [BOARD_DAS1702AO] = { 251 .name = "das-1702ao", 252 .id = DAS1800_ID_AO, 253 .ai_speed = 6250, 254 }, 255 [BOARD_DAS1801ST] = { 256 .name = "das-1801st", 257 .id = DAS1800_ID_ST, 258 .ai_speed = 3000, 259 .is_01_series = 1, 260 }, 261 [BOARD_DAS1801ST_DA] = { 262 .name = "das-1801st-da", 263 .id = DAS1800_ID_ST_DA, 264 .ai_speed = 3000, 265 .is_01_series = 1, 266 }, 267 [BOARD_DAS1802ST] = { 268 .name = "das-1802st", 269 .id = DAS1800_ID_ST, 270 .ai_speed = 3000, 271 }, 272 [BOARD_DAS1802ST_DA] = { 273 .name = "das-1802st-da", 274 .id = DAS1800_ID_ST_DA, 275 .ai_speed = 3000, 276 }, 277 [BOARD_DAS1802HR] = { 278 .name = "das-1802hr", 279 .id = DAS1800_ID_HR, 280 .ai_speed = 10000, 281 }, 282 [BOARD_DAS1802HR_DA] = { 283 .name = "das-1802hr-da", 284 .id = DAS1800_ID_HR_DA, 285 .ai_speed = 10000, 286 }, 287 [BOARD_DAS1801HC] = { 288 .name = "das-1801hc", 289 .id = DAS1800_ID_HC, 290 .ai_speed = 3000, 291 .is_01_series = 1, 292 }, 293 [BOARD_DAS1802HC] = { 294 .name = "das-1802hc", 295 .id = DAS1800_ID_HC, 296 .ai_speed = 3000, 297 }, 298 [BOARD_DAS1801AO] = { 299 .name = "das-1801ao", 300 .id = DAS1800_ID_AO, 301 .ai_speed = 3000, 302 .is_01_series = 1, 303 }, 304 [BOARD_DAS1802AO] = { 305 .name = "das-1802ao", 306 .id = DAS1800_ID_AO, 307 .ai_speed = 3000, 308 }, 309}; 310 311struct das1800_private { 312 struct comedi_isadma *dma; 313 int irq_dma_bits; 314 int dma_bits; 315 unsigned short *fifo_buf; 316 unsigned long iobase2; 317 bool ai_is_unipolar; 318}; 319 320static void das1800_ai_munge(struct comedi_device *dev, 321 struct comedi_subdevice *s, 322 void *data, unsigned int num_bytes, 323 unsigned int start_chan_index) 324{ 325 struct das1800_private *devpriv = dev->private; 326 unsigned short *array = data; 327 unsigned int num_samples = comedi_bytes_to_samples(s, num_bytes); 328 unsigned int i; 329 330 if (devpriv->ai_is_unipolar) 331 return; 332 333 for (i = 0; i < num_samples; i++) 334 array[i] = comedi_offset_munge(s, array[i]); 335} 336 337static void das1800_handle_fifo_half_full(struct comedi_device *dev, 338 struct comedi_subdevice *s) 339{ 340 struct das1800_private *devpriv = dev->private; 341 unsigned int nsamples = comedi_nsamples_left(s, FIFO_SIZE / 2); 342 343 insw(dev->iobase + DAS1800_FIFO, devpriv->fifo_buf, nsamples); 344 comedi_buf_write_samples(s, devpriv->fifo_buf, nsamples); 345} 346 347static void das1800_handle_fifo_not_empty(struct comedi_device *dev, 348 struct comedi_subdevice *s) 349{ 350 struct comedi_cmd *cmd = &s->async->cmd; 351 unsigned short dpnt; 352 353 while (inb(dev->iobase + DAS1800_STATUS) & FNE) { 354 dpnt = inw(dev->iobase + DAS1800_FIFO); 355 comedi_buf_write_samples(s, &dpnt, 1); 356 357 if (cmd->stop_src == TRIG_COUNT && 358 s->async->scans_done >= cmd->stop_arg) 359 break; 360 } 361} 362 363static void das1800_flush_dma_channel(struct comedi_device *dev, 364 struct comedi_subdevice *s, 365 struct comedi_isadma_desc *desc) 366{ 367 unsigned int residue = comedi_isadma_disable(desc->chan); 368 unsigned int nbytes = desc->size - residue; 369 unsigned int nsamples; 370 371 /* figure out how many points to read */ 372 nsamples = comedi_bytes_to_samples(s, nbytes); 373 nsamples = comedi_nsamples_left(s, nsamples); 374 375 comedi_buf_write_samples(s, desc->virt_addr, nsamples); 376} 377 378static void das1800_flush_dma(struct comedi_device *dev, 379 struct comedi_subdevice *s) 380{ 381 struct das1800_private *devpriv = dev->private; 382 struct comedi_isadma *dma = devpriv->dma; 383 struct comedi_isadma_desc *desc = &dma->desc[dma->cur_dma]; 384 const int dual_dma = devpriv->irq_dma_bits & DMA_DUAL; 385 386 das1800_flush_dma_channel(dev, s, desc); 387 388 if (dual_dma) { 389 /* switch to other channel and flush it */ 390 dma->cur_dma = 1 - dma->cur_dma; 391 desc = &dma->desc[dma->cur_dma]; 392 das1800_flush_dma_channel(dev, s, desc); 393 } 394 395 /* get any remaining samples in fifo */ 396 das1800_handle_fifo_not_empty(dev, s); 397} 398 399static void das1800_handle_dma(struct comedi_device *dev, 400 struct comedi_subdevice *s, unsigned int status) 401{ 402 struct das1800_private *devpriv = dev->private; 403 struct comedi_isadma *dma = devpriv->dma; 404 struct comedi_isadma_desc *desc = &dma->desc[dma->cur_dma]; 405 const int dual_dma = devpriv->irq_dma_bits & DMA_DUAL; 406 407 das1800_flush_dma_channel(dev, s, desc); 408 409 /* re-enable dma channel */ 410 comedi_isadma_program(desc); 411 412 if (status & DMATC) { 413 /* clear DMATC interrupt bit */ 414 outb(CLEAR_INTR_MASK & ~DMATC, dev->iobase + DAS1800_STATUS); 415 /* switch dma channels for next time, if appropriate */ 416 if (dual_dma) 417 dma->cur_dma = 1 - dma->cur_dma; 418 } 419} 420 421static int das1800_ai_cancel(struct comedi_device *dev, 422 struct comedi_subdevice *s) 423{ 424 struct das1800_private *devpriv = dev->private; 425 struct comedi_isadma *dma = devpriv->dma; 426 struct comedi_isadma_desc *desc; 427 int i; 428 429 /* disable and stop conversions */ 430 outb(0x0, dev->iobase + DAS1800_STATUS); 431 outb(0x0, dev->iobase + DAS1800_CONTROL_B); 432 outb(0x0, dev->iobase + DAS1800_CONTROL_A); 433 434 if (dma) { 435 for (i = 0; i < 2; i++) { 436 desc = &dma->desc[i]; 437 if (desc->chan) 438 comedi_isadma_disable(desc->chan); 439 } 440 } 441 442 return 0; 443} 444 445static void das1800_ai_handler(struct comedi_device *dev) 446{ 447 struct das1800_private *devpriv = dev->private; 448 struct comedi_subdevice *s = dev->read_subdev; 449 struct comedi_async *async = s->async; 450 struct comedi_cmd *cmd = &async->cmd; 451 unsigned int status = inb(dev->iobase + DAS1800_STATUS); 452 453 /* select adc register (spinlock is already held) */ 454 outb(ADC, dev->iobase + DAS1800_SELECT); 455 456 /* get samples with dma, fifo, or polled as necessary */ 457 if (devpriv->irq_dma_bits & DMA_ENABLED) 458 das1800_handle_dma(dev, s, status); 459 else if (status & FHF) 460 das1800_handle_fifo_half_full(dev, s); 461 else if (status & FNE) 462 das1800_handle_fifo_not_empty(dev, s); 463 464 /* if the card's fifo has overflowed */ 465 if (status & OVF) { 466 /* clear OVF interrupt bit */ 467 outb(CLEAR_INTR_MASK & ~OVF, dev->iobase + DAS1800_STATUS); 468 dev_err(dev->class_dev, "FIFO overflow\n"); 469 async->events |= COMEDI_CB_ERROR; 470 comedi_handle_events(dev, s); 471 return; 472 } 473 /* stop taking data if appropriate */ 474 /* stop_src TRIG_EXT */ 475 if (status & CT0TC) { 476 /* clear CT0TC interrupt bit */ 477 outb(CLEAR_INTR_MASK & ~CT0TC, dev->iobase + DAS1800_STATUS); 478 /* get all remaining samples before quitting */ 479 if (devpriv->irq_dma_bits & DMA_ENABLED) 480 das1800_flush_dma(dev, s); 481 else 482 das1800_handle_fifo_not_empty(dev, s); 483 async->events |= COMEDI_CB_EOA; 484 } else if (cmd->stop_src == TRIG_COUNT && 485 async->scans_done >= cmd->stop_arg) { 486 async->events |= COMEDI_CB_EOA; 487 } 488 489 comedi_handle_events(dev, s); 490} 491 492static int das1800_ai_poll(struct comedi_device *dev, 493 struct comedi_subdevice *s) 494{ 495 unsigned long flags; 496 497 /* 498 * Protects the indirect addressing selected by DAS1800_SELECT 499 * in das1800_ai_handler() also prevents race with das1800_interrupt(). 500 */ 501 spin_lock_irqsave(&dev->spinlock, flags); 502 503 das1800_ai_handler(dev); 504 505 spin_unlock_irqrestore(&dev->spinlock, flags); 506 507 return comedi_buf_n_bytes_ready(s); 508} 509 510static irqreturn_t das1800_interrupt(int irq, void *d) 511{ 512 struct comedi_device *dev = d; 513 unsigned int status; 514 515 if (!dev->attached) { 516 dev_err(dev->class_dev, "premature interrupt\n"); 517 return IRQ_HANDLED; 518 } 519 520 /* 521 * Protects the indirect addressing selected by DAS1800_SELECT 522 * in das1800_ai_handler() also prevents race with das1800_ai_poll(). 523 */ 524 spin_lock(&dev->spinlock); 525 526 status = inb(dev->iobase + DAS1800_STATUS); 527 528 /* if interrupt was not caused by das-1800 */ 529 if (!(status & INT)) { 530 spin_unlock(&dev->spinlock); 531 return IRQ_NONE; 532 } 533 /* clear the interrupt status bit INT */ 534 outb(CLEAR_INTR_MASK & ~INT, dev->iobase + DAS1800_STATUS); 535 /* handle interrupt */ 536 das1800_ai_handler(dev); 537 538 spin_unlock(&dev->spinlock); 539 return IRQ_HANDLED; 540} 541 542static int das1800_ai_fixup_paced_timing(struct comedi_device *dev, 543 struct comedi_cmd *cmd) 544{ 545 unsigned int arg = cmd->convert_arg; 546 547 /* 548 * Paced mode: 549 * scan_begin_src is TRIG_FOLLOW 550 * convert_src is TRIG_TIMER 551 * 552 * The convert_arg sets the pacer sample acquisition time. 553 * The max acquisition speed is limited to the boards 554 * 'ai_speed' (this was already verified). The min speed is 555 * limited by the cascaded 8254 timer. 556 */ 557 comedi_8254_cascade_ns_to_timer(dev->pacer, &arg, cmd->flags); 558 return comedi_check_trigger_arg_is(&cmd->convert_arg, arg); 559} 560 561static int das1800_ai_fixup_burst_timing(struct comedi_device *dev, 562 struct comedi_cmd *cmd) 563{ 564 unsigned int arg = cmd->convert_arg; 565 int err = 0; 566 567 /* 568 * Burst mode: 569 * scan_begin_src is TRIG_TIMER or TRIG_EXT 570 * convert_src is TRIG_TIMER 571 * 572 * The convert_arg sets burst sample acquisition time. 573 * The max acquisition speed is limited to the boards 574 * 'ai_speed' (this was already verified). The min speed is 575 * limiited to 64 microseconds, 576 */ 577 err |= comedi_check_trigger_arg_max(&arg, 64000); 578 579 /* round to microseconds then verify */ 580 switch (cmd->flags & CMDF_ROUND_MASK) { 581 case CMDF_ROUND_NEAREST: 582 default: 583 arg = DIV_ROUND_CLOSEST(arg, 1000); 584 break; 585 case CMDF_ROUND_DOWN: 586 arg = arg / 1000; 587 break; 588 case CMDF_ROUND_UP: 589 arg = DIV_ROUND_UP(arg, 1000); 590 break; 591 } 592 err |= comedi_check_trigger_arg_is(&cmd->convert_arg, arg * 1000); 593 594 /* 595 * The pacer can be used to set the scan sample rate. The max scan 596 * speed is limited by the conversion speed and the number of channels 597 * to convert. The min speed is limited by the cascaded 8254 timer. 598 */ 599 if (cmd->scan_begin_src == TRIG_TIMER) { 600 arg = cmd->convert_arg * cmd->chanlist_len; 601 err |= comedi_check_trigger_arg_min(&cmd->scan_begin_arg, arg); 602 603 arg = cmd->scan_begin_arg; 604 comedi_8254_cascade_ns_to_timer(dev->pacer, &arg, cmd->flags); 605 err |= comedi_check_trigger_arg_is(&cmd->scan_begin_arg, arg); 606 } 607 608 return err; 609} 610 611static int das1800_ai_check_chanlist(struct comedi_device *dev, 612 struct comedi_subdevice *s, 613 struct comedi_cmd *cmd) 614{ 615 unsigned int range = CR_RANGE(cmd->chanlist[0]); 616 bool unipolar0 = comedi_range_is_unipolar(s, range); 617 int i; 618 619 for (i = 1; i < cmd->chanlist_len; i++) { 620 range = CR_RANGE(cmd->chanlist[i]); 621 622 if (unipolar0 != comedi_range_is_unipolar(s, range)) { 623 dev_dbg(dev->class_dev, 624 "unipolar and bipolar ranges cannot be mixed in the chanlist\n"); 625 return -EINVAL; 626 } 627 } 628 629 return 0; 630} 631 632static int das1800_ai_cmdtest(struct comedi_device *dev, 633 struct comedi_subdevice *s, 634 struct comedi_cmd *cmd) 635{ 636 const struct das1800_board *board = dev->board_ptr; 637 int err = 0; 638 639 /* Step 1 : check if triggers are trivially valid */ 640 641 err |= comedi_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_EXT); 642 err |= comedi_check_trigger_src(&cmd->scan_begin_src, 643 TRIG_FOLLOW | TRIG_TIMER | TRIG_EXT); 644 err |= comedi_check_trigger_src(&cmd->convert_src, 645 TRIG_TIMER | TRIG_EXT); 646 err |= comedi_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT); 647 err |= comedi_check_trigger_src(&cmd->stop_src, 648 TRIG_COUNT | TRIG_EXT | TRIG_NONE); 649 650 if (err) 651 return 1; 652 653 /* Step 2a : make sure trigger sources are unique */ 654 655 err |= comedi_check_trigger_is_unique(cmd->start_src); 656 err |= comedi_check_trigger_is_unique(cmd->scan_begin_src); 657 err |= comedi_check_trigger_is_unique(cmd->convert_src); 658 err |= comedi_check_trigger_is_unique(cmd->stop_src); 659 660 /* Step 2b : and mutually compatible */ 661 662 /* burst scans must use timed conversions */ 663 if (cmd->scan_begin_src != TRIG_FOLLOW && 664 cmd->convert_src != TRIG_TIMER) 665 err |= -EINVAL; 666 667 /* the external pin TGIN must use the same polarity */ 668 if (cmd->start_src == TRIG_EXT && cmd->stop_src == TRIG_EXT) 669 err |= comedi_check_trigger_arg_is(&cmd->start_arg, 670 cmd->stop_arg); 671 672 if (err) 673 return 2; 674 675 /* Step 3: check if arguments are trivially valid */ 676 677 if (cmd->start_arg == TRIG_NOW) 678 err |= comedi_check_trigger_arg_is(&cmd->start_arg, 0); 679 680 if (cmd->convert_src == TRIG_TIMER) { 681 err |= comedi_check_trigger_arg_min(&cmd->convert_arg, 682 board->ai_speed); 683 } 684 685 err |= comedi_check_trigger_arg_min(&cmd->chanlist_len, 1); 686 err |= comedi_check_trigger_arg_is(&cmd->scan_end_arg, 687 cmd->chanlist_len); 688 689 switch (cmd->stop_src) { 690 case TRIG_COUNT: 691 err |= comedi_check_trigger_arg_min(&cmd->stop_arg, 1); 692 break; 693 case TRIG_NONE: 694 err |= comedi_check_trigger_arg_is(&cmd->stop_arg, 0); 695 break; 696 default: 697 break; 698 } 699 700 if (err) 701 return 3; 702 703 /* Step 4: fix up any arguments */ 704 705 if (cmd->convert_src == TRIG_TIMER) { 706 if (cmd->scan_begin_src == TRIG_FOLLOW) 707 err |= das1800_ai_fixup_paced_timing(dev, cmd); 708 else /* TRIG_TIMER or TRIG_EXT */ 709 err |= das1800_ai_fixup_burst_timing(dev, cmd); 710 } 711 712 if (err) 713 return 4; 714 715 /* Step 5: check channel list if it exists */ 716 if (cmd->chanlist && cmd->chanlist_len > 0) 717 err |= das1800_ai_check_chanlist(dev, s, cmd); 718 719 if (err) 720 return 5; 721 722 return 0; 723} 724 725static unsigned char das1800_ai_chanspec_bits(struct comedi_subdevice *s, 726 unsigned int chanspec) 727{ 728 unsigned int range = CR_RANGE(chanspec); 729 unsigned int aref = CR_AREF(chanspec); 730 unsigned char bits; 731 732 bits = UQEN; 733 if (aref != AREF_DIFF) 734 bits |= SD; 735 if (aref == AREF_COMMON) 736 bits |= CMEN; 737 if (comedi_range_is_unipolar(s, range)) 738 bits |= UB; 739 740 return bits; 741} 742 743static unsigned int das1800_ai_transfer_size(struct comedi_device *dev, 744 struct comedi_subdevice *s, 745 unsigned int maxbytes, 746 unsigned int ns) 747{ 748 struct comedi_cmd *cmd = &s->async->cmd; 749 unsigned int max_samples = comedi_bytes_to_samples(s, maxbytes); 750 unsigned int samples; 751 752 samples = max_samples; 753 754 /* for timed modes, make dma buffer fill in 'ns' time */ 755 switch (cmd->scan_begin_src) { 756 case TRIG_FOLLOW: /* not in burst mode */ 757 if (cmd->convert_src == TRIG_TIMER) 758 samples = ns / cmd->convert_arg; 759 break; 760 case TRIG_TIMER: 761 samples = ns / (cmd->scan_begin_arg * cmd->chanlist_len); 762 break; 763 } 764 765 /* limit samples to what is remaining in the command */ 766 samples = comedi_nsamples_left(s, samples); 767 768 if (samples > max_samples) 769 samples = max_samples; 770 if (samples < 1) 771 samples = 1; 772 773 return comedi_samples_to_bytes(s, samples); 774} 775 776static void das1800_ai_setup_dma(struct comedi_device *dev, 777 struct comedi_subdevice *s) 778{ 779 struct das1800_private *devpriv = dev->private; 780 struct comedi_isadma *dma = devpriv->dma; 781 struct comedi_isadma_desc *desc; 782 unsigned int bytes; 783 784 if ((devpriv->irq_dma_bits & DMA_ENABLED) == 0) 785 return; 786 787 dma->cur_dma = 0; 788 desc = &dma->desc[0]; 789 790 /* determine a dma transfer size to fill buffer in 0.3 sec */ 791 bytes = das1800_ai_transfer_size(dev, s, desc->maxsize, 300000000); 792 793 desc->size = bytes; 794 comedi_isadma_program(desc); 795 796 /* set up dual dma if appropriate */ 797 if (devpriv->irq_dma_bits & DMA_DUAL) { 798 desc = &dma->desc[1]; 799 desc->size = bytes; 800 comedi_isadma_program(desc); 801 } 802} 803 804static void das1800_ai_set_chanlist(struct comedi_device *dev, 805 unsigned int *chanlist, unsigned int len) 806{ 807 unsigned long flags; 808 unsigned int i; 809 810 /* protects the indirect addressing selected by DAS1800_SELECT */ 811 spin_lock_irqsave(&dev->spinlock, flags); 812 813 /* select QRAM register and set start address */ 814 outb(QRAM, dev->iobase + DAS1800_SELECT); 815 outb(len - 1, dev->iobase + DAS1800_QRAM_ADDRESS); 816 817 /* make channel / gain list */ 818 for (i = 0; i < len; i++) { 819 unsigned int chan = CR_CHAN(chanlist[i]); 820 unsigned int range = CR_RANGE(chanlist[i]); 821 unsigned short val; 822 823 val = chan | ((range & 0x3) << 8); 824 outw(val, dev->iobase + DAS1800_QRAM); 825 } 826 827 /* finish write to QRAM */ 828 outb(len - 1, dev->iobase + DAS1800_QRAM_ADDRESS); 829 830 spin_unlock_irqrestore(&dev->spinlock, flags); 831} 832 833static int das1800_ai_cmd(struct comedi_device *dev, 834 struct comedi_subdevice *s) 835{ 836 struct das1800_private *devpriv = dev->private; 837 int control_a, control_c; 838 struct comedi_async *async = s->async; 839 const struct comedi_cmd *cmd = &async->cmd; 840 unsigned int range0 = CR_RANGE(cmd->chanlist[0]); 841 842 /* 843 * Disable dma on CMDF_WAKE_EOS, or CMDF_PRIORITY (because dma in 844 * handler is unsafe at hard real-time priority). 845 */ 846 if (cmd->flags & (CMDF_WAKE_EOS | CMDF_PRIORITY)) 847 devpriv->irq_dma_bits &= ~DMA_ENABLED; 848 else 849 devpriv->irq_dma_bits |= devpriv->dma_bits; 850 /* interrupt on end of conversion for CMDF_WAKE_EOS */ 851 if (cmd->flags & CMDF_WAKE_EOS) { 852 /* interrupt fifo not empty */ 853 devpriv->irq_dma_bits &= ~FIMD; 854 } else { 855 /* interrupt fifo half full */ 856 devpriv->irq_dma_bits |= FIMD; 857 } 858 859 das1800_ai_cancel(dev, s); 860 861 devpriv->ai_is_unipolar = comedi_range_is_unipolar(s, range0); 862 863 control_a = FFEN; 864 if (cmd->stop_src == TRIG_EXT) 865 control_a |= ATEN; 866 if (cmd->start_src == TRIG_EXT) 867 control_a |= TGEN | CGSL; 868 else /* TRIG_NOW */ 869 control_a |= CGEN; 870 if (control_a & (ATEN | TGEN)) { 871 if ((cmd->start_arg & CR_INVERT) || (cmd->stop_arg & CR_INVERT)) 872 control_a |= TGPL; 873 } 874 875 control_c = das1800_ai_chanspec_bits(s, cmd->chanlist[0]); 876 /* set clock source to internal or external */ 877 if (cmd->scan_begin_src == TRIG_FOLLOW) { 878 /* not in burst mode */ 879 if (cmd->convert_src == TRIG_TIMER) { 880 /* trig on cascaded counters */ 881 control_c |= IPCLK; 882 } else { /* TRIG_EXT */ 883 /* trig on falling edge of external trigger */ 884 control_c |= XPCLK; 885 } 886 } else if (cmd->scan_begin_src == TRIG_TIMER) { 887 /* burst mode with internal pacer clock */ 888 control_c |= BMDE | IPCLK; 889 } else { /* TRIG_EXT */ 890 /* burst mode with external trigger */ 891 control_c |= BMDE | XPCLK; 892 } 893 894 das1800_ai_set_chanlist(dev, cmd->chanlist, cmd->chanlist_len); 895 896 /* setup cascaded counters for conversion/scan frequency */ 897 if ((cmd->scan_begin_src == TRIG_FOLLOW || 898 cmd->scan_begin_src == TRIG_TIMER) && 899 cmd->convert_src == TRIG_TIMER) { 900 comedi_8254_update_divisors(dev->pacer); 901 comedi_8254_pacer_enable(dev->pacer, 1, 2, true); 902 } 903 904 /* setup counter 0 for 'about triggering' */ 905 if (cmd->stop_src == TRIG_EXT) 906 comedi_8254_load(dev->pacer, 0, 1, I8254_MODE0 | I8254_BINARY); 907 908 das1800_ai_setup_dma(dev, s); 909 outb(control_c, dev->iobase + DAS1800_CONTROL_C); 910 /* set conversion rate and length for burst mode */ 911 if (control_c & BMDE) { 912 outb(cmd->convert_arg / 1000 - 1, /* microseconds - 1 */ 913 dev->iobase + DAS1800_BURST_RATE); 914 outb(cmd->chanlist_len - 1, dev->iobase + DAS1800_BURST_LENGTH); 915 } 916 917 /* enable and start conversions */ 918 outb(devpriv->irq_dma_bits, dev->iobase + DAS1800_CONTROL_B); 919 outb(control_a, dev->iobase + DAS1800_CONTROL_A); 920 outb(CVEN, dev->iobase + DAS1800_STATUS); 921 922 return 0; 923} 924 925static int das1800_ai_eoc(struct comedi_device *dev, 926 struct comedi_subdevice *s, 927 struct comedi_insn *insn, 928 unsigned long context) 929{ 930 unsigned char status; 931 932 status = inb(dev->iobase + DAS1800_STATUS); 933 if (status & FNE) 934 return 0; 935 return -EBUSY; 936} 937 938static int das1800_ai_insn_read(struct comedi_device *dev, 939 struct comedi_subdevice *s, 940 struct comedi_insn *insn, 941 unsigned int *data) 942{ 943 unsigned int range = CR_RANGE(insn->chanspec); 944 bool is_unipolar = comedi_range_is_unipolar(s, range); 945 int ret = 0; 946 int n; 947 unsigned short dpnt; 948 unsigned long flags; 949 950 outb(das1800_ai_chanspec_bits(s, insn->chanspec), 951 dev->iobase + DAS1800_CONTROL_C); /* software pacer */ 952 outb(CVEN, dev->iobase + DAS1800_STATUS); /* enable conversions */ 953 outb(0x0, dev->iobase + DAS1800_CONTROL_A); /* reset fifo */ 954 outb(FFEN, dev->iobase + DAS1800_CONTROL_A); 955 956 das1800_ai_set_chanlist(dev, &insn->chanspec, 1); 957 958 /* protects the indirect addressing selected by DAS1800_SELECT */ 959 spin_lock_irqsave(&dev->spinlock, flags); 960 961 /* select ai fifo register */ 962 outb(ADC, dev->iobase + DAS1800_SELECT); 963 964 for (n = 0; n < insn->n; n++) { 965 /* trigger conversion */ 966 outb(0, dev->iobase + DAS1800_FIFO); 967 968 ret = comedi_timeout(dev, s, insn, das1800_ai_eoc, 0); 969 if (ret) 970 break; 971 972 dpnt = inw(dev->iobase + DAS1800_FIFO); 973 if (!is_unipolar) 974 dpnt = comedi_offset_munge(s, dpnt); 975 data[n] = dpnt; 976 } 977 spin_unlock_irqrestore(&dev->spinlock, flags); 978 979 return ret ? ret : insn->n; 980} 981 982static int das1800_ao_insn_write(struct comedi_device *dev, 983 struct comedi_subdevice *s, 984 struct comedi_insn *insn, 985 unsigned int *data) 986{ 987 unsigned int chan = CR_CHAN(insn->chanspec); 988 unsigned int update_chan = s->n_chan - 1; 989 unsigned long flags; 990 int i; 991 992 /* protects the indirect addressing selected by DAS1800_SELECT */ 993 spin_lock_irqsave(&dev->spinlock, flags); 994 995 for (i = 0; i < insn->n; i++) { 996 unsigned int val = data[i]; 997 998 s->readback[chan] = val; 999 1000 val = comedi_offset_munge(s, val); 1001 1002 /* load this channel (and update if it's the last channel) */ 1003 outb(DAC(chan), dev->iobase + DAS1800_SELECT); 1004 outw(val, dev->iobase + DAS1800_DAC); 1005 1006 /* update all channels */ 1007 if (chan != update_chan) { 1008 val = comedi_offset_munge(s, s->readback[update_chan]); 1009 1010 outb(DAC(update_chan), dev->iobase + DAS1800_SELECT); 1011 outw(val, dev->iobase + DAS1800_DAC); 1012 } 1013 } 1014 spin_unlock_irqrestore(&dev->spinlock, flags); 1015 1016 return insn->n; 1017} 1018 1019static int das1800_di_insn_bits(struct comedi_device *dev, 1020 struct comedi_subdevice *s, 1021 struct comedi_insn *insn, 1022 unsigned int *data) 1023{ 1024 data[1] = inb(dev->iobase + DAS1800_DIGITAL) & 0xf; 1025 data[0] = 0; 1026 1027 return insn->n; 1028} 1029 1030static int das1800_do_insn_bits(struct comedi_device *dev, 1031 struct comedi_subdevice *s, 1032 struct comedi_insn *insn, 1033 unsigned int *data) 1034{ 1035 if (comedi_dio_update_state(s, data)) 1036 outb(s->state, dev->iobase + DAS1800_DIGITAL); 1037 1038 data[1] = s->state; 1039 1040 return insn->n; 1041} 1042 1043static void das1800_init_dma(struct comedi_device *dev, 1044 struct comedi_devconfig *it) 1045{ 1046 struct das1800_private *devpriv = dev->private; 1047 unsigned int *dma_chan; 1048 1049 /* 1050 * it->options[2] is DMA channel 0 1051 * it->options[3] is DMA channel 1 1052 * 1053 * Encode the DMA channels into 2 digit hexadecimal for switch. 1054 */ 1055 dma_chan = &it->options[2]; 1056 1057 switch ((dma_chan[0] & 0x7) | (dma_chan[1] << 4)) { 1058 case 0x5: /* dma0 == 5 */ 1059 devpriv->dma_bits = DMA_CH5; 1060 break; 1061 case 0x6: /* dma0 == 6 */ 1062 devpriv->dma_bits = DMA_CH6; 1063 break; 1064 case 0x7: /* dma0 == 7 */ 1065 devpriv->dma_bits = DMA_CH7; 1066 break; 1067 case 0x65: /* dma0 == 5, dma1 == 6 */ 1068 devpriv->dma_bits = DMA_CH5_CH6; 1069 break; 1070 case 0x76: /* dma0 == 6, dma1 == 7 */ 1071 devpriv->dma_bits = DMA_CH6_CH7; 1072 break; 1073 case 0x57: /* dma0 == 7, dma1 == 5 */ 1074 devpriv->dma_bits = DMA_CH7_CH5; 1075 break; 1076 default: 1077 return; 1078 } 1079 1080 /* DMA can use 1 or 2 buffers, each with a separate channel */ 1081 devpriv->dma = comedi_isadma_alloc(dev, dma_chan[1] ? 2 : 1, 1082 dma_chan[0], dma_chan[1], 1083 DMA_BUF_SIZE, COMEDI_ISADMA_READ); 1084 if (!devpriv->dma) 1085 devpriv->dma_bits = 0; 1086} 1087 1088static void das1800_free_dma(struct comedi_device *dev) 1089{ 1090 struct das1800_private *devpriv = dev->private; 1091 1092 if (devpriv) 1093 comedi_isadma_free(devpriv->dma); 1094} 1095 1096static int das1800_probe(struct comedi_device *dev) 1097{ 1098 const struct das1800_board *board = dev->board_ptr; 1099 unsigned char id; 1100 1101 id = (inb(dev->iobase + DAS1800_DIGITAL) >> 4) & 0xf; 1102 1103 /* 1104 * The dev->board_ptr will be set by comedi_device_attach() if the 1105 * board name provided by the user matches a board->name in this 1106 * driver. If so, this function sanity checks the id to verify that 1107 * the board is correct. 1108 */ 1109 if (board) { 1110 if (board->id == id) 1111 return 0; 1112 dev_err(dev->class_dev, 1113 "probed id does not match board id (0x%x != 0x%x)\n", 1114 id, board->id); 1115 return -ENODEV; 1116 } 1117 1118 /* 1119 * If the dev->board_ptr is not set, the user is trying to attach 1120 * an unspecified board to this driver. In this case the id is used 1121 * to 'probe' for the dev->board_ptr. 1122 */ 1123 switch (id) { 1124 case DAS1800_ID_ST_DA: 1125 /* das-1701st-da, das-1702st-da, das-1801st-da, das-1802st-da */ 1126 board = &das1800_boards[BOARD_DAS1801ST_DA]; 1127 break; 1128 case DAS1800_ID_HR_DA: 1129 /* das-1702hr-da, das-1802hr-da */ 1130 board = &das1800_boards[BOARD_DAS1802HR_DA]; 1131 break; 1132 case DAS1800_ID_AO: 1133 /* das-1701ao, das-1702ao, das-1801ao, das-1802ao */ 1134 board = &das1800_boards[BOARD_DAS1801AO]; 1135 break; 1136 case DAS1800_ID_HR: 1137 /* das-1702hr, das-1802hr */ 1138 board = &das1800_boards[BOARD_DAS1802HR]; 1139 break; 1140 case DAS1800_ID_ST: 1141 /* das-1701st, das-1702st, das-1801st, das-1802st */ 1142 board = &das1800_boards[BOARD_DAS1801ST]; 1143 break; 1144 case DAS1800_ID_HC: 1145 /* das-1801hc, das-1802hc */ 1146 board = &das1800_boards[BOARD_DAS1801HC]; 1147 break; 1148 default: 1149 dev_err(dev->class_dev, "invalid probe id 0x%x\n", id); 1150 return -ENODEV; 1151 } 1152 dev->board_ptr = board; 1153 dev->board_name = board->name; 1154 dev_warn(dev->class_dev, 1155 "probed id 0x%0x: %s series (not recommended)\n", 1156 id, board->name); 1157 return 0; 1158} 1159 1160static int das1800_attach(struct comedi_device *dev, 1161 struct comedi_devconfig *it) 1162{ 1163 const struct das1800_board *board; 1164 struct das1800_private *devpriv; 1165 struct comedi_subdevice *s; 1166 unsigned int irq = it->options[1]; 1167 bool is_16bit; 1168 int ret; 1169 int i; 1170 1171 devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); 1172 if (!devpriv) 1173 return -ENOMEM; 1174 1175 ret = comedi_request_region(dev, it->options[0], DAS1800_SIZE); 1176 if (ret) 1177 return ret; 1178 1179 ret = das1800_probe(dev); 1180 if (ret) 1181 return ret; 1182 board = dev->board_ptr; 1183 1184 is_16bit = board->id == DAS1800_ID_HR || board->id == DAS1800_ID_HR_DA; 1185 1186 /* waveform 'ao' boards have additional io ports */ 1187 if (board->id == DAS1800_ID_AO) { 1188 unsigned long iobase2 = dev->iobase + IOBASE2; 1189 1190 ret = __comedi_request_region(dev, iobase2, DAS1800_SIZE); 1191 if (ret) 1192 return ret; 1193 devpriv->iobase2 = iobase2; 1194 } 1195 1196 if (irq == 3 || irq == 5 || irq == 7 || irq == 10 || irq == 11 || 1197 irq == 15) { 1198 ret = request_irq(irq, das1800_interrupt, 0, 1199 dev->board_name, dev); 1200 if (ret == 0) { 1201 dev->irq = irq; 1202 1203 switch (irq) { 1204 case 3: 1205 devpriv->irq_dma_bits |= 0x8; 1206 break; 1207 case 5: 1208 devpriv->irq_dma_bits |= 0x10; 1209 break; 1210 case 7: 1211 devpriv->irq_dma_bits |= 0x18; 1212 break; 1213 case 10: 1214 devpriv->irq_dma_bits |= 0x28; 1215 break; 1216 case 11: 1217 devpriv->irq_dma_bits |= 0x30; 1218 break; 1219 case 15: 1220 devpriv->irq_dma_bits |= 0x38; 1221 break; 1222 } 1223 } 1224 } 1225 1226 /* an irq and one dma channel is required to use dma */ 1227 if (dev->irq & it->options[2]) 1228 das1800_init_dma(dev, it); 1229 1230 devpriv->fifo_buf = kmalloc_array(FIFO_SIZE, 1231 sizeof(*devpriv->fifo_buf), 1232 GFP_KERNEL); 1233 if (!devpriv->fifo_buf) 1234 return -ENOMEM; 1235 1236 dev->pacer = comedi_8254_io_alloc(dev->iobase + DAS1800_COUNTER, 1237 I8254_OSC_BASE_5MHZ, I8254_IO8, 0); 1238 if (IS_ERR(dev->pacer)) 1239 return PTR_ERR(dev->pacer); 1240 1241 ret = comedi_alloc_subdevices(dev, 4); 1242 if (ret) 1243 return ret; 1244 1245 /* 1246 * Analog Input subdevice 1247 * 1248 * The "hc" type boards have 64 analog input channels and a 64 1249 * entry QRAM fifo. 1250 * 1251 * All the other board types have 16 on-board channels. Each channel 1252 * can be expanded to 16 channels with the addition of an EXP-1800 1253 * expansion board for a total of 256 channels. The QRAM fifo on 1254 * these boards has 256 entries. 1255 * 1256 * From the datasheets it's not clear what the comedi channel to 1257 * actual physical channel mapping is when EXP-1800 boards are used. 1258 */ 1259 s = &dev->subdevices[0]; 1260 s->type = COMEDI_SUBD_AI; 1261 s->subdev_flags = SDF_READABLE | SDF_DIFF | SDF_GROUND; 1262 if (board->id != DAS1800_ID_HC) 1263 s->subdev_flags |= SDF_COMMON; 1264 s->n_chan = (board->id == DAS1800_ID_HC) ? 64 : 256; 1265 s->maxdata = is_16bit ? 0xffff : 0x0fff; 1266 s->range_table = board->is_01_series ? &das1801_ai_range 1267 : &das1802_ai_range; 1268 s->insn_read = das1800_ai_insn_read; 1269 if (dev->irq) { 1270 dev->read_subdev = s; 1271 s->subdev_flags |= SDF_CMD_READ; 1272 s->len_chanlist = s->n_chan; 1273 s->do_cmd = das1800_ai_cmd; 1274 s->do_cmdtest = das1800_ai_cmdtest; 1275 s->poll = das1800_ai_poll; 1276 s->cancel = das1800_ai_cancel; 1277 s->munge = das1800_ai_munge; 1278 } 1279 1280 /* Analog Output subdevice */ 1281 s = &dev->subdevices[1]; 1282 if (board->id == DAS1800_ID_ST_DA || board->id == DAS1800_ID_HR_DA) { 1283 s->type = COMEDI_SUBD_AO; 1284 s->subdev_flags = SDF_WRITABLE; 1285 s->n_chan = (board->id == DAS1800_ID_ST_DA) ? 4 : 2; 1286 s->maxdata = is_16bit ? 0xffff : 0x0fff; 1287 s->range_table = &range_bipolar10; 1288 s->insn_write = das1800_ao_insn_write; 1289 1290 ret = comedi_alloc_subdev_readback(s); 1291 if (ret) 1292 return ret; 1293 1294 /* initialize all channels to 0V */ 1295 for (i = 0; i < s->n_chan; i++) { 1296 /* spinlock is not necessary during the attach */ 1297 outb(DAC(i), dev->iobase + DAS1800_SELECT); 1298 outw(0, dev->iobase + DAS1800_DAC); 1299 } 1300 } else if (board->id == DAS1800_ID_AO) { 1301 /* 1302 * 'ao' boards have waveform analog outputs that are not 1303 * currently supported. 1304 */ 1305 s->type = COMEDI_SUBD_UNUSED; 1306 } else { 1307 s->type = COMEDI_SUBD_UNUSED; 1308 } 1309 1310 /* Digital Input subdevice */ 1311 s = &dev->subdevices[2]; 1312 s->type = COMEDI_SUBD_DI; 1313 s->subdev_flags = SDF_READABLE; 1314 s->n_chan = 4; 1315 s->maxdata = 1; 1316 s->range_table = &range_digital; 1317 s->insn_bits = das1800_di_insn_bits; 1318 1319 /* Digital Output subdevice */ 1320 s = &dev->subdevices[3]; 1321 s->type = COMEDI_SUBD_DO; 1322 s->subdev_flags = SDF_WRITABLE; 1323 s->n_chan = (board->id == DAS1800_ID_HC) ? 8 : 4; 1324 s->maxdata = 1; 1325 s->range_table = &range_digital; 1326 s->insn_bits = das1800_do_insn_bits; 1327 1328 das1800_ai_cancel(dev, dev->read_subdev); 1329 1330 /* initialize digital out channels */ 1331 outb(0, dev->iobase + DAS1800_DIGITAL); 1332 1333 return 0; 1334}; 1335 1336static void das1800_detach(struct comedi_device *dev) 1337{ 1338 struct das1800_private *devpriv = dev->private; 1339 1340 das1800_free_dma(dev); 1341 if (devpriv) { 1342 kfree(devpriv->fifo_buf); 1343 if (devpriv->iobase2) 1344 release_region(devpriv->iobase2, DAS1800_SIZE); 1345 } 1346 comedi_legacy_detach(dev); 1347} 1348 1349static struct comedi_driver das1800_driver = { 1350 .driver_name = "das1800", 1351 .module = THIS_MODULE, 1352 .attach = das1800_attach, 1353 .detach = das1800_detach, 1354 .num_names = ARRAY_SIZE(das1800_boards), 1355 .board_name = &das1800_boards[0].name, 1356 .offset = sizeof(struct das1800_board), 1357}; 1358module_comedi_driver(das1800_driver); 1359 1360MODULE_AUTHOR("Comedi https://www.comedi.org"); 1361MODULE_DESCRIPTION("Comedi driver for DAS1800 compatible ISA boards"); 1362MODULE_LICENSE("GPL"); 1363