Lines Matching +full:board +full:- +full:2

1 // SPDX-License-Identifier: GPL-2.0+
7 * COMEDI - Linux Control and Measurement Device Interface
14 * Devices: [Keithley Metrabyte] DAS-800 (das-800), DAS-801 (das-801),
15 * DAS-802 (das-802),
16 * [Measurement Computing] CIO-DAS800 (cio-das800),
17 * CIO-DAS801 (cio-das801), CIO-DAS802 (cio-das802),
18 * CIO-DAS802/16 (cio-das802/16)
19 * Status: works, cio-das802/16 untested - email me if you have tested it
22 * [0] - I/O port base address
23 * [1] - IRQ (optional, required for timed or externally triggered conversions)
33 * DAS-800 board with fixed gain.
35 * The cio-das802/16 does not have a fifo-empty status bit! Therefore
36 * only fifo-half-full transfers are possible with this card.
60 #define DAS800_CONTROL1 2
62 #define DAS800_CONV_CONTROL 2
69 #define DAS800_SCAN_LIMITS 2
70 #define DAS800_STATUS 2
74 #define CIO_FFOV 0x8 /* cio-das802/16 fifo overflow */
75 #define CIO_ENHF 0x90 /* cio-das802/16 fifo half full int ena */
162 .name = "das-800",
168 .name = "cio-das800",
174 .name = "das-801",
180 .name = "cio-das801",
186 .name = "das-802",
192 .name = "cio-das802",
198 .name = "cio-das802/16",
213 * Select dev->iobase + 2 to be desired register in das800_ind_write()
216 outb(reg, dev->iobase + DAS800_GAIN); in das800_ind_write()
217 outb(val, dev->iobase + 2); in das800_ind_write()
223 * Select dev->iobase + 7 to be desired register in das800_ind_read()
226 outb(reg, dev->iobase + DAS800_GAIN); in das800_ind_read()
227 return inb(dev->iobase + 7); in das800_ind_read()
232 const struct das800_board *board = dev->board_ptr; in das800_enable() local
233 struct das800_private *devpriv = dev->private; in das800_enable()
236 spin_lock_irqsave(&dev->spinlock, irq_flags); in das800_enable()
237 /* enable fifo-half full interrupts for cio-das802/16 */ in das800_enable()
238 if (board->resolution == 16) in das800_enable()
239 outb(CIO_ENHF, dev->iobase + DAS800_GAIN); in das800_enable()
243 das800_ind_write(dev, CONTROL1_INTE | devpriv->do_bits, CONTROL1); in das800_enable()
244 spin_unlock_irqrestore(&dev->spinlock, irq_flags); in das800_enable()
251 spin_lock_irqsave(&dev->spinlock, irq_flags); in das800_disable()
254 spin_unlock_irqrestore(&dev->spinlock, irq_flags); in das800_disable()
267 unsigned int chan0 = CR_CHAN(cmd->chanlist[0]); in das800_ai_check_chanlist()
268 unsigned int range0 = CR_RANGE(cmd->chanlist[0]); in das800_ai_check_chanlist()
271 for (i = 1; i < cmd->chanlist_len; i++) { in das800_ai_check_chanlist()
272 unsigned int chan = CR_CHAN(cmd->chanlist[i]); in das800_ai_check_chanlist()
273 unsigned int range = CR_RANGE(cmd->chanlist[i]); in das800_ai_check_chanlist()
275 if (chan != (chan0 + i) % s->n_chan) { in das800_ai_check_chanlist()
276 dev_dbg(dev->class_dev, in das800_ai_check_chanlist()
278 return -EINVAL; in das800_ai_check_chanlist()
282 dev_dbg(dev->class_dev, in das800_ai_check_chanlist()
284 return -EINVAL; in das800_ai_check_chanlist()
295 const struct das800_board *board = dev->board_ptr; in das800_ai_do_cmdtest() local
300 err |= comedi_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_EXT); in das800_ai_do_cmdtest()
301 err |= comedi_check_trigger_src(&cmd->scan_begin_src, TRIG_FOLLOW); in das800_ai_do_cmdtest()
302 err |= comedi_check_trigger_src(&cmd->convert_src, in das800_ai_do_cmdtest()
304 err |= comedi_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT); in das800_ai_do_cmdtest()
305 err |= comedi_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE); in das800_ai_do_cmdtest()
310 /* Step 2a : make sure trigger sources are unique */ in das800_ai_do_cmdtest()
312 err |= comedi_check_trigger_is_unique(cmd->start_src); in das800_ai_do_cmdtest()
313 err |= comedi_check_trigger_is_unique(cmd->convert_src); in das800_ai_do_cmdtest()
314 err |= comedi_check_trigger_is_unique(cmd->stop_src); in das800_ai_do_cmdtest()
316 /* Step 2b : and mutually compatible */ in das800_ai_do_cmdtest()
319 return 2; in das800_ai_do_cmdtest()
323 err |= comedi_check_trigger_arg_is(&cmd->start_arg, 0); in das800_ai_do_cmdtest()
325 if (cmd->convert_src == TRIG_TIMER) { in das800_ai_do_cmdtest()
326 err |= comedi_check_trigger_arg_min(&cmd->convert_arg, in das800_ai_do_cmdtest()
327 board->ai_speed); in das800_ai_do_cmdtest()
330 err |= comedi_check_trigger_arg_min(&cmd->chanlist_len, 1); in das800_ai_do_cmdtest()
331 err |= comedi_check_trigger_arg_is(&cmd->scan_end_arg, in das800_ai_do_cmdtest()
332 cmd->chanlist_len); in das800_ai_do_cmdtest()
334 if (cmd->stop_src == TRIG_COUNT) in das800_ai_do_cmdtest()
335 err |= comedi_check_trigger_arg_min(&cmd->stop_arg, 1); in das800_ai_do_cmdtest()
337 err |= comedi_check_trigger_arg_is(&cmd->stop_arg, 0); in das800_ai_do_cmdtest()
344 if (cmd->convert_src == TRIG_TIMER) { in das800_ai_do_cmdtest()
345 unsigned int arg = cmd->convert_arg; in das800_ai_do_cmdtest()
347 comedi_8254_cascade_ns_to_timer(dev->pacer, &arg, cmd->flags); in das800_ai_do_cmdtest()
348 err |= comedi_check_trigger_arg_is(&cmd->convert_arg, arg); in das800_ai_do_cmdtest()
355 if (cmd->chanlist && cmd->chanlist_len > 0) in das800_ai_do_cmdtest()
367 const struct das800_board *board = dev->board_ptr; in das800_ai_do_cmd() local
368 struct comedi_async *async = s->async; in das800_ai_do_cmd()
369 struct comedi_cmd *cmd = &async->cmd; in das800_ai_do_cmd()
370 unsigned int gain = CR_RANGE(cmd->chanlist[0]); in das800_ai_do_cmd()
371 unsigned int start_chan = CR_CHAN(cmd->chanlist[0]); in das800_ai_do_cmd()
372 unsigned int end_chan = (start_chan + cmd->chanlist_len - 1) % 8; in das800_ai_do_cmd()
379 spin_lock_irqsave(&dev->spinlock, irq_flags); in das800_ai_do_cmd()
382 spin_unlock_irqrestore(&dev->spinlock, irq_flags); in das800_ai_do_cmd()
385 if (board->resolution == 12 && gain > 0) in das800_ai_do_cmd()
388 outb(gain, dev->iobase + DAS800_GAIN); in das800_ai_do_cmd()
395 if (cmd->start_src == TRIG_EXT) in das800_ai_do_cmd()
397 if (cmd->convert_src == TRIG_TIMER) { in das800_ai_do_cmd()
399 comedi_8254_update_divisors(dev->pacer); in das800_ai_do_cmd()
400 comedi_8254_pacer_enable(dev->pacer, 1, 2, true); in das800_ai_do_cmd()
403 spin_lock_irqsave(&dev->spinlock, irq_flags); in das800_ai_do_cmd()
405 spin_unlock_irqrestore(&dev->spinlock, irq_flags); in das800_ai_do_cmd()
413 unsigned int lsb = inb(dev->iobase + DAS800_LSB); in das800_ai_get_sample()
414 unsigned int msb = inb(dev->iobase + DAS800_MSB); in das800_ai_get_sample()
422 struct das800_private *devpriv = dev->private; in das800_interrupt()
423 struct comedi_subdevice *s = dev->read_subdev; in das800_interrupt()
433 status = inb(dev->iobase + DAS800_STATUS); in das800_interrupt()
436 if (!dev->attached) in das800_interrupt()
439 async = s->async; in das800_interrupt()
440 cmd = &async->cmd; in das800_interrupt()
442 spin_lock_irqsave(&dev->spinlock, irq_flags); in das800_interrupt()
451 spin_unlock_irqrestore(&dev->spinlock, irq_flags); in das800_interrupt()
457 if (s->maxdata == 0x0fff) { in das800_interrupt()
461 /* cio-das802/16 has no fifo empty status bit */ in das800_interrupt()
463 fifo_overflow = !!(inb(dev->iobase + DAS800_GAIN) & in das800_interrupt()
469 if (s->maxdata == 0x0fff) in das800_interrupt()
470 val >>= 4; /* 12-bit sample */ in das800_interrupt()
472 val &= s->maxdata; in das800_interrupt()
475 if (cmd->stop_src == TRIG_COUNT && in das800_interrupt()
476 async->scans_done >= cmd->stop_arg) { in das800_interrupt()
477 async->events |= COMEDI_CB_EOA; in das800_interrupt()
483 spin_unlock_irqrestore(&dev->spinlock, irq_flags); in das800_interrupt()
484 async->events |= COMEDI_CB_ERROR; in das800_interrupt()
489 if (!(async->events & COMEDI_CB_CANCEL_MASK)) { in das800_interrupt()
491 * Re-enable card's interrupt. in das800_interrupt()
494 das800_ind_write(dev, CONTROL1_INTE | devpriv->do_bits, in das800_interrupt()
496 spin_unlock_irqrestore(&dev->spinlock, irq_flags); in das800_interrupt()
499 spin_unlock_irqrestore(&dev->spinlock, irq_flags); in das800_interrupt()
513 status = inb(dev->iobase + DAS800_STATUS); in das800_ai_eoc()
516 return -EBUSY; in das800_ai_eoc()
524 struct das800_private *devpriv = dev->private; in das800_ai_insn_read()
525 unsigned int chan = CR_CHAN(insn->chanspec); in das800_ai_insn_read()
526 unsigned int range = CR_RANGE(insn->chanspec); in das800_ai_insn_read()
535 spin_lock_irqsave(&dev->spinlock, irq_flags); in das800_ai_insn_read()
536 das800_ind_write(dev, chan | devpriv->do_bits, CONTROL1); in das800_ai_insn_read()
537 spin_unlock_irqrestore(&dev->spinlock, irq_flags); in das800_ai_insn_read()
540 if (s->maxdata == 0x0fff && range) in das800_ai_insn_read()
543 outb(range, dev->iobase + DAS800_GAIN); in das800_ai_insn_read()
547 for (i = 0; i < insn->n; i++) { in das800_ai_insn_read()
549 outb_p(0, dev->iobase + DAS800_MSB); in das800_ai_insn_read()
556 if (s->maxdata == 0x0fff) in das800_ai_insn_read()
557 val >>= 4; /* 12-bit sample */ in das800_ai_insn_read()
558 data[i] = val & s->maxdata; in das800_ai_insn_read()
561 return insn->n; in das800_ai_insn_read()
569 data[1] = (inb(dev->iobase + DAS800_STATUS) >> 4) & 0x7; in das800_di_insn_bits()
571 return insn->n; in das800_di_insn_bits()
579 struct das800_private *devpriv = dev->private; in das800_do_insn_bits()
583 devpriv->do_bits = s->state << 4; in das800_do_insn_bits()
585 spin_lock_irqsave(&dev->spinlock, irq_flags); in das800_do_insn_bits()
586 das800_ind_write(dev, CONTROL1_INTE | devpriv->do_bits, in das800_do_insn_bits()
588 spin_unlock_irqrestore(&dev->spinlock, irq_flags); in das800_do_insn_bits()
591 data[1] = s->state; in das800_do_insn_bits()
593 return insn->n; in das800_do_insn_bits()
598 const struct das800_board *board = dev->board_ptr; in das800_probe() local
599 int index = board ? board - das800_boards : -EINVAL; in das800_probe()
604 * The dev->board_ptr will be set by comedi_device_attach() if the in das800_probe()
605 * board name provided by the user matches a board->name in this in das800_probe()
607 * that the board is correct. in das800_probe()
609 * If the dev->board_ptr is not set, the user is trying to attach in das800_probe()
610 * an unspecified board to this driver. In this case the id_bits in das800_probe()
611 * are used to 'probe' for the correct dev->board_ptr. in das800_probe()
613 spin_lock_irqsave(&dev->spinlock, irq_flags); in das800_probe()
615 spin_unlock_irqrestore(&dev->spinlock, irq_flags); in das800_probe()
620 return board; in das800_probe()
625 return board; in das800_probe()
631 return board; in das800_probe()
635 dev_dbg(dev->class_dev, "Board model: 0x%x (unknown)\n", in das800_probe()
639 dev_dbg(dev->class_dev, "Board model (probed): %s series\n", in das800_probe()
647 const struct das800_board *board; in das800_attach() local
650 unsigned int irq = it->options[1]; in das800_attach()
656 return -ENOMEM; in das800_attach()
658 ret = comedi_request_region(dev, it->options[0], 0x8); in das800_attach()
662 board = das800_probe(dev); in das800_attach()
663 if (!board) in das800_attach()
664 return -ENODEV; in das800_attach()
665 dev->board_ptr = board; in das800_attach()
666 dev->board_name = board->name; in das800_attach()
672 dev->irq = irq; in das800_attach()
675 dev->pacer = comedi_8254_io_alloc(dev->iobase + DAS800_8254, in das800_attach()
677 if (IS_ERR(dev->pacer)) in das800_attach()
678 return PTR_ERR(dev->pacer); in das800_attach()
685 s = &dev->subdevices[0]; in das800_attach()
686 dev->read_subdev = s; in das800_attach()
687 s->type = COMEDI_SUBD_AI; in das800_attach()
688 s->subdev_flags = SDF_READABLE | SDF_GROUND; in das800_attach()
689 s->n_chan = 8; in das800_attach()
690 s->maxdata = (1 << board->resolution) - 1; in das800_attach()
691 s->range_table = board->ai_range; in das800_attach()
692 s->insn_read = das800_ai_insn_read; in das800_attach()
693 if (dev->irq) { in das800_attach()
694 s->subdev_flags |= SDF_CMD_READ; in das800_attach()
695 s->len_chanlist = 8; in das800_attach()
696 s->do_cmdtest = das800_ai_do_cmdtest; in das800_attach()
697 s->do_cmd = das800_ai_do_cmd; in das800_attach()
698 s->cancel = das800_cancel; in das800_attach()
702 s = &dev->subdevices[1]; in das800_attach()
703 s->type = COMEDI_SUBD_DI; in das800_attach()
704 s->subdev_flags = SDF_READABLE; in das800_attach()
705 s->n_chan = 3; in das800_attach()
706 s->maxdata = 1; in das800_attach()
707 s->range_table = &range_digital; in das800_attach()
708 s->insn_bits = das800_di_insn_bits; in das800_attach()
711 s = &dev->subdevices[2]; in das800_attach()
712 s->type = COMEDI_SUBD_DO; in das800_attach()
713 s->subdev_flags = SDF_WRITABLE; in das800_attach()
714 s->n_chan = 4; in das800_attach()
715 s->maxdata = 1; in das800_attach()
716 s->range_table = &range_digital; in das800_attach()
717 s->insn_bits = das800_do_insn_bits; in das800_attach()
722 spin_lock_irqsave(&dev->spinlock, irq_flags); in das800_attach()
723 das800_ind_write(dev, CONTROL1_INTE | devpriv->do_bits, CONTROL1); in das800_attach()
724 spin_unlock_irqrestore(&dev->spinlock, irq_flags); in das800_attach()
741 MODULE_DESCRIPTION("Comedi low-level driver");