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>
58 /* file removed due to GPL incompatibility */
59 #include "me4000_fw.h"
62 #define PCI_VENDOR_ID_MEILHAUS 0x1402
64 #define PCI_DEVICE_ID_MEILHAUS_ME4650 0x4650
65 #define PCI_DEVICE_ID_MEILHAUS_ME4660 0x4660
66 #define PCI_DEVICE_ID_MEILHAUS_ME4660I 0x4661
67 #define PCI_DEVICE_ID_MEILHAUS_ME4660S 0x4662
68 #define PCI_DEVICE_ID_MEILHAUS_ME4660IS 0x4663
69 #define PCI_DEVICE_ID_MEILHAUS_ME4670 0x4670
70 #define PCI_DEVICE_ID_MEILHAUS_ME4670I 0x4671
71 #define PCI_DEVICE_ID_MEILHAUS_ME4670S 0x4672
72 #define PCI_DEVICE_ID_MEILHAUS_ME4670IS 0x4673
73 #define PCI_DEVICE_ID_MEILHAUS_ME4680 0x4680
74 #define PCI_DEVICE_ID_MEILHAUS_ME4680I 0x4681
75 #define PCI_DEVICE_ID_MEILHAUS_ME4680S 0x4682
76 #define PCI_DEVICE_ID_MEILHAUS_ME4680IS 0x4683
80 unsigned short device_id;
91 static const struct me4000_board me4000_boards[] = {
94 .device_id = PCI_DEVICE_ID_MEILHAUS_ME4650,
99 .device_id = PCI_DEVICE_ID_MEILHAUS_ME4660,
106 .device_id = PCI_DEVICE_ID_MEILHAUS_ME4660I,
113 .device_id = PCI_DEVICE_ID_MEILHAUS_ME4660S,
121 .device_id = PCI_DEVICE_ID_MEILHAUS_ME4660IS,
129 .device_id = PCI_DEVICE_ID_MEILHAUS_ME4670,
138 .device_id = PCI_DEVICE_ID_MEILHAUS_ME4670I,
147 .device_id = PCI_DEVICE_ID_MEILHAUS_ME4670S,
157 .device_id = PCI_DEVICE_ID_MEILHAUS_ME4670IS,
167 .device_id = PCI_DEVICE_ID_MEILHAUS_ME4680,
177 .device_id = PCI_DEVICE_ID_MEILHAUS_ME4680I,
187 .device_id = PCI_DEVICE_ID_MEILHAUS_ME4680S,
198 .device_id = PCI_DEVICE_ID_MEILHAUS_ME4680IS,
210 static const struct comedi_lrange me4000_ai_range = {
220 #define FIRMWARE_NOT_AVAILABLE 1
221 #if FIRMWARE_NOT_AVAILABLE
222 extern unsigned char *xilinx_firm;
225 static int xilinx_download(struct comedi_device *dev)
227 struct pci_dev *pcidev = comedi_to_pci_dev(dev);
228 struct me4000_info *info = dev->private;
229 unsigned long xilinx_iobase = pci_resource_start(pcidev, 5);
231 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(xilinx_iobase + 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], xilinx_iobase);
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 void me4000_reset(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);
353 /*=============================================================================
355 ===========================================================================*/
357 static int me4000_ai_insn_read(struct comedi_device *dev,
358 struct comedi_subdevice *subdevice,
359 struct comedi_insn *insn, unsigned int *data)
361 const struct me4000_board *thisboard = comedi_board(dev);
362 int chan = CR_CHAN(insn->chanspec);
363 int rang = CR_RANGE(insn->chanspec);
364 int aref = CR_AREF(insn->chanspec);
366 unsigned long entry = 0;
372 } else if (insn->n > 1) {
374 "comedi%d: me4000: me4000_ai_insn_read(): "
375 "Invalid instruction length %d\n", dev->minor, insn->n);
381 entry |= ME4000_AI_LIST_RANGE_UNIPOLAR_2_5;
384 entry |= ME4000_AI_LIST_RANGE_UNIPOLAR_10;
387 entry |= ME4000_AI_LIST_RANGE_BIPOLAR_2_5;
390 entry |= ME4000_AI_LIST_RANGE_BIPOLAR_10;
394 "comedi%d: me4000: me4000_ai_insn_read(): "
395 "Invalid range specified\n", dev->minor);
402 if (chan >= thisboard->ai_nchan) {
404 "comedi%d: me4000: me4000_ai_insn_read(): "
405 "Analog input is not available\n", dev->minor);
408 entry |= ME4000_AI_LIST_INPUT_SINGLE_ENDED | chan;
412 if (rang == 0 || rang == 1) {
414 "comedi%d: me4000: me4000_ai_insn_read(): "
415 "Range must be bipolar when aref = diff\n",
420 if (chan >= thisboard->ai_diff_nchan) {
422 "comedi%d: me4000: me4000_ai_insn_read(): "
423 "Analog input is not available\n", dev->minor);
426 entry |= ME4000_AI_LIST_INPUT_DIFFERENTIAL | chan;
430 "comedi%d: me4000: me4000_ai_insn_read(): "
431 "Invalid aref specified\n", dev->minor);
435 entry |= ME4000_AI_LIST_LAST_ENTRY;
437 /* Clear channel list, data fifo and both stop bits */
438 tmp = inl(dev->iobase + ME4000_AI_CTRL_REG);
439 tmp &= ~(ME4000_AI_CTRL_BIT_CHANNEL_FIFO |
440 ME4000_AI_CTRL_BIT_DATA_FIFO |
441 ME4000_AI_CTRL_BIT_STOP | ME4000_AI_CTRL_BIT_IMMEDIATE_STOP);
442 outl(tmp, dev->iobase + ME4000_AI_CTRL_REG);
444 /* Set the acquisition mode to single */
445 tmp &= ~(ME4000_AI_CTRL_BIT_MODE_0 | ME4000_AI_CTRL_BIT_MODE_1 |
446 ME4000_AI_CTRL_BIT_MODE_2);
447 outl(tmp, dev->iobase + ME4000_AI_CTRL_REG);
449 /* Enable channel list and data fifo */
450 tmp |= ME4000_AI_CTRL_BIT_CHANNEL_FIFO | ME4000_AI_CTRL_BIT_DATA_FIFO;
451 outl(tmp, dev->iobase + ME4000_AI_CTRL_REG);
453 /* Generate channel list entry */
454 outl(entry, dev->iobase + ME4000_AI_CHANNEL_LIST_REG);
456 /* Set the timer to maximum sample rate */
457 outl(ME4000_AI_MIN_TICKS, dev->iobase + ME4000_AI_CHAN_TIMER_REG);
458 outl(ME4000_AI_MIN_TICKS, dev->iobase + ME4000_AI_CHAN_PRE_TIMER_REG);
460 /* Start conversion by dummy read */
461 inl(dev->iobase + ME4000_AI_START_REG);
463 /* Wait until ready */
465 if (!(inl(dev->iobase + ME4000_AI_STATUS_REG) &
466 ME4000_AI_STATUS_BIT_EF_DATA)) {
468 "comedi%d: me4000: me4000_ai_insn_read(): "
469 "Value not available after wait\n", dev->minor);
473 /* Read value from data fifo */
474 lval = inl(dev->iobase + ME4000_AI_DATA_REG) & 0xFFFF;
475 data[0] = lval ^ 0x8000;
480 static int me4000_ai_cancel(struct comedi_device *dev,
481 struct comedi_subdevice *s)
485 /* Stop any running conversion */
486 tmp = inl(dev->iobase + ME4000_AI_CTRL_REG);
487 tmp &= ~(ME4000_AI_CTRL_BIT_STOP | ME4000_AI_CTRL_BIT_IMMEDIATE_STOP);
488 outl(tmp, dev->iobase + ME4000_AI_CTRL_REG);
490 /* Clear the control register */
491 outl(0x0, dev->iobase + ME4000_AI_CTRL_REG);
496 static int ai_check_chanlist(struct comedi_device *dev,
497 struct comedi_subdevice *s, struct comedi_cmd *cmd)
499 const struct me4000_board *thisboard = comedi_board(dev);
503 /* Check whether a channel list is available */
504 if (!cmd->chanlist_len) {
506 "comedi%d: me4000: ai_check_chanlist(): "
507 "No channel list available\n", dev->minor);
511 /* Check the channel list size */
512 if (cmd->chanlist_len > ME4000_AI_CHANNEL_LIST_COUNT) {
514 "comedi%d: me4000: ai_check_chanlist(): "
515 "Channel list is to large\n", dev->minor);
519 /* Check the pointer */
520 if (!cmd->chanlist) {
522 "comedi%d: me4000: ai_check_chanlist(): "
523 "NULL pointer to channel list\n", dev->minor);
527 /* Check whether aref is equal for all entries */
528 aref = CR_AREF(cmd->chanlist[0]);
529 for (i = 0; i < cmd->chanlist_len; i++) {
530 if (CR_AREF(cmd->chanlist[i]) != aref) {
532 "comedi%d: me4000: ai_check_chanlist(): "
533 "Mode is not equal for all entries\n",
539 /* Check whether channels are available for this ending */
540 if (aref == SDF_DIFF) {
541 for (i = 0; i < cmd->chanlist_len; i++) {
542 if (CR_CHAN(cmd->chanlist[i]) >=
543 thisboard->ai_diff_nchan) {
545 "comedi%d: me4000: ai_check_chanlist():"
546 " Channel number to high\n", dev->minor);
551 for (i = 0; i < cmd->chanlist_len; i++) {
552 if (CR_CHAN(cmd->chanlist[i]) >= thisboard->ai_nchan) {
554 "comedi%d: me4000: ai_check_chanlist(): "
555 "Channel number to high\n", dev->minor);
561 /* Check if bipolar is set for all entries when in differential mode */
562 if (aref == SDF_DIFF) {
563 for (i = 0; i < cmd->chanlist_len; i++) {
564 if (CR_RANGE(cmd->chanlist[i]) != 1 &&
565 CR_RANGE(cmd->chanlist[i]) != 2) {
567 "comedi%d: me4000: ai_check_chanlist(): "
568 "Bipolar is not selected in "
569 "differential mode\n",
579 static int ai_round_cmd_args(struct comedi_device *dev,
580 struct comedi_subdevice *s,
581 struct comedi_cmd *cmd,
582 unsigned int *init_ticks,
583 unsigned int *scan_ticks, unsigned int *chan_ticks)
592 if (cmd->start_arg) {
593 *init_ticks = (cmd->start_arg * 33) / 1000;
594 rest = (cmd->start_arg * 33) % 1000;
596 if ((cmd->flags & TRIG_ROUND_MASK) == TRIG_ROUND_NEAREST) {
599 } else if ((cmd->flags & TRIG_ROUND_MASK) == TRIG_ROUND_UP) {
605 if (cmd->scan_begin_arg) {
606 *scan_ticks = (cmd->scan_begin_arg * 33) / 1000;
607 rest = (cmd->scan_begin_arg * 33) % 1000;
609 if ((cmd->flags & TRIG_ROUND_MASK) == TRIG_ROUND_NEAREST) {
612 } else if ((cmd->flags & TRIG_ROUND_MASK) == TRIG_ROUND_UP) {
618 if (cmd->convert_arg) {
619 *chan_ticks = (cmd->convert_arg * 33) / 1000;
620 rest = (cmd->convert_arg * 33) % 1000;
622 if ((cmd->flags & TRIG_ROUND_MASK) == TRIG_ROUND_NEAREST) {
625 } else if ((cmd->flags & TRIG_ROUND_MASK) == TRIG_ROUND_UP) {
634 static void ai_write_timer(struct comedi_device *dev,
635 unsigned int init_ticks,
636 unsigned int scan_ticks, unsigned int chan_ticks)
638 outl(init_ticks - 1, dev->iobase + ME4000_AI_SCAN_PRE_TIMER_LOW_REG);
639 outl(0x0, dev->iobase + ME4000_AI_SCAN_PRE_TIMER_HIGH_REG);
642 outl(scan_ticks - 1, dev->iobase + ME4000_AI_SCAN_TIMER_LOW_REG);
643 outl(0x0, dev->iobase + ME4000_AI_SCAN_TIMER_HIGH_REG);
646 outl(chan_ticks - 1, dev->iobase + ME4000_AI_CHAN_PRE_TIMER_REG);
647 outl(chan_ticks - 1, dev->iobase + ME4000_AI_CHAN_TIMER_REG);
650 static int ai_write_chanlist(struct comedi_device *dev,
651 struct comedi_subdevice *s, struct comedi_cmd *cmd)
659 for (i = 0; i < cmd->chanlist_len; i++) {
660 chan = CR_CHAN(cmd->chanlist[i]);
661 rang = CR_RANGE(cmd->chanlist[i]);
662 aref = CR_AREF(cmd->chanlist[i]);
667 entry |= ME4000_AI_LIST_RANGE_UNIPOLAR_2_5;
669 entry |= ME4000_AI_LIST_RANGE_UNIPOLAR_10;
671 entry |= ME4000_AI_LIST_RANGE_BIPOLAR_2_5;
673 entry |= ME4000_AI_LIST_RANGE_BIPOLAR_10;
675 if (aref == SDF_DIFF)
676 entry |= ME4000_AI_LIST_INPUT_DIFFERENTIAL;
678 entry |= ME4000_AI_LIST_INPUT_SINGLE_ENDED;
680 outl(entry, dev->iobase + ME4000_AI_CHANNEL_LIST_REG);
686 static int ai_prepare(struct comedi_device *dev,
687 struct comedi_subdevice *s,
688 struct comedi_cmd *cmd,
689 unsigned int init_ticks,
690 unsigned int scan_ticks, unsigned int chan_ticks)
693 unsigned long tmp = 0;
695 /* Write timer arguments */
696 ai_write_timer(dev, init_ticks, scan_ticks, chan_ticks);
698 /* Reset control register */
699 outl(tmp, dev->iobase + ME4000_AI_CTRL_REG);
702 if ((cmd->start_src == TRIG_EXT &&
703 cmd->scan_begin_src == TRIG_TIMER &&
704 cmd->convert_src == TRIG_TIMER) ||
705 (cmd->start_src == TRIG_EXT &&
706 cmd->scan_begin_src == TRIG_FOLLOW &&
707 cmd->convert_src == TRIG_TIMER)) {
708 tmp = ME4000_AI_CTRL_BIT_MODE_1 |
709 ME4000_AI_CTRL_BIT_CHANNEL_FIFO |
710 ME4000_AI_CTRL_BIT_DATA_FIFO;
711 } else if (cmd->start_src == TRIG_EXT &&
712 cmd->scan_begin_src == TRIG_EXT &&
713 cmd->convert_src == TRIG_TIMER) {
714 tmp = ME4000_AI_CTRL_BIT_MODE_2 |
715 ME4000_AI_CTRL_BIT_CHANNEL_FIFO |
716 ME4000_AI_CTRL_BIT_DATA_FIFO;
717 } else if (cmd->start_src == TRIG_EXT &&
718 cmd->scan_begin_src == TRIG_EXT &&
719 cmd->convert_src == TRIG_EXT) {
720 tmp = ME4000_AI_CTRL_BIT_MODE_0 |
721 ME4000_AI_CTRL_BIT_MODE_1 |
722 ME4000_AI_CTRL_BIT_CHANNEL_FIFO |
723 ME4000_AI_CTRL_BIT_DATA_FIFO;
725 tmp = ME4000_AI_CTRL_BIT_MODE_0 |
726 ME4000_AI_CTRL_BIT_CHANNEL_FIFO |
727 ME4000_AI_CTRL_BIT_DATA_FIFO;
731 if (cmd->stop_src == TRIG_COUNT) {
732 outl(cmd->chanlist_len * cmd->stop_arg,
733 dev->iobase + ME4000_AI_SAMPLE_COUNTER_REG);
734 tmp |= ME4000_AI_CTRL_BIT_HF_IRQ | ME4000_AI_CTRL_BIT_SC_IRQ;
735 } else if (cmd->stop_src == TRIG_NONE &&
736 cmd->scan_end_src == TRIG_COUNT) {
737 outl(cmd->scan_end_arg,
738 dev->iobase + ME4000_AI_SAMPLE_COUNTER_REG);
739 tmp |= ME4000_AI_CTRL_BIT_HF_IRQ | ME4000_AI_CTRL_BIT_SC_IRQ;
741 tmp |= ME4000_AI_CTRL_BIT_HF_IRQ;
744 /* Write the setup to the control register */
745 outl(tmp, dev->iobase + ME4000_AI_CTRL_REG);
747 /* Write the channel list */
748 ai_write_chanlist(dev, s, cmd);
753 static int me4000_ai_do_cmd(struct comedi_device *dev,
754 struct comedi_subdevice *s)
757 unsigned int init_ticks = 0;
758 unsigned int scan_ticks = 0;
759 unsigned int chan_ticks = 0;
760 struct comedi_cmd *cmd = &s->async->cmd;
762 /* Reset the analog input */
763 err = me4000_ai_cancel(dev, s);
767 /* Round the timer arguments */
768 err = ai_round_cmd_args(dev,
769 s, cmd, &init_ticks, &scan_ticks, &chan_ticks);
773 /* Prepare the AI for acquisition */
774 err = ai_prepare(dev, s, cmd, init_ticks, scan_ticks, chan_ticks);
778 /* Start acquistion by dummy read */
779 inl(dev->iobase + ME4000_AI_START_REG);
785 * me4000_ai_do_cmd_test():
787 * The demo cmd.c in ./comedilib/demo specifies 6 return values:
792 * - argument conflict
794 * So I tried to adopt this scheme.
796 static int me4000_ai_do_cmd_test(struct comedi_device *dev,
797 struct comedi_subdevice *s,
798 struct comedi_cmd *cmd)
801 unsigned int init_ticks;
802 unsigned int chan_ticks;
803 unsigned int scan_ticks;
806 /* Only rounding flags are implemented */
807 cmd->flags &= TRIG_ROUND_NEAREST | TRIG_ROUND_UP | TRIG_ROUND_DOWN;
809 /* Round the timer arguments */
810 ai_round_cmd_args(dev, s, cmd, &init_ticks, &scan_ticks, &chan_ticks);
813 * Stage 1. Check if the trigger sources are generally valid.
815 switch (cmd->start_src) {
820 cmd->start_src &= TRIG_NOW | TRIG_EXT;
825 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
826 "Invalid start source\n", dev->minor);
827 cmd->start_src = TRIG_NOW;
830 switch (cmd->scan_begin_src) {
836 cmd->scan_begin_src &= TRIG_FOLLOW | TRIG_TIMER | TRIG_EXT;
841 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
842 "Invalid scan begin source\n", dev->minor);
843 cmd->scan_begin_src = TRIG_FOLLOW;
846 switch (cmd->convert_src) {
851 cmd->convert_src &= TRIG_TIMER | TRIG_EXT;
856 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
857 "Invalid convert source\n", dev->minor);
858 cmd->convert_src = TRIG_TIMER;
861 switch (cmd->scan_end_src) {
866 cmd->scan_end_src &= TRIG_NONE | TRIG_COUNT;
871 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
872 "Invalid scan end source\n", dev->minor);
873 cmd->scan_end_src = TRIG_NONE;
876 switch (cmd->stop_src) {
881 cmd->stop_src &= TRIG_NONE | TRIG_COUNT;
886 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
887 "Invalid stop source\n", dev->minor);
888 cmd->stop_src = TRIG_NONE;
895 * Stage 2. Check for trigger source conflicts.
897 if (cmd->start_src == TRIG_NOW &&
898 cmd->scan_begin_src == TRIG_TIMER &&
899 cmd->convert_src == TRIG_TIMER) {
900 } else if (cmd->start_src == TRIG_NOW &&
901 cmd->scan_begin_src == TRIG_FOLLOW &&
902 cmd->convert_src == TRIG_TIMER) {
903 } else if (cmd->start_src == TRIG_EXT &&
904 cmd->scan_begin_src == TRIG_TIMER &&
905 cmd->convert_src == TRIG_TIMER) {
906 } else if (cmd->start_src == TRIG_EXT &&
907 cmd->scan_begin_src == TRIG_FOLLOW &&
908 cmd->convert_src == TRIG_TIMER) {
909 } else if (cmd->start_src == TRIG_EXT &&
910 cmd->scan_begin_src == TRIG_EXT &&
911 cmd->convert_src == TRIG_TIMER) {
912 } else if (cmd->start_src == TRIG_EXT &&
913 cmd->scan_begin_src == TRIG_EXT &&
914 cmd->convert_src == TRIG_EXT) {
917 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
918 "Invalid start trigger combination\n", dev->minor);
919 cmd->start_src = TRIG_NOW;
920 cmd->scan_begin_src = TRIG_FOLLOW;
921 cmd->convert_src = TRIG_TIMER;
925 if (cmd->stop_src == TRIG_NONE && cmd->scan_end_src == TRIG_NONE) {
926 } else if (cmd->stop_src == TRIG_COUNT &&
927 cmd->scan_end_src == TRIG_NONE) {
928 } else if (cmd->stop_src == TRIG_NONE &&
929 cmd->scan_end_src == TRIG_COUNT) {
930 } else if (cmd->stop_src == TRIG_COUNT &&
931 cmd->scan_end_src == TRIG_COUNT) {
934 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
935 "Invalid stop trigger combination\n", dev->minor);
936 cmd->stop_src = TRIG_NONE;
937 cmd->scan_end_src = TRIG_NONE;
944 * Stage 3. Check if arguments are generally valid.
946 if (cmd->chanlist_len < 1) {
948 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
949 "No channel list\n", dev->minor);
950 cmd->chanlist_len = 1;
953 if (init_ticks < 66) {
955 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
956 "Start arg to low\n", dev->minor);
957 cmd->start_arg = 2000;
960 if (scan_ticks && scan_ticks < 67) {
962 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
963 "Scan begin arg to low\n", dev->minor);
964 cmd->scan_begin_arg = 2031;
967 if (chan_ticks < 66) {
969 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
970 "Convert arg to low\n", dev->minor);
971 cmd->convert_arg = 2000;
979 * Stage 4. Check for argument conflicts.
981 if (cmd->start_src == TRIG_NOW &&
982 cmd->scan_begin_src == TRIG_TIMER &&
983 cmd->convert_src == TRIG_TIMER) {
985 /* Check timer arguments */
986 if (init_ticks < ME4000_AI_MIN_TICKS) {
988 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
989 "Invalid start arg\n", dev->minor);
990 cmd->start_arg = 2000; /* 66 ticks at least */
993 if (chan_ticks < ME4000_AI_MIN_TICKS) {
995 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
996 "Invalid convert arg\n", dev->minor);
997 cmd->convert_arg = 2000; /* 66 ticks at least */
1000 if (scan_ticks <= cmd->chanlist_len * chan_ticks) {
1002 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1003 "Invalid scan end arg\n", dev->minor);
1005 /* At least one tick more */
1006 cmd->scan_end_arg = 2000 * cmd->chanlist_len + 31;
1009 } else if (cmd->start_src == TRIG_NOW &&
1010 cmd->scan_begin_src == TRIG_FOLLOW &&
1011 cmd->convert_src == TRIG_TIMER) {
1013 /* Check timer arguments */
1014 if (init_ticks < ME4000_AI_MIN_TICKS) {
1016 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1017 "Invalid start arg\n", dev->minor);
1018 cmd->start_arg = 2000; /* 66 ticks at least */
1021 if (chan_ticks < ME4000_AI_MIN_TICKS) {
1023 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1024 "Invalid convert arg\n", dev->minor);
1025 cmd->convert_arg = 2000; /* 66 ticks at least */
1028 } else if (cmd->start_src == TRIG_EXT &&
1029 cmd->scan_begin_src == TRIG_TIMER &&
1030 cmd->convert_src == TRIG_TIMER) {
1032 /* Check timer arguments */
1033 if (init_ticks < ME4000_AI_MIN_TICKS) {
1035 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1036 "Invalid start arg\n", dev->minor);
1037 cmd->start_arg = 2000; /* 66 ticks at least */
1040 if (chan_ticks < ME4000_AI_MIN_TICKS) {
1042 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1043 "Invalid convert arg\n", dev->minor);
1044 cmd->convert_arg = 2000; /* 66 ticks at least */
1047 if (scan_ticks <= cmd->chanlist_len * chan_ticks) {
1049 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1050 "Invalid scan end arg\n", dev->minor);
1052 /* At least one tick more */
1053 cmd->scan_end_arg = 2000 * cmd->chanlist_len + 31;
1056 } else if (cmd->start_src == TRIG_EXT &&
1057 cmd->scan_begin_src == TRIG_FOLLOW &&
1058 cmd->convert_src == TRIG_TIMER) {
1060 /* Check timer arguments */
1061 if (init_ticks < ME4000_AI_MIN_TICKS) {
1063 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1064 "Invalid start arg\n", dev->minor);
1065 cmd->start_arg = 2000; /* 66 ticks at least */
1068 if (chan_ticks < ME4000_AI_MIN_TICKS) {
1070 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1071 "Invalid convert arg\n", dev->minor);
1072 cmd->convert_arg = 2000; /* 66 ticks at least */
1075 } else if (cmd->start_src == TRIG_EXT &&
1076 cmd->scan_begin_src == TRIG_EXT &&
1077 cmd->convert_src == TRIG_TIMER) {
1079 /* Check timer arguments */
1080 if (init_ticks < ME4000_AI_MIN_TICKS) {
1082 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1083 "Invalid start arg\n", dev->minor);
1084 cmd->start_arg = 2000; /* 66 ticks at least */
1087 if (chan_ticks < ME4000_AI_MIN_TICKS) {
1089 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1090 "Invalid convert arg\n", dev->minor);
1091 cmd->convert_arg = 2000; /* 66 ticks at least */
1094 } else if (cmd->start_src == TRIG_EXT &&
1095 cmd->scan_begin_src == TRIG_EXT &&
1096 cmd->convert_src == TRIG_EXT) {
1098 /* Check timer arguments */
1099 if (init_ticks < ME4000_AI_MIN_TICKS) {
1101 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1102 "Invalid start arg\n", dev->minor);
1103 cmd->start_arg = 2000; /* 66 ticks at least */
1107 if (cmd->stop_src == TRIG_COUNT) {
1108 if (cmd->stop_arg == 0) {
1110 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1111 "Invalid stop arg\n", dev->minor);
1116 if (cmd->scan_end_src == TRIG_COUNT) {
1117 if (cmd->scan_end_arg == 0) {
1119 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1120 "Invalid scan end arg\n", dev->minor);
1121 cmd->scan_end_arg = 1;
1130 * Stage 5. Check the channel list.
1132 if (ai_check_chanlist(dev, s, cmd))
1138 static irqreturn_t me4000_ai_isr(int irq, void *dev_id)
1141 struct comedi_device *dev = dev_id;
1142 struct comedi_subdevice *s = &dev->subdevices[0];
1150 /* Reset all events */
1151 s->async->events = 0;
1153 /* Check if irq number is right */
1154 if (irq != dev->irq) {
1156 "comedi%d: me4000: me4000_ai_isr(): "
1157 "Incorrect interrupt num: %d\n", dev->minor, irq);
1161 if (inl(dev->iobase + ME4000_IRQ_STATUS_REG) &
1162 ME4000_IRQ_STATUS_BIT_AI_HF) {
1163 /* Read status register to find out what happened */
1164 tmp = inl(dev->iobase + ME4000_AI_CTRL_REG);
1166 if (!(tmp & ME4000_AI_STATUS_BIT_FF_DATA) &&
1167 !(tmp & ME4000_AI_STATUS_BIT_HF_DATA) &&
1168 (tmp & ME4000_AI_STATUS_BIT_EF_DATA)) {
1169 c = ME4000_AI_FIFO_COUNT;
1172 * FIFO overflow, so stop conversion
1173 * and disable all interrupts
1175 tmp |= ME4000_AI_CTRL_BIT_IMMEDIATE_STOP;
1176 tmp &= ~(ME4000_AI_CTRL_BIT_HF_IRQ |
1177 ME4000_AI_CTRL_BIT_SC_IRQ);
1178 outl(tmp, dev->iobase + ME4000_AI_CTRL_REG);
1180 s->async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
1183 "comedi%d: me4000: me4000_ai_isr(): "
1184 "FIFO overflow\n", dev->minor);
1185 } else if ((tmp & ME4000_AI_STATUS_BIT_FF_DATA)
1186 && !(tmp & ME4000_AI_STATUS_BIT_HF_DATA)
1187 && (tmp & ME4000_AI_STATUS_BIT_EF_DATA)) {
1188 s->async->events |= COMEDI_CB_BLOCK;
1190 c = ME4000_AI_FIFO_COUNT / 2;
1193 "comedi%d: me4000: me4000_ai_isr(): "
1194 "Can't determine state of fifo\n", dev->minor);
1198 * Undefined state, so stop conversion
1199 * and disable all interrupts
1201 tmp |= ME4000_AI_CTRL_BIT_IMMEDIATE_STOP;
1202 tmp &= ~(ME4000_AI_CTRL_BIT_HF_IRQ |
1203 ME4000_AI_CTRL_BIT_SC_IRQ);
1204 outl(tmp, dev->iobase + ME4000_AI_CTRL_REG);
1206 s->async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
1209 "comedi%d: me4000: me4000_ai_isr(): "
1210 "Undefined FIFO state\n", dev->minor);
1213 for (i = 0; i < c; i++) {
1214 /* Read value from data fifo */
1215 lval = inl(dev->iobase + ME4000_AI_DATA_REG) & 0xFFFF;
1218 if (!comedi_buf_put(s->async, lval)) {
1220 * Buffer overflow, so stop conversion
1221 * and disable all interrupts
1223 tmp |= ME4000_AI_CTRL_BIT_IMMEDIATE_STOP;
1224 tmp &= ~(ME4000_AI_CTRL_BIT_HF_IRQ |
1225 ME4000_AI_CTRL_BIT_SC_IRQ);
1226 outl(tmp, dev->iobase + ME4000_AI_CTRL_REG);
1228 s->async->events |= COMEDI_CB_OVERFLOW;
1231 "comedi%d: me4000: me4000_ai_isr(): "
1232 "Buffer overflow\n", dev->minor);
1238 /* Work is done, so reset the interrupt */
1239 tmp |= ME4000_AI_CTRL_BIT_HF_IRQ_RESET;
1240 outl(tmp, dev->iobase + ME4000_AI_CTRL_REG);
1241 tmp &= ~ME4000_AI_CTRL_BIT_HF_IRQ_RESET;
1242 outl(tmp, dev->iobase + ME4000_AI_CTRL_REG);
1245 if (inl(dev->iobase + ME4000_IRQ_STATUS_REG) &
1246 ME4000_IRQ_STATUS_BIT_SC) {
1247 s->async->events |= COMEDI_CB_BLOCK | COMEDI_CB_EOA;
1250 * Acquisition is complete, so stop
1251 * conversion and disable all interrupts
1253 tmp = inl(dev->iobase + ME4000_AI_CTRL_REG);
1254 tmp |= ME4000_AI_CTRL_BIT_IMMEDIATE_STOP;
1255 tmp &= ~(ME4000_AI_CTRL_BIT_HF_IRQ | ME4000_AI_CTRL_BIT_SC_IRQ);
1256 outl(tmp, dev->iobase + ME4000_AI_CTRL_REG);
1258 /* Poll data until fifo empty */
1259 while (inl(dev->iobase + ME4000_AI_CTRL_REG) &
1260 ME4000_AI_STATUS_BIT_EF_DATA) {
1261 /* Read value from data fifo */
1262 lval = inl(dev->iobase + ME4000_AI_DATA_REG) & 0xFFFF;
1265 if (!comedi_buf_put(s->async, lval)) {
1267 "comedi%d: me4000: me4000_ai_isr(): "
1268 "Buffer overflow\n", dev->minor);
1269 s->async->events |= COMEDI_CB_OVERFLOW;
1274 /* Work is done, so reset the interrupt */
1275 tmp |= ME4000_AI_CTRL_BIT_SC_IRQ_RESET;
1276 outl(tmp, dev->iobase + ME4000_AI_CTRL_REG);
1277 tmp &= ~ME4000_AI_CTRL_BIT_SC_IRQ_RESET;
1278 outl(tmp, dev->iobase + ME4000_AI_CTRL_REG);
1281 if (s->async->events)
1282 comedi_event(dev, s);
1287 /*=============================================================================
1288 Analog output section
1289 ===========================================================================*/
1291 static int me4000_ao_insn_write(struct comedi_device *dev,
1292 struct comedi_subdevice *s,
1293 struct comedi_insn *insn, unsigned int *data)
1295 const struct me4000_board *thisboard = comedi_board(dev);
1296 struct me4000_info *info = dev->private;
1297 int chan = CR_CHAN(insn->chanspec);
1298 int rang = CR_RANGE(insn->chanspec);
1299 int aref = CR_AREF(insn->chanspec);
1304 } else if (insn->n > 1) {
1306 "comedi%d: me4000: me4000_ao_insn_write(): "
1307 "Invalid instruction length %d\n", dev->minor, insn->n);
1311 if (chan >= thisboard->ao_nchan) {
1313 "comedi%d: me4000: me4000_ao_insn_write(): "
1314 "Invalid channel %d\n", dev->minor, insn->n);
1320 "comedi%d: me4000: me4000_ao_insn_write(): "
1321 "Invalid range %d\n", dev->minor, insn->n);
1325 if (aref != AREF_GROUND && aref != AREF_COMMON) {
1327 "comedi%d: me4000: me4000_ao_insn_write(): "
1328 "Invalid aref %d\n", dev->minor, insn->n);
1332 /* Stop any running conversion */
1333 tmp = inl(dev->iobase + ME4000_AO_CTRL_REG(chan));
1334 tmp |= ME4000_AO_CTRL_BIT_IMMEDIATE_STOP;
1335 outl(tmp, dev->iobase + ME4000_AO_CTRL_REG(chan));
1337 /* Clear control register and set to single mode */
1338 outl(0x0, dev->iobase + ME4000_AO_CTRL_REG(chan));
1340 /* Write data value */
1341 outl(data[0], dev->iobase + ME4000_AO_SINGLE_REG(chan));
1343 /* Store in the mirror */
1344 info->ao_readback[chan] = data[0];
1349 static int me4000_ao_insn_read(struct comedi_device *dev,
1350 struct comedi_subdevice *s,
1351 struct comedi_insn *insn, unsigned int *data)
1353 struct me4000_info *info = dev->private;
1354 int chan = CR_CHAN(insn->chanspec);
1358 } else if (insn->n > 1) {
1360 ("comedi%d: me4000: me4000_ao_insn_read(): "
1361 "Invalid instruction length\n", dev->minor);
1365 data[0] = info->ao_readback[chan];
1370 /*=============================================================================
1372 ===========================================================================*/
1374 static int me4000_dio_insn_bits(struct comedi_device *dev,
1375 struct comedi_subdevice *s,
1376 struct comedi_insn *insn, unsigned int *data)
1379 * The insn data consists of a mask in data[0] and the new data
1380 * in data[1]. The mask defines which bits we are concerning about.
1381 * The new data must be anded with the mask.
1382 * Each channel corresponds to a bit.
1385 /* Check if requested ports are configured for output */
1386 if ((s->io_bits & data[0]) != data[0])
1389 s->state &= ~data[0];
1390 s->state |= data[0] & data[1];
1392 /* Write out the new digital output lines */
1393 outl((s->state >> 0) & 0xFF,
1394 dev->iobase + ME4000_DIO_PORT_0_REG);
1395 outl((s->state >> 8) & 0xFF,
1396 dev->iobase + ME4000_DIO_PORT_1_REG);
1397 outl((s->state >> 16) & 0xFF,
1398 dev->iobase + ME4000_DIO_PORT_2_REG);
1399 outl((s->state >> 24) & 0xFF,
1400 dev->iobase + ME4000_DIO_PORT_3_REG);
1403 /* On return, data[1] contains the value of
1404 the digital input and output lines. */
1405 data[1] = ((inl(dev->iobase + ME4000_DIO_PORT_0_REG) & 0xFF) << 0) |
1406 ((inl(dev->iobase + ME4000_DIO_PORT_1_REG) & 0xFF) << 8) |
1407 ((inl(dev->iobase + ME4000_DIO_PORT_2_REG) & 0xFF) << 16) |
1408 ((inl(dev->iobase + ME4000_DIO_PORT_3_REG) & 0xFF) << 24);
1413 static int me4000_dio_insn_config(struct comedi_device *dev,
1414 struct comedi_subdevice *s,
1415 struct comedi_insn *insn, unsigned int *data)
1418 int chan = CR_CHAN(insn->chanspec);
1423 case INSN_CONFIG_DIO_QUERY:
1425 (s->io_bits & (1 << chan)) ? COMEDI_OUTPUT : COMEDI_INPUT;
1427 case INSN_CONFIG_DIO_INPUT:
1428 case INSN_CONFIG_DIO_OUTPUT:
1433 * The input or output configuration of each digital line is
1434 * configured by a special insn_config instruction. chanspec
1435 * contains the channel to be changed, and data[0] contains the
1436 * value INSN_CONFIG_DIO_INPUT or INSN_CONFIG_DIO_OUTPUT.
1437 * On the ME-4000 it is only possible to switch port wise (8 bit)
1440 tmp = inl(dev->iobase + ME4000_DIO_CTRL_REG);
1442 if (data[0] == INSN_CONFIG_DIO_OUTPUT) {
1445 tmp &= ~(ME4000_DIO_CTRL_BIT_MODE_0 |
1446 ME4000_DIO_CTRL_BIT_MODE_1);
1447 tmp |= ME4000_DIO_CTRL_BIT_MODE_0;
1448 } else if (chan < 16) {
1450 * Chech for optoisolated ME-4000 version.
1451 * If one the first port is a fixed output
1452 * port and the second is a fixed input port.
1454 if (!inl(dev->iobase + ME4000_DIO_DIR_REG))
1457 s->io_bits |= 0xFF00;
1458 tmp &= ~(ME4000_DIO_CTRL_BIT_MODE_2 |
1459 ME4000_DIO_CTRL_BIT_MODE_3);
1460 tmp |= ME4000_DIO_CTRL_BIT_MODE_2;
1461 } else if (chan < 24) {
1462 s->io_bits |= 0xFF0000;
1463 tmp &= ~(ME4000_DIO_CTRL_BIT_MODE_4 |
1464 ME4000_DIO_CTRL_BIT_MODE_5);
1465 tmp |= ME4000_DIO_CTRL_BIT_MODE_4;
1466 } else if (chan < 32) {
1467 s->io_bits |= 0xFF000000;
1468 tmp &= ~(ME4000_DIO_CTRL_BIT_MODE_6 |
1469 ME4000_DIO_CTRL_BIT_MODE_7);
1470 tmp |= ME4000_DIO_CTRL_BIT_MODE_6;
1477 * Chech for optoisolated ME-4000 version.
1478 * If one the first port is a fixed output
1479 * port and the second is a fixed input port.
1481 if (!inl(dev->iobase + ME4000_DIO_DIR_REG))
1484 s->io_bits &= ~0xFF;
1485 tmp &= ~(ME4000_DIO_CTRL_BIT_MODE_0 |
1486 ME4000_DIO_CTRL_BIT_MODE_1);
1487 } else if (chan < 16) {
1488 s->io_bits &= ~0xFF00;
1489 tmp &= ~(ME4000_DIO_CTRL_BIT_MODE_2 |
1490 ME4000_DIO_CTRL_BIT_MODE_3);
1491 } else if (chan < 24) {
1492 s->io_bits &= ~0xFF0000;
1493 tmp &= ~(ME4000_DIO_CTRL_BIT_MODE_4 |
1494 ME4000_DIO_CTRL_BIT_MODE_5);
1495 } else if (chan < 32) {
1496 s->io_bits &= ~0xFF000000;
1497 tmp &= ~(ME4000_DIO_CTRL_BIT_MODE_6 |
1498 ME4000_DIO_CTRL_BIT_MODE_7);
1504 outl(tmp, dev->iobase + ME4000_DIO_CTRL_REG);
1509 /*=============================================================================
1511 ===========================================================================*/
1513 static int me4000_cnt_insn_config(struct comedi_device *dev,
1514 struct comedi_subdevice *s,
1515 struct comedi_insn *insn,
1518 struct me4000_info *info = dev->private;
1526 err = i8254_load(info->timer_regbase, 0, insn->chanspec, 0,
1527 I8254_MODE0 | I8254_BINARY);
1531 case GPCT_SET_OPERATION:
1535 err = i8254_set_mode(info->timer_regbase, 0, insn->chanspec,
1536 (data[1] << 1) | I8254_BINARY);
1547 static int me4000_cnt_insn_read(struct comedi_device *dev,
1548 struct comedi_subdevice *s,
1549 struct comedi_insn *insn, unsigned int *data)
1551 struct me4000_info *info = dev->private;
1558 "comedi%d: me4000: me4000_cnt_insn_read(): "
1559 "Invalid instruction length %d\n",
1560 dev->minor, insn->n);
1564 data[0] = i8254_read(info->timer_regbase, 0, insn->chanspec);
1569 static int me4000_cnt_insn_write(struct comedi_device *dev,
1570 struct comedi_subdevice *s,
1571 struct comedi_insn *insn, unsigned int *data)
1573 struct me4000_info *info = dev->private;
1577 } else if (insn->n > 1) {
1579 "comedi%d: me4000: me4000_cnt_insn_write(): "
1580 "Invalid instruction length %d\n",
1581 dev->minor, insn->n);
1585 i8254_write(info->timer_regbase, 0, insn->chanspec, data[0]);
1590 static const void *me4000_find_boardinfo(struct comedi_device *dev,
1591 struct pci_dev *pcidev)
1593 const struct me4000_board *thisboard;
1596 for (i = 0; i < ARRAY_SIZE(me4000_boards); i++) {
1597 thisboard = &me4000_boards[i];
1598 if (thisboard->device_id == pcidev->device)
1604 static int me4000_attach_pci(struct comedi_device *dev,
1605 struct pci_dev *pcidev)
1607 const struct me4000_board *thisboard;
1608 struct me4000_info *info;
1609 struct comedi_subdevice *s;
1612 comedi_set_hw_dev(dev, &pcidev->dev);
1614 thisboard = me4000_find_boardinfo(dev, pcidev);
1617 dev->board_ptr = thisboard;
1618 dev->board_name = thisboard->name;
1620 result = alloc_private(dev, sizeof(*info));
1623 info = dev->private;
1625 result = comedi_pci_enable(pcidev, dev->board_name);
1629 info->plx_regbase = pci_resource_start(pcidev, 1);
1630 dev->iobase = pci_resource_start(pcidev, 2);
1631 info->timer_regbase = pci_resource_start(pcidev, 3);
1632 if (!info->plx_regbase || !dev->iobase || !info->timer_regbase)
1635 result = xilinx_download(dev);
1641 result = comedi_alloc_subdevices(dev, 4);
1645 /*=========================================================================
1646 Analog input subdevice
1647 ========================================================================*/
1649 s = &dev->subdevices[0];
1651 if (thisboard->ai_nchan) {
1652 s->type = COMEDI_SUBD_AI;
1654 SDF_READABLE | SDF_COMMON | SDF_GROUND | SDF_DIFF;
1655 s->n_chan = thisboard->ai_nchan;
1656 s->maxdata = 0xFFFF; /* 16 bit ADC */
1657 s->len_chanlist = ME4000_AI_CHANNEL_LIST_COUNT;
1658 s->range_table = &me4000_ai_range;
1659 s->insn_read = me4000_ai_insn_read;
1661 if (pcidev->irq > 0) {
1662 if (request_irq(pcidev->irq, me4000_ai_isr,
1663 IRQF_SHARED, dev->board_name, dev)) {
1664 dev_warn(dev->class_dev,
1665 "request_irq failed\n");
1667 dev->read_subdev = s;
1668 s->subdev_flags |= SDF_CMD_READ;
1669 s->cancel = me4000_ai_cancel;
1670 s->do_cmdtest = me4000_ai_do_cmd_test;
1671 s->do_cmd = me4000_ai_do_cmd;
1673 dev->irq = pcidev->irq;
1676 dev_warn(dev->class_dev, "No interrupt available\n");
1679 s->type = COMEDI_SUBD_UNUSED;
1682 /*=========================================================================
1683 Analog output subdevice
1684 ========================================================================*/
1686 s = &dev->subdevices[1];
1688 if (thisboard->ao_nchan) {
1689 s->type = COMEDI_SUBD_AO;
1690 s->subdev_flags = SDF_WRITEABLE | SDF_COMMON | SDF_GROUND;
1691 s->n_chan = thisboard->ao_nchan;
1692 s->maxdata = 0xFFFF; /* 16 bit DAC */
1693 s->range_table = &range_bipolar10;
1694 s->insn_write = me4000_ao_insn_write;
1695 s->insn_read = me4000_ao_insn_read;
1697 s->type = COMEDI_SUBD_UNUSED;
1700 /*=========================================================================
1701 Digital I/O subdevice
1702 ========================================================================*/
1704 s = &dev->subdevices[2];
1706 if (thisboard->dio_nchan) {
1707 s->type = COMEDI_SUBD_DIO;
1708 s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
1709 s->n_chan = thisboard->dio_nchan;
1711 s->range_table = &range_digital;
1712 s->insn_bits = me4000_dio_insn_bits;
1713 s->insn_config = me4000_dio_insn_config;
1715 s->type = COMEDI_SUBD_UNUSED;
1719 * Check for optoisolated ME-4000 version. If one the first
1720 * port is a fixed output port and the second is a fixed input port.
1722 if (!inl(dev->iobase + ME4000_DIO_DIR_REG)) {
1724 outl(ME4000_DIO_CTRL_BIT_MODE_0,
1725 dev->iobase + ME4000_DIO_DIR_REG);
1728 /*=========================================================================
1730 ========================================================================*/
1732 s = &dev->subdevices[3];
1734 if (thisboard->has_counter) {
1735 s->type = COMEDI_SUBD_COUNTER;
1736 s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
1738 s->maxdata = 0xFFFF; /* 16 bit counters */
1739 s->insn_read = me4000_cnt_insn_read;
1740 s->insn_write = me4000_cnt_insn_write;
1741 s->insn_config = me4000_cnt_insn_config;
1743 s->type = COMEDI_SUBD_UNUSED;
1749 static void me4000_detach(struct comedi_device *dev)
1751 struct pci_dev *pcidev = comedi_to_pci_dev(dev);
1754 free_irq(dev->irq, dev);
1758 comedi_pci_disable(pcidev);
1763 static struct comedi_driver me4000_driver = {
1764 .driver_name = "me4000",
1765 .module = THIS_MODULE,
1766 .attach_pci = me4000_attach_pci,
1767 .detach = me4000_detach,
1770 static int __devinit me4000_pci_probe(struct pci_dev *dev,
1771 const struct pci_device_id *ent)
1773 return comedi_pci_auto_config(dev, &me4000_driver);
1776 static void __devexit me4000_pci_remove(struct pci_dev *dev)
1778 comedi_pci_auto_unconfig(dev);
1781 static DEFINE_PCI_DEVICE_TABLE(me4000_pci_table) = {
1782 {PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4650)},
1783 {PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4660)},
1784 {PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4660I)},
1785 {PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4660S)},
1786 {PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4660IS)},
1787 {PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4670)},
1788 {PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4670I)},
1789 {PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4670S)},
1790 {PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4670IS)},
1791 {PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4680)},
1792 {PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4680I)},
1793 {PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4680S)},
1794 {PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4680IS)},
1797 MODULE_DEVICE_TABLE(pci, me4000_pci_table);
1799 static struct pci_driver me4000_pci_driver = {
1801 .id_table = me4000_pci_table,
1802 .probe = me4000_pci_probe,
1803 .remove = __devexit_p(me4000_pci_remove),
1805 module_comedi_pci_driver(me4000_driver, me4000_pci_driver);
1807 MODULE_AUTHOR("Comedi http://www.comedi.org");
1808 MODULE_DESCRIPTION("Comedi low-level driver");
1809 MODULE_LICENSE("GPL");