Lines Matching +full:mux +full:- +full:ctrl +full:- +full:list

1 // SPDX-License-Identifier: GPL-2.0
6 * Description: Advantech PCL-818 cards, PCL-718
8 * Devices: [Advantech] PCL-818L (pcl818l), PCL-818H (pcl818h),
9 * PCL-818HD (pcl818hd), PCL-818HG (pcl818hg), PCL-818 (pcl818),
10 * PCL-718 (pcl718)
14 * Differences are only at maximal sample speed, range list and FIFO
18 * PCL-818HD and PCL-818HG support 1kword FIFO. Driver support this FIFO
37 * Options for PCL-818L:
38 * [0] - IO Base
39 * [1] - IRQ (0=disable, 2, 3, 4, 5, 6, 7)
40 * [2] - DMA (0=disable, 1, 3)
41 * [3] - 0, 10=10MHz clock for 8254
43 * [4] - 0, 5=A/D input -5V.. +5V
44 * 1, 10=A/D input -10V..+10V
45 * [5] - 0, 5=D/A output 0-5V (internal reference -5V)
46 * 1, 10=D/A output 0-10V (internal reference -10V)
49 * Options for PCL-818, PCL-818H:
50 * [0] - IO Base
51 * [1] - IRQ (0=disable, 2, 3, 4, 5, 6, 7)
52 * [2] - DMA (0=disable, 1, 3)
53 * [3] - 0, 10=10MHz clock for 8254
55 * [4] - 0, 5=D/A output 0-5V (internal reference -5V)
56 * 1, 10=D/A output 0-10V (internal reference -10V)
59 * Options for PCL-818HD, PCL-818HG:
60 * [0] - IO Base
61 * [1] - IRQ (0=disable, 2, 3, 4, 5, 6, 7)
62 * [2] - DMA/FIFO (-1=use FIFO, 0=disable both FIFO and DMA,
64 * [3] - 0, 10=10MHz clock for 8254
66 * [4] - 0, 5=D/A output 0-5V (internal reference -5V)
67 * 1, 10=D/A output 0-10V (internal reference -10V)
70 * Options for PCL-718:
71 * [0] - IO Base
72 * [1] - IRQ (0=disable, 2, 3, 4, 5, 6, 7)
73 * [2] - DMA (0=disable, 1, 3)
74 * [3] - 0, 10=10MHz clock for 8254
76 * [4] - 0=A/D Range is +/-10V
77 * 1= +/-5V
78 * 2= +/-2.5V
79 * 3= +/-1V
80 * 4= +/-0.5V
82 * 6= 0-10V
83 * 7= 0-5V
84 * 8= 0-2V
85 * 9= 0-1V
87 * [5] - 0, 5=D/A outputs 0-5V (internal reference -5V)
88 * 1, 10=D/A outputs 0-10V (internal reference -10V)
90 * [6] - 0, 60=max 60kHz A/D sampling
91 * 1,100=max 100kHz A/D sampling (PCL-718 with Option 001 installed)
290 /* MUX setting for actual AI operations */
292 unsigned int act_chanlist_len; /* how long is actual MUX list */
293 unsigned int act_chanlist_pos; /* actual position in MUX list */
303 struct pcl818_private *devpriv = dev->private; in pcl818_ai_setup_dma()
304 struct comedi_isadma *dma = devpriv->dma; in pcl818_ai_setup_dma()
305 struct comedi_isadma_desc *desc = &dma->desc[dma->cur_dma]; in pcl818_ai_setup_dma()
306 unsigned int max_samples = comedi_bytes_to_samples(s, desc->maxsize); in pcl818_ai_setup_dma()
309 comedi_isadma_disable(dma->chan); in pcl818_ai_setup_dma()
317 nsamples -= unread_samples; in pcl818_ai_setup_dma()
318 desc->size = comedi_samples_to_bytes(s, nsamples); in pcl818_ai_setup_dma()
327 outb(chan, dev->iobase + PCL818_MUX_REG); in pcl818_ai_set_chan_range()
328 outb(range, dev->iobase + PCL818_RANGE_REG); in pcl818_ai_set_chan_range()
336 dev->iobase + PCL818_MUX_REG); in pcl818_ai_set_chan_scan()
343 struct pcl818_private *devpriv = dev->private; in pcl818_ai_setup_chanlist()
349 devpriv->act_chanlist_len = seglen; in pcl818_ai_setup_chanlist()
350 devpriv->act_chanlist_pos = 0; in pcl818_ai_setup_chanlist()
352 /* store range list to card */ in pcl818_ai_setup_chanlist()
357 devpriv->act_chanlist[i] = last_chan; in pcl818_ai_setup_chanlist()
370 outb(0, dev->iobase + PCL818_STATUS_REG); in pcl818_ai_clear_eoc()
376 outb(0, dev->iobase + PCL818_AI_LSB_REG); in pcl818_ai_soft_trig()
385 val = inb(dev->iobase + PCL818_FI_DATALO); in pcl818_ai_get_fifo_sample()
386 val |= (inb(dev->iobase + PCL818_FI_DATAHI) << 8); in pcl818_ai_get_fifo_sample()
391 return (val >> 4) & s->maxdata; in pcl818_ai_get_fifo_sample()
400 val = inb(dev->iobase + PCL818_AI_MSB_REG) << 8; in pcl818_ai_get_sample()
401 val |= inb(dev->iobase + PCL818_AI_LSB_REG); in pcl818_ai_get_sample()
406 return (val >> 4) & s->maxdata; in pcl818_ai_get_sample()
416 status = inb(dev->iobase + PCL818_STATUS_REG); in pcl818_ai_eoc()
419 return -EBUSY; in pcl818_ai_eoc()
426 struct pcl818_private *devpriv = dev->private; in pcl818_ai_write_sample()
427 struct comedi_cmd *cmd = &s->async->cmd; in pcl818_ai_write_sample()
430 expected_chan = devpriv->act_chanlist[devpriv->act_chanlist_pos]; in pcl818_ai_write_sample()
432 dev_dbg(dev->class_dev, in pcl818_ai_write_sample()
433 "A/D mode1/3 %s - channel dropout %d!=%d !\n", in pcl818_ai_write_sample()
434 (devpriv->dma) ? "DMA" : in pcl818_ai_write_sample()
435 (devpriv->usefifo) ? "FIFO" : "IRQ", in pcl818_ai_write_sample()
437 s->async->events |= COMEDI_CB_ERROR; in pcl818_ai_write_sample()
443 devpriv->act_chanlist_pos++; in pcl818_ai_write_sample()
444 if (devpriv->act_chanlist_pos >= devpriv->act_chanlist_len) in pcl818_ai_write_sample()
445 devpriv->act_chanlist_pos = 0; in pcl818_ai_write_sample()
447 if (cmd->stop_src == TRIG_COUNT && in pcl818_ai_write_sample()
448 s->async->scans_done >= cmd->stop_arg) { in pcl818_ai_write_sample()
449 s->async->events |= COMEDI_CB_EOA; in pcl818_ai_write_sample()
463 dev_err(dev->class_dev, "A/D mode1/3 IRQ without DRDY!\n"); in pcl818_handle_eoc()
464 s->async->events |= COMEDI_CB_ERROR; in pcl818_handle_eoc()
475 struct pcl818_private *devpriv = dev->private; in pcl818_handle_dma()
476 struct comedi_isadma *dma = devpriv->dma; in pcl818_handle_dma()
477 struct comedi_isadma_desc *desc = &dma->desc[dma->cur_dma]; in pcl818_handle_dma()
478 unsigned short *ptr = desc->virt_addr; in pcl818_handle_dma()
479 unsigned int nsamples = comedi_bytes_to_samples(s, desc->size); in pcl818_handle_dma()
485 dma->cur_dma = 1 - dma->cur_dma; in pcl818_handle_dma()
491 val = (val >> 4) & s->maxdata; in pcl818_handle_dma()
505 status = inb(dev->iobase + PCL818_FI_STATUS); in pcl818_handle_fifo()
508 dev_err(dev->class_dev, "A/D mode1/3 FIFO overflow!\n"); in pcl818_handle_fifo()
509 s->async->events |= COMEDI_CB_ERROR; in pcl818_handle_fifo()
514 dev_err(dev->class_dev, in pcl818_handle_fifo()
516 s->async->events |= COMEDI_CB_ERROR; in pcl818_handle_fifo()
535 struct pcl818_private *devpriv = dev->private; in pcl818_interrupt()
536 struct comedi_subdevice *s = dev->read_subdev; in pcl818_interrupt()
537 struct comedi_cmd *cmd = &s->async->cmd; in pcl818_interrupt()
539 if (!dev->attached || !devpriv->ai_cmd_running) { in pcl818_interrupt()
544 if (devpriv->ai_cmd_canceled) { in pcl818_interrupt()
551 s->async->scans_done = cmd->stop_arg; in pcl818_interrupt()
552 s->cancel(dev, s); in pcl818_interrupt()
556 if (devpriv->dma) in pcl818_interrupt()
558 else if (devpriv->usefifo) in pcl818_interrupt()
578 dev_err(dev->class_dev, "range/channel list is empty!\n"); in check_channel_list()
592 (CR_CHAN(chansegment[i - 1]) + 1) % s->n_chan; in check_channel_list()
594 /* channel list isn't continuous :-( */ in check_channel_list()
595 dev_dbg(dev->class_dev, in check_channel_list()
596 "channel list must be continuous! chanlist[%i]=%d but must be %d or %d!\n", in check_channel_list()
601 /* well, this is next correct channel in list */ in check_channel_list()
608 dev_dbg(dev->class_dev, in check_channel_list()
616 return 0; /* chan/gain list is strange */ in check_channel_list()
635 const struct pcl818_board *board = dev->board_ptr; in ai_cmdtest()
640 err |= comedi_check_trigger_src(&cmd->start_src, TRIG_NOW); in ai_cmdtest()
641 err |= comedi_check_trigger_src(&cmd->scan_begin_src, TRIG_FOLLOW); in ai_cmdtest()
642 err |= comedi_check_trigger_src(&cmd->convert_src, in ai_cmdtest()
644 err |= comedi_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT); in ai_cmdtest()
645 err |= comedi_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE); in ai_cmdtest()
652 err |= comedi_check_trigger_is_unique(cmd->convert_src); in ai_cmdtest()
653 err |= comedi_check_trigger_is_unique(cmd->stop_src); in ai_cmdtest()
662 err |= comedi_check_trigger_arg_is(&cmd->start_arg, 0); in ai_cmdtest()
663 err |= comedi_check_trigger_arg_is(&cmd->scan_begin_arg, 0); in ai_cmdtest()
665 if (cmd->convert_src == TRIG_TIMER) { in ai_cmdtest()
666 err |= comedi_check_trigger_arg_min(&cmd->convert_arg, in ai_cmdtest()
667 board->ns_min); in ai_cmdtest()
669 err |= comedi_check_trigger_arg_is(&cmd->convert_arg, 0); in ai_cmdtest()
672 err |= comedi_check_trigger_arg_is(&cmd->scan_end_arg, in ai_cmdtest()
673 cmd->chanlist_len); in ai_cmdtest()
675 if (cmd->stop_src == TRIG_COUNT) in ai_cmdtest()
676 err |= comedi_check_trigger_arg_min(&cmd->stop_arg, 1); in ai_cmdtest()
678 err |= comedi_check_trigger_arg_is(&cmd->stop_arg, 0); in ai_cmdtest()
685 if (cmd->convert_src == TRIG_TIMER) { in ai_cmdtest()
686 unsigned int arg = cmd->convert_arg; in ai_cmdtest()
688 comedi_8254_cascade_ns_to_timer(dev->pacer, &arg, cmd->flags); in ai_cmdtest()
689 err |= comedi_check_trigger_arg_is(&cmd->convert_arg, arg); in ai_cmdtest()
697 if (cmd->chanlist) { in ai_cmdtest()
698 if (!check_channel_list(dev, s, cmd->chanlist, in ai_cmdtest()
699 cmd->chanlist_len)) in ai_cmdtest()
700 return 5; /* incorrect channels list */ in ai_cmdtest()
709 struct pcl818_private *devpriv = dev->private; in pcl818_ai_cmd()
710 struct comedi_isadma *dma = devpriv->dma; in pcl818_ai_cmd()
711 struct comedi_cmd *cmd = &s->async->cmd; in pcl818_ai_cmd()
712 unsigned int ctrl = 0; in pcl818_ai_cmd() local
715 if (devpriv->ai_cmd_running) in pcl818_ai_cmd()
716 return -EBUSY; in pcl818_ai_cmd()
718 seglen = check_channel_list(dev, s, cmd->chanlist, cmd->chanlist_len); in pcl818_ai_cmd()
720 return -EINVAL; in pcl818_ai_cmd()
721 pcl818_ai_setup_chanlist(dev, cmd->chanlist, seglen); in pcl818_ai_cmd()
723 devpriv->ai_cmd_running = 1; in pcl818_ai_cmd()
724 devpriv->ai_cmd_canceled = 0; in pcl818_ai_cmd()
725 devpriv->act_chanlist_pos = 0; in pcl818_ai_cmd()
727 if (cmd->convert_src == TRIG_TIMER) in pcl818_ai_cmd()
728 ctrl |= PCL818_CTRL_PACER_TRIG; in pcl818_ai_cmd()
730 ctrl |= PCL818_CTRL_EXT_TRIG; in pcl818_ai_cmd()
732 outb(0, dev->iobase + PCL818_CNTENABLE_REG); in pcl818_ai_cmd()
736 dma->cur_dma = 0; in pcl818_ai_cmd()
739 ctrl |= PCL818_CTRL_INTE | PCL818_CTRL_IRQ(dev->irq) | in pcl818_ai_cmd()
741 } else if (devpriv->usefifo) { in pcl818_ai_cmd()
743 outb(1, dev->iobase + PCL818_FI_ENABLE); in pcl818_ai_cmd()
745 ctrl |= PCL818_CTRL_INTE | PCL818_CTRL_IRQ(dev->irq); in pcl818_ai_cmd()
747 outb(ctrl, dev->iobase + PCL818_CTRL_REG); in pcl818_ai_cmd()
749 if (cmd->convert_src == TRIG_TIMER) { in pcl818_ai_cmd()
750 comedi_8254_update_divisors(dev->pacer); in pcl818_ai_cmd()
751 comedi_8254_pacer_enable(dev->pacer, 1, 2, true); in pcl818_ai_cmd()
760 struct pcl818_private *devpriv = dev->private; in pcl818_ai_cancel()
761 struct comedi_isadma *dma = devpriv->dma; in pcl818_ai_cancel()
762 struct comedi_cmd *cmd = &s->async->cmd; in pcl818_ai_cancel()
764 if (!devpriv->ai_cmd_running) in pcl818_ai_cancel()
768 if (cmd->stop_src == TRIG_NONE || in pcl818_ai_cancel()
769 (cmd->stop_src == TRIG_COUNT && in pcl818_ai_cancel()
770 s->async->scans_done < cmd->stop_arg)) { in pcl818_ai_cancel()
771 if (!devpriv->ai_cmd_canceled) { in pcl818_ai_cancel()
776 devpriv->ai_cmd_canceled = 1; in pcl818_ai_cancel()
780 comedi_isadma_disable(dma->chan); in pcl818_ai_cancel()
783 outb(PCL818_CTRL_DISABLE_TRIG, dev->iobase + PCL818_CTRL_REG); in pcl818_ai_cancel()
784 comedi_8254_pacer_enable(dev->pacer, 1, 2, false); in pcl818_ai_cancel()
787 if (devpriv->usefifo) { /* FIFO shutdown */ in pcl818_ai_cancel()
788 outb(0, dev->iobase + PCL818_FI_INTCLR); in pcl818_ai_cancel()
789 outb(0, dev->iobase + PCL818_FI_FLUSH); in pcl818_ai_cancel()
790 outb(0, dev->iobase + PCL818_FI_ENABLE); in pcl818_ai_cancel()
792 devpriv->ai_cmd_running = 0; in pcl818_ai_cancel()
793 devpriv->ai_cmd_canceled = 0; in pcl818_ai_cancel()
803 unsigned int chan = CR_CHAN(insn->chanspec); in pcl818_ai_insn_read()
804 unsigned int range = CR_RANGE(insn->chanspec); in pcl818_ai_insn_read()
808 outb(PCL818_CTRL_SOFT_TRIG, dev->iobase + PCL818_CTRL_REG); in pcl818_ai_insn_read()
813 for (i = 0; i < insn->n; i++) { in pcl818_ai_insn_read()
825 return ret ? ret : insn->n; in pcl818_ai_insn_read()
833 unsigned int chan = CR_CHAN(insn->chanspec); in pcl818_ao_insn_write()
834 unsigned int val = s->readback[chan]; in pcl818_ao_insn_write()
837 for (i = 0; i < insn->n; i++) { in pcl818_ao_insn_write()
840 dev->iobase + PCL818_AO_LSB_REG(chan)); in pcl818_ao_insn_write()
842 dev->iobase + PCL818_AO_MSB_REG(chan)); in pcl818_ao_insn_write()
844 s->readback[chan] = val; in pcl818_ao_insn_write()
846 return insn->n; in pcl818_ao_insn_write()
854 data[1] = inb(dev->iobase + PCL818_DO_DI_LSB_REG) | in pcl818_di_insn_bits()
855 (inb(dev->iobase + PCL818_DO_DI_MSB_REG) << 8); in pcl818_di_insn_bits()
857 return insn->n; in pcl818_di_insn_bits()
866 outb(s->state & 0xff, dev->iobase + PCL818_DO_DI_LSB_REG); in pcl818_do_insn_bits()
867 outb((s->state >> 8), dev->iobase + PCL818_DO_DI_MSB_REG); in pcl818_do_insn_bits()
870 data[1] = s->state; in pcl818_do_insn_bits()
872 return insn->n; in pcl818_do_insn_bits()
877 const struct pcl818_board *board = dev->board_ptr; in pcl818_reset()
881 if (board->has_fifo) { in pcl818_reset()
882 outb(0, dev->iobase + PCL818_FI_INTCLR); in pcl818_reset()
883 outb(0, dev->iobase + PCL818_FI_FLUSH); in pcl818_reset()
884 outb(0, dev->iobase + PCL818_FI_ENABLE); in pcl818_reset()
888 outb(PCL818_CTRL_DISABLE_TRIG, dev->iobase + PCL818_CTRL_REG); in pcl818_reset()
894 outb(0, dev->iobase + PCL818_CNTENABLE_REG); in pcl818_reset()
897 for (chan = 0; chan < board->n_aochan; chan++) { in pcl818_reset()
898 outb(0, dev->iobase + PCL818_AO_LSB_REG(chan)); in pcl818_reset()
899 outb(0, dev->iobase + PCL818_AO_MSB_REG(chan)); in pcl818_reset()
903 outb(0, dev->iobase + PCL818_DO_DI_MSB_REG); in pcl818_reset()
904 outb(0, dev->iobase + PCL818_DO_DI_LSB_REG); in pcl818_reset()
911 const struct pcl818_board *board = dev->board_ptr; in pcl818_set_ai_range_table()
914 s->range_table = board->ai_range_type; in pcl818_set_ai_range_table()
917 if (board->is_818) { in pcl818_set_ai_range_table()
918 if (it->options[4] == 1 || it->options[4] == 10) { in pcl818_set_ai_range_table()
919 /* secondary range list jumper selectable */ in pcl818_set_ai_range_table()
920 s->range_table = &range_pcl818l_h_ai; in pcl818_set_ai_range_table()
923 switch (it->options[4]) { in pcl818_set_ai_range_table()
925 s->range_table = &range_bipolar10; in pcl818_set_ai_range_table()
928 s->range_table = &range_bipolar5; in pcl818_set_ai_range_table()
931 s->range_table = &range_bipolar2_5; in pcl818_set_ai_range_table()
934 s->range_table = &range718_bipolar1; in pcl818_set_ai_range_table()
937 s->range_table = &range718_bipolar0_5; in pcl818_set_ai_range_table()
940 s->range_table = &range_unipolar10; in pcl818_set_ai_range_table()
943 s->range_table = &range_unipolar5; in pcl818_set_ai_range_table()
946 s->range_table = &range718_unipolar2; in pcl818_set_ai_range_table()
949 s->range_table = &range718_unipolar1; in pcl818_set_ai_range_table()
952 s->range_table = &range_unknown; in pcl818_set_ai_range_table()
960 struct pcl818_private *devpriv = dev->private; in pcl818_alloc_dma()
967 devpriv->dma = comedi_isadma_alloc(dev, 2, dma_chan, dma_chan, in pcl818_alloc_dma()
973 struct pcl818_private *devpriv = dev->private; in pcl818_free_dma()
976 comedi_isadma_free(devpriv->dma); in pcl818_free_dma()
981 const struct pcl818_board *board = dev->board_ptr; in pcl818_attach()
989 return -ENOMEM; in pcl818_attach()
991 ret = comedi_request_region(dev, it->options[0], in pcl818_attach()
992 board->has_fifo ? 0x20 : 0x10); in pcl818_attach()
996 /* we can use IRQ 2-7 for async command support */ in pcl818_attach()
997 if (it->options[1] >= 2 && it->options[1] <= 7) { in pcl818_attach()
998 ret = request_irq(it->options[1], pcl818_interrupt, 0, in pcl818_attach()
999 dev->board_name, dev); in pcl818_attach()
1001 dev->irq = it->options[1]; in pcl818_attach()
1005 if (dev->irq && board->has_fifo && it->options[2] == -1) in pcl818_attach()
1006 devpriv->usefifo = 1; in pcl818_attach()
1009 if (dev->irq && board->has_dma) in pcl818_attach()
1010 pcl818_alloc_dma(dev, it->options[2]); in pcl818_attach()
1013 if ((it->options[3] == 0) || (it->options[3] == 10)) in pcl818_attach()
1018 dev->pacer = comedi_8254_io_alloc(dev->iobase + PCL818_TIMER_BASE, in pcl818_attach()
1020 if (IS_ERR(dev->pacer)) in pcl818_attach()
1021 return PTR_ERR(dev->pacer); in pcl818_attach()
1024 devpriv->ns_min = board->ns_min; in pcl818_attach()
1025 if (!board->is_818) { in pcl818_attach()
1027 if ((it->options[6] == 1) || (it->options[6] == 100)) in pcl818_attach()
1028 devpriv->ns_min = 10000; in pcl818_attach()
1035 s = &dev->subdevices[0]; in pcl818_attach()
1036 s->type = COMEDI_SUBD_AI; in pcl818_attach()
1037 s->subdev_flags = SDF_READABLE; in pcl818_attach()
1038 if (check_single_ended(dev->iobase)) { in pcl818_attach()
1039 s->n_chan = 16; in pcl818_attach()
1040 s->subdev_flags |= SDF_COMMON | SDF_GROUND; in pcl818_attach()
1042 s->n_chan = 8; in pcl818_attach()
1043 s->subdev_flags |= SDF_DIFF; in pcl818_attach()
1045 s->maxdata = 0x0fff; in pcl818_attach()
1049 s->insn_read = pcl818_ai_insn_read; in pcl818_attach()
1050 if (dev->irq) { in pcl818_attach()
1051 dev->read_subdev = s; in pcl818_attach()
1052 s->subdev_flags |= SDF_CMD_READ; in pcl818_attach()
1053 s->len_chanlist = s->n_chan; in pcl818_attach()
1054 s->do_cmdtest = ai_cmdtest; in pcl818_attach()
1055 s->do_cmd = pcl818_ai_cmd; in pcl818_attach()
1056 s->cancel = pcl818_ai_cancel; in pcl818_attach()
1060 s = &dev->subdevices[1]; in pcl818_attach()
1061 if (board->n_aochan) { in pcl818_attach()
1062 s->type = COMEDI_SUBD_AO; in pcl818_attach()
1063 s->subdev_flags = SDF_WRITABLE | SDF_GROUND; in pcl818_attach()
1064 s->n_chan = board->n_aochan; in pcl818_attach()
1065 s->maxdata = 0x0fff; in pcl818_attach()
1066 s->range_table = &range_unipolar5; in pcl818_attach()
1067 if (board->is_818) { in pcl818_attach()
1068 if ((it->options[4] == 1) || (it->options[4] == 10)) in pcl818_attach()
1069 s->range_table = &range_unipolar10; in pcl818_attach()
1070 if (it->options[4] == 2) in pcl818_attach()
1071 s->range_table = &range_unknown; in pcl818_attach()
1073 if ((it->options[5] == 1) || (it->options[5] == 10)) in pcl818_attach()
1074 s->range_table = &range_unipolar10; in pcl818_attach()
1075 if (it->options[5] == 2) in pcl818_attach()
1076 s->range_table = &range_unknown; in pcl818_attach()
1078 s->insn_write = pcl818_ao_insn_write; in pcl818_attach()
1084 s->type = COMEDI_SUBD_UNUSED; in pcl818_attach()
1088 s = &dev->subdevices[2]; in pcl818_attach()
1089 s->type = COMEDI_SUBD_DI; in pcl818_attach()
1090 s->subdev_flags = SDF_READABLE; in pcl818_attach()
1091 s->n_chan = 16; in pcl818_attach()
1092 s->maxdata = 1; in pcl818_attach()
1093 s->range_table = &range_digital; in pcl818_attach()
1094 s->insn_bits = pcl818_di_insn_bits; in pcl818_attach()
1097 s = &dev->subdevices[3]; in pcl818_attach()
1098 s->type = COMEDI_SUBD_DO; in pcl818_attach()
1099 s->subdev_flags = SDF_WRITABLE; in pcl818_attach()
1100 s->n_chan = 16; in pcl818_attach()
1101 s->maxdata = 1; in pcl818_attach()
1102 s->range_table = &range_digital; in pcl818_attach()
1103 s->insn_bits = pcl818_do_insn_bits; in pcl818_attach()
1112 struct pcl818_private *devpriv = dev->private; in pcl818_detach()
1115 pcl818_ai_cancel(dev, dev->read_subdev); in pcl818_detach()
1134 MODULE_DESCRIPTION("Comedi low-level driver");