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: not applicable, uses PCI auto config
40 The firmware required by these boards is available in the
41 comedi_nonfree_firmware tarball available from
42 http://www.comedi.org. However, the driver's support for
43 loading the firmware through comedi_config is currently
48 #include <linux/interrupt.h>
49 #include "../comedidev.h"
51 #include <linux/delay.h>
52 #include <linux/list.h>
53 #include <linux/spinlock.h>
57 /* file removed due to GPL incompatibility */
58 #include "me4000_fw.h"
61 #define PCI_VENDOR_ID_MEILHAUS 0x1402
63 #define PCI_DEVICE_ID_MEILHAUS_ME4650 0x4650
64 #define PCI_DEVICE_ID_MEILHAUS_ME4660 0x4660
65 #define PCI_DEVICE_ID_MEILHAUS_ME4660I 0x4661
66 #define PCI_DEVICE_ID_MEILHAUS_ME4660S 0x4662
67 #define PCI_DEVICE_ID_MEILHAUS_ME4660IS 0x4663
68 #define PCI_DEVICE_ID_MEILHAUS_ME4670 0x4670
69 #define PCI_DEVICE_ID_MEILHAUS_ME4670I 0x4671
70 #define PCI_DEVICE_ID_MEILHAUS_ME4670S 0x4672
71 #define PCI_DEVICE_ID_MEILHAUS_ME4670IS 0x4673
72 #define PCI_DEVICE_ID_MEILHAUS_ME4680 0x4680
73 #define PCI_DEVICE_ID_MEILHAUS_ME4680I 0x4681
74 #define PCI_DEVICE_ID_MEILHAUS_ME4680S 0x4682
75 #define PCI_DEVICE_ID_MEILHAUS_ME4680IS 0x4683
79 unsigned short device_id;
90 static const struct me4000_board me4000_boards[] = {
93 .device_id = PCI_DEVICE_ID_MEILHAUS_ME4650,
98 .device_id = PCI_DEVICE_ID_MEILHAUS_ME4660,
105 .device_id = PCI_DEVICE_ID_MEILHAUS_ME4660I,
112 .device_id = PCI_DEVICE_ID_MEILHAUS_ME4660S,
120 .device_id = PCI_DEVICE_ID_MEILHAUS_ME4660IS,
128 .device_id = PCI_DEVICE_ID_MEILHAUS_ME4670,
137 .device_id = PCI_DEVICE_ID_MEILHAUS_ME4670I,
146 .device_id = PCI_DEVICE_ID_MEILHAUS_ME4670S,
156 .device_id = PCI_DEVICE_ID_MEILHAUS_ME4670IS,
166 .device_id = PCI_DEVICE_ID_MEILHAUS_ME4680,
176 .device_id = PCI_DEVICE_ID_MEILHAUS_ME4680I,
186 .device_id = PCI_DEVICE_ID_MEILHAUS_ME4680S,
197 .device_id = PCI_DEVICE_ID_MEILHAUS_ME4680IS,
209 static const struct comedi_lrange me4000_ai_range = {
219 #define FIRMWARE_NOT_AVAILABLE 1
220 #if FIRMWARE_NOT_AVAILABLE
221 extern unsigned char *xilinx_firm;
224 static int xilinx_download(struct comedi_device *dev)
226 struct me4000_info *info = dev->private;
228 wait_queue_head_t queue;
232 init_waitqueue_head(&queue);
235 * Set PLX local interrupt 2 polarity to high.
236 * Interrupt is thrown by init pin of xilinx.
238 outl(0x10, info->plx_regbase + PLX_INTCSR);
240 /* Set /CS and /WRITE of the Xilinx */
241 value = inl(info->plx_regbase + PLX_ICR);
243 outl(value, info->plx_regbase + PLX_ICR);
245 /* Init Xilinx with CS1 */
246 inb(info->program_regbase + 0xC8);
248 /* Wait until /INIT pin is set */
250 if (!(inl(info->plx_regbase + PLX_INTCSR) & 0x20)) {
252 "comedi%d: me4000: xilinx_download(): "
253 "Can't init Xilinx\n", dev->minor);
257 /* Reset /CS and /WRITE of the Xilinx */
258 value = inl(info->plx_regbase + PLX_ICR);
260 outl(value, info->plx_regbase + PLX_ICR);
261 if (FIRMWARE_NOT_AVAILABLE) {
262 comedi_error(dev, "xilinx firmware unavailable "
263 "due to licensing, aborting");
266 /* Download Xilinx firmware */
267 size = (xilinx_firm[0] << 24) + (xilinx_firm[1] << 16) +
268 (xilinx_firm[2] << 8) + xilinx_firm[3];
271 for (idx = 0; idx < size; idx++) {
272 outb(xilinx_firm[16 + idx], info->program_regbase);
275 /* Check if BUSY flag is low */
276 if (inl(info->plx_regbase + PLX_ICR) & 0x20) {
278 "comedi%d: me4000: xilinx_download(): "
279 "Xilinx is still busy (idx = %d)\n",
286 /* If done flag is high download was successful */
287 if (inl(info->plx_regbase + PLX_ICR) & 0x4) {
290 "comedi%d: me4000: xilinx_download(): "
291 "DONE flag is not set\n", dev->minor);
293 "comedi%d: me4000: xilinx_download(): "
294 "Download not successful\n", dev->minor);
298 /* Set /CS and /WRITE */
299 value = inl(info->plx_regbase + PLX_ICR);
301 outl(value, info->plx_regbase + PLX_ICR);
306 static int reset_board(struct comedi_device *dev)
308 struct me4000_info *info = dev->private;
312 /* Make a hardware reset */
313 val = inl(info->plx_regbase + PLX_ICR);
315 outl(val, info->plx_regbase + PLX_ICR);
317 outl(val , info->plx_regbase + PLX_ICR);
319 /* 0x8000 to the DACs means an output voltage of 0V */
320 for (chan = 0; chan < 4; chan++)
321 outl(0x8000, dev->iobase + ME4000_AO_SINGLE_REG(chan));
323 /* Set both stop bits in the analog input control register */
324 outl(ME4000_AI_CTRL_BIT_IMMEDIATE_STOP | ME4000_AI_CTRL_BIT_STOP,
325 dev->iobase + ME4000_AI_CTRL_REG);
327 /* Set both stop bits in the analog output control register */
328 val = ME4000_AO_CTRL_BIT_IMMEDIATE_STOP | ME4000_AO_CTRL_BIT_STOP;
329 for (chan = 0; chan < 4; chan++)
330 outl(val, dev->iobase + ME4000_AO_CTRL_REG(chan));
332 /* Enable interrupts on the PLX */
333 outl(0x43, info->plx_regbase + PLX_INTCSR);
335 /* Set the adustment register for AO demux */
336 outl(ME4000_AO_DEMUX_ADJUST_VALUE,
337 dev->iobase + ME4000_AO_DEMUX_ADJUST_REG);
340 * Set digital I/O direction for port 0
341 * to output on isolated versions
343 if (!(inl(dev->iobase + ME4000_DIO_DIR_REG) & 0x1))
344 outl(0x1, dev->iobase + ME4000_DIO_CTRL_REG);
349 /*=============================================================================
351 ===========================================================================*/
353 static int me4000_ai_insn_read(struct comedi_device *dev,
354 struct comedi_subdevice *subdevice,
355 struct comedi_insn *insn, unsigned int *data)
357 const struct me4000_board *thisboard = comedi_board(dev);
358 int chan = CR_CHAN(insn->chanspec);
359 int rang = CR_RANGE(insn->chanspec);
360 int aref = CR_AREF(insn->chanspec);
362 unsigned long entry = 0;
368 } else if (insn->n > 1) {
370 "comedi%d: me4000: me4000_ai_insn_read(): "
371 "Invalid instruction length %d\n", dev->minor, insn->n);
377 entry |= ME4000_AI_LIST_RANGE_UNIPOLAR_2_5;
380 entry |= ME4000_AI_LIST_RANGE_UNIPOLAR_10;
383 entry |= ME4000_AI_LIST_RANGE_BIPOLAR_2_5;
386 entry |= ME4000_AI_LIST_RANGE_BIPOLAR_10;
390 "comedi%d: me4000: me4000_ai_insn_read(): "
391 "Invalid range specified\n", dev->minor);
398 if (chan >= thisboard->ai_nchan) {
400 "comedi%d: me4000: me4000_ai_insn_read(): "
401 "Analog input is not available\n", dev->minor);
404 entry |= ME4000_AI_LIST_INPUT_SINGLE_ENDED | chan;
408 if (rang == 0 || rang == 1) {
410 "comedi%d: me4000: me4000_ai_insn_read(): "
411 "Range must be bipolar when aref = diff\n",
416 if (chan >= thisboard->ai_diff_nchan) {
418 "comedi%d: me4000: me4000_ai_insn_read(): "
419 "Analog input is not available\n", dev->minor);
422 entry |= ME4000_AI_LIST_INPUT_DIFFERENTIAL | chan;
426 "comedi%d: me4000: me4000_ai_insn_read(): "
427 "Invalid aref specified\n", dev->minor);
431 entry |= ME4000_AI_LIST_LAST_ENTRY;
433 /* Clear channel list, data fifo and both stop bits */
434 tmp = inl(dev->iobase + ME4000_AI_CTRL_REG);
435 tmp &= ~(ME4000_AI_CTRL_BIT_CHANNEL_FIFO |
436 ME4000_AI_CTRL_BIT_DATA_FIFO |
437 ME4000_AI_CTRL_BIT_STOP | ME4000_AI_CTRL_BIT_IMMEDIATE_STOP);
438 outl(tmp, dev->iobase + ME4000_AI_CTRL_REG);
440 /* Set the acquisition mode to single */
441 tmp &= ~(ME4000_AI_CTRL_BIT_MODE_0 | ME4000_AI_CTRL_BIT_MODE_1 |
442 ME4000_AI_CTRL_BIT_MODE_2);
443 outl(tmp, dev->iobase + ME4000_AI_CTRL_REG);
445 /* Enable channel list and data fifo */
446 tmp |= ME4000_AI_CTRL_BIT_CHANNEL_FIFO | ME4000_AI_CTRL_BIT_DATA_FIFO;
447 outl(tmp, dev->iobase + ME4000_AI_CTRL_REG);
449 /* Generate channel list entry */
450 outl(entry, dev->iobase + ME4000_AI_CHANNEL_LIST_REG);
452 /* Set the timer to maximum sample rate */
453 outl(ME4000_AI_MIN_TICKS, dev->iobase + ME4000_AI_CHAN_TIMER_REG);
454 outl(ME4000_AI_MIN_TICKS, dev->iobase + ME4000_AI_CHAN_PRE_TIMER_REG);
456 /* Start conversion by dummy read */
457 inl(dev->iobase + ME4000_AI_START_REG);
459 /* Wait until ready */
461 if (!(inl(dev->iobase + ME4000_AI_STATUS_REG) &
462 ME4000_AI_STATUS_BIT_EF_DATA)) {
464 "comedi%d: me4000: me4000_ai_insn_read(): "
465 "Value not available after wait\n", dev->minor);
469 /* Read value from data fifo */
470 lval = inl(dev->iobase + ME4000_AI_DATA_REG) & 0xFFFF;
471 data[0] = lval ^ 0x8000;
476 static int me4000_ai_cancel(struct comedi_device *dev,
477 struct comedi_subdevice *s)
481 /* Stop any running conversion */
482 tmp = inl(dev->iobase + ME4000_AI_CTRL_REG);
483 tmp &= ~(ME4000_AI_CTRL_BIT_STOP | ME4000_AI_CTRL_BIT_IMMEDIATE_STOP);
484 outl(tmp, dev->iobase + ME4000_AI_CTRL_REG);
486 /* Clear the control register */
487 outl(0x0, dev->iobase + ME4000_AI_CTRL_REG);
492 static int ai_check_chanlist(struct comedi_device *dev,
493 struct comedi_subdevice *s, struct comedi_cmd *cmd)
495 const struct me4000_board *thisboard = comedi_board(dev);
499 /* Check whether a channel list is available */
500 if (!cmd->chanlist_len) {
502 "comedi%d: me4000: ai_check_chanlist(): "
503 "No channel list available\n", dev->minor);
507 /* Check the channel list size */
508 if (cmd->chanlist_len > ME4000_AI_CHANNEL_LIST_COUNT) {
510 "comedi%d: me4000: ai_check_chanlist(): "
511 "Channel list is to large\n", dev->minor);
515 /* Check the pointer */
516 if (!cmd->chanlist) {
518 "comedi%d: me4000: ai_check_chanlist(): "
519 "NULL pointer to channel list\n", dev->minor);
523 /* Check whether aref is equal for all entries */
524 aref = CR_AREF(cmd->chanlist[0]);
525 for (i = 0; i < cmd->chanlist_len; i++) {
526 if (CR_AREF(cmd->chanlist[i]) != aref) {
528 "comedi%d: me4000: ai_check_chanlist(): "
529 "Mode is not equal for all entries\n",
535 /* Check whether channels are available for this ending */
536 if (aref == SDF_DIFF) {
537 for (i = 0; i < cmd->chanlist_len; i++) {
538 if (CR_CHAN(cmd->chanlist[i]) >=
539 thisboard->ai_diff_nchan) {
541 "comedi%d: me4000: ai_check_chanlist():"
542 " Channel number to high\n", dev->minor);
547 for (i = 0; i < cmd->chanlist_len; i++) {
548 if (CR_CHAN(cmd->chanlist[i]) >= thisboard->ai_nchan) {
550 "comedi%d: me4000: ai_check_chanlist(): "
551 "Channel number to high\n", dev->minor);
557 /* Check if bipolar is set for all entries when in differential mode */
558 if (aref == SDF_DIFF) {
559 for (i = 0; i < cmd->chanlist_len; i++) {
560 if (CR_RANGE(cmd->chanlist[i]) != 1 &&
561 CR_RANGE(cmd->chanlist[i]) != 2) {
563 "comedi%d: me4000: ai_check_chanlist(): "
564 "Bipolar is not selected in "
565 "differential mode\n",
575 static int ai_round_cmd_args(struct comedi_device *dev,
576 struct comedi_subdevice *s,
577 struct comedi_cmd *cmd,
578 unsigned int *init_ticks,
579 unsigned int *scan_ticks, unsigned int *chan_ticks)
588 if (cmd->start_arg) {
589 *init_ticks = (cmd->start_arg * 33) / 1000;
590 rest = (cmd->start_arg * 33) % 1000;
592 if ((cmd->flags & TRIG_ROUND_MASK) == TRIG_ROUND_NEAREST) {
595 } else if ((cmd->flags & TRIG_ROUND_MASK) == TRIG_ROUND_UP) {
601 if (cmd->scan_begin_arg) {
602 *scan_ticks = (cmd->scan_begin_arg * 33) / 1000;
603 rest = (cmd->scan_begin_arg * 33) % 1000;
605 if ((cmd->flags & TRIG_ROUND_MASK) == TRIG_ROUND_NEAREST) {
608 } else if ((cmd->flags & TRIG_ROUND_MASK) == TRIG_ROUND_UP) {
614 if (cmd->convert_arg) {
615 *chan_ticks = (cmd->convert_arg * 33) / 1000;
616 rest = (cmd->convert_arg * 33) % 1000;
618 if ((cmd->flags & TRIG_ROUND_MASK) == TRIG_ROUND_NEAREST) {
621 } else if ((cmd->flags & TRIG_ROUND_MASK) == TRIG_ROUND_UP) {
630 static void ai_write_timer(struct comedi_device *dev,
631 unsigned int init_ticks,
632 unsigned int scan_ticks, unsigned int chan_ticks)
634 outl(init_ticks - 1, dev->iobase + ME4000_AI_SCAN_PRE_TIMER_LOW_REG);
635 outl(0x0, dev->iobase + ME4000_AI_SCAN_PRE_TIMER_HIGH_REG);
638 outl(scan_ticks - 1, dev->iobase + ME4000_AI_SCAN_TIMER_LOW_REG);
639 outl(0x0, dev->iobase + ME4000_AI_SCAN_TIMER_HIGH_REG);
642 outl(chan_ticks - 1, dev->iobase + ME4000_AI_CHAN_PRE_TIMER_REG);
643 outl(chan_ticks - 1, dev->iobase + ME4000_AI_CHAN_TIMER_REG);
646 static int ai_write_chanlist(struct comedi_device *dev,
647 struct comedi_subdevice *s, struct comedi_cmd *cmd)
655 for (i = 0; i < cmd->chanlist_len; i++) {
656 chan = CR_CHAN(cmd->chanlist[i]);
657 rang = CR_RANGE(cmd->chanlist[i]);
658 aref = CR_AREF(cmd->chanlist[i]);
663 entry |= ME4000_AI_LIST_RANGE_UNIPOLAR_2_5;
665 entry |= ME4000_AI_LIST_RANGE_UNIPOLAR_10;
667 entry |= ME4000_AI_LIST_RANGE_BIPOLAR_2_5;
669 entry |= ME4000_AI_LIST_RANGE_BIPOLAR_10;
671 if (aref == SDF_DIFF)
672 entry |= ME4000_AI_LIST_INPUT_DIFFERENTIAL;
674 entry |= ME4000_AI_LIST_INPUT_SINGLE_ENDED;
676 outl(entry, dev->iobase + ME4000_AI_CHANNEL_LIST_REG);
682 static int ai_prepare(struct comedi_device *dev,
683 struct comedi_subdevice *s,
684 struct comedi_cmd *cmd,
685 unsigned int init_ticks,
686 unsigned int scan_ticks, unsigned int chan_ticks)
689 unsigned long tmp = 0;
691 /* Write timer arguments */
692 ai_write_timer(dev, init_ticks, scan_ticks, chan_ticks);
694 /* Reset control register */
695 outl(tmp, dev->iobase + ME4000_AI_CTRL_REG);
698 if ((cmd->start_src == TRIG_EXT &&
699 cmd->scan_begin_src == TRIG_TIMER &&
700 cmd->convert_src == TRIG_TIMER) ||
701 (cmd->start_src == TRIG_EXT &&
702 cmd->scan_begin_src == TRIG_FOLLOW &&
703 cmd->convert_src == TRIG_TIMER)) {
704 tmp = ME4000_AI_CTRL_BIT_MODE_1 |
705 ME4000_AI_CTRL_BIT_CHANNEL_FIFO |
706 ME4000_AI_CTRL_BIT_DATA_FIFO;
707 } else if (cmd->start_src == TRIG_EXT &&
708 cmd->scan_begin_src == TRIG_EXT &&
709 cmd->convert_src == TRIG_TIMER) {
710 tmp = ME4000_AI_CTRL_BIT_MODE_2 |
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_EXT) {
716 tmp = ME4000_AI_CTRL_BIT_MODE_0 |
717 ME4000_AI_CTRL_BIT_MODE_1 |
718 ME4000_AI_CTRL_BIT_CHANNEL_FIFO |
719 ME4000_AI_CTRL_BIT_DATA_FIFO;
721 tmp = ME4000_AI_CTRL_BIT_MODE_0 |
722 ME4000_AI_CTRL_BIT_CHANNEL_FIFO |
723 ME4000_AI_CTRL_BIT_DATA_FIFO;
727 if (cmd->stop_src == TRIG_COUNT) {
728 outl(cmd->chanlist_len * cmd->stop_arg,
729 dev->iobase + ME4000_AI_SAMPLE_COUNTER_REG);
730 tmp |= ME4000_AI_CTRL_BIT_HF_IRQ | ME4000_AI_CTRL_BIT_SC_IRQ;
731 } else if (cmd->stop_src == TRIG_NONE &&
732 cmd->scan_end_src == TRIG_COUNT) {
733 outl(cmd->scan_end_arg,
734 dev->iobase + ME4000_AI_SAMPLE_COUNTER_REG);
735 tmp |= ME4000_AI_CTRL_BIT_HF_IRQ | ME4000_AI_CTRL_BIT_SC_IRQ;
737 tmp |= ME4000_AI_CTRL_BIT_HF_IRQ;
740 /* Write the setup to the control register */
741 outl(tmp, dev->iobase + ME4000_AI_CTRL_REG);
743 /* Write the channel list */
744 ai_write_chanlist(dev, s, cmd);
749 static int me4000_ai_do_cmd(struct comedi_device *dev,
750 struct comedi_subdevice *s)
753 unsigned int init_ticks = 0;
754 unsigned int scan_ticks = 0;
755 unsigned int chan_ticks = 0;
756 struct comedi_cmd *cmd = &s->async->cmd;
758 /* Reset the analog input */
759 err = me4000_ai_cancel(dev, s);
763 /* Round the timer arguments */
764 err = ai_round_cmd_args(dev,
765 s, cmd, &init_ticks, &scan_ticks, &chan_ticks);
769 /* Prepare the AI for acquisition */
770 err = ai_prepare(dev, s, cmd, init_ticks, scan_ticks, chan_ticks);
774 /* Start acquistion by dummy read */
775 inl(dev->iobase + ME4000_AI_START_REG);
781 * me4000_ai_do_cmd_test():
783 * The demo cmd.c in ./comedilib/demo specifies 6 return values:
788 * - argument conflict
790 * So I tried to adopt this scheme.
792 static int me4000_ai_do_cmd_test(struct comedi_device *dev,
793 struct comedi_subdevice *s,
794 struct comedi_cmd *cmd)
797 unsigned int init_ticks;
798 unsigned int chan_ticks;
799 unsigned int scan_ticks;
802 /* Only rounding flags are implemented */
803 cmd->flags &= TRIG_ROUND_NEAREST | TRIG_ROUND_UP | TRIG_ROUND_DOWN;
805 /* Round the timer arguments */
806 ai_round_cmd_args(dev, s, cmd, &init_ticks, &scan_ticks, &chan_ticks);
809 * Stage 1. Check if the trigger sources are generally valid.
811 switch (cmd->start_src) {
816 cmd->start_src &= TRIG_NOW | TRIG_EXT;
821 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
822 "Invalid start source\n", dev->minor);
823 cmd->start_src = TRIG_NOW;
826 switch (cmd->scan_begin_src) {
832 cmd->scan_begin_src &= TRIG_FOLLOW | TRIG_TIMER | TRIG_EXT;
837 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
838 "Invalid scan begin source\n", dev->minor);
839 cmd->scan_begin_src = TRIG_FOLLOW;
842 switch (cmd->convert_src) {
847 cmd->convert_src &= TRIG_TIMER | TRIG_EXT;
852 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
853 "Invalid convert source\n", dev->minor);
854 cmd->convert_src = TRIG_TIMER;
857 switch (cmd->scan_end_src) {
862 cmd->scan_end_src &= TRIG_NONE | TRIG_COUNT;
867 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
868 "Invalid scan end source\n", dev->minor);
869 cmd->scan_end_src = TRIG_NONE;
872 switch (cmd->stop_src) {
877 cmd->stop_src &= TRIG_NONE | TRIG_COUNT;
882 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
883 "Invalid stop source\n", dev->minor);
884 cmd->stop_src = TRIG_NONE;
891 * Stage 2. Check for trigger source conflicts.
893 if (cmd->start_src == TRIG_NOW &&
894 cmd->scan_begin_src == TRIG_TIMER &&
895 cmd->convert_src == TRIG_TIMER) {
896 } else if (cmd->start_src == TRIG_NOW &&
897 cmd->scan_begin_src == TRIG_FOLLOW &&
898 cmd->convert_src == TRIG_TIMER) {
899 } else if (cmd->start_src == TRIG_EXT &&
900 cmd->scan_begin_src == TRIG_TIMER &&
901 cmd->convert_src == TRIG_TIMER) {
902 } else if (cmd->start_src == TRIG_EXT &&
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_EXT &&
907 cmd->convert_src == TRIG_TIMER) {
908 } else if (cmd->start_src == TRIG_EXT &&
909 cmd->scan_begin_src == TRIG_EXT &&
910 cmd->convert_src == TRIG_EXT) {
913 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
914 "Invalid start trigger combination\n", dev->minor);
915 cmd->start_src = TRIG_NOW;
916 cmd->scan_begin_src = TRIG_FOLLOW;
917 cmd->convert_src = TRIG_TIMER;
921 if (cmd->stop_src == TRIG_NONE && cmd->scan_end_src == TRIG_NONE) {
922 } else if (cmd->stop_src == TRIG_COUNT &&
923 cmd->scan_end_src == TRIG_NONE) {
924 } else if (cmd->stop_src == TRIG_NONE &&
925 cmd->scan_end_src == TRIG_COUNT) {
926 } else if (cmd->stop_src == TRIG_COUNT &&
927 cmd->scan_end_src == TRIG_COUNT) {
930 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
931 "Invalid stop trigger combination\n", dev->minor);
932 cmd->stop_src = TRIG_NONE;
933 cmd->scan_end_src = TRIG_NONE;
940 * Stage 3. Check if arguments are generally valid.
942 if (cmd->chanlist_len < 1) {
944 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
945 "No channel list\n", dev->minor);
946 cmd->chanlist_len = 1;
949 if (init_ticks < 66) {
951 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
952 "Start arg to low\n", dev->minor);
953 cmd->start_arg = 2000;
956 if (scan_ticks && scan_ticks < 67) {
958 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
959 "Scan begin arg to low\n", dev->minor);
960 cmd->scan_begin_arg = 2031;
963 if (chan_ticks < 66) {
965 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
966 "Convert arg to low\n", dev->minor);
967 cmd->convert_arg = 2000;
975 * Stage 4. Check for argument conflicts.
977 if (cmd->start_src == TRIG_NOW &&
978 cmd->scan_begin_src == TRIG_TIMER &&
979 cmd->convert_src == TRIG_TIMER) {
981 /* Check timer arguments */
982 if (init_ticks < ME4000_AI_MIN_TICKS) {
984 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
985 "Invalid start arg\n", dev->minor);
986 cmd->start_arg = 2000; /* 66 ticks at least */
989 if (chan_ticks < ME4000_AI_MIN_TICKS) {
991 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
992 "Invalid convert arg\n", dev->minor);
993 cmd->convert_arg = 2000; /* 66 ticks at least */
996 if (scan_ticks <= cmd->chanlist_len * chan_ticks) {
998 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
999 "Invalid scan end arg\n", dev->minor);
1001 /* At least one tick more */
1002 cmd->scan_end_arg = 2000 * cmd->chanlist_len + 31;
1005 } else if (cmd->start_src == TRIG_NOW &&
1006 cmd->scan_begin_src == TRIG_FOLLOW &&
1007 cmd->convert_src == TRIG_TIMER) {
1009 /* Check timer arguments */
1010 if (init_ticks < ME4000_AI_MIN_TICKS) {
1012 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1013 "Invalid start arg\n", dev->minor);
1014 cmd->start_arg = 2000; /* 66 ticks at least */
1017 if (chan_ticks < ME4000_AI_MIN_TICKS) {
1019 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1020 "Invalid convert arg\n", dev->minor);
1021 cmd->convert_arg = 2000; /* 66 ticks at least */
1024 } else if (cmd->start_src == TRIG_EXT &&
1025 cmd->scan_begin_src == TRIG_TIMER &&
1026 cmd->convert_src == TRIG_TIMER) {
1028 /* Check timer arguments */
1029 if (init_ticks < ME4000_AI_MIN_TICKS) {
1031 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1032 "Invalid start arg\n", dev->minor);
1033 cmd->start_arg = 2000; /* 66 ticks at least */
1036 if (chan_ticks < ME4000_AI_MIN_TICKS) {
1038 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1039 "Invalid convert arg\n", dev->minor);
1040 cmd->convert_arg = 2000; /* 66 ticks at least */
1043 if (scan_ticks <= cmd->chanlist_len * chan_ticks) {
1045 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1046 "Invalid scan end arg\n", dev->minor);
1048 /* At least one tick more */
1049 cmd->scan_end_arg = 2000 * cmd->chanlist_len + 31;
1052 } else if (cmd->start_src == TRIG_EXT &&
1053 cmd->scan_begin_src == TRIG_FOLLOW &&
1054 cmd->convert_src == TRIG_TIMER) {
1056 /* Check timer arguments */
1057 if (init_ticks < ME4000_AI_MIN_TICKS) {
1059 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1060 "Invalid start arg\n", dev->minor);
1061 cmd->start_arg = 2000; /* 66 ticks at least */
1064 if (chan_ticks < ME4000_AI_MIN_TICKS) {
1066 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1067 "Invalid convert arg\n", dev->minor);
1068 cmd->convert_arg = 2000; /* 66 ticks at least */
1071 } else if (cmd->start_src == TRIG_EXT &&
1072 cmd->scan_begin_src == TRIG_EXT &&
1073 cmd->convert_src == TRIG_TIMER) {
1075 /* Check timer arguments */
1076 if (init_ticks < ME4000_AI_MIN_TICKS) {
1078 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1079 "Invalid start arg\n", dev->minor);
1080 cmd->start_arg = 2000; /* 66 ticks at least */
1083 if (chan_ticks < ME4000_AI_MIN_TICKS) {
1085 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1086 "Invalid convert arg\n", dev->minor);
1087 cmd->convert_arg = 2000; /* 66 ticks at least */
1090 } else if (cmd->start_src == TRIG_EXT &&
1091 cmd->scan_begin_src == TRIG_EXT &&
1092 cmd->convert_src == TRIG_EXT) {
1094 /* Check timer arguments */
1095 if (init_ticks < ME4000_AI_MIN_TICKS) {
1097 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1098 "Invalid start arg\n", dev->minor);
1099 cmd->start_arg = 2000; /* 66 ticks at least */
1103 if (cmd->stop_src == TRIG_COUNT) {
1104 if (cmd->stop_arg == 0) {
1106 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1107 "Invalid stop arg\n", dev->minor);
1112 if (cmd->scan_end_src == TRIG_COUNT) {
1113 if (cmd->scan_end_arg == 0) {
1115 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1116 "Invalid scan end arg\n", dev->minor);
1117 cmd->scan_end_arg = 1;
1126 * Stage 5. Check the channel list.
1128 if (ai_check_chanlist(dev, s, cmd))
1134 static irqreturn_t me4000_ai_isr(int irq, void *dev_id)
1137 struct comedi_device *dev = dev_id;
1138 struct comedi_subdevice *s = &dev->subdevices[0];
1146 /* Reset all events */
1147 s->async->events = 0;
1149 /* Check if irq number is right */
1150 if (irq != dev->irq) {
1152 "comedi%d: me4000: me4000_ai_isr(): "
1153 "Incorrect interrupt num: %d\n", dev->minor, irq);
1157 if (inl(dev->iobase + ME4000_IRQ_STATUS_REG) &
1158 ME4000_IRQ_STATUS_BIT_AI_HF) {
1159 /* Read status register to find out what happened */
1160 tmp = inl(dev->iobase + ME4000_AI_CTRL_REG);
1162 if (!(tmp & ME4000_AI_STATUS_BIT_FF_DATA) &&
1163 !(tmp & ME4000_AI_STATUS_BIT_HF_DATA) &&
1164 (tmp & ME4000_AI_STATUS_BIT_EF_DATA)) {
1165 c = ME4000_AI_FIFO_COUNT;
1168 * FIFO overflow, so stop conversion
1169 * and disable all interrupts
1171 tmp |= ME4000_AI_CTRL_BIT_IMMEDIATE_STOP;
1172 tmp &= ~(ME4000_AI_CTRL_BIT_HF_IRQ |
1173 ME4000_AI_CTRL_BIT_SC_IRQ);
1174 outl(tmp, dev->iobase + ME4000_AI_CTRL_REG);
1176 s->async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
1179 "comedi%d: me4000: me4000_ai_isr(): "
1180 "FIFO overflow\n", dev->minor);
1181 } else if ((tmp & ME4000_AI_STATUS_BIT_FF_DATA)
1182 && !(tmp & ME4000_AI_STATUS_BIT_HF_DATA)
1183 && (tmp & ME4000_AI_STATUS_BIT_EF_DATA)) {
1184 s->async->events |= COMEDI_CB_BLOCK;
1186 c = ME4000_AI_FIFO_COUNT / 2;
1189 "comedi%d: me4000: me4000_ai_isr(): "
1190 "Can't determine state of fifo\n", dev->minor);
1194 * Undefined state, so stop conversion
1195 * and disable all interrupts
1197 tmp |= ME4000_AI_CTRL_BIT_IMMEDIATE_STOP;
1198 tmp &= ~(ME4000_AI_CTRL_BIT_HF_IRQ |
1199 ME4000_AI_CTRL_BIT_SC_IRQ);
1200 outl(tmp, dev->iobase + ME4000_AI_CTRL_REG);
1202 s->async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
1205 "comedi%d: me4000: me4000_ai_isr(): "
1206 "Undefined FIFO state\n", dev->minor);
1209 for (i = 0; i < c; i++) {
1210 /* Read value from data fifo */
1211 lval = inl(dev->iobase + ME4000_AI_DATA_REG) & 0xFFFF;
1214 if (!comedi_buf_put(s->async, lval)) {
1216 * Buffer overflow, so stop conversion
1217 * and disable all interrupts
1219 tmp |= ME4000_AI_CTRL_BIT_IMMEDIATE_STOP;
1220 tmp &= ~(ME4000_AI_CTRL_BIT_HF_IRQ |
1221 ME4000_AI_CTRL_BIT_SC_IRQ);
1222 outl(tmp, dev->iobase + ME4000_AI_CTRL_REG);
1224 s->async->events |= COMEDI_CB_OVERFLOW;
1227 "comedi%d: me4000: me4000_ai_isr(): "
1228 "Buffer overflow\n", dev->minor);
1234 /* Work is done, so reset the interrupt */
1235 tmp |= ME4000_AI_CTRL_BIT_HF_IRQ_RESET;
1236 outl(tmp, dev->iobase + ME4000_AI_CTRL_REG);
1237 tmp &= ~ME4000_AI_CTRL_BIT_HF_IRQ_RESET;
1238 outl(tmp, dev->iobase + ME4000_AI_CTRL_REG);
1241 if (inl(dev->iobase + ME4000_IRQ_STATUS_REG) &
1242 ME4000_IRQ_STATUS_BIT_SC) {
1243 s->async->events |= COMEDI_CB_BLOCK | COMEDI_CB_EOA;
1246 * Acquisition is complete, so stop
1247 * conversion and disable all interrupts
1249 tmp = inl(dev->iobase + ME4000_AI_CTRL_REG);
1250 tmp |= ME4000_AI_CTRL_BIT_IMMEDIATE_STOP;
1251 tmp &= ~(ME4000_AI_CTRL_BIT_HF_IRQ | ME4000_AI_CTRL_BIT_SC_IRQ);
1252 outl(tmp, dev->iobase + ME4000_AI_CTRL_REG);
1254 /* Poll data until fifo empty */
1255 while (inl(dev->iobase + ME4000_AI_CTRL_REG) &
1256 ME4000_AI_STATUS_BIT_EF_DATA) {
1257 /* Read value from data fifo */
1258 lval = inl(dev->iobase + ME4000_AI_DATA_REG) & 0xFFFF;
1261 if (!comedi_buf_put(s->async, lval)) {
1263 "comedi%d: me4000: me4000_ai_isr(): "
1264 "Buffer overflow\n", dev->minor);
1265 s->async->events |= COMEDI_CB_OVERFLOW;
1270 /* Work is done, so reset the interrupt */
1271 tmp |= ME4000_AI_CTRL_BIT_SC_IRQ_RESET;
1272 outl(tmp, dev->iobase + ME4000_AI_CTRL_REG);
1273 tmp &= ~ME4000_AI_CTRL_BIT_SC_IRQ_RESET;
1274 outl(tmp, dev->iobase + ME4000_AI_CTRL_REG);
1277 if (s->async->events)
1278 comedi_event(dev, s);
1283 /*=============================================================================
1284 Analog output section
1285 ===========================================================================*/
1287 static int me4000_ao_insn_write(struct comedi_device *dev,
1288 struct comedi_subdevice *s,
1289 struct comedi_insn *insn, unsigned int *data)
1291 const struct me4000_board *thisboard = comedi_board(dev);
1292 struct me4000_info *info = dev->private;
1293 int chan = CR_CHAN(insn->chanspec);
1294 int rang = CR_RANGE(insn->chanspec);
1295 int aref = CR_AREF(insn->chanspec);
1300 } else if (insn->n > 1) {
1302 "comedi%d: me4000: me4000_ao_insn_write(): "
1303 "Invalid instruction length %d\n", dev->minor, insn->n);
1307 if (chan >= thisboard->ao_nchan) {
1309 "comedi%d: me4000: me4000_ao_insn_write(): "
1310 "Invalid channel %d\n", dev->minor, insn->n);
1316 "comedi%d: me4000: me4000_ao_insn_write(): "
1317 "Invalid range %d\n", dev->minor, insn->n);
1321 if (aref != AREF_GROUND && aref != AREF_COMMON) {
1323 "comedi%d: me4000: me4000_ao_insn_write(): "
1324 "Invalid aref %d\n", dev->minor, insn->n);
1328 /* Stop any running conversion */
1329 tmp = inl(dev->iobase + ME4000_AO_CTRL_REG(chan));
1330 tmp |= ME4000_AO_CTRL_BIT_IMMEDIATE_STOP;
1331 outl(tmp, dev->iobase + ME4000_AO_CTRL_REG(chan));
1333 /* Clear control register and set to single mode */
1334 outl(0x0, dev->iobase + ME4000_AO_CTRL_REG(chan));
1336 /* Write data value */
1337 outl(data[0], dev->iobase + ME4000_AO_SINGLE_REG(chan));
1339 /* Store in the mirror */
1340 info->ao_readback[chan] = data[0];
1345 static int me4000_ao_insn_read(struct comedi_device *dev,
1346 struct comedi_subdevice *s,
1347 struct comedi_insn *insn, unsigned int *data)
1349 struct me4000_info *info = dev->private;
1350 int chan = CR_CHAN(insn->chanspec);
1354 } else if (insn->n > 1) {
1356 ("comedi%d: me4000: me4000_ao_insn_read(): "
1357 "Invalid instruction length\n", dev->minor);
1361 data[0] = info->ao_readback[chan];
1366 /*=============================================================================
1368 ===========================================================================*/
1370 static int me4000_dio_insn_bits(struct comedi_device *dev,
1371 struct comedi_subdevice *s,
1372 struct comedi_insn *insn, unsigned int *data)
1375 * The insn data consists of a mask in data[0] and the new data
1376 * in data[1]. The mask defines which bits we are concerning about.
1377 * The new data must be anded with the mask.
1378 * Each channel corresponds to a bit.
1381 /* Check if requested ports are configured for output */
1382 if ((s->io_bits & data[0]) != data[0])
1385 s->state &= ~data[0];
1386 s->state |= data[0] & data[1];
1388 /* Write out the new digital output lines */
1389 outl((s->state >> 0) & 0xFF,
1390 dev->iobase + ME4000_DIO_PORT_0_REG);
1391 outl((s->state >> 8) & 0xFF,
1392 dev->iobase + ME4000_DIO_PORT_1_REG);
1393 outl((s->state >> 16) & 0xFF,
1394 dev->iobase + ME4000_DIO_PORT_2_REG);
1395 outl((s->state >> 24) & 0xFF,
1396 dev->iobase + ME4000_DIO_PORT_3_REG);
1399 /* On return, data[1] contains the value of
1400 the digital input and output lines. */
1401 data[1] = ((inl(dev->iobase + ME4000_DIO_PORT_0_REG) & 0xFF) << 0) |
1402 ((inl(dev->iobase + ME4000_DIO_PORT_1_REG) & 0xFF) << 8) |
1403 ((inl(dev->iobase + ME4000_DIO_PORT_2_REG) & 0xFF) << 16) |
1404 ((inl(dev->iobase + ME4000_DIO_PORT_3_REG) & 0xFF) << 24);
1409 static int me4000_dio_insn_config(struct comedi_device *dev,
1410 struct comedi_subdevice *s,
1411 struct comedi_insn *insn, unsigned int *data)
1414 int chan = CR_CHAN(insn->chanspec);
1419 case INSN_CONFIG_DIO_QUERY:
1421 (s->io_bits & (1 << chan)) ? COMEDI_OUTPUT : COMEDI_INPUT;
1423 case INSN_CONFIG_DIO_INPUT:
1424 case INSN_CONFIG_DIO_OUTPUT:
1429 * The input or output configuration of each digital line is
1430 * configured by a special insn_config instruction. chanspec
1431 * contains the channel to be changed, and data[0] contains the
1432 * value INSN_CONFIG_DIO_INPUT or INSN_CONFIG_DIO_OUTPUT.
1433 * On the ME-4000 it is only possible to switch port wise (8 bit)
1436 tmp = inl(dev->iobase + ME4000_DIO_CTRL_REG);
1438 if (data[0] == INSN_CONFIG_DIO_OUTPUT) {
1441 tmp &= ~(ME4000_DIO_CTRL_BIT_MODE_0 |
1442 ME4000_DIO_CTRL_BIT_MODE_1);
1443 tmp |= ME4000_DIO_CTRL_BIT_MODE_0;
1444 } else if (chan < 16) {
1446 * Chech for optoisolated ME-4000 version.
1447 * If one the first port is a fixed output
1448 * port and the second is a fixed input port.
1450 if (!inl(dev->iobase + ME4000_DIO_DIR_REG))
1453 s->io_bits |= 0xFF00;
1454 tmp &= ~(ME4000_DIO_CTRL_BIT_MODE_2 |
1455 ME4000_DIO_CTRL_BIT_MODE_3);
1456 tmp |= ME4000_DIO_CTRL_BIT_MODE_2;
1457 } else if (chan < 24) {
1458 s->io_bits |= 0xFF0000;
1459 tmp &= ~(ME4000_DIO_CTRL_BIT_MODE_4 |
1460 ME4000_DIO_CTRL_BIT_MODE_5);
1461 tmp |= ME4000_DIO_CTRL_BIT_MODE_4;
1462 } else if (chan < 32) {
1463 s->io_bits |= 0xFF000000;
1464 tmp &= ~(ME4000_DIO_CTRL_BIT_MODE_6 |
1465 ME4000_DIO_CTRL_BIT_MODE_7);
1466 tmp |= ME4000_DIO_CTRL_BIT_MODE_6;
1473 * Chech for optoisolated ME-4000 version.
1474 * If one the first port is a fixed output
1475 * port and the second is a fixed input port.
1477 if (!inl(dev->iobase + ME4000_DIO_DIR_REG))
1480 s->io_bits &= ~0xFF;
1481 tmp &= ~(ME4000_DIO_CTRL_BIT_MODE_0 |
1482 ME4000_DIO_CTRL_BIT_MODE_1);
1483 } else if (chan < 16) {
1484 s->io_bits &= ~0xFF00;
1485 tmp &= ~(ME4000_DIO_CTRL_BIT_MODE_2 |
1486 ME4000_DIO_CTRL_BIT_MODE_3);
1487 } else if (chan < 24) {
1488 s->io_bits &= ~0xFF0000;
1489 tmp &= ~(ME4000_DIO_CTRL_BIT_MODE_4 |
1490 ME4000_DIO_CTRL_BIT_MODE_5);
1491 } else if (chan < 32) {
1492 s->io_bits &= ~0xFF000000;
1493 tmp &= ~(ME4000_DIO_CTRL_BIT_MODE_6 |
1494 ME4000_DIO_CTRL_BIT_MODE_7);
1500 outl(tmp, dev->iobase + ME4000_DIO_CTRL_REG);
1505 /*=============================================================================
1507 ===========================================================================*/
1509 static int cnt_reset(struct comedi_device *dev, unsigned int channel)
1511 struct me4000_info *info = dev->private;
1515 outb(0x30, info->timer_regbase + ME4000_CNT_CTRL_REG);
1516 outb(0x00, info->timer_regbase + ME4000_CNT_COUNTER_0_REG);
1517 outb(0x00, info->timer_regbase + ME4000_CNT_COUNTER_0_REG);
1520 outb(0x70, info->timer_regbase + ME4000_CNT_CTRL_REG);
1521 outb(0x00, info->timer_regbase + ME4000_CNT_COUNTER_1_REG);
1522 outb(0x00, info->timer_regbase + ME4000_CNT_COUNTER_1_REG);
1525 outb(0xB0, info->timer_regbase + ME4000_CNT_CTRL_REG);
1526 outb(0x00, info->timer_regbase + ME4000_CNT_COUNTER_2_REG);
1527 outb(0x00, info->timer_regbase + ME4000_CNT_COUNTER_2_REG);
1531 "comedi%d: me4000: cnt_reset(): Invalid channel\n",
1539 static int cnt_config(struct comedi_device *dev, unsigned int channel,
1542 struct me4000_info *info = dev->private;
1547 tmp |= ME4000_CNT_COUNTER_0;
1550 tmp |= ME4000_CNT_COUNTER_1;
1553 tmp |= ME4000_CNT_COUNTER_2;
1557 "comedi%d: me4000: cnt_config(): Invalid channel\n",
1564 tmp |= ME4000_CNT_MODE_0;
1567 tmp |= ME4000_CNT_MODE_1;
1570 tmp |= ME4000_CNT_MODE_2;
1573 tmp |= ME4000_CNT_MODE_3;
1576 tmp |= ME4000_CNT_MODE_4;
1579 tmp |= ME4000_CNT_MODE_5;
1583 "comedi%d: me4000: cnt_config(): Invalid counter mode\n",
1588 /* Write the control word */
1590 outb(tmp, info->timer_regbase + ME4000_CNT_CTRL_REG);
1595 static int me4000_cnt_insn_config(struct comedi_device *dev,
1596 struct comedi_subdevice *s,
1597 struct comedi_insn *insn, unsigned int *data)
1606 "comedi%d: me4000: me4000_cnt_insn_config(): "
1607 "Invalid instruction length%d\n",
1608 dev->minor, insn->n);
1612 err = cnt_reset(dev, insn->chanspec);
1616 case GPCT_SET_OPERATION:
1619 "comedi%d: me4000: me4000_cnt_insn_config(): "
1620 "Invalid instruction length%d\n",
1621 dev->minor, insn->n);
1625 err = cnt_config(dev, insn->chanspec, data[1]);
1631 "comedi%d: me4000: me4000_cnt_insn_config(): "
1632 "Invalid instruction\n", dev->minor);
1639 static int me4000_cnt_insn_read(struct comedi_device *dev,
1640 struct comedi_subdevice *s,
1641 struct comedi_insn *insn, unsigned int *data)
1643 struct me4000_info *info = dev->private;
1651 "comedi%d: me4000: me4000_cnt_insn_read(): "
1652 "Invalid instruction length %d\n",
1653 dev->minor, insn->n);
1657 switch (insn->chanspec) {
1659 tmp = inb(info->timer_regbase + ME4000_CNT_COUNTER_0_REG);
1661 tmp = inb(info->timer_regbase + ME4000_CNT_COUNTER_0_REG);
1662 data[0] |= tmp << 8;
1665 tmp = inb(info->timer_regbase + ME4000_CNT_COUNTER_1_REG);
1667 tmp = inb(info->timer_regbase + ME4000_CNT_COUNTER_1_REG);
1668 data[0] |= tmp << 8;
1671 tmp = inb(info->timer_regbase + ME4000_CNT_COUNTER_2_REG);
1673 tmp = inb(info->timer_regbase + ME4000_CNT_COUNTER_2_REG);
1674 data[0] |= tmp << 8;
1678 "comedi%d: me4000: me4000_cnt_insn_read(): "
1679 "Invalid channel %d\n",
1680 dev->minor, insn->chanspec);
1687 static int me4000_cnt_insn_write(struct comedi_device *dev,
1688 struct comedi_subdevice *s,
1689 struct comedi_insn *insn, unsigned int *data)
1691 struct me4000_info *info = dev->private;
1696 } else if (insn->n > 1) {
1698 "comedi%d: me4000: me4000_cnt_insn_write(): "
1699 "Invalid instruction length %d\n",
1700 dev->minor, insn->n);
1704 switch (insn->chanspec) {
1706 tmp = data[0] & 0xFF;
1707 outb(tmp, info->timer_regbase + ME4000_CNT_COUNTER_0_REG);
1708 tmp = (data[0] >> 8) & 0xFF;
1709 outb(tmp, info->timer_regbase + ME4000_CNT_COUNTER_0_REG);
1712 tmp = data[0] & 0xFF;
1713 outb(tmp, info->timer_regbase + ME4000_CNT_COUNTER_1_REG);
1714 tmp = (data[0] >> 8) & 0xFF;
1715 outb(tmp, info->timer_regbase + ME4000_CNT_COUNTER_1_REG);
1718 tmp = data[0] & 0xFF;
1719 outb(tmp, info->timer_regbase + ME4000_CNT_COUNTER_2_REG);
1720 tmp = (data[0] >> 8) & 0xFF;
1721 outb(tmp, info->timer_regbase + ME4000_CNT_COUNTER_2_REG);
1725 "comedi%d: me4000: me4000_cnt_insn_write(): "
1726 "Invalid channel %d\n",
1727 dev->minor, insn->chanspec);
1734 static const void *me4000_find_boardinfo(struct comedi_device *dev,
1735 struct pci_dev *pcidev)
1737 const struct me4000_board *thisboard;
1740 for (i = 0; i < ARRAY_SIZE(me4000_boards); i++) {
1741 thisboard = &me4000_boards[i];
1742 if (thisboard->device_id == pcidev->device)
1748 static int me4000_attach_pci(struct comedi_device *dev,
1749 struct pci_dev *pcidev)
1751 const struct me4000_board *thisboard;
1752 struct me4000_info *info;
1753 struct comedi_subdevice *s;
1756 comedi_set_hw_dev(dev, &pcidev->dev);
1758 thisboard = me4000_find_boardinfo(dev, pcidev);
1761 dev->board_ptr = thisboard;
1762 dev->board_name = thisboard->name;
1764 result = alloc_private(dev, sizeof(*info));
1767 info = dev->private;
1769 result = comedi_pci_enable(pcidev, dev->board_name);
1773 info->plx_regbase = pci_resource_start(pcidev, 1);
1774 if (!info->plx_regbase)
1777 dev->iobase = pci_resource_start(pcidev, 2);
1781 info->timer_regbase = pci_resource_start(pcidev, 3);
1782 if (!info->timer_regbase)
1785 info->program_regbase = pci_resource_start(pcidev, 5);
1786 if (!info->program_regbase)
1789 dev->irq = pcidev->irq;
1791 result = xilinx_download(dev);
1795 result = reset_board(dev);
1799 result = comedi_alloc_subdevices(dev, 4);
1803 /*=========================================================================
1804 Analog input subdevice
1805 ========================================================================*/
1807 s = &dev->subdevices[0];
1809 if (thisboard->ai_nchan) {
1810 s->type = COMEDI_SUBD_AI;
1812 SDF_READABLE | SDF_COMMON | SDF_GROUND | SDF_DIFF;
1813 s->n_chan = thisboard->ai_nchan;
1814 s->maxdata = 0xFFFF; /* 16 bit ADC */
1815 s->len_chanlist = ME4000_AI_CHANNEL_LIST_COUNT;
1816 s->range_table = &me4000_ai_range;
1817 s->insn_read = me4000_ai_insn_read;
1820 if (request_irq(dev->irq, me4000_ai_isr,
1821 IRQF_SHARED, "ME-4000", dev)) {
1823 ("comedi%d: me4000: me4000_attach(): "
1824 "Unable to allocate irq\n", dev->minor);
1826 dev->read_subdev = s;
1827 s->subdev_flags |= SDF_CMD_READ;
1828 s->cancel = me4000_ai_cancel;
1829 s->do_cmdtest = me4000_ai_do_cmd_test;
1830 s->do_cmd = me4000_ai_do_cmd;
1834 "comedi%d: me4000: me4000_attach(): "
1835 "No interrupt available\n", dev->minor);
1838 s->type = COMEDI_SUBD_UNUSED;
1841 /*=========================================================================
1842 Analog output subdevice
1843 ========================================================================*/
1845 s = &dev->subdevices[1];
1847 if (thisboard->ao_nchan) {
1848 s->type = COMEDI_SUBD_AO;
1849 s->subdev_flags = SDF_WRITEABLE | SDF_COMMON | SDF_GROUND;
1850 s->n_chan = thisboard->ao_nchan;
1851 s->maxdata = 0xFFFF; /* 16 bit DAC */
1852 s->range_table = &range_bipolar10;
1853 s->insn_write = me4000_ao_insn_write;
1854 s->insn_read = me4000_ao_insn_read;
1856 s->type = COMEDI_SUBD_UNUSED;
1859 /*=========================================================================
1860 Digital I/O subdevice
1861 ========================================================================*/
1863 s = &dev->subdevices[2];
1865 if (thisboard->dio_nchan) {
1866 s->type = COMEDI_SUBD_DIO;
1867 s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
1868 s->n_chan = thisboard->dio_nchan;
1870 s->range_table = &range_digital;
1871 s->insn_bits = me4000_dio_insn_bits;
1872 s->insn_config = me4000_dio_insn_config;
1874 s->type = COMEDI_SUBD_UNUSED;
1878 * Check for optoisolated ME-4000 version. If one the first
1879 * port is a fixed output port and the second is a fixed input port.
1881 if (!inl(dev->iobase + ME4000_DIO_DIR_REG)) {
1883 outl(ME4000_DIO_CTRL_BIT_MODE_0,
1884 dev->iobase + ME4000_DIO_DIR_REG);
1887 /*=========================================================================
1889 ========================================================================*/
1891 s = &dev->subdevices[3];
1893 if (thisboard->has_counter) {
1894 s->type = COMEDI_SUBD_COUNTER;
1895 s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
1897 s->maxdata = 0xFFFF; /* 16 bit counters */
1898 s->insn_read = me4000_cnt_insn_read;
1899 s->insn_write = me4000_cnt_insn_write;
1900 s->insn_config = me4000_cnt_insn_config;
1902 s->type = COMEDI_SUBD_UNUSED;
1908 static void me4000_detach(struct comedi_device *dev)
1910 struct pci_dev *pcidev = comedi_to_pci_dev(dev);
1915 comedi_pci_disable(pcidev);
1920 static struct comedi_driver me4000_driver = {
1921 .driver_name = "me4000",
1922 .module = THIS_MODULE,
1923 .attach_pci = me4000_attach_pci,
1924 .detach = me4000_detach,
1927 static int __devinit me4000_pci_probe(struct pci_dev *dev,
1928 const struct pci_device_id *ent)
1930 return comedi_pci_auto_config(dev, &me4000_driver);
1933 static void __devexit me4000_pci_remove(struct pci_dev *dev)
1935 comedi_pci_auto_unconfig(dev);
1938 static DEFINE_PCI_DEVICE_TABLE(me4000_pci_table) = {
1939 {PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4650)},
1940 {PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4660)},
1941 {PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4660I)},
1942 {PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4660S)},
1943 {PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4660IS)},
1944 {PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4670)},
1945 {PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4670I)},
1946 {PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4670S)},
1947 {PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4670IS)},
1948 {PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4680)},
1949 {PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4680I)},
1950 {PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4680S)},
1951 {PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4680IS)},
1954 MODULE_DEVICE_TABLE(pci, me4000_pci_table);
1956 static struct pci_driver me4000_pci_driver = {
1958 .id_table = me4000_pci_table,
1959 .probe = me4000_pci_probe,
1960 .remove = __devexit_p(me4000_pci_remove),
1962 module_comedi_pci_driver(me4000_driver, me4000_pci_driver);
1964 MODULE_AUTHOR("Comedi http://www.comedi.org");
1965 MODULE_DESCRIPTION("Comedi low-level driver");
1966 MODULE_LICENSE("GPL");