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 pci_dev *pcidev = comedi_to_pci_dev(dev);
227 struct me4000_info *info = dev->private;
228 unsigned long xilinx_iobase = pci_resource_start(pcidev, 5);
230 wait_queue_head_t queue;
237 init_waitqueue_head(&queue);
240 * Set PLX local interrupt 2 polarity to high.
241 * Interrupt is thrown by init pin of xilinx.
243 outl(0x10, info->plx_regbase + PLX_INTCSR);
245 /* Set /CS and /WRITE of the Xilinx */
246 value = inl(info->plx_regbase + PLX_ICR);
248 outl(value, info->plx_regbase + PLX_ICR);
250 /* Init Xilinx with CS1 */
251 inb(xilinx_iobase + 0xC8);
253 /* Wait until /INIT pin is set */
255 if (!(inl(info->plx_regbase + PLX_INTCSR) & 0x20)) {
257 "comedi%d: me4000: xilinx_download(): "
258 "Can't init Xilinx\n", dev->minor);
262 /* Reset /CS and /WRITE of the Xilinx */
263 value = inl(info->plx_regbase + PLX_ICR);
265 outl(value, info->plx_regbase + PLX_ICR);
266 if (FIRMWARE_NOT_AVAILABLE) {
267 comedi_error(dev, "xilinx firmware unavailable "
268 "due to licensing, aborting");
271 /* Download Xilinx firmware */
272 size = (xilinx_firm[0] << 24) + (xilinx_firm[1] << 16) +
273 (xilinx_firm[2] << 8) + xilinx_firm[3];
276 for (idx = 0; idx < size; idx++) {
277 outb(xilinx_firm[16 + idx], xilinx_iobase);
280 /* Check if BUSY flag is low */
281 if (inl(info->plx_regbase + PLX_ICR) & 0x20) {
283 "comedi%d: me4000: xilinx_download(): "
284 "Xilinx is still busy (idx = %d)\n",
291 /* If done flag is high download was successful */
292 if (inl(info->plx_regbase + PLX_ICR) & 0x4) {
295 "comedi%d: me4000: xilinx_download(): "
296 "DONE flag is not set\n", dev->minor);
298 "comedi%d: me4000: xilinx_download(): "
299 "Download not successful\n", dev->minor);
303 /* Set /CS and /WRITE */
304 value = inl(info->plx_regbase + PLX_ICR);
306 outl(value, info->plx_regbase + PLX_ICR);
311 static int reset_board(struct comedi_device *dev)
313 struct me4000_info *info = dev->private;
317 /* Make a hardware reset */
318 val = inl(info->plx_regbase + PLX_ICR);
320 outl(val, info->plx_regbase + PLX_ICR);
322 outl(val , info->plx_regbase + PLX_ICR);
324 /* 0x8000 to the DACs means an output voltage of 0V */
325 for (chan = 0; chan < 4; chan++)
326 outl(0x8000, dev->iobase + ME4000_AO_SINGLE_REG(chan));
328 /* Set both stop bits in the analog input control register */
329 outl(ME4000_AI_CTRL_BIT_IMMEDIATE_STOP | ME4000_AI_CTRL_BIT_STOP,
330 dev->iobase + ME4000_AI_CTRL_REG);
332 /* Set both stop bits in the analog output control register */
333 val = ME4000_AO_CTRL_BIT_IMMEDIATE_STOP | ME4000_AO_CTRL_BIT_STOP;
334 for (chan = 0; chan < 4; chan++)
335 outl(val, dev->iobase + ME4000_AO_CTRL_REG(chan));
337 /* Enable interrupts on the PLX */
338 outl(0x43, info->plx_regbase + PLX_INTCSR);
340 /* Set the adustment register for AO demux */
341 outl(ME4000_AO_DEMUX_ADJUST_VALUE,
342 dev->iobase + ME4000_AO_DEMUX_ADJUST_REG);
345 * Set digital I/O direction for port 0
346 * to output on isolated versions
348 if (!(inl(dev->iobase + ME4000_DIO_DIR_REG) & 0x1))
349 outl(0x1, dev->iobase + ME4000_DIO_CTRL_REG);
354 /*=============================================================================
356 ===========================================================================*/
358 static int me4000_ai_insn_read(struct comedi_device *dev,
359 struct comedi_subdevice *subdevice,
360 struct comedi_insn *insn, unsigned int *data)
362 const struct me4000_board *thisboard = comedi_board(dev);
363 int chan = CR_CHAN(insn->chanspec);
364 int rang = CR_RANGE(insn->chanspec);
365 int aref = CR_AREF(insn->chanspec);
367 unsigned long entry = 0;
373 } else if (insn->n > 1) {
375 "comedi%d: me4000: me4000_ai_insn_read(): "
376 "Invalid instruction length %d\n", dev->minor, insn->n);
382 entry |= ME4000_AI_LIST_RANGE_UNIPOLAR_2_5;
385 entry |= ME4000_AI_LIST_RANGE_UNIPOLAR_10;
388 entry |= ME4000_AI_LIST_RANGE_BIPOLAR_2_5;
391 entry |= ME4000_AI_LIST_RANGE_BIPOLAR_10;
395 "comedi%d: me4000: me4000_ai_insn_read(): "
396 "Invalid range specified\n", dev->minor);
403 if (chan >= thisboard->ai_nchan) {
405 "comedi%d: me4000: me4000_ai_insn_read(): "
406 "Analog input is not available\n", dev->minor);
409 entry |= ME4000_AI_LIST_INPUT_SINGLE_ENDED | chan;
413 if (rang == 0 || rang == 1) {
415 "comedi%d: me4000: me4000_ai_insn_read(): "
416 "Range must be bipolar when aref = diff\n",
421 if (chan >= thisboard->ai_diff_nchan) {
423 "comedi%d: me4000: me4000_ai_insn_read(): "
424 "Analog input is not available\n", dev->minor);
427 entry |= ME4000_AI_LIST_INPUT_DIFFERENTIAL | chan;
431 "comedi%d: me4000: me4000_ai_insn_read(): "
432 "Invalid aref specified\n", dev->minor);
436 entry |= ME4000_AI_LIST_LAST_ENTRY;
438 /* Clear channel list, data fifo and both stop bits */
439 tmp = inl(dev->iobase + ME4000_AI_CTRL_REG);
440 tmp &= ~(ME4000_AI_CTRL_BIT_CHANNEL_FIFO |
441 ME4000_AI_CTRL_BIT_DATA_FIFO |
442 ME4000_AI_CTRL_BIT_STOP | ME4000_AI_CTRL_BIT_IMMEDIATE_STOP);
443 outl(tmp, dev->iobase + ME4000_AI_CTRL_REG);
445 /* Set the acquisition mode to single */
446 tmp &= ~(ME4000_AI_CTRL_BIT_MODE_0 | ME4000_AI_CTRL_BIT_MODE_1 |
447 ME4000_AI_CTRL_BIT_MODE_2);
448 outl(tmp, dev->iobase + ME4000_AI_CTRL_REG);
450 /* Enable channel list and data fifo */
451 tmp |= ME4000_AI_CTRL_BIT_CHANNEL_FIFO | ME4000_AI_CTRL_BIT_DATA_FIFO;
452 outl(tmp, dev->iobase + ME4000_AI_CTRL_REG);
454 /* Generate channel list entry */
455 outl(entry, dev->iobase + ME4000_AI_CHANNEL_LIST_REG);
457 /* Set the timer to maximum sample rate */
458 outl(ME4000_AI_MIN_TICKS, dev->iobase + ME4000_AI_CHAN_TIMER_REG);
459 outl(ME4000_AI_MIN_TICKS, dev->iobase + ME4000_AI_CHAN_PRE_TIMER_REG);
461 /* Start conversion by dummy read */
462 inl(dev->iobase + ME4000_AI_START_REG);
464 /* Wait until ready */
466 if (!(inl(dev->iobase + ME4000_AI_STATUS_REG) &
467 ME4000_AI_STATUS_BIT_EF_DATA)) {
469 "comedi%d: me4000: me4000_ai_insn_read(): "
470 "Value not available after wait\n", dev->minor);
474 /* Read value from data fifo */
475 lval = inl(dev->iobase + ME4000_AI_DATA_REG) & 0xFFFF;
476 data[0] = lval ^ 0x8000;
481 static int me4000_ai_cancel(struct comedi_device *dev,
482 struct comedi_subdevice *s)
486 /* Stop any running conversion */
487 tmp = inl(dev->iobase + ME4000_AI_CTRL_REG);
488 tmp &= ~(ME4000_AI_CTRL_BIT_STOP | ME4000_AI_CTRL_BIT_IMMEDIATE_STOP);
489 outl(tmp, dev->iobase + ME4000_AI_CTRL_REG);
491 /* Clear the control register */
492 outl(0x0, dev->iobase + ME4000_AI_CTRL_REG);
497 static int ai_check_chanlist(struct comedi_device *dev,
498 struct comedi_subdevice *s, struct comedi_cmd *cmd)
500 const struct me4000_board *thisboard = comedi_board(dev);
504 /* Check whether a channel list is available */
505 if (!cmd->chanlist_len) {
507 "comedi%d: me4000: ai_check_chanlist(): "
508 "No channel list available\n", dev->minor);
512 /* Check the channel list size */
513 if (cmd->chanlist_len > ME4000_AI_CHANNEL_LIST_COUNT) {
515 "comedi%d: me4000: ai_check_chanlist(): "
516 "Channel list is to large\n", dev->minor);
520 /* Check the pointer */
521 if (!cmd->chanlist) {
523 "comedi%d: me4000: ai_check_chanlist(): "
524 "NULL pointer to channel list\n", dev->minor);
528 /* Check whether aref is equal for all entries */
529 aref = CR_AREF(cmd->chanlist[0]);
530 for (i = 0; i < cmd->chanlist_len; i++) {
531 if (CR_AREF(cmd->chanlist[i]) != aref) {
533 "comedi%d: me4000: ai_check_chanlist(): "
534 "Mode is not equal for all entries\n",
540 /* Check whether channels are available for this ending */
541 if (aref == SDF_DIFF) {
542 for (i = 0; i < cmd->chanlist_len; i++) {
543 if (CR_CHAN(cmd->chanlist[i]) >=
544 thisboard->ai_diff_nchan) {
546 "comedi%d: me4000: ai_check_chanlist():"
547 " Channel number to high\n", dev->minor);
552 for (i = 0; i < cmd->chanlist_len; i++) {
553 if (CR_CHAN(cmd->chanlist[i]) >= thisboard->ai_nchan) {
555 "comedi%d: me4000: ai_check_chanlist(): "
556 "Channel number to high\n", dev->minor);
562 /* Check if bipolar is set for all entries when in differential mode */
563 if (aref == SDF_DIFF) {
564 for (i = 0; i < cmd->chanlist_len; i++) {
565 if (CR_RANGE(cmd->chanlist[i]) != 1 &&
566 CR_RANGE(cmd->chanlist[i]) != 2) {
568 "comedi%d: me4000: ai_check_chanlist(): "
569 "Bipolar is not selected in "
570 "differential mode\n",
580 static int ai_round_cmd_args(struct comedi_device *dev,
581 struct comedi_subdevice *s,
582 struct comedi_cmd *cmd,
583 unsigned int *init_ticks,
584 unsigned int *scan_ticks, unsigned int *chan_ticks)
593 if (cmd->start_arg) {
594 *init_ticks = (cmd->start_arg * 33) / 1000;
595 rest = (cmd->start_arg * 33) % 1000;
597 if ((cmd->flags & TRIG_ROUND_MASK) == TRIG_ROUND_NEAREST) {
600 } else if ((cmd->flags & TRIG_ROUND_MASK) == TRIG_ROUND_UP) {
606 if (cmd->scan_begin_arg) {
607 *scan_ticks = (cmd->scan_begin_arg * 33) / 1000;
608 rest = (cmd->scan_begin_arg * 33) % 1000;
610 if ((cmd->flags & TRIG_ROUND_MASK) == TRIG_ROUND_NEAREST) {
613 } else if ((cmd->flags & TRIG_ROUND_MASK) == TRIG_ROUND_UP) {
619 if (cmd->convert_arg) {
620 *chan_ticks = (cmd->convert_arg * 33) / 1000;
621 rest = (cmd->convert_arg * 33) % 1000;
623 if ((cmd->flags & TRIG_ROUND_MASK) == TRIG_ROUND_NEAREST) {
626 } else if ((cmd->flags & TRIG_ROUND_MASK) == TRIG_ROUND_UP) {
635 static void ai_write_timer(struct comedi_device *dev,
636 unsigned int init_ticks,
637 unsigned int scan_ticks, unsigned int chan_ticks)
639 outl(init_ticks - 1, dev->iobase + ME4000_AI_SCAN_PRE_TIMER_LOW_REG);
640 outl(0x0, dev->iobase + ME4000_AI_SCAN_PRE_TIMER_HIGH_REG);
643 outl(scan_ticks - 1, dev->iobase + ME4000_AI_SCAN_TIMER_LOW_REG);
644 outl(0x0, dev->iobase + ME4000_AI_SCAN_TIMER_HIGH_REG);
647 outl(chan_ticks - 1, dev->iobase + ME4000_AI_CHAN_PRE_TIMER_REG);
648 outl(chan_ticks - 1, dev->iobase + ME4000_AI_CHAN_TIMER_REG);
651 static int ai_write_chanlist(struct comedi_device *dev,
652 struct comedi_subdevice *s, struct comedi_cmd *cmd)
660 for (i = 0; i < cmd->chanlist_len; i++) {
661 chan = CR_CHAN(cmd->chanlist[i]);
662 rang = CR_RANGE(cmd->chanlist[i]);
663 aref = CR_AREF(cmd->chanlist[i]);
668 entry |= ME4000_AI_LIST_RANGE_UNIPOLAR_2_5;
670 entry |= ME4000_AI_LIST_RANGE_UNIPOLAR_10;
672 entry |= ME4000_AI_LIST_RANGE_BIPOLAR_2_5;
674 entry |= ME4000_AI_LIST_RANGE_BIPOLAR_10;
676 if (aref == SDF_DIFF)
677 entry |= ME4000_AI_LIST_INPUT_DIFFERENTIAL;
679 entry |= ME4000_AI_LIST_INPUT_SINGLE_ENDED;
681 outl(entry, dev->iobase + ME4000_AI_CHANNEL_LIST_REG);
687 static int ai_prepare(struct comedi_device *dev,
688 struct comedi_subdevice *s,
689 struct comedi_cmd *cmd,
690 unsigned int init_ticks,
691 unsigned int scan_ticks, unsigned int chan_ticks)
694 unsigned long tmp = 0;
696 /* Write timer arguments */
697 ai_write_timer(dev, init_ticks, scan_ticks, chan_ticks);
699 /* Reset control register */
700 outl(tmp, dev->iobase + ME4000_AI_CTRL_REG);
703 if ((cmd->start_src == TRIG_EXT &&
704 cmd->scan_begin_src == TRIG_TIMER &&
705 cmd->convert_src == TRIG_TIMER) ||
706 (cmd->start_src == TRIG_EXT &&
707 cmd->scan_begin_src == TRIG_FOLLOW &&
708 cmd->convert_src == TRIG_TIMER)) {
709 tmp = ME4000_AI_CTRL_BIT_MODE_1 |
710 ME4000_AI_CTRL_BIT_CHANNEL_FIFO |
711 ME4000_AI_CTRL_BIT_DATA_FIFO;
712 } else if (cmd->start_src == TRIG_EXT &&
713 cmd->scan_begin_src == TRIG_EXT &&
714 cmd->convert_src == TRIG_TIMER) {
715 tmp = ME4000_AI_CTRL_BIT_MODE_2 |
716 ME4000_AI_CTRL_BIT_CHANNEL_FIFO |
717 ME4000_AI_CTRL_BIT_DATA_FIFO;
718 } else if (cmd->start_src == TRIG_EXT &&
719 cmd->scan_begin_src == TRIG_EXT &&
720 cmd->convert_src == TRIG_EXT) {
721 tmp = ME4000_AI_CTRL_BIT_MODE_0 |
722 ME4000_AI_CTRL_BIT_MODE_1 |
723 ME4000_AI_CTRL_BIT_CHANNEL_FIFO |
724 ME4000_AI_CTRL_BIT_DATA_FIFO;
726 tmp = ME4000_AI_CTRL_BIT_MODE_0 |
727 ME4000_AI_CTRL_BIT_CHANNEL_FIFO |
728 ME4000_AI_CTRL_BIT_DATA_FIFO;
732 if (cmd->stop_src == TRIG_COUNT) {
733 outl(cmd->chanlist_len * cmd->stop_arg,
734 dev->iobase + ME4000_AI_SAMPLE_COUNTER_REG);
735 tmp |= ME4000_AI_CTRL_BIT_HF_IRQ | ME4000_AI_CTRL_BIT_SC_IRQ;
736 } else if (cmd->stop_src == TRIG_NONE &&
737 cmd->scan_end_src == TRIG_COUNT) {
738 outl(cmd->scan_end_arg,
739 dev->iobase + ME4000_AI_SAMPLE_COUNTER_REG);
740 tmp |= ME4000_AI_CTRL_BIT_HF_IRQ | ME4000_AI_CTRL_BIT_SC_IRQ;
742 tmp |= ME4000_AI_CTRL_BIT_HF_IRQ;
745 /* Write the setup to the control register */
746 outl(tmp, dev->iobase + ME4000_AI_CTRL_REG);
748 /* Write the channel list */
749 ai_write_chanlist(dev, s, cmd);
754 static int me4000_ai_do_cmd(struct comedi_device *dev,
755 struct comedi_subdevice *s)
758 unsigned int init_ticks = 0;
759 unsigned int scan_ticks = 0;
760 unsigned int chan_ticks = 0;
761 struct comedi_cmd *cmd = &s->async->cmd;
763 /* Reset the analog input */
764 err = me4000_ai_cancel(dev, s);
768 /* Round the timer arguments */
769 err = ai_round_cmd_args(dev,
770 s, cmd, &init_ticks, &scan_ticks, &chan_ticks);
774 /* Prepare the AI for acquisition */
775 err = ai_prepare(dev, s, cmd, init_ticks, scan_ticks, chan_ticks);
779 /* Start acquistion by dummy read */
780 inl(dev->iobase + ME4000_AI_START_REG);
786 * me4000_ai_do_cmd_test():
788 * The demo cmd.c in ./comedilib/demo specifies 6 return values:
793 * - argument conflict
795 * So I tried to adopt this scheme.
797 static int me4000_ai_do_cmd_test(struct comedi_device *dev,
798 struct comedi_subdevice *s,
799 struct comedi_cmd *cmd)
802 unsigned int init_ticks;
803 unsigned int chan_ticks;
804 unsigned int scan_ticks;
807 /* Only rounding flags are implemented */
808 cmd->flags &= TRIG_ROUND_NEAREST | TRIG_ROUND_UP | TRIG_ROUND_DOWN;
810 /* Round the timer arguments */
811 ai_round_cmd_args(dev, s, cmd, &init_ticks, &scan_ticks, &chan_ticks);
814 * Stage 1. Check if the trigger sources are generally valid.
816 switch (cmd->start_src) {
821 cmd->start_src &= TRIG_NOW | TRIG_EXT;
826 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
827 "Invalid start source\n", dev->minor);
828 cmd->start_src = TRIG_NOW;
831 switch (cmd->scan_begin_src) {
837 cmd->scan_begin_src &= TRIG_FOLLOW | TRIG_TIMER | TRIG_EXT;
842 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
843 "Invalid scan begin source\n", dev->minor);
844 cmd->scan_begin_src = TRIG_FOLLOW;
847 switch (cmd->convert_src) {
852 cmd->convert_src &= TRIG_TIMER | TRIG_EXT;
857 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
858 "Invalid convert source\n", dev->minor);
859 cmd->convert_src = TRIG_TIMER;
862 switch (cmd->scan_end_src) {
867 cmd->scan_end_src &= TRIG_NONE | TRIG_COUNT;
872 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
873 "Invalid scan end source\n", dev->minor);
874 cmd->scan_end_src = TRIG_NONE;
877 switch (cmd->stop_src) {
882 cmd->stop_src &= TRIG_NONE | TRIG_COUNT;
887 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
888 "Invalid stop source\n", dev->minor);
889 cmd->stop_src = TRIG_NONE;
896 * Stage 2. Check for trigger source conflicts.
898 if (cmd->start_src == TRIG_NOW &&
899 cmd->scan_begin_src == TRIG_TIMER &&
900 cmd->convert_src == TRIG_TIMER) {
901 } else if (cmd->start_src == TRIG_NOW &&
902 cmd->scan_begin_src == TRIG_FOLLOW &&
903 cmd->convert_src == TRIG_TIMER) {
904 } else if (cmd->start_src == TRIG_EXT &&
905 cmd->scan_begin_src == TRIG_TIMER &&
906 cmd->convert_src == TRIG_TIMER) {
907 } else if (cmd->start_src == TRIG_EXT &&
908 cmd->scan_begin_src == TRIG_FOLLOW &&
909 cmd->convert_src == TRIG_TIMER) {
910 } else if (cmd->start_src == TRIG_EXT &&
911 cmd->scan_begin_src == TRIG_EXT &&
912 cmd->convert_src == TRIG_TIMER) {
913 } else if (cmd->start_src == TRIG_EXT &&
914 cmd->scan_begin_src == TRIG_EXT &&
915 cmd->convert_src == TRIG_EXT) {
918 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
919 "Invalid start trigger combination\n", dev->minor);
920 cmd->start_src = TRIG_NOW;
921 cmd->scan_begin_src = TRIG_FOLLOW;
922 cmd->convert_src = TRIG_TIMER;
926 if (cmd->stop_src == TRIG_NONE && cmd->scan_end_src == TRIG_NONE) {
927 } else if (cmd->stop_src == TRIG_COUNT &&
928 cmd->scan_end_src == TRIG_NONE) {
929 } else if (cmd->stop_src == TRIG_NONE &&
930 cmd->scan_end_src == TRIG_COUNT) {
931 } else if (cmd->stop_src == TRIG_COUNT &&
932 cmd->scan_end_src == TRIG_COUNT) {
935 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
936 "Invalid stop trigger combination\n", dev->minor);
937 cmd->stop_src = TRIG_NONE;
938 cmd->scan_end_src = TRIG_NONE;
945 * Stage 3. Check if arguments are generally valid.
947 if (cmd->chanlist_len < 1) {
949 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
950 "No channel list\n", dev->minor);
951 cmd->chanlist_len = 1;
954 if (init_ticks < 66) {
956 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
957 "Start arg to low\n", dev->minor);
958 cmd->start_arg = 2000;
961 if (scan_ticks && scan_ticks < 67) {
963 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
964 "Scan begin arg to low\n", dev->minor);
965 cmd->scan_begin_arg = 2031;
968 if (chan_ticks < 66) {
970 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
971 "Convert arg to low\n", dev->minor);
972 cmd->convert_arg = 2000;
980 * Stage 4. Check for argument conflicts.
982 if (cmd->start_src == TRIG_NOW &&
983 cmd->scan_begin_src == TRIG_TIMER &&
984 cmd->convert_src == TRIG_TIMER) {
986 /* Check timer arguments */
987 if (init_ticks < ME4000_AI_MIN_TICKS) {
989 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
990 "Invalid start arg\n", dev->minor);
991 cmd->start_arg = 2000; /* 66 ticks at least */
994 if (chan_ticks < ME4000_AI_MIN_TICKS) {
996 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
997 "Invalid convert arg\n", dev->minor);
998 cmd->convert_arg = 2000; /* 66 ticks at least */
1001 if (scan_ticks <= cmd->chanlist_len * chan_ticks) {
1003 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1004 "Invalid scan end arg\n", dev->minor);
1006 /* At least one tick more */
1007 cmd->scan_end_arg = 2000 * cmd->chanlist_len + 31;
1010 } else if (cmd->start_src == TRIG_NOW &&
1011 cmd->scan_begin_src == TRIG_FOLLOW &&
1012 cmd->convert_src == TRIG_TIMER) {
1014 /* Check timer arguments */
1015 if (init_ticks < ME4000_AI_MIN_TICKS) {
1017 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1018 "Invalid start arg\n", dev->minor);
1019 cmd->start_arg = 2000; /* 66 ticks at least */
1022 if (chan_ticks < ME4000_AI_MIN_TICKS) {
1024 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1025 "Invalid convert arg\n", dev->minor);
1026 cmd->convert_arg = 2000; /* 66 ticks at least */
1029 } else if (cmd->start_src == TRIG_EXT &&
1030 cmd->scan_begin_src == TRIG_TIMER &&
1031 cmd->convert_src == TRIG_TIMER) {
1033 /* Check timer arguments */
1034 if (init_ticks < ME4000_AI_MIN_TICKS) {
1036 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1037 "Invalid start arg\n", dev->minor);
1038 cmd->start_arg = 2000; /* 66 ticks at least */
1041 if (chan_ticks < ME4000_AI_MIN_TICKS) {
1043 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1044 "Invalid convert arg\n", dev->minor);
1045 cmd->convert_arg = 2000; /* 66 ticks at least */
1048 if (scan_ticks <= cmd->chanlist_len * chan_ticks) {
1050 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1051 "Invalid scan end arg\n", dev->minor);
1053 /* At least one tick more */
1054 cmd->scan_end_arg = 2000 * cmd->chanlist_len + 31;
1057 } else if (cmd->start_src == TRIG_EXT &&
1058 cmd->scan_begin_src == TRIG_FOLLOW &&
1059 cmd->convert_src == TRIG_TIMER) {
1061 /* Check timer arguments */
1062 if (init_ticks < ME4000_AI_MIN_TICKS) {
1064 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1065 "Invalid start arg\n", dev->minor);
1066 cmd->start_arg = 2000; /* 66 ticks at least */
1069 if (chan_ticks < ME4000_AI_MIN_TICKS) {
1071 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1072 "Invalid convert arg\n", dev->minor);
1073 cmd->convert_arg = 2000; /* 66 ticks at least */
1076 } else if (cmd->start_src == TRIG_EXT &&
1077 cmd->scan_begin_src == TRIG_EXT &&
1078 cmd->convert_src == TRIG_TIMER) {
1080 /* Check timer arguments */
1081 if (init_ticks < ME4000_AI_MIN_TICKS) {
1083 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1084 "Invalid start arg\n", dev->minor);
1085 cmd->start_arg = 2000; /* 66 ticks at least */
1088 if (chan_ticks < ME4000_AI_MIN_TICKS) {
1090 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1091 "Invalid convert arg\n", dev->minor);
1092 cmd->convert_arg = 2000; /* 66 ticks at least */
1095 } else if (cmd->start_src == TRIG_EXT &&
1096 cmd->scan_begin_src == TRIG_EXT &&
1097 cmd->convert_src == TRIG_EXT) {
1099 /* Check timer arguments */
1100 if (init_ticks < ME4000_AI_MIN_TICKS) {
1102 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1103 "Invalid start arg\n", dev->minor);
1104 cmd->start_arg = 2000; /* 66 ticks at least */
1108 if (cmd->stop_src == TRIG_COUNT) {
1109 if (cmd->stop_arg == 0) {
1111 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1112 "Invalid stop arg\n", dev->minor);
1117 if (cmd->scan_end_src == TRIG_COUNT) {
1118 if (cmd->scan_end_arg == 0) {
1120 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1121 "Invalid scan end arg\n", dev->minor);
1122 cmd->scan_end_arg = 1;
1131 * Stage 5. Check the channel list.
1133 if (ai_check_chanlist(dev, s, cmd))
1139 static irqreturn_t me4000_ai_isr(int irq, void *dev_id)
1142 struct comedi_device *dev = dev_id;
1143 struct comedi_subdevice *s = &dev->subdevices[0];
1151 /* Reset all events */
1152 s->async->events = 0;
1154 /* Check if irq number is right */
1155 if (irq != dev->irq) {
1157 "comedi%d: me4000: me4000_ai_isr(): "
1158 "Incorrect interrupt num: %d\n", dev->minor, irq);
1162 if (inl(dev->iobase + ME4000_IRQ_STATUS_REG) &
1163 ME4000_IRQ_STATUS_BIT_AI_HF) {
1164 /* Read status register to find out what happened */
1165 tmp = inl(dev->iobase + ME4000_AI_CTRL_REG);
1167 if (!(tmp & ME4000_AI_STATUS_BIT_FF_DATA) &&
1168 !(tmp & ME4000_AI_STATUS_BIT_HF_DATA) &&
1169 (tmp & ME4000_AI_STATUS_BIT_EF_DATA)) {
1170 c = ME4000_AI_FIFO_COUNT;
1173 * FIFO overflow, so stop conversion
1174 * and disable all interrupts
1176 tmp |= ME4000_AI_CTRL_BIT_IMMEDIATE_STOP;
1177 tmp &= ~(ME4000_AI_CTRL_BIT_HF_IRQ |
1178 ME4000_AI_CTRL_BIT_SC_IRQ);
1179 outl(tmp, dev->iobase + ME4000_AI_CTRL_REG);
1181 s->async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
1184 "comedi%d: me4000: me4000_ai_isr(): "
1185 "FIFO overflow\n", dev->minor);
1186 } else if ((tmp & ME4000_AI_STATUS_BIT_FF_DATA)
1187 && !(tmp & ME4000_AI_STATUS_BIT_HF_DATA)
1188 && (tmp & ME4000_AI_STATUS_BIT_EF_DATA)) {
1189 s->async->events |= COMEDI_CB_BLOCK;
1191 c = ME4000_AI_FIFO_COUNT / 2;
1194 "comedi%d: me4000: me4000_ai_isr(): "
1195 "Can't determine state of fifo\n", dev->minor);
1199 * Undefined state, so stop conversion
1200 * and disable all interrupts
1202 tmp |= ME4000_AI_CTRL_BIT_IMMEDIATE_STOP;
1203 tmp &= ~(ME4000_AI_CTRL_BIT_HF_IRQ |
1204 ME4000_AI_CTRL_BIT_SC_IRQ);
1205 outl(tmp, dev->iobase + ME4000_AI_CTRL_REG);
1207 s->async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
1210 "comedi%d: me4000: me4000_ai_isr(): "
1211 "Undefined FIFO state\n", dev->minor);
1214 for (i = 0; i < c; i++) {
1215 /* Read value from data fifo */
1216 lval = inl(dev->iobase + ME4000_AI_DATA_REG) & 0xFFFF;
1219 if (!comedi_buf_put(s->async, lval)) {
1221 * Buffer overflow, so stop conversion
1222 * and disable all interrupts
1224 tmp |= ME4000_AI_CTRL_BIT_IMMEDIATE_STOP;
1225 tmp &= ~(ME4000_AI_CTRL_BIT_HF_IRQ |
1226 ME4000_AI_CTRL_BIT_SC_IRQ);
1227 outl(tmp, dev->iobase + ME4000_AI_CTRL_REG);
1229 s->async->events |= COMEDI_CB_OVERFLOW;
1232 "comedi%d: me4000: me4000_ai_isr(): "
1233 "Buffer overflow\n", dev->minor);
1239 /* Work is done, so reset the interrupt */
1240 tmp |= ME4000_AI_CTRL_BIT_HF_IRQ_RESET;
1241 outl(tmp, dev->iobase + ME4000_AI_CTRL_REG);
1242 tmp &= ~ME4000_AI_CTRL_BIT_HF_IRQ_RESET;
1243 outl(tmp, dev->iobase + ME4000_AI_CTRL_REG);
1246 if (inl(dev->iobase + ME4000_IRQ_STATUS_REG) &
1247 ME4000_IRQ_STATUS_BIT_SC) {
1248 s->async->events |= COMEDI_CB_BLOCK | COMEDI_CB_EOA;
1251 * Acquisition is complete, so stop
1252 * conversion and disable all interrupts
1254 tmp = inl(dev->iobase + ME4000_AI_CTRL_REG);
1255 tmp |= ME4000_AI_CTRL_BIT_IMMEDIATE_STOP;
1256 tmp &= ~(ME4000_AI_CTRL_BIT_HF_IRQ | ME4000_AI_CTRL_BIT_SC_IRQ);
1257 outl(tmp, dev->iobase + ME4000_AI_CTRL_REG);
1259 /* Poll data until fifo empty */
1260 while (inl(dev->iobase + ME4000_AI_CTRL_REG) &
1261 ME4000_AI_STATUS_BIT_EF_DATA) {
1262 /* Read value from data fifo */
1263 lval = inl(dev->iobase + ME4000_AI_DATA_REG) & 0xFFFF;
1266 if (!comedi_buf_put(s->async, lval)) {
1268 "comedi%d: me4000: me4000_ai_isr(): "
1269 "Buffer overflow\n", dev->minor);
1270 s->async->events |= COMEDI_CB_OVERFLOW;
1275 /* Work is done, so reset the interrupt */
1276 tmp |= ME4000_AI_CTRL_BIT_SC_IRQ_RESET;
1277 outl(tmp, dev->iobase + ME4000_AI_CTRL_REG);
1278 tmp &= ~ME4000_AI_CTRL_BIT_SC_IRQ_RESET;
1279 outl(tmp, dev->iobase + ME4000_AI_CTRL_REG);
1282 if (s->async->events)
1283 comedi_event(dev, s);
1288 /*=============================================================================
1289 Analog output section
1290 ===========================================================================*/
1292 static int me4000_ao_insn_write(struct comedi_device *dev,
1293 struct comedi_subdevice *s,
1294 struct comedi_insn *insn, unsigned int *data)
1296 const struct me4000_board *thisboard = comedi_board(dev);
1297 struct me4000_info *info = dev->private;
1298 int chan = CR_CHAN(insn->chanspec);
1299 int rang = CR_RANGE(insn->chanspec);
1300 int aref = CR_AREF(insn->chanspec);
1305 } else if (insn->n > 1) {
1307 "comedi%d: me4000: me4000_ao_insn_write(): "
1308 "Invalid instruction length %d\n", dev->minor, insn->n);
1312 if (chan >= thisboard->ao_nchan) {
1314 "comedi%d: me4000: me4000_ao_insn_write(): "
1315 "Invalid channel %d\n", dev->minor, insn->n);
1321 "comedi%d: me4000: me4000_ao_insn_write(): "
1322 "Invalid range %d\n", dev->minor, insn->n);
1326 if (aref != AREF_GROUND && aref != AREF_COMMON) {
1328 "comedi%d: me4000: me4000_ao_insn_write(): "
1329 "Invalid aref %d\n", dev->minor, insn->n);
1333 /* Stop any running conversion */
1334 tmp = inl(dev->iobase + ME4000_AO_CTRL_REG(chan));
1335 tmp |= ME4000_AO_CTRL_BIT_IMMEDIATE_STOP;
1336 outl(tmp, dev->iobase + ME4000_AO_CTRL_REG(chan));
1338 /* Clear control register and set to single mode */
1339 outl(0x0, dev->iobase + ME4000_AO_CTRL_REG(chan));
1341 /* Write data value */
1342 outl(data[0], dev->iobase + ME4000_AO_SINGLE_REG(chan));
1344 /* Store in the mirror */
1345 info->ao_readback[chan] = data[0];
1350 static int me4000_ao_insn_read(struct comedi_device *dev,
1351 struct comedi_subdevice *s,
1352 struct comedi_insn *insn, unsigned int *data)
1354 struct me4000_info *info = dev->private;
1355 int chan = CR_CHAN(insn->chanspec);
1359 } else if (insn->n > 1) {
1361 ("comedi%d: me4000: me4000_ao_insn_read(): "
1362 "Invalid instruction length\n", dev->minor);
1366 data[0] = info->ao_readback[chan];
1371 /*=============================================================================
1373 ===========================================================================*/
1375 static int me4000_dio_insn_bits(struct comedi_device *dev,
1376 struct comedi_subdevice *s,
1377 struct comedi_insn *insn, unsigned int *data)
1380 * The insn data consists of a mask in data[0] and the new data
1381 * in data[1]. The mask defines which bits we are concerning about.
1382 * The new data must be anded with the mask.
1383 * Each channel corresponds to a bit.
1386 /* Check if requested ports are configured for output */
1387 if ((s->io_bits & data[0]) != data[0])
1390 s->state &= ~data[0];
1391 s->state |= data[0] & data[1];
1393 /* Write out the new digital output lines */
1394 outl((s->state >> 0) & 0xFF,
1395 dev->iobase + ME4000_DIO_PORT_0_REG);
1396 outl((s->state >> 8) & 0xFF,
1397 dev->iobase + ME4000_DIO_PORT_1_REG);
1398 outl((s->state >> 16) & 0xFF,
1399 dev->iobase + ME4000_DIO_PORT_2_REG);
1400 outl((s->state >> 24) & 0xFF,
1401 dev->iobase + ME4000_DIO_PORT_3_REG);
1404 /* On return, data[1] contains the value of
1405 the digital input and output lines. */
1406 data[1] = ((inl(dev->iobase + ME4000_DIO_PORT_0_REG) & 0xFF) << 0) |
1407 ((inl(dev->iobase + ME4000_DIO_PORT_1_REG) & 0xFF) << 8) |
1408 ((inl(dev->iobase + ME4000_DIO_PORT_2_REG) & 0xFF) << 16) |
1409 ((inl(dev->iobase + ME4000_DIO_PORT_3_REG) & 0xFF) << 24);
1414 static int me4000_dio_insn_config(struct comedi_device *dev,
1415 struct comedi_subdevice *s,
1416 struct comedi_insn *insn, unsigned int *data)
1419 int chan = CR_CHAN(insn->chanspec);
1424 case INSN_CONFIG_DIO_QUERY:
1426 (s->io_bits & (1 << chan)) ? COMEDI_OUTPUT : COMEDI_INPUT;
1428 case INSN_CONFIG_DIO_INPUT:
1429 case INSN_CONFIG_DIO_OUTPUT:
1434 * The input or output configuration of each digital line is
1435 * configured by a special insn_config instruction. chanspec
1436 * contains the channel to be changed, and data[0] contains the
1437 * value INSN_CONFIG_DIO_INPUT or INSN_CONFIG_DIO_OUTPUT.
1438 * On the ME-4000 it is only possible to switch port wise (8 bit)
1441 tmp = inl(dev->iobase + ME4000_DIO_CTRL_REG);
1443 if (data[0] == INSN_CONFIG_DIO_OUTPUT) {
1446 tmp &= ~(ME4000_DIO_CTRL_BIT_MODE_0 |
1447 ME4000_DIO_CTRL_BIT_MODE_1);
1448 tmp |= ME4000_DIO_CTRL_BIT_MODE_0;
1449 } else if (chan < 16) {
1451 * Chech for optoisolated ME-4000 version.
1452 * If one the first port is a fixed output
1453 * port and the second is a fixed input port.
1455 if (!inl(dev->iobase + ME4000_DIO_DIR_REG))
1458 s->io_bits |= 0xFF00;
1459 tmp &= ~(ME4000_DIO_CTRL_BIT_MODE_2 |
1460 ME4000_DIO_CTRL_BIT_MODE_3);
1461 tmp |= ME4000_DIO_CTRL_BIT_MODE_2;
1462 } else if (chan < 24) {
1463 s->io_bits |= 0xFF0000;
1464 tmp &= ~(ME4000_DIO_CTRL_BIT_MODE_4 |
1465 ME4000_DIO_CTRL_BIT_MODE_5);
1466 tmp |= ME4000_DIO_CTRL_BIT_MODE_4;
1467 } else if (chan < 32) {
1468 s->io_bits |= 0xFF000000;
1469 tmp &= ~(ME4000_DIO_CTRL_BIT_MODE_6 |
1470 ME4000_DIO_CTRL_BIT_MODE_7);
1471 tmp |= ME4000_DIO_CTRL_BIT_MODE_6;
1478 * Chech for optoisolated ME-4000 version.
1479 * If one the first port is a fixed output
1480 * port and the second is a fixed input port.
1482 if (!inl(dev->iobase + ME4000_DIO_DIR_REG))
1485 s->io_bits &= ~0xFF;
1486 tmp &= ~(ME4000_DIO_CTRL_BIT_MODE_0 |
1487 ME4000_DIO_CTRL_BIT_MODE_1);
1488 } else if (chan < 16) {
1489 s->io_bits &= ~0xFF00;
1490 tmp &= ~(ME4000_DIO_CTRL_BIT_MODE_2 |
1491 ME4000_DIO_CTRL_BIT_MODE_3);
1492 } else if (chan < 24) {
1493 s->io_bits &= ~0xFF0000;
1494 tmp &= ~(ME4000_DIO_CTRL_BIT_MODE_4 |
1495 ME4000_DIO_CTRL_BIT_MODE_5);
1496 } else if (chan < 32) {
1497 s->io_bits &= ~0xFF000000;
1498 tmp &= ~(ME4000_DIO_CTRL_BIT_MODE_6 |
1499 ME4000_DIO_CTRL_BIT_MODE_7);
1505 outl(tmp, dev->iobase + ME4000_DIO_CTRL_REG);
1510 /*=============================================================================
1512 ===========================================================================*/
1514 static int cnt_reset(struct comedi_device *dev, unsigned int channel)
1516 struct me4000_info *info = dev->private;
1520 outb(0x30, info->timer_regbase + ME4000_CNT_CTRL_REG);
1521 outb(0x00, info->timer_regbase + ME4000_CNT_COUNTER_0_REG);
1522 outb(0x00, info->timer_regbase + ME4000_CNT_COUNTER_0_REG);
1525 outb(0x70, info->timer_regbase + ME4000_CNT_CTRL_REG);
1526 outb(0x00, info->timer_regbase + ME4000_CNT_COUNTER_1_REG);
1527 outb(0x00, info->timer_regbase + ME4000_CNT_COUNTER_1_REG);
1530 outb(0xB0, info->timer_regbase + ME4000_CNT_CTRL_REG);
1531 outb(0x00, info->timer_regbase + ME4000_CNT_COUNTER_2_REG);
1532 outb(0x00, info->timer_regbase + ME4000_CNT_COUNTER_2_REG);
1536 "comedi%d: me4000: cnt_reset(): Invalid channel\n",
1544 static int cnt_config(struct comedi_device *dev, unsigned int channel,
1547 struct me4000_info *info = dev->private;
1552 tmp |= ME4000_CNT_COUNTER_0;
1555 tmp |= ME4000_CNT_COUNTER_1;
1558 tmp |= ME4000_CNT_COUNTER_2;
1562 "comedi%d: me4000: cnt_config(): Invalid channel\n",
1569 tmp |= ME4000_CNT_MODE_0;
1572 tmp |= ME4000_CNT_MODE_1;
1575 tmp |= ME4000_CNT_MODE_2;
1578 tmp |= ME4000_CNT_MODE_3;
1581 tmp |= ME4000_CNT_MODE_4;
1584 tmp |= ME4000_CNT_MODE_5;
1588 "comedi%d: me4000: cnt_config(): Invalid counter mode\n",
1593 /* Write the control word */
1595 outb(tmp, info->timer_regbase + ME4000_CNT_CTRL_REG);
1600 static int me4000_cnt_insn_config(struct comedi_device *dev,
1601 struct comedi_subdevice *s,
1602 struct comedi_insn *insn, unsigned int *data)
1611 "comedi%d: me4000: me4000_cnt_insn_config(): "
1612 "Invalid instruction length%d\n",
1613 dev->minor, insn->n);
1617 err = cnt_reset(dev, insn->chanspec);
1621 case GPCT_SET_OPERATION:
1624 "comedi%d: me4000: me4000_cnt_insn_config(): "
1625 "Invalid instruction length%d\n",
1626 dev->minor, insn->n);
1630 err = cnt_config(dev, insn->chanspec, data[1]);
1636 "comedi%d: me4000: me4000_cnt_insn_config(): "
1637 "Invalid instruction\n", dev->minor);
1644 static int me4000_cnt_insn_read(struct comedi_device *dev,
1645 struct comedi_subdevice *s,
1646 struct comedi_insn *insn, unsigned int *data)
1648 struct me4000_info *info = dev->private;
1656 "comedi%d: me4000: me4000_cnt_insn_read(): "
1657 "Invalid instruction length %d\n",
1658 dev->minor, insn->n);
1662 switch (insn->chanspec) {
1664 tmp = inb(info->timer_regbase + ME4000_CNT_COUNTER_0_REG);
1666 tmp = inb(info->timer_regbase + ME4000_CNT_COUNTER_0_REG);
1667 data[0] |= tmp << 8;
1670 tmp = inb(info->timer_regbase + ME4000_CNT_COUNTER_1_REG);
1672 tmp = inb(info->timer_regbase + ME4000_CNT_COUNTER_1_REG);
1673 data[0] |= tmp << 8;
1676 tmp = inb(info->timer_regbase + ME4000_CNT_COUNTER_2_REG);
1678 tmp = inb(info->timer_regbase + ME4000_CNT_COUNTER_2_REG);
1679 data[0] |= tmp << 8;
1683 "comedi%d: me4000: me4000_cnt_insn_read(): "
1684 "Invalid channel %d\n",
1685 dev->minor, insn->chanspec);
1692 static int me4000_cnt_insn_write(struct comedi_device *dev,
1693 struct comedi_subdevice *s,
1694 struct comedi_insn *insn, unsigned int *data)
1696 struct me4000_info *info = dev->private;
1701 } else if (insn->n > 1) {
1703 "comedi%d: me4000: me4000_cnt_insn_write(): "
1704 "Invalid instruction length %d\n",
1705 dev->minor, insn->n);
1709 switch (insn->chanspec) {
1711 tmp = data[0] & 0xFF;
1712 outb(tmp, info->timer_regbase + ME4000_CNT_COUNTER_0_REG);
1713 tmp = (data[0] >> 8) & 0xFF;
1714 outb(tmp, info->timer_regbase + ME4000_CNT_COUNTER_0_REG);
1717 tmp = data[0] & 0xFF;
1718 outb(tmp, info->timer_regbase + ME4000_CNT_COUNTER_1_REG);
1719 tmp = (data[0] >> 8) & 0xFF;
1720 outb(tmp, info->timer_regbase + ME4000_CNT_COUNTER_1_REG);
1723 tmp = data[0] & 0xFF;
1724 outb(tmp, info->timer_regbase + ME4000_CNT_COUNTER_2_REG);
1725 tmp = (data[0] >> 8) & 0xFF;
1726 outb(tmp, info->timer_regbase + ME4000_CNT_COUNTER_2_REG);
1730 "comedi%d: me4000: me4000_cnt_insn_write(): "
1731 "Invalid channel %d\n",
1732 dev->minor, insn->chanspec);
1739 static const void *me4000_find_boardinfo(struct comedi_device *dev,
1740 struct pci_dev *pcidev)
1742 const struct me4000_board *thisboard;
1745 for (i = 0; i < ARRAY_SIZE(me4000_boards); i++) {
1746 thisboard = &me4000_boards[i];
1747 if (thisboard->device_id == pcidev->device)
1753 static int me4000_attach_pci(struct comedi_device *dev,
1754 struct pci_dev *pcidev)
1756 const struct me4000_board *thisboard;
1757 struct me4000_info *info;
1758 struct comedi_subdevice *s;
1761 comedi_set_hw_dev(dev, &pcidev->dev);
1763 thisboard = me4000_find_boardinfo(dev, pcidev);
1766 dev->board_ptr = thisboard;
1767 dev->board_name = thisboard->name;
1769 result = alloc_private(dev, sizeof(*info));
1772 info = dev->private;
1774 result = comedi_pci_enable(pcidev, dev->board_name);
1778 info->plx_regbase = pci_resource_start(pcidev, 1);
1779 if (!info->plx_regbase)
1782 dev->iobase = pci_resource_start(pcidev, 2);
1786 info->timer_regbase = pci_resource_start(pcidev, 3);
1787 if (!info->timer_regbase)
1790 dev->irq = pcidev->irq;
1792 result = xilinx_download(dev);
1796 result = reset_board(dev);
1800 result = comedi_alloc_subdevices(dev, 4);
1804 /*=========================================================================
1805 Analog input subdevice
1806 ========================================================================*/
1808 s = &dev->subdevices[0];
1810 if (thisboard->ai_nchan) {
1811 s->type = COMEDI_SUBD_AI;
1813 SDF_READABLE | SDF_COMMON | SDF_GROUND | SDF_DIFF;
1814 s->n_chan = thisboard->ai_nchan;
1815 s->maxdata = 0xFFFF; /* 16 bit ADC */
1816 s->len_chanlist = ME4000_AI_CHANNEL_LIST_COUNT;
1817 s->range_table = &me4000_ai_range;
1818 s->insn_read = me4000_ai_insn_read;
1821 if (request_irq(dev->irq, me4000_ai_isr,
1822 IRQF_SHARED, "ME-4000", dev)) {
1824 ("comedi%d: me4000: me4000_attach(): "
1825 "Unable to allocate irq\n", dev->minor);
1827 dev->read_subdev = s;
1828 s->subdev_flags |= SDF_CMD_READ;
1829 s->cancel = me4000_ai_cancel;
1830 s->do_cmdtest = me4000_ai_do_cmd_test;
1831 s->do_cmd = me4000_ai_do_cmd;
1835 "comedi%d: me4000: me4000_attach(): "
1836 "No interrupt available\n", dev->minor);
1839 s->type = COMEDI_SUBD_UNUSED;
1842 /*=========================================================================
1843 Analog output subdevice
1844 ========================================================================*/
1846 s = &dev->subdevices[1];
1848 if (thisboard->ao_nchan) {
1849 s->type = COMEDI_SUBD_AO;
1850 s->subdev_flags = SDF_WRITEABLE | SDF_COMMON | SDF_GROUND;
1851 s->n_chan = thisboard->ao_nchan;
1852 s->maxdata = 0xFFFF; /* 16 bit DAC */
1853 s->range_table = &range_bipolar10;
1854 s->insn_write = me4000_ao_insn_write;
1855 s->insn_read = me4000_ao_insn_read;
1857 s->type = COMEDI_SUBD_UNUSED;
1860 /*=========================================================================
1861 Digital I/O subdevice
1862 ========================================================================*/
1864 s = &dev->subdevices[2];
1866 if (thisboard->dio_nchan) {
1867 s->type = COMEDI_SUBD_DIO;
1868 s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
1869 s->n_chan = thisboard->dio_nchan;
1871 s->range_table = &range_digital;
1872 s->insn_bits = me4000_dio_insn_bits;
1873 s->insn_config = me4000_dio_insn_config;
1875 s->type = COMEDI_SUBD_UNUSED;
1879 * Check for optoisolated ME-4000 version. If one the first
1880 * port is a fixed output port and the second is a fixed input port.
1882 if (!inl(dev->iobase + ME4000_DIO_DIR_REG)) {
1884 outl(ME4000_DIO_CTRL_BIT_MODE_0,
1885 dev->iobase + ME4000_DIO_DIR_REG);
1888 /*=========================================================================
1890 ========================================================================*/
1892 s = &dev->subdevices[3];
1894 if (thisboard->has_counter) {
1895 s->type = COMEDI_SUBD_COUNTER;
1896 s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
1898 s->maxdata = 0xFFFF; /* 16 bit counters */
1899 s->insn_read = me4000_cnt_insn_read;
1900 s->insn_write = me4000_cnt_insn_write;
1901 s->insn_config = me4000_cnt_insn_config;
1903 s->type = COMEDI_SUBD_UNUSED;
1909 static void me4000_detach(struct comedi_device *dev)
1911 struct pci_dev *pcidev = comedi_to_pci_dev(dev);
1916 comedi_pci_disable(pcidev);
1921 static struct comedi_driver me4000_driver = {
1922 .driver_name = "me4000",
1923 .module = THIS_MODULE,
1924 .attach_pci = me4000_attach_pci,
1925 .detach = me4000_detach,
1928 static int __devinit me4000_pci_probe(struct pci_dev *dev,
1929 const struct pci_device_id *ent)
1931 return comedi_pci_auto_config(dev, &me4000_driver);
1934 static void __devexit me4000_pci_remove(struct pci_dev *dev)
1936 comedi_pci_auto_unconfig(dev);
1939 static DEFINE_PCI_DEVICE_TABLE(me4000_pci_table) = {
1940 {PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4650)},
1941 {PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4660)},
1942 {PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4660I)},
1943 {PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4660S)},
1944 {PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4660IS)},
1945 {PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4670)},
1946 {PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4670I)},
1947 {PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4670S)},
1948 {PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4670IS)},
1949 {PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4680)},
1950 {PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4680I)},
1951 {PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4680S)},
1952 {PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4680IS)},
1955 MODULE_DEVICE_TABLE(pci, me4000_pci_table);
1957 static struct pci_driver me4000_pci_driver = {
1959 .id_table = me4000_pci_table,
1960 .probe = me4000_pci_probe,
1961 .remove = __devexit_p(me4000_pci_remove),
1963 module_comedi_pci_driver(me4000_driver, me4000_pci_driver);
1965 MODULE_AUTHOR("Comedi http://www.comedi.org");
1966 MODULE_DESCRIPTION("Comedi low-level driver");
1967 MODULE_LICENSE("GPL");