2 comedi/drivers/me4000.c
3 Source code for the Meilhaus ME-4000 board family.
5 COMEDI - Linux Control and Measurement Device Interface
6 Copyright (C) 2000 David A. Schleef <ds@schleef.org>
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 Description: Meilhaus ME-4000 series boards
26 Devices: [Meilhaus] ME-4650 (me4000), ME-4670i, ME-4680, ME-4680i, ME-4680is
27 Author: gg (Guenter Gebhardt <g.gebhardt@meilhaus.com>)
28 Updated: Mon, 18 Mar 2002 15:34:01 -0800
29 Status: broken (no support for loading firmware)
38 Configuration Options:
40 [0] - PCI bus number (optional)
41 [1] - PCI slot number (optional)
43 If bus/slot is not specified, the first available PCI
46 The firmware required by these boards is available in the
47 comedi_nonfree_firmware tarball available from
48 http://www.comedi.org. However, the driver's support for
49 loading the firmware through comedi_config is currently
54 #include <linux/interrupt.h>
55 #include "../comedidev.h"
57 #include <linux/delay.h>
58 #include <linux/list.h>
59 #include <linux/spinlock.h>
63 /* file removed due to GPL incompatibility */
64 #include "me4000_fw.h"
67 #define PCI_VENDOR_ID_MEILHAUS 0x1402
69 #define PCI_DEVICE_ID_MEILHAUS_ME4650 0x4650
70 #define PCI_DEVICE_ID_MEILHAUS_ME4660 0x4660
71 #define PCI_DEVICE_ID_MEILHAUS_ME4660I 0x4661
72 #define PCI_DEVICE_ID_MEILHAUS_ME4660S 0x4662
73 #define PCI_DEVICE_ID_MEILHAUS_ME4660IS 0x4663
74 #define PCI_DEVICE_ID_MEILHAUS_ME4670 0x4670
75 #define PCI_DEVICE_ID_MEILHAUS_ME4670I 0x4671
76 #define PCI_DEVICE_ID_MEILHAUS_ME4670S 0x4672
77 #define PCI_DEVICE_ID_MEILHAUS_ME4670IS 0x4673
78 #define PCI_DEVICE_ID_MEILHAUS_ME4680 0x4680
79 #define PCI_DEVICE_ID_MEILHAUS_ME4680I 0x4681
80 #define PCI_DEVICE_ID_MEILHAUS_ME4680S 0x4682
81 #define PCI_DEVICE_ID_MEILHAUS_ME4680IS 0x4683
85 unsigned short device_id;
96 static const struct me4000_board me4000_boards[] = {
99 .device_id = PCI_DEVICE_ID_MEILHAUS_ME4650,
104 .device_id = PCI_DEVICE_ID_MEILHAUS_ME4660,
111 .device_id = PCI_DEVICE_ID_MEILHAUS_ME4660I,
118 .device_id = PCI_DEVICE_ID_MEILHAUS_ME4660S,
126 .device_id = PCI_DEVICE_ID_MEILHAUS_ME4660IS,
134 .device_id = PCI_DEVICE_ID_MEILHAUS_ME4670,
143 .device_id = PCI_DEVICE_ID_MEILHAUS_ME4670I,
152 .device_id = PCI_DEVICE_ID_MEILHAUS_ME4670S,
162 .device_id = PCI_DEVICE_ID_MEILHAUS_ME4670IS,
172 .device_id = PCI_DEVICE_ID_MEILHAUS_ME4680,
182 .device_id = PCI_DEVICE_ID_MEILHAUS_ME4680I,
192 .device_id = PCI_DEVICE_ID_MEILHAUS_ME4680S,
203 .device_id = PCI_DEVICE_ID_MEILHAUS_ME4680IS,
215 static const struct comedi_lrange me4000_ai_range = {
225 #define FIRMWARE_NOT_AVAILABLE 1
226 #if FIRMWARE_NOT_AVAILABLE
227 extern unsigned char *xilinx_firm;
230 static int xilinx_download(struct comedi_device *dev)
232 struct me4000_info *info = dev->private;
234 wait_queue_head_t queue;
238 init_waitqueue_head(&queue);
241 * Set PLX local interrupt 2 polarity to high.
242 * Interrupt is thrown by init pin of xilinx.
244 outl(0x10, info->plx_regbase + PLX_INTCSR);
246 /* Set /CS and /WRITE of the Xilinx */
247 value = inl(info->plx_regbase + PLX_ICR);
249 outl(value, info->plx_regbase + PLX_ICR);
251 /* Init Xilinx with CS1 */
252 inb(info->program_regbase + 0xC8);
254 /* Wait until /INIT pin is set */
256 if (!(inl(info->plx_regbase + PLX_INTCSR) & 0x20)) {
258 "comedi%d: me4000: xilinx_download(): "
259 "Can't init Xilinx\n", dev->minor);
263 /* Reset /CS and /WRITE of the Xilinx */
264 value = inl(info->plx_regbase + PLX_ICR);
266 outl(value, info->plx_regbase + PLX_ICR);
267 if (FIRMWARE_NOT_AVAILABLE) {
268 comedi_error(dev, "xilinx firmware unavailable "
269 "due to licensing, aborting");
272 /* Download Xilinx firmware */
273 size = (xilinx_firm[0] << 24) + (xilinx_firm[1] << 16) +
274 (xilinx_firm[2] << 8) + xilinx_firm[3];
277 for (idx = 0; idx < size; idx++) {
278 outb(xilinx_firm[16 + idx], info->program_regbase);
281 /* Check if BUSY flag is low */
282 if (inl(info->plx_regbase + PLX_ICR) & 0x20) {
284 "comedi%d: me4000: xilinx_download(): "
285 "Xilinx is still busy (idx = %d)\n",
292 /* If done flag is high download was successful */
293 if (inl(info->plx_regbase + PLX_ICR) & 0x4) {
296 "comedi%d: me4000: xilinx_download(): "
297 "DONE flag is not set\n", dev->minor);
299 "comedi%d: me4000: xilinx_download(): "
300 "Download not successful\n", dev->minor);
304 /* Set /CS and /WRITE */
305 value = inl(info->plx_regbase + PLX_ICR);
307 outl(value, info->plx_regbase + PLX_ICR);
312 static int reset_board(struct comedi_device *dev)
314 struct me4000_info *info = dev->private;
318 /* Make a hardware reset */
319 val = inl(info->plx_regbase + PLX_ICR);
321 outl(val, info->plx_regbase + PLX_ICR);
323 outl(val , info->plx_regbase + PLX_ICR);
325 /* 0x8000 to the DACs means an output voltage of 0V */
326 for (chan = 0; chan < 4; chan++)
327 outl(0x8000, dev->iobase + ME4000_AO_SINGLE_REG(chan));
329 /* Set both stop bits in the analog input control register */
330 outl(ME4000_AI_CTRL_BIT_IMMEDIATE_STOP | ME4000_AI_CTRL_BIT_STOP,
331 dev->iobase + ME4000_AI_CTRL_REG);
333 /* Set both stop bits in the analog output control register */
334 val = ME4000_AO_CTRL_BIT_IMMEDIATE_STOP | ME4000_AO_CTRL_BIT_STOP;
335 for (chan = 0; chan < 4; chan++)
336 outl(val, dev->iobase + ME4000_AO_CTRL_REG(chan));
338 /* Enable interrupts on the PLX */
339 outl(0x43, info->plx_regbase + PLX_INTCSR);
341 /* Set the adustment register for AO demux */
342 outl(ME4000_AO_DEMUX_ADJUST_VALUE,
343 dev->iobase + ME4000_AO_DEMUX_ADJUST_REG);
346 * Set digital I/O direction for port 0
347 * to output on isolated versions
349 if (!(inl(dev->iobase + ME4000_DIO_DIR_REG) & 0x1))
350 outl(0x1, dev->iobase + ME4000_DIO_CTRL_REG);
355 /*=============================================================================
357 ===========================================================================*/
359 static int me4000_ai_insn_read(struct comedi_device *dev,
360 struct comedi_subdevice *subdevice,
361 struct comedi_insn *insn, unsigned int *data)
363 const struct me4000_board *thisboard = comedi_board(dev);
364 int chan = CR_CHAN(insn->chanspec);
365 int rang = CR_RANGE(insn->chanspec);
366 int aref = CR_AREF(insn->chanspec);
368 unsigned long entry = 0;
374 } else if (insn->n > 1) {
376 "comedi%d: me4000: me4000_ai_insn_read(): "
377 "Invalid instruction length %d\n", dev->minor, insn->n);
383 entry |= ME4000_AI_LIST_RANGE_UNIPOLAR_2_5;
386 entry |= ME4000_AI_LIST_RANGE_UNIPOLAR_10;
389 entry |= ME4000_AI_LIST_RANGE_BIPOLAR_2_5;
392 entry |= ME4000_AI_LIST_RANGE_BIPOLAR_10;
396 "comedi%d: me4000: me4000_ai_insn_read(): "
397 "Invalid range specified\n", dev->minor);
404 if (chan >= thisboard->ai_nchan) {
406 "comedi%d: me4000: me4000_ai_insn_read(): "
407 "Analog input is not available\n", dev->minor);
410 entry |= ME4000_AI_LIST_INPUT_SINGLE_ENDED | chan;
414 if (rang == 0 || rang == 1) {
416 "comedi%d: me4000: me4000_ai_insn_read(): "
417 "Range must be bipolar when aref = diff\n",
422 if (chan >= thisboard->ai_diff_nchan) {
424 "comedi%d: me4000: me4000_ai_insn_read(): "
425 "Analog input is not available\n", dev->minor);
428 entry |= ME4000_AI_LIST_INPUT_DIFFERENTIAL | chan;
432 "comedi%d: me4000: me4000_ai_insn_read(): "
433 "Invalid aref specified\n", dev->minor);
437 entry |= ME4000_AI_LIST_LAST_ENTRY;
439 /* Clear channel list, data fifo and both stop bits */
440 tmp = inl(dev->iobase + ME4000_AI_CTRL_REG);
441 tmp &= ~(ME4000_AI_CTRL_BIT_CHANNEL_FIFO |
442 ME4000_AI_CTRL_BIT_DATA_FIFO |
443 ME4000_AI_CTRL_BIT_STOP | ME4000_AI_CTRL_BIT_IMMEDIATE_STOP);
444 outl(tmp, dev->iobase + ME4000_AI_CTRL_REG);
446 /* Set the acquisition mode to single */
447 tmp &= ~(ME4000_AI_CTRL_BIT_MODE_0 | ME4000_AI_CTRL_BIT_MODE_1 |
448 ME4000_AI_CTRL_BIT_MODE_2);
449 outl(tmp, dev->iobase + ME4000_AI_CTRL_REG);
451 /* Enable channel list and data fifo */
452 tmp |= ME4000_AI_CTRL_BIT_CHANNEL_FIFO | ME4000_AI_CTRL_BIT_DATA_FIFO;
453 outl(tmp, dev->iobase + ME4000_AI_CTRL_REG);
455 /* Generate channel list entry */
456 outl(entry, dev->iobase + ME4000_AI_CHANNEL_LIST_REG);
458 /* Set the timer to maximum sample rate */
459 outl(ME4000_AI_MIN_TICKS, dev->iobase + ME4000_AI_CHAN_TIMER_REG);
460 outl(ME4000_AI_MIN_TICKS, dev->iobase + ME4000_AI_CHAN_PRE_TIMER_REG);
462 /* Start conversion by dummy read */
463 inl(dev->iobase + ME4000_AI_START_REG);
465 /* Wait until ready */
467 if (!(inl(dev->iobase + ME4000_AI_STATUS_REG) &
468 ME4000_AI_STATUS_BIT_EF_DATA)) {
470 "comedi%d: me4000: me4000_ai_insn_read(): "
471 "Value not available after wait\n", dev->minor);
475 /* Read value from data fifo */
476 lval = inl(dev->iobase + ME4000_AI_DATA_REG) & 0xFFFF;
477 data[0] = lval ^ 0x8000;
482 static int me4000_ai_cancel(struct comedi_device *dev,
483 struct comedi_subdevice *s)
487 /* Stop any running conversion */
488 tmp = inl(dev->iobase + ME4000_AI_CTRL_REG);
489 tmp &= ~(ME4000_AI_CTRL_BIT_STOP | ME4000_AI_CTRL_BIT_IMMEDIATE_STOP);
490 outl(tmp, dev->iobase + ME4000_AI_CTRL_REG);
492 /* Clear the control register */
493 outl(0x0, dev->iobase + ME4000_AI_CTRL_REG);
498 static int ai_check_chanlist(struct comedi_device *dev,
499 struct comedi_subdevice *s, struct comedi_cmd *cmd)
501 const struct me4000_board *thisboard = comedi_board(dev);
505 /* Check whether a channel list is available */
506 if (!cmd->chanlist_len) {
508 "comedi%d: me4000: ai_check_chanlist(): "
509 "No channel list available\n", dev->minor);
513 /* Check the channel list size */
514 if (cmd->chanlist_len > ME4000_AI_CHANNEL_LIST_COUNT) {
516 "comedi%d: me4000: ai_check_chanlist(): "
517 "Channel list is to large\n", dev->minor);
521 /* Check the pointer */
522 if (!cmd->chanlist) {
524 "comedi%d: me4000: ai_check_chanlist(): "
525 "NULL pointer to channel list\n", dev->minor);
529 /* Check whether aref is equal for all entries */
530 aref = CR_AREF(cmd->chanlist[0]);
531 for (i = 0; i < cmd->chanlist_len; i++) {
532 if (CR_AREF(cmd->chanlist[i]) != aref) {
534 "comedi%d: me4000: ai_check_chanlist(): "
535 "Mode is not equal for all entries\n",
541 /* Check whether channels are available for this ending */
542 if (aref == SDF_DIFF) {
543 for (i = 0; i < cmd->chanlist_len; i++) {
544 if (CR_CHAN(cmd->chanlist[i]) >=
545 thisboard->ai_diff_nchan) {
547 "comedi%d: me4000: ai_check_chanlist():"
548 " Channel number to high\n", dev->minor);
553 for (i = 0; i < cmd->chanlist_len; i++) {
554 if (CR_CHAN(cmd->chanlist[i]) >= thisboard->ai_nchan) {
556 "comedi%d: me4000: ai_check_chanlist(): "
557 "Channel number to high\n", dev->minor);
563 /* Check if bipolar is set for all entries when in differential mode */
564 if (aref == SDF_DIFF) {
565 for (i = 0; i < cmd->chanlist_len; i++) {
566 if (CR_RANGE(cmd->chanlist[i]) != 1 &&
567 CR_RANGE(cmd->chanlist[i]) != 2) {
569 "comedi%d: me4000: ai_check_chanlist(): "
570 "Bipolar is not selected in "
571 "differential mode\n",
581 static int ai_round_cmd_args(struct comedi_device *dev,
582 struct comedi_subdevice *s,
583 struct comedi_cmd *cmd,
584 unsigned int *init_ticks,
585 unsigned int *scan_ticks, unsigned int *chan_ticks)
594 if (cmd->start_arg) {
595 *init_ticks = (cmd->start_arg * 33) / 1000;
596 rest = (cmd->start_arg * 33) % 1000;
598 if ((cmd->flags & TRIG_ROUND_MASK) == TRIG_ROUND_NEAREST) {
601 } else if ((cmd->flags & TRIG_ROUND_MASK) == TRIG_ROUND_UP) {
607 if (cmd->scan_begin_arg) {
608 *scan_ticks = (cmd->scan_begin_arg * 33) / 1000;
609 rest = (cmd->scan_begin_arg * 33) % 1000;
611 if ((cmd->flags & TRIG_ROUND_MASK) == TRIG_ROUND_NEAREST) {
614 } else if ((cmd->flags & TRIG_ROUND_MASK) == TRIG_ROUND_UP) {
620 if (cmd->convert_arg) {
621 *chan_ticks = (cmd->convert_arg * 33) / 1000;
622 rest = (cmd->convert_arg * 33) % 1000;
624 if ((cmd->flags & TRIG_ROUND_MASK) == TRIG_ROUND_NEAREST) {
627 } else if ((cmd->flags & TRIG_ROUND_MASK) == TRIG_ROUND_UP) {
636 static void ai_write_timer(struct comedi_device *dev,
637 unsigned int init_ticks,
638 unsigned int scan_ticks, unsigned int chan_ticks)
640 outl(init_ticks - 1, dev->iobase + ME4000_AI_SCAN_PRE_TIMER_LOW_REG);
641 outl(0x0, dev->iobase + ME4000_AI_SCAN_PRE_TIMER_HIGH_REG);
644 outl(scan_ticks - 1, dev->iobase + ME4000_AI_SCAN_TIMER_LOW_REG);
645 outl(0x0, dev->iobase + ME4000_AI_SCAN_TIMER_HIGH_REG);
648 outl(chan_ticks - 1, dev->iobase + ME4000_AI_CHAN_PRE_TIMER_REG);
649 outl(chan_ticks - 1, dev->iobase + ME4000_AI_CHAN_TIMER_REG);
652 static int ai_write_chanlist(struct comedi_device *dev,
653 struct comedi_subdevice *s, struct comedi_cmd *cmd)
661 for (i = 0; i < cmd->chanlist_len; i++) {
662 chan = CR_CHAN(cmd->chanlist[i]);
663 rang = CR_RANGE(cmd->chanlist[i]);
664 aref = CR_AREF(cmd->chanlist[i]);
669 entry |= ME4000_AI_LIST_RANGE_UNIPOLAR_2_5;
671 entry |= ME4000_AI_LIST_RANGE_UNIPOLAR_10;
673 entry |= ME4000_AI_LIST_RANGE_BIPOLAR_2_5;
675 entry |= ME4000_AI_LIST_RANGE_BIPOLAR_10;
677 if (aref == SDF_DIFF)
678 entry |= ME4000_AI_LIST_INPUT_DIFFERENTIAL;
680 entry |= ME4000_AI_LIST_INPUT_SINGLE_ENDED;
682 outl(entry, dev->iobase + ME4000_AI_CHANNEL_LIST_REG);
688 static int ai_prepare(struct comedi_device *dev,
689 struct comedi_subdevice *s,
690 struct comedi_cmd *cmd,
691 unsigned int init_ticks,
692 unsigned int scan_ticks, unsigned int chan_ticks)
695 unsigned long tmp = 0;
697 /* Write timer arguments */
698 ai_write_timer(dev, init_ticks, scan_ticks, chan_ticks);
700 /* Reset control register */
701 outl(tmp, dev->iobase + ME4000_AI_CTRL_REG);
704 if ((cmd->start_src == TRIG_EXT &&
705 cmd->scan_begin_src == TRIG_TIMER &&
706 cmd->convert_src == TRIG_TIMER) ||
707 (cmd->start_src == TRIG_EXT &&
708 cmd->scan_begin_src == TRIG_FOLLOW &&
709 cmd->convert_src == TRIG_TIMER)) {
710 tmp = ME4000_AI_CTRL_BIT_MODE_1 |
711 ME4000_AI_CTRL_BIT_CHANNEL_FIFO |
712 ME4000_AI_CTRL_BIT_DATA_FIFO;
713 } else if (cmd->start_src == TRIG_EXT &&
714 cmd->scan_begin_src == TRIG_EXT &&
715 cmd->convert_src == TRIG_TIMER) {
716 tmp = ME4000_AI_CTRL_BIT_MODE_2 |
717 ME4000_AI_CTRL_BIT_CHANNEL_FIFO |
718 ME4000_AI_CTRL_BIT_DATA_FIFO;
719 } else if (cmd->start_src == TRIG_EXT &&
720 cmd->scan_begin_src == TRIG_EXT &&
721 cmd->convert_src == TRIG_EXT) {
722 tmp = ME4000_AI_CTRL_BIT_MODE_0 |
723 ME4000_AI_CTRL_BIT_MODE_1 |
724 ME4000_AI_CTRL_BIT_CHANNEL_FIFO |
725 ME4000_AI_CTRL_BIT_DATA_FIFO;
727 tmp = ME4000_AI_CTRL_BIT_MODE_0 |
728 ME4000_AI_CTRL_BIT_CHANNEL_FIFO |
729 ME4000_AI_CTRL_BIT_DATA_FIFO;
733 if (cmd->stop_src == TRIG_COUNT) {
734 outl(cmd->chanlist_len * cmd->stop_arg,
735 dev->iobase + ME4000_AI_SAMPLE_COUNTER_REG);
736 tmp |= ME4000_AI_CTRL_BIT_HF_IRQ | ME4000_AI_CTRL_BIT_SC_IRQ;
737 } else if (cmd->stop_src == TRIG_NONE &&
738 cmd->scan_end_src == TRIG_COUNT) {
739 outl(cmd->scan_end_arg,
740 dev->iobase + ME4000_AI_SAMPLE_COUNTER_REG);
741 tmp |= ME4000_AI_CTRL_BIT_HF_IRQ | ME4000_AI_CTRL_BIT_SC_IRQ;
743 tmp |= ME4000_AI_CTRL_BIT_HF_IRQ;
746 /* Write the setup to the control register */
747 outl(tmp, dev->iobase + ME4000_AI_CTRL_REG);
749 /* Write the channel list */
750 ai_write_chanlist(dev, s, cmd);
755 static int me4000_ai_do_cmd(struct comedi_device *dev,
756 struct comedi_subdevice *s)
759 unsigned int init_ticks = 0;
760 unsigned int scan_ticks = 0;
761 unsigned int chan_ticks = 0;
762 struct comedi_cmd *cmd = &s->async->cmd;
764 /* Reset the analog input */
765 err = me4000_ai_cancel(dev, s);
769 /* Round the timer arguments */
770 err = ai_round_cmd_args(dev,
771 s, cmd, &init_ticks, &scan_ticks, &chan_ticks);
775 /* Prepare the AI for acquisition */
776 err = ai_prepare(dev, s, cmd, init_ticks, scan_ticks, chan_ticks);
780 /* Start acquistion by dummy read */
781 inl(dev->iobase + ME4000_AI_START_REG);
787 * me4000_ai_do_cmd_test():
789 * The demo cmd.c in ./comedilib/demo specifies 6 return values:
794 * - argument conflict
796 * So I tried to adopt this scheme.
798 static int me4000_ai_do_cmd_test(struct comedi_device *dev,
799 struct comedi_subdevice *s,
800 struct comedi_cmd *cmd)
803 unsigned int init_ticks;
804 unsigned int chan_ticks;
805 unsigned int scan_ticks;
808 /* Only rounding flags are implemented */
809 cmd->flags &= TRIG_ROUND_NEAREST | TRIG_ROUND_UP | TRIG_ROUND_DOWN;
811 /* Round the timer arguments */
812 ai_round_cmd_args(dev, s, cmd, &init_ticks, &scan_ticks, &chan_ticks);
815 * Stage 1. Check if the trigger sources are generally valid.
817 switch (cmd->start_src) {
822 cmd->start_src &= TRIG_NOW | TRIG_EXT;
827 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
828 "Invalid start source\n", dev->minor);
829 cmd->start_src = TRIG_NOW;
832 switch (cmd->scan_begin_src) {
838 cmd->scan_begin_src &= TRIG_FOLLOW | TRIG_TIMER | TRIG_EXT;
843 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
844 "Invalid scan begin source\n", dev->minor);
845 cmd->scan_begin_src = TRIG_FOLLOW;
848 switch (cmd->convert_src) {
853 cmd->convert_src &= TRIG_TIMER | TRIG_EXT;
858 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
859 "Invalid convert source\n", dev->minor);
860 cmd->convert_src = TRIG_TIMER;
863 switch (cmd->scan_end_src) {
868 cmd->scan_end_src &= TRIG_NONE | TRIG_COUNT;
873 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
874 "Invalid scan end source\n", dev->minor);
875 cmd->scan_end_src = TRIG_NONE;
878 switch (cmd->stop_src) {
883 cmd->stop_src &= TRIG_NONE | TRIG_COUNT;
888 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
889 "Invalid stop source\n", dev->minor);
890 cmd->stop_src = TRIG_NONE;
897 * Stage 2. Check for trigger source conflicts.
899 if (cmd->start_src == TRIG_NOW &&
900 cmd->scan_begin_src == TRIG_TIMER &&
901 cmd->convert_src == TRIG_TIMER) {
902 } else if (cmd->start_src == TRIG_NOW &&
903 cmd->scan_begin_src == TRIG_FOLLOW &&
904 cmd->convert_src == TRIG_TIMER) {
905 } else if (cmd->start_src == TRIG_EXT &&
906 cmd->scan_begin_src == TRIG_TIMER &&
907 cmd->convert_src == TRIG_TIMER) {
908 } else if (cmd->start_src == TRIG_EXT &&
909 cmd->scan_begin_src == TRIG_FOLLOW &&
910 cmd->convert_src == TRIG_TIMER) {
911 } else if (cmd->start_src == TRIG_EXT &&
912 cmd->scan_begin_src == TRIG_EXT &&
913 cmd->convert_src == TRIG_TIMER) {
914 } else if (cmd->start_src == TRIG_EXT &&
915 cmd->scan_begin_src == TRIG_EXT &&
916 cmd->convert_src == TRIG_EXT) {
919 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
920 "Invalid start trigger combination\n", dev->minor);
921 cmd->start_src = TRIG_NOW;
922 cmd->scan_begin_src = TRIG_FOLLOW;
923 cmd->convert_src = TRIG_TIMER;
927 if (cmd->stop_src == TRIG_NONE && cmd->scan_end_src == TRIG_NONE) {
928 } else if (cmd->stop_src == TRIG_COUNT &&
929 cmd->scan_end_src == TRIG_NONE) {
930 } else if (cmd->stop_src == TRIG_NONE &&
931 cmd->scan_end_src == TRIG_COUNT) {
932 } else if (cmd->stop_src == TRIG_COUNT &&
933 cmd->scan_end_src == TRIG_COUNT) {
936 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
937 "Invalid stop trigger combination\n", dev->minor);
938 cmd->stop_src = TRIG_NONE;
939 cmd->scan_end_src = TRIG_NONE;
946 * Stage 3. Check if arguments are generally valid.
948 if (cmd->chanlist_len < 1) {
950 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
951 "No channel list\n", dev->minor);
952 cmd->chanlist_len = 1;
955 if (init_ticks < 66) {
957 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
958 "Start arg to low\n", dev->minor);
959 cmd->start_arg = 2000;
962 if (scan_ticks && scan_ticks < 67) {
964 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
965 "Scan begin arg to low\n", dev->minor);
966 cmd->scan_begin_arg = 2031;
969 if (chan_ticks < 66) {
971 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
972 "Convert arg to low\n", dev->minor);
973 cmd->convert_arg = 2000;
981 * Stage 4. Check for argument conflicts.
983 if (cmd->start_src == TRIG_NOW &&
984 cmd->scan_begin_src == TRIG_TIMER &&
985 cmd->convert_src == TRIG_TIMER) {
987 /* Check timer arguments */
988 if (init_ticks < ME4000_AI_MIN_TICKS) {
990 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
991 "Invalid start arg\n", dev->minor);
992 cmd->start_arg = 2000; /* 66 ticks at least */
995 if (chan_ticks < ME4000_AI_MIN_TICKS) {
997 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
998 "Invalid convert arg\n", dev->minor);
999 cmd->convert_arg = 2000; /* 66 ticks at least */
1002 if (scan_ticks <= cmd->chanlist_len * chan_ticks) {
1004 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1005 "Invalid scan end arg\n", dev->minor);
1007 /* At least one tick more */
1008 cmd->scan_end_arg = 2000 * cmd->chanlist_len + 31;
1011 } else if (cmd->start_src == TRIG_NOW &&
1012 cmd->scan_begin_src == TRIG_FOLLOW &&
1013 cmd->convert_src == TRIG_TIMER) {
1015 /* Check timer arguments */
1016 if (init_ticks < ME4000_AI_MIN_TICKS) {
1018 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1019 "Invalid start arg\n", dev->minor);
1020 cmd->start_arg = 2000; /* 66 ticks at least */
1023 if (chan_ticks < ME4000_AI_MIN_TICKS) {
1025 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1026 "Invalid convert arg\n", dev->minor);
1027 cmd->convert_arg = 2000; /* 66 ticks at least */
1030 } else if (cmd->start_src == TRIG_EXT &&
1031 cmd->scan_begin_src == TRIG_TIMER &&
1032 cmd->convert_src == TRIG_TIMER) {
1034 /* Check timer arguments */
1035 if (init_ticks < ME4000_AI_MIN_TICKS) {
1037 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1038 "Invalid start arg\n", dev->minor);
1039 cmd->start_arg = 2000; /* 66 ticks at least */
1042 if (chan_ticks < ME4000_AI_MIN_TICKS) {
1044 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1045 "Invalid convert arg\n", dev->minor);
1046 cmd->convert_arg = 2000; /* 66 ticks at least */
1049 if (scan_ticks <= cmd->chanlist_len * chan_ticks) {
1051 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1052 "Invalid scan end arg\n", dev->minor);
1054 /* At least one tick more */
1055 cmd->scan_end_arg = 2000 * cmd->chanlist_len + 31;
1058 } else if (cmd->start_src == TRIG_EXT &&
1059 cmd->scan_begin_src == TRIG_FOLLOW &&
1060 cmd->convert_src == TRIG_TIMER) {
1062 /* Check timer arguments */
1063 if (init_ticks < ME4000_AI_MIN_TICKS) {
1065 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1066 "Invalid start arg\n", dev->minor);
1067 cmd->start_arg = 2000; /* 66 ticks at least */
1070 if (chan_ticks < ME4000_AI_MIN_TICKS) {
1072 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1073 "Invalid convert arg\n", dev->minor);
1074 cmd->convert_arg = 2000; /* 66 ticks at least */
1077 } else if (cmd->start_src == TRIG_EXT &&
1078 cmd->scan_begin_src == TRIG_EXT &&
1079 cmd->convert_src == TRIG_TIMER) {
1081 /* Check timer arguments */
1082 if (init_ticks < ME4000_AI_MIN_TICKS) {
1084 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1085 "Invalid start arg\n", dev->minor);
1086 cmd->start_arg = 2000; /* 66 ticks at least */
1089 if (chan_ticks < ME4000_AI_MIN_TICKS) {
1091 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1092 "Invalid convert arg\n", dev->minor);
1093 cmd->convert_arg = 2000; /* 66 ticks at least */
1096 } else if (cmd->start_src == TRIG_EXT &&
1097 cmd->scan_begin_src == TRIG_EXT &&
1098 cmd->convert_src == TRIG_EXT) {
1100 /* Check timer arguments */
1101 if (init_ticks < ME4000_AI_MIN_TICKS) {
1103 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1104 "Invalid start arg\n", dev->minor);
1105 cmd->start_arg = 2000; /* 66 ticks at least */
1109 if (cmd->stop_src == TRIG_COUNT) {
1110 if (cmd->stop_arg == 0) {
1112 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1113 "Invalid stop arg\n", dev->minor);
1118 if (cmd->scan_end_src == TRIG_COUNT) {
1119 if (cmd->scan_end_arg == 0) {
1121 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1122 "Invalid scan end arg\n", dev->minor);
1123 cmd->scan_end_arg = 1;
1132 * Stage 5. Check the channel list.
1134 if (ai_check_chanlist(dev, s, cmd))
1140 static irqreturn_t me4000_ai_isr(int irq, void *dev_id)
1143 struct comedi_device *dev = dev_id;
1144 struct comedi_subdevice *s = &dev->subdevices[0];
1152 /* Reset all events */
1153 s->async->events = 0;
1155 /* Check if irq number is right */
1156 if (irq != dev->irq) {
1158 "comedi%d: me4000: me4000_ai_isr(): "
1159 "Incorrect interrupt num: %d\n", dev->minor, irq);
1163 if (inl(dev->iobase + ME4000_IRQ_STATUS_REG) &
1164 ME4000_IRQ_STATUS_BIT_AI_HF) {
1165 /* Read status register to find out what happened */
1166 tmp = inl(dev->iobase + ME4000_AI_CTRL_REG);
1168 if (!(tmp & ME4000_AI_STATUS_BIT_FF_DATA) &&
1169 !(tmp & ME4000_AI_STATUS_BIT_HF_DATA) &&
1170 (tmp & ME4000_AI_STATUS_BIT_EF_DATA)) {
1171 c = ME4000_AI_FIFO_COUNT;
1174 * FIFO overflow, so stop conversion
1175 * and disable all interrupts
1177 tmp |= ME4000_AI_CTRL_BIT_IMMEDIATE_STOP;
1178 tmp &= ~(ME4000_AI_CTRL_BIT_HF_IRQ |
1179 ME4000_AI_CTRL_BIT_SC_IRQ);
1180 outl(tmp, dev->iobase + ME4000_AI_CTRL_REG);
1182 s->async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
1185 "comedi%d: me4000: me4000_ai_isr(): "
1186 "FIFO overflow\n", dev->minor);
1187 } else if ((tmp & ME4000_AI_STATUS_BIT_FF_DATA)
1188 && !(tmp & ME4000_AI_STATUS_BIT_HF_DATA)
1189 && (tmp & ME4000_AI_STATUS_BIT_EF_DATA)) {
1190 s->async->events |= COMEDI_CB_BLOCK;
1192 c = ME4000_AI_FIFO_COUNT / 2;
1195 "comedi%d: me4000: me4000_ai_isr(): "
1196 "Can't determine state of fifo\n", dev->minor);
1200 * Undefined state, so stop conversion
1201 * and disable all interrupts
1203 tmp |= ME4000_AI_CTRL_BIT_IMMEDIATE_STOP;
1204 tmp &= ~(ME4000_AI_CTRL_BIT_HF_IRQ |
1205 ME4000_AI_CTRL_BIT_SC_IRQ);
1206 outl(tmp, dev->iobase + ME4000_AI_CTRL_REG);
1208 s->async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
1211 "comedi%d: me4000: me4000_ai_isr(): "
1212 "Undefined FIFO state\n", dev->minor);
1215 for (i = 0; i < c; i++) {
1216 /* Read value from data fifo */
1217 lval = inl(dev->iobase + ME4000_AI_DATA_REG) & 0xFFFF;
1220 if (!comedi_buf_put(s->async, lval)) {
1222 * Buffer overflow, so stop conversion
1223 * and disable all interrupts
1225 tmp |= ME4000_AI_CTRL_BIT_IMMEDIATE_STOP;
1226 tmp &= ~(ME4000_AI_CTRL_BIT_HF_IRQ |
1227 ME4000_AI_CTRL_BIT_SC_IRQ);
1228 outl(tmp, dev->iobase + ME4000_AI_CTRL_REG);
1230 s->async->events |= COMEDI_CB_OVERFLOW;
1233 "comedi%d: me4000: me4000_ai_isr(): "
1234 "Buffer overflow\n", dev->minor);
1240 /* Work is done, so reset the interrupt */
1241 tmp |= ME4000_AI_CTRL_BIT_HF_IRQ_RESET;
1242 outl(tmp, dev->iobase + ME4000_AI_CTRL_REG);
1243 tmp &= ~ME4000_AI_CTRL_BIT_HF_IRQ_RESET;
1244 outl(tmp, dev->iobase + ME4000_AI_CTRL_REG);
1247 if (inl(dev->iobase + ME4000_IRQ_STATUS_REG) &
1248 ME4000_IRQ_STATUS_BIT_SC) {
1249 s->async->events |= COMEDI_CB_BLOCK | COMEDI_CB_EOA;
1252 * Acquisition is complete, so stop
1253 * conversion and disable all interrupts
1255 tmp = inl(dev->iobase + ME4000_AI_CTRL_REG);
1256 tmp |= ME4000_AI_CTRL_BIT_IMMEDIATE_STOP;
1257 tmp &= ~(ME4000_AI_CTRL_BIT_HF_IRQ | ME4000_AI_CTRL_BIT_SC_IRQ);
1258 outl(tmp, dev->iobase + ME4000_AI_CTRL_REG);
1260 /* Poll data until fifo empty */
1261 while (inl(dev->iobase + ME4000_AI_CTRL_REG) &
1262 ME4000_AI_STATUS_BIT_EF_DATA) {
1263 /* Read value from data fifo */
1264 lval = inl(dev->iobase + ME4000_AI_DATA_REG) & 0xFFFF;
1267 if (!comedi_buf_put(s->async, lval)) {
1269 "comedi%d: me4000: me4000_ai_isr(): "
1270 "Buffer overflow\n", dev->minor);
1271 s->async->events |= COMEDI_CB_OVERFLOW;
1276 /* Work is done, so reset the interrupt */
1277 tmp |= ME4000_AI_CTRL_BIT_SC_IRQ_RESET;
1278 outl(tmp, dev->iobase + ME4000_AI_CTRL_REG);
1279 tmp &= ~ME4000_AI_CTRL_BIT_SC_IRQ_RESET;
1280 outl(tmp, dev->iobase + ME4000_AI_CTRL_REG);
1283 if (s->async->events)
1284 comedi_event(dev, s);
1289 /*=============================================================================
1290 Analog output section
1291 ===========================================================================*/
1293 static int me4000_ao_insn_write(struct comedi_device *dev,
1294 struct comedi_subdevice *s,
1295 struct comedi_insn *insn, unsigned int *data)
1297 const struct me4000_board *thisboard = comedi_board(dev);
1298 struct me4000_info *info = dev->private;
1299 int chan = CR_CHAN(insn->chanspec);
1300 int rang = CR_RANGE(insn->chanspec);
1301 int aref = CR_AREF(insn->chanspec);
1306 } else if (insn->n > 1) {
1308 "comedi%d: me4000: me4000_ao_insn_write(): "
1309 "Invalid instruction length %d\n", dev->minor, insn->n);
1313 if (chan >= thisboard->ao_nchan) {
1315 "comedi%d: me4000: me4000_ao_insn_write(): "
1316 "Invalid channel %d\n", dev->minor, insn->n);
1322 "comedi%d: me4000: me4000_ao_insn_write(): "
1323 "Invalid range %d\n", dev->minor, insn->n);
1327 if (aref != AREF_GROUND && aref != AREF_COMMON) {
1329 "comedi%d: me4000: me4000_ao_insn_write(): "
1330 "Invalid aref %d\n", dev->minor, insn->n);
1334 /* Stop any running conversion */
1335 tmp = inl(dev->iobase + ME4000_AO_CTRL_REG(chan));
1336 tmp |= ME4000_AO_CTRL_BIT_IMMEDIATE_STOP;
1337 outl(tmp, dev->iobase + ME4000_AO_CTRL_REG(chan));
1339 /* Clear control register and set to single mode */
1340 outl(0x0, dev->iobase + ME4000_AO_CTRL_REG(chan));
1342 /* Write data value */
1343 outl(data[0], dev->iobase + ME4000_AO_SINGLE_REG(chan));
1345 /* Store in the mirror */
1346 info->ao_readback[chan] = data[0];
1351 static int me4000_ao_insn_read(struct comedi_device *dev,
1352 struct comedi_subdevice *s,
1353 struct comedi_insn *insn, unsigned int *data)
1355 struct me4000_info *info = dev->private;
1356 int chan = CR_CHAN(insn->chanspec);
1360 } else if (insn->n > 1) {
1362 ("comedi%d: me4000: me4000_ao_insn_read(): "
1363 "Invalid instruction length\n", dev->minor);
1367 data[0] = info->ao_readback[chan];
1372 /*=============================================================================
1374 ===========================================================================*/
1376 static int me4000_dio_insn_bits(struct comedi_device *dev,
1377 struct comedi_subdevice *s,
1378 struct comedi_insn *insn, unsigned int *data)
1381 * The insn data consists of a mask in data[0] and the new data
1382 * in data[1]. The mask defines which bits we are concerning about.
1383 * The new data must be anded with the mask.
1384 * Each channel corresponds to a bit.
1387 /* Check if requested ports are configured for output */
1388 if ((s->io_bits & data[0]) != data[0])
1391 s->state &= ~data[0];
1392 s->state |= data[0] & data[1];
1394 /* Write out the new digital output lines */
1395 outl((s->state >> 0) & 0xFF,
1396 dev->iobase + ME4000_DIO_PORT_0_REG);
1397 outl((s->state >> 8) & 0xFF,
1398 dev->iobase + ME4000_DIO_PORT_1_REG);
1399 outl((s->state >> 16) & 0xFF,
1400 dev->iobase + ME4000_DIO_PORT_2_REG);
1401 outl((s->state >> 24) & 0xFF,
1402 dev->iobase + ME4000_DIO_PORT_3_REG);
1405 /* On return, data[1] contains the value of
1406 the digital input and output lines. */
1407 data[1] = ((inl(dev->iobase + ME4000_DIO_PORT_0_REG) & 0xFF) << 0) |
1408 ((inl(dev->iobase + ME4000_DIO_PORT_1_REG) & 0xFF) << 8) |
1409 ((inl(dev->iobase + ME4000_DIO_PORT_2_REG) & 0xFF) << 16) |
1410 ((inl(dev->iobase + ME4000_DIO_PORT_3_REG) & 0xFF) << 24);
1415 static int me4000_dio_insn_config(struct comedi_device *dev,
1416 struct comedi_subdevice *s,
1417 struct comedi_insn *insn, unsigned int *data)
1420 int chan = CR_CHAN(insn->chanspec);
1425 case INSN_CONFIG_DIO_QUERY:
1427 (s->io_bits & (1 << chan)) ? COMEDI_OUTPUT : COMEDI_INPUT;
1429 case INSN_CONFIG_DIO_INPUT:
1430 case INSN_CONFIG_DIO_OUTPUT:
1435 * The input or output configuration of each digital line is
1436 * configured by a special insn_config instruction. chanspec
1437 * contains the channel to be changed, and data[0] contains the
1438 * value INSN_CONFIG_DIO_INPUT or INSN_CONFIG_DIO_OUTPUT.
1439 * On the ME-4000 it is only possible to switch port wise (8 bit)
1442 tmp = inl(dev->iobase + ME4000_DIO_CTRL_REG);
1444 if (data[0] == INSN_CONFIG_DIO_OUTPUT) {
1447 tmp &= ~(ME4000_DIO_CTRL_BIT_MODE_0 |
1448 ME4000_DIO_CTRL_BIT_MODE_1);
1449 tmp |= ME4000_DIO_CTRL_BIT_MODE_0;
1450 } else if (chan < 16) {
1452 * Chech for optoisolated ME-4000 version.
1453 * If one the first port is a fixed output
1454 * port and the second is a fixed input port.
1456 if (!inl(dev->iobase + ME4000_DIO_DIR_REG))
1459 s->io_bits |= 0xFF00;
1460 tmp &= ~(ME4000_DIO_CTRL_BIT_MODE_2 |
1461 ME4000_DIO_CTRL_BIT_MODE_3);
1462 tmp |= ME4000_DIO_CTRL_BIT_MODE_2;
1463 } else if (chan < 24) {
1464 s->io_bits |= 0xFF0000;
1465 tmp &= ~(ME4000_DIO_CTRL_BIT_MODE_4 |
1466 ME4000_DIO_CTRL_BIT_MODE_5);
1467 tmp |= ME4000_DIO_CTRL_BIT_MODE_4;
1468 } else if (chan < 32) {
1469 s->io_bits |= 0xFF000000;
1470 tmp &= ~(ME4000_DIO_CTRL_BIT_MODE_6 |
1471 ME4000_DIO_CTRL_BIT_MODE_7);
1472 tmp |= ME4000_DIO_CTRL_BIT_MODE_6;
1479 * Chech for optoisolated ME-4000 version.
1480 * If one the first port is a fixed output
1481 * port and the second is a fixed input port.
1483 if (!inl(dev->iobase + ME4000_DIO_DIR_REG))
1486 s->io_bits &= ~0xFF;
1487 tmp &= ~(ME4000_DIO_CTRL_BIT_MODE_0 |
1488 ME4000_DIO_CTRL_BIT_MODE_1);
1489 } else if (chan < 16) {
1490 s->io_bits &= ~0xFF00;
1491 tmp &= ~(ME4000_DIO_CTRL_BIT_MODE_2 |
1492 ME4000_DIO_CTRL_BIT_MODE_3);
1493 } else if (chan < 24) {
1494 s->io_bits &= ~0xFF0000;
1495 tmp &= ~(ME4000_DIO_CTRL_BIT_MODE_4 |
1496 ME4000_DIO_CTRL_BIT_MODE_5);
1497 } else if (chan < 32) {
1498 s->io_bits &= ~0xFF000000;
1499 tmp &= ~(ME4000_DIO_CTRL_BIT_MODE_6 |
1500 ME4000_DIO_CTRL_BIT_MODE_7);
1506 outl(tmp, dev->iobase + ME4000_DIO_CTRL_REG);
1511 /*=============================================================================
1513 ===========================================================================*/
1515 static int cnt_reset(struct comedi_device *dev, unsigned int channel)
1517 struct me4000_info *info = dev->private;
1521 outb(0x30, info->timer_regbase + ME4000_CNT_CTRL_REG);
1522 outb(0x00, info->timer_regbase + ME4000_CNT_COUNTER_0_REG);
1523 outb(0x00, info->timer_regbase + ME4000_CNT_COUNTER_0_REG);
1526 outb(0x70, info->timer_regbase + ME4000_CNT_CTRL_REG);
1527 outb(0x00, info->timer_regbase + ME4000_CNT_COUNTER_1_REG);
1528 outb(0x00, info->timer_regbase + ME4000_CNT_COUNTER_1_REG);
1531 outb(0xB0, info->timer_regbase + ME4000_CNT_CTRL_REG);
1532 outb(0x00, info->timer_regbase + ME4000_CNT_COUNTER_2_REG);
1533 outb(0x00, info->timer_regbase + ME4000_CNT_COUNTER_2_REG);
1537 "comedi%d: me4000: cnt_reset(): Invalid channel\n",
1545 static int cnt_config(struct comedi_device *dev, unsigned int channel,
1548 struct me4000_info *info = dev->private;
1553 tmp |= ME4000_CNT_COUNTER_0;
1556 tmp |= ME4000_CNT_COUNTER_1;
1559 tmp |= ME4000_CNT_COUNTER_2;
1563 "comedi%d: me4000: cnt_config(): Invalid channel\n",
1570 tmp |= ME4000_CNT_MODE_0;
1573 tmp |= ME4000_CNT_MODE_1;
1576 tmp |= ME4000_CNT_MODE_2;
1579 tmp |= ME4000_CNT_MODE_3;
1582 tmp |= ME4000_CNT_MODE_4;
1585 tmp |= ME4000_CNT_MODE_5;
1589 "comedi%d: me4000: cnt_config(): Invalid counter mode\n",
1594 /* Write the control word */
1596 outb(tmp, info->timer_regbase + ME4000_CNT_CTRL_REG);
1601 static int me4000_cnt_insn_config(struct comedi_device *dev,
1602 struct comedi_subdevice *s,
1603 struct comedi_insn *insn, unsigned int *data)
1612 "comedi%d: me4000: me4000_cnt_insn_config(): "
1613 "Invalid instruction length%d\n",
1614 dev->minor, insn->n);
1618 err = cnt_reset(dev, insn->chanspec);
1622 case GPCT_SET_OPERATION:
1625 "comedi%d: me4000: me4000_cnt_insn_config(): "
1626 "Invalid instruction length%d\n",
1627 dev->minor, insn->n);
1631 err = cnt_config(dev, insn->chanspec, data[1]);
1637 "comedi%d: me4000: me4000_cnt_insn_config(): "
1638 "Invalid instruction\n", dev->minor);
1645 static int me4000_cnt_insn_read(struct comedi_device *dev,
1646 struct comedi_subdevice *s,
1647 struct comedi_insn *insn, unsigned int *data)
1649 struct me4000_info *info = dev->private;
1657 "comedi%d: me4000: me4000_cnt_insn_read(): "
1658 "Invalid instruction length %d\n",
1659 dev->minor, insn->n);
1663 switch (insn->chanspec) {
1665 tmp = inb(info->timer_regbase + ME4000_CNT_COUNTER_0_REG);
1667 tmp = inb(info->timer_regbase + ME4000_CNT_COUNTER_0_REG);
1668 data[0] |= tmp << 8;
1671 tmp = inb(info->timer_regbase + ME4000_CNT_COUNTER_1_REG);
1673 tmp = inb(info->timer_regbase + ME4000_CNT_COUNTER_1_REG);
1674 data[0] |= tmp << 8;
1677 tmp = inb(info->timer_regbase + ME4000_CNT_COUNTER_2_REG);
1679 tmp = inb(info->timer_regbase + ME4000_CNT_COUNTER_2_REG);
1680 data[0] |= tmp << 8;
1684 "comedi%d: me4000: me4000_cnt_insn_read(): "
1685 "Invalid channel %d\n",
1686 dev->minor, insn->chanspec);
1693 static int me4000_cnt_insn_write(struct comedi_device *dev,
1694 struct comedi_subdevice *s,
1695 struct comedi_insn *insn, unsigned int *data)
1697 struct me4000_info *info = dev->private;
1702 } else if (insn->n > 1) {
1704 "comedi%d: me4000: me4000_cnt_insn_write(): "
1705 "Invalid instruction length %d\n",
1706 dev->minor, insn->n);
1710 switch (insn->chanspec) {
1712 tmp = data[0] & 0xFF;
1713 outb(tmp, info->timer_regbase + ME4000_CNT_COUNTER_0_REG);
1714 tmp = (data[0] >> 8) & 0xFF;
1715 outb(tmp, info->timer_regbase + ME4000_CNT_COUNTER_0_REG);
1718 tmp = data[0] & 0xFF;
1719 outb(tmp, info->timer_regbase + ME4000_CNT_COUNTER_1_REG);
1720 tmp = (data[0] >> 8) & 0xFF;
1721 outb(tmp, info->timer_regbase + ME4000_CNT_COUNTER_1_REG);
1724 tmp = data[0] & 0xFF;
1725 outb(tmp, info->timer_regbase + ME4000_CNT_COUNTER_2_REG);
1726 tmp = (data[0] >> 8) & 0xFF;
1727 outb(tmp, info->timer_regbase + ME4000_CNT_COUNTER_2_REG);
1731 "comedi%d: me4000: me4000_cnt_insn_write(): "
1732 "Invalid channel %d\n",
1733 dev->minor, insn->chanspec);
1740 static int me4000_probe(struct comedi_device *dev, struct comedi_devconfig *it)
1742 struct me4000_info *info;
1743 struct pci_dev *pci_device = NULL;
1745 const struct me4000_board *board;
1747 /* Allocate private memory */
1748 result = alloc_private(dev, sizeof(*info));
1751 info = dev->private;
1754 * Probe the device to determine what device in the series it is.
1756 for_each_pci_dev(pci_device) {
1757 if (pci_device->vendor == PCI_VENDOR_ID_MEILHAUS) {
1758 for (i = 0; i < ARRAY_SIZE(me4000_boards); i++) {
1759 if (me4000_boards[i].device_id ==
1760 pci_device->device) {
1763 * bus/slot requested?
1765 if ((it->options[0] != 0)
1766 || (it->options[1] != 0)) {
1768 * Are we on the wrong
1771 if (pci_device->bus->number !=
1774 PCI_SLOT(pci_device->devfn)
1775 != it->options[1]) {
1779 dev->board_ptr = me4000_boards + i;
1780 board = comedi_board(dev);
1781 info->pci_dev_p = pci_device;
1790 dev->board_name = board->name;
1792 result = comedi_pci_enable(pci_device, dev->board_name);
1796 info->plx_regbase = pci_resource_start(pci_device, 1);
1797 if (!info->plx_regbase)
1800 dev->iobase = pci_resource_start(pci_device, 2);
1804 info->timer_regbase = pci_resource_start(pci_device, 3);
1805 if (!info->timer_regbase)
1808 info->program_regbase = pci_resource_start(pci_device, 5);
1809 if (!info->program_regbase)
1812 dev->irq = pci_device->irq;
1814 result = xilinx_download(dev);
1818 result = reset_board(dev);
1825 static int me4000_attach(struct comedi_device *dev, struct comedi_devconfig *it)
1827 const struct me4000_board *thisboard;
1828 struct comedi_subdevice *s;
1831 result = me4000_probe(dev, it);
1834 thisboard = comedi_board(dev);
1836 result = comedi_alloc_subdevices(dev, 4);
1840 /*=========================================================================
1841 Analog input subdevice
1842 ========================================================================*/
1844 s = &dev->subdevices[0];
1846 if (thisboard->ai_nchan) {
1847 s->type = COMEDI_SUBD_AI;
1849 SDF_READABLE | SDF_COMMON | SDF_GROUND | SDF_DIFF;
1850 s->n_chan = thisboard->ai_nchan;
1851 s->maxdata = 0xFFFF; /* 16 bit ADC */
1852 s->len_chanlist = ME4000_AI_CHANNEL_LIST_COUNT;
1853 s->range_table = &me4000_ai_range;
1854 s->insn_read = me4000_ai_insn_read;
1857 if (request_irq(dev->irq, me4000_ai_isr,
1858 IRQF_SHARED, "ME-4000", dev)) {
1860 ("comedi%d: me4000: me4000_attach(): "
1861 "Unable to allocate irq\n", dev->minor);
1863 dev->read_subdev = s;
1864 s->subdev_flags |= SDF_CMD_READ;
1865 s->cancel = me4000_ai_cancel;
1866 s->do_cmdtest = me4000_ai_do_cmd_test;
1867 s->do_cmd = me4000_ai_do_cmd;
1871 "comedi%d: me4000: me4000_attach(): "
1872 "No interrupt available\n", dev->minor);
1875 s->type = COMEDI_SUBD_UNUSED;
1878 /*=========================================================================
1879 Analog output subdevice
1880 ========================================================================*/
1882 s = &dev->subdevices[1];
1884 if (thisboard->ao_nchan) {
1885 s->type = COMEDI_SUBD_AO;
1886 s->subdev_flags = SDF_WRITEABLE | SDF_COMMON | SDF_GROUND;
1887 s->n_chan = thisboard->ao_nchan;
1888 s->maxdata = 0xFFFF; /* 16 bit DAC */
1889 s->range_table = &range_bipolar10;
1890 s->insn_write = me4000_ao_insn_write;
1891 s->insn_read = me4000_ao_insn_read;
1893 s->type = COMEDI_SUBD_UNUSED;
1896 /*=========================================================================
1897 Digital I/O subdevice
1898 ========================================================================*/
1900 s = &dev->subdevices[2];
1902 if (thisboard->dio_nchan) {
1903 s->type = COMEDI_SUBD_DIO;
1904 s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
1905 s->n_chan = thisboard->dio_nchan;
1907 s->range_table = &range_digital;
1908 s->insn_bits = me4000_dio_insn_bits;
1909 s->insn_config = me4000_dio_insn_config;
1911 s->type = COMEDI_SUBD_UNUSED;
1915 * Check for optoisolated ME-4000 version. If one the first
1916 * port is a fixed output port and the second is a fixed input port.
1918 if (!inl(dev->iobase + ME4000_DIO_DIR_REG)) {
1920 outl(ME4000_DIO_CTRL_BIT_MODE_0,
1921 dev->iobase + ME4000_DIO_DIR_REG);
1924 /*=========================================================================
1926 ========================================================================*/
1928 s = &dev->subdevices[3];
1930 if (thisboard->has_counter) {
1931 s->type = COMEDI_SUBD_COUNTER;
1932 s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
1934 s->maxdata = 0xFFFF; /* 16 bit counters */
1935 s->insn_read = me4000_cnt_insn_read;
1936 s->insn_write = me4000_cnt_insn_write;
1937 s->insn_config = me4000_cnt_insn_config;
1939 s->type = COMEDI_SUBD_UNUSED;
1945 static void me4000_detach(struct comedi_device *dev)
1947 struct me4000_info *info = dev->private;
1950 if (info->pci_dev_p) {
1952 if (info->plx_regbase)
1953 comedi_pci_disable(info->pci_dev_p);
1954 pci_dev_put(info->pci_dev_p);
1959 static struct comedi_driver me4000_driver = {
1960 .driver_name = "me4000",
1961 .module = THIS_MODULE,
1962 .attach = me4000_attach,
1963 .detach = me4000_detach,
1966 static int __devinit me4000_pci_probe(struct pci_dev *dev,
1967 const struct pci_device_id *ent)
1969 return comedi_pci_auto_config(dev, &me4000_driver);
1972 static void __devexit me4000_pci_remove(struct pci_dev *dev)
1974 comedi_pci_auto_unconfig(dev);
1977 static DEFINE_PCI_DEVICE_TABLE(me4000_pci_table) = {
1978 {PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4650)},
1979 {PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4660)},
1980 {PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4660I)},
1981 {PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4660S)},
1982 {PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4660IS)},
1983 {PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4670)},
1984 {PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4670I)},
1985 {PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4670S)},
1986 {PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4670IS)},
1987 {PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4680)},
1988 {PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4680I)},
1989 {PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4680S)},
1990 {PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4680IS)},
1993 MODULE_DEVICE_TABLE(pci, me4000_pci_table);
1995 static struct pci_driver me4000_pci_driver = {
1997 .id_table = me4000_pci_table,
1998 .probe = me4000_pci_probe,
1999 .remove = __devexit_p(me4000_pci_remove),
2001 module_comedi_pci_driver(me4000_driver, me4000_pci_driver);
2003 MODULE_AUTHOR("Comedi http://www.comedi.org");
2004 MODULE_DESCRIPTION("Comedi low-level driver");
2005 MODULE_LICENSE("GPL");