2 comedi/drivers/me4000.c
3 Source code for the Meilhaus ME-4000 board family.
5 COMEDI - Linux Control and Measurement Device Interface
6 Copyright (C) 2000 David A. Schleef <ds@schleef.org>
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 Description: Meilhaus ME-4000 series boards
26 Devices: [Meilhaus] ME-4650 (me4000), ME-4670i, ME-4680, ME-4680i, ME-4680is
27 Author: gg (Guenter Gebhardt <g.gebhardt@meilhaus.com>)
28 Updated: Mon, 18 Mar 2002 15:34:01 -0800
29 Status: broken (no support for loading firmware)
38 Configuration Options:
40 [0] - PCI bus number (optional)
41 [1] - PCI slot number (optional)
43 If bus/slot is not specified, the first available PCI
46 The firmware required by these boards is available in the
47 comedi_nonfree_firmware tarball available from
48 http://www.comedi.org. However, the driver's support for
49 loading the firmware through comedi_config is currently
54 #include <linux/interrupt.h>
55 #include "../comedidev.h"
57 #include <linux/delay.h>
58 #include <linux/list.h>
59 #include <linux/spinlock.h>
63 /* file removed due to GPL incompatibility */
64 #include "me4000_fw.h"
67 #define PCI_VENDOR_ID_MEILHAUS 0x1402
69 #define PCI_DEVICE_ID_MEILHAUS_ME4650 0x4650
70 #define PCI_DEVICE_ID_MEILHAUS_ME4660 0x4660
71 #define PCI_DEVICE_ID_MEILHAUS_ME4660I 0x4661
72 #define PCI_DEVICE_ID_MEILHAUS_ME4660S 0x4662
73 #define PCI_DEVICE_ID_MEILHAUS_ME4660IS 0x4663
74 #define PCI_DEVICE_ID_MEILHAUS_ME4670 0x4670
75 #define PCI_DEVICE_ID_MEILHAUS_ME4670I 0x4671
76 #define PCI_DEVICE_ID_MEILHAUS_ME4670S 0x4672
77 #define PCI_DEVICE_ID_MEILHAUS_ME4670IS 0x4673
78 #define PCI_DEVICE_ID_MEILHAUS_ME4680 0x4680
79 #define PCI_DEVICE_ID_MEILHAUS_ME4680I 0x4681
80 #define PCI_DEVICE_ID_MEILHAUS_ME4680S 0x4682
81 #define PCI_DEVICE_ID_MEILHAUS_ME4680IS 0x4683
85 unsigned short device_id;
96 static const struct me4000_board me4000_boards[] = {
99 .device_id = PCI_DEVICE_ID_MEILHAUS_ME4650,
104 .device_id = PCI_DEVICE_ID_MEILHAUS_ME4660,
111 .device_id = PCI_DEVICE_ID_MEILHAUS_ME4660I,
118 .device_id = PCI_DEVICE_ID_MEILHAUS_ME4660S,
126 .device_id = PCI_DEVICE_ID_MEILHAUS_ME4660IS,
134 .device_id = PCI_DEVICE_ID_MEILHAUS_ME4670,
143 .device_id = PCI_DEVICE_ID_MEILHAUS_ME4670I,
152 .device_id = PCI_DEVICE_ID_MEILHAUS_ME4670S,
162 .device_id = PCI_DEVICE_ID_MEILHAUS_ME4670IS,
172 .device_id = PCI_DEVICE_ID_MEILHAUS_ME4680,
182 .device_id = PCI_DEVICE_ID_MEILHAUS_ME4680I,
192 .device_id = PCI_DEVICE_ID_MEILHAUS_ME4680S,
203 .device_id = PCI_DEVICE_ID_MEILHAUS_ME4680IS,
215 /*-----------------------------------------------------------------------------
216 Meilhaus function prototypes
217 ---------------------------------------------------------------------------*/
218 static int init_board_info(struct comedi_device *dev,
219 struct pci_dev *pci_dev_p);
220 static int init_ao_context(struct comedi_device *dev);
221 static int xilinx_download(struct comedi_device *dev);
222 static int reset_board(struct comedi_device *dev);
224 static int ai_write_chanlist(struct comedi_device *dev,
225 struct comedi_subdevice *s,
226 struct comedi_cmd *cmd);
228 static const struct comedi_lrange me4000_ai_range = {
238 static const struct comedi_lrange me4000_ao_range = {
245 static int me4000_probe(struct comedi_device *dev, struct comedi_devconfig *it)
247 struct pci_dev *pci_device = NULL;
249 const struct me4000_board *board;
251 /* Allocate private memory */
252 if (alloc_private(dev, sizeof(struct me4000_info)) < 0)
256 * Probe the device to determine what device in the series it is.
258 for_each_pci_dev(pci_device) {
259 if (pci_device->vendor == PCI_VENDOR_ID_MEILHAUS) {
260 for (i = 0; i < ARRAY_SIZE(me4000_boards); i++) {
261 if (me4000_boards[i].device_id ==
262 pci_device->device) {
265 * bus/slot requested?
267 if ((it->options[0] != 0)
268 || (it->options[1] != 0)) {
270 * Are we on the wrong
273 if (pci_device->bus->number !=
276 PCI_SLOT(pci_device->devfn)
281 dev->board_ptr = me4000_boards + i;
282 board = comedi_board(dev);
283 info->pci_dev_p = pci_device;
292 dev->board_name = board->name;
294 result = comedi_pci_enable(pci_device, dev->board_name);
298 info->plx_regbase = pci_resource_start(pci_device, 1);
299 if (!info->plx_regbase)
302 dev->iobase = pci_resource_start(pci_device, 2);
306 info->timer_regbase = pci_resource_start(pci_device, 3);
307 if (!info->timer_regbase)
310 info->program_regbase = pci_resource_start(pci_device, 5);
311 if (!info->program_regbase)
314 result = init_board_info(dev, pci_device);
318 result = init_ao_context(dev);
322 result = xilinx_download(dev);
326 result = reset_board(dev);
333 static int init_board_info(struct comedi_device *dev, struct pci_dev *pci_dev_p)
337 /* Init spin locks */
338 /* spin_lock_init(&info->preload_lock); */
339 /* spin_lock_init(&info->ai_ctrl_lock); */
341 /* Get the serial number */
342 result = pci_read_config_dword(pci_dev_p, 0x2C, &info->serial_no);
343 if (result != PCIBIOS_SUCCESSFUL)
346 /* Get the hardware revision */
347 result = pci_read_config_byte(pci_dev_p, 0x08, &info->hw_revision);
348 if (result != PCIBIOS_SUCCESSFUL)
351 /* Get the vendor id */
352 info->vendor_id = pci_dev_p->vendor;
354 /* Get the device id */
355 info->device_id = pci_dev_p->device;
357 /* Get the irq assigned to the board */
358 info->irq = pci_dev_p->irq;
363 static int init_ao_context(struct comedi_device *dev)
365 const struct me4000_board *thisboard = comedi_board(dev);
368 for (i = 0; i < thisboard->ao_nchan; i++) {
369 /* spin_lock_init(&info->ao_context[i].use_lock); */
370 info->ao_context[i].irq = info->irq;
374 info->ao_context[i].ctrl_reg =
375 dev->iobase + ME4000_AO_00_CTRL_REG;
376 info->ao_context[i].status_reg =
377 dev->iobase + ME4000_AO_00_STATUS_REG;
378 info->ao_context[i].fifo_reg =
379 dev->iobase + ME4000_AO_00_FIFO_REG;
380 info->ao_context[i].single_reg =
381 dev->iobase + ME4000_AO_00_SINGLE_REG;
382 info->ao_context[i].timer_reg =
383 dev->iobase + ME4000_AO_00_TIMER_REG;
384 info->ao_context[i].irq_status_reg =
385 dev->iobase + ME4000_IRQ_STATUS_REG;
386 info->ao_context[i].preload_reg =
387 dev->iobase + ME4000_AO_LOADSETREG_XX;
390 info->ao_context[i].ctrl_reg =
391 dev->iobase + ME4000_AO_01_CTRL_REG;
392 info->ao_context[i].status_reg =
393 dev->iobase + ME4000_AO_01_STATUS_REG;
394 info->ao_context[i].fifo_reg =
395 dev->iobase + ME4000_AO_01_FIFO_REG;
396 info->ao_context[i].single_reg =
397 dev->iobase + ME4000_AO_01_SINGLE_REG;
398 info->ao_context[i].timer_reg =
399 dev->iobase + ME4000_AO_01_TIMER_REG;
400 info->ao_context[i].irq_status_reg =
401 dev->iobase + ME4000_IRQ_STATUS_REG;
402 info->ao_context[i].preload_reg =
403 dev->iobase + ME4000_AO_LOADSETREG_XX;
406 info->ao_context[i].ctrl_reg =
407 dev->iobase + ME4000_AO_02_CTRL_REG;
408 info->ao_context[i].status_reg =
409 dev->iobase + ME4000_AO_02_STATUS_REG;
410 info->ao_context[i].fifo_reg =
411 dev->iobase + ME4000_AO_02_FIFO_REG;
412 info->ao_context[i].single_reg =
413 dev->iobase + ME4000_AO_02_SINGLE_REG;
414 info->ao_context[i].timer_reg =
415 dev->iobase + ME4000_AO_02_TIMER_REG;
416 info->ao_context[i].irq_status_reg =
417 dev->iobase + ME4000_IRQ_STATUS_REG;
418 info->ao_context[i].preload_reg =
419 dev->iobase + ME4000_AO_LOADSETREG_XX;
422 info->ao_context[i].ctrl_reg =
423 dev->iobase + ME4000_AO_03_CTRL_REG;
424 info->ao_context[i].status_reg =
425 dev->iobase + ME4000_AO_03_STATUS_REG;
426 info->ao_context[i].fifo_reg =
427 dev->iobase + ME4000_AO_03_FIFO_REG;
428 info->ao_context[i].single_reg =
429 dev->iobase + ME4000_AO_03_SINGLE_REG;
430 info->ao_context[i].timer_reg =
431 dev->iobase + ME4000_AO_03_TIMER_REG;
432 info->ao_context[i].irq_status_reg =
433 dev->iobase + ME4000_IRQ_STATUS_REG;
434 info->ao_context[i].preload_reg =
435 dev->iobase + ME4000_AO_LOADSETREG_XX;
445 #define FIRMWARE_NOT_AVAILABLE 1
446 #if FIRMWARE_NOT_AVAILABLE
447 extern unsigned char *xilinx_firm;
450 static int xilinx_download(struct comedi_device *dev)
453 wait_queue_head_t queue;
457 init_waitqueue_head(&queue);
460 * Set PLX local interrupt 2 polarity to high.
461 * Interrupt is thrown by init pin of xilinx.
463 outl(0x10, info->plx_regbase + PLX_INTCSR);
465 /* Set /CS and /WRITE of the Xilinx */
466 value = inl(info->plx_regbase + PLX_ICR);
468 outl(value, info->plx_regbase + PLX_ICR);
470 /* Init Xilinx with CS1 */
471 inb(info->program_regbase + 0xC8);
473 /* Wait until /INIT pin is set */
475 if (!(inl(info->plx_regbase + PLX_INTCSR) & 0x20)) {
477 "comedi%d: me4000: xilinx_download(): "
478 "Can't init Xilinx\n", dev->minor);
482 /* Reset /CS and /WRITE of the Xilinx */
483 value = inl(info->plx_regbase + PLX_ICR);
485 outl(value, info->plx_regbase + PLX_ICR);
486 if (FIRMWARE_NOT_AVAILABLE) {
487 comedi_error(dev, "xilinx firmware unavailable "
488 "due to licensing, aborting");
491 /* Download Xilinx firmware */
492 size = (xilinx_firm[0] << 24) + (xilinx_firm[1] << 16) +
493 (xilinx_firm[2] << 8) + xilinx_firm[3];
496 for (idx = 0; idx < size; idx++) {
497 outb(xilinx_firm[16 + idx], info->program_regbase);
500 /* Check if BUSY flag is low */
501 if (inl(info->plx_regbase + PLX_ICR) & 0x20) {
503 "comedi%d: me4000: xilinx_download(): "
504 "Xilinx is still busy (idx = %d)\n",
511 /* If done flag is high download was successful */
512 if (inl(info->plx_regbase + PLX_ICR) & 0x4) {
515 "comedi%d: me4000: xilinx_download(): "
516 "DONE flag is not set\n", dev->minor);
518 "comedi%d: me4000: xilinx_download(): "
519 "Download not successful\n", dev->minor);
523 /* Set /CS and /WRITE */
524 value = inl(info->plx_regbase + PLX_ICR);
526 outl(value, info->plx_regbase + PLX_ICR);
531 static int reset_board(struct comedi_device *dev)
535 /* Make a hardware reset */
536 icr = inl(info->plx_regbase + PLX_ICR);
538 outl(icr, info->plx_regbase + PLX_ICR);
540 outl(icr, info->plx_regbase + PLX_ICR);
542 /* 0x8000 to the DACs means an output voltage of 0V */
543 outl(0x8000, dev->iobase + ME4000_AO_00_SINGLE_REG);
544 outl(0x8000, dev->iobase + ME4000_AO_01_SINGLE_REG);
545 outl(0x8000, dev->iobase + ME4000_AO_02_SINGLE_REG);
546 outl(0x8000, dev->iobase + ME4000_AO_03_SINGLE_REG);
548 /* Set both stop bits in the analog input control register */
549 outl(ME4000_AI_CTRL_BIT_IMMEDIATE_STOP | ME4000_AI_CTRL_BIT_STOP,
550 dev->iobase + ME4000_AI_CTRL_REG);
552 /* Set both stop bits in the analog output control register */
553 outl(ME4000_AO_CTRL_BIT_IMMEDIATE_STOP | ME4000_AO_CTRL_BIT_STOP,
554 dev->iobase + ME4000_AO_00_CTRL_REG);
555 outl(ME4000_AO_CTRL_BIT_IMMEDIATE_STOP | ME4000_AO_CTRL_BIT_STOP,
556 dev->iobase + ME4000_AO_01_CTRL_REG);
557 outl(ME4000_AO_CTRL_BIT_IMMEDIATE_STOP | ME4000_AO_CTRL_BIT_STOP,
558 dev->iobase + ME4000_AO_02_CTRL_REG);
559 outl(ME4000_AO_CTRL_BIT_IMMEDIATE_STOP | ME4000_AO_CTRL_BIT_STOP,
560 dev->iobase + ME4000_AO_03_CTRL_REG);
562 /* Enable interrupts on the PLX */
563 outl(0x43, info->plx_regbase + PLX_INTCSR);
565 /* Set the adustment register for AO demux */
566 outl(ME4000_AO_DEMUX_ADJUST_VALUE,
567 dev->iobase + ME4000_AO_DEMUX_ADJUST_REG);
570 * Set digital I/O direction for port 0
571 * to output on isolated versions
573 if (!(inl(dev->iobase + ME4000_DIO_DIR_REG) & 0x1))
574 outl(0x1, dev->iobase + ME4000_DIO_CTRL_REG);
579 /*=============================================================================
581 ===========================================================================*/
583 static int me4000_ai_insn_read(struct comedi_device *dev,
584 struct comedi_subdevice *subdevice,
585 struct comedi_insn *insn, unsigned int *data)
587 const struct me4000_board *thisboard = comedi_board(dev);
588 int chan = CR_CHAN(insn->chanspec);
589 int rang = CR_RANGE(insn->chanspec);
590 int aref = CR_AREF(insn->chanspec);
592 unsigned long entry = 0;
598 } else if (insn->n > 1) {
600 "comedi%d: me4000: me4000_ai_insn_read(): "
601 "Invalid instruction length %d\n", dev->minor, insn->n);
607 entry |= ME4000_AI_LIST_RANGE_UNIPOLAR_2_5;
610 entry |= ME4000_AI_LIST_RANGE_UNIPOLAR_10;
613 entry |= ME4000_AI_LIST_RANGE_BIPOLAR_2_5;
616 entry |= ME4000_AI_LIST_RANGE_BIPOLAR_10;
620 "comedi%d: me4000: me4000_ai_insn_read(): "
621 "Invalid range specified\n", dev->minor);
628 if (chan >= thisboard->ai_nchan) {
630 "comedi%d: me4000: me4000_ai_insn_read(): "
631 "Analog input is not available\n", dev->minor);
634 entry |= ME4000_AI_LIST_INPUT_SINGLE_ENDED | chan;
638 if (rang == 0 || rang == 1) {
640 "comedi%d: me4000: me4000_ai_insn_read(): "
641 "Range must be bipolar when aref = diff\n",
646 if (chan >= thisboard->ai_diff_nchan) {
648 "comedi%d: me4000: me4000_ai_insn_read(): "
649 "Analog input is not available\n", dev->minor);
652 entry |= ME4000_AI_LIST_INPUT_DIFFERENTIAL | chan;
656 "comedi%d: me4000: me4000_ai_insn_read(): "
657 "Invalid aref specified\n", dev->minor);
661 entry |= ME4000_AI_LIST_LAST_ENTRY;
663 /* Clear channel list, data fifo and both stop bits */
664 tmp = inl(dev->iobase + ME4000_AI_CTRL_REG);
665 tmp &= ~(ME4000_AI_CTRL_BIT_CHANNEL_FIFO |
666 ME4000_AI_CTRL_BIT_DATA_FIFO |
667 ME4000_AI_CTRL_BIT_STOP | ME4000_AI_CTRL_BIT_IMMEDIATE_STOP);
668 outl(tmp, dev->iobase + ME4000_AI_CTRL_REG);
670 /* Set the acquisition mode to single */
671 tmp &= ~(ME4000_AI_CTRL_BIT_MODE_0 | ME4000_AI_CTRL_BIT_MODE_1 |
672 ME4000_AI_CTRL_BIT_MODE_2);
673 outl(tmp, dev->iobase + ME4000_AI_CTRL_REG);
675 /* Enable channel list and data fifo */
676 tmp |= ME4000_AI_CTRL_BIT_CHANNEL_FIFO | ME4000_AI_CTRL_BIT_DATA_FIFO;
677 outl(tmp, dev->iobase + ME4000_AI_CTRL_REG);
679 /* Generate channel list entry */
680 outl(entry, dev->iobase + ME4000_AI_CHANNEL_LIST_REG);
682 /* Set the timer to maximum sample rate */
683 outl(ME4000_AI_MIN_TICKS, dev->iobase + ME4000_AI_CHAN_TIMER_REG);
684 outl(ME4000_AI_MIN_TICKS, dev->iobase + ME4000_AI_CHAN_PRE_TIMER_REG);
686 /* Start conversion by dummy read */
687 inl(dev->iobase + ME4000_AI_START_REG);
689 /* Wait until ready */
691 if (!(inl(dev->iobase + ME4000_AI_STATUS_REG) &
692 ME4000_AI_STATUS_BIT_EF_DATA)) {
694 "comedi%d: me4000: me4000_ai_insn_read(): "
695 "Value not available after wait\n", dev->minor);
699 /* Read value from data fifo */
700 lval = inl(dev->iobase + ME4000_AI_DATA_REG) & 0xFFFF;
701 data[0] = lval ^ 0x8000;
706 static int me4000_ai_cancel(struct comedi_device *dev,
707 struct comedi_subdevice *s)
711 /* Stop any running conversion */
712 tmp = inl(dev->iobase + ME4000_AI_CTRL_REG);
713 tmp &= ~(ME4000_AI_CTRL_BIT_STOP | ME4000_AI_CTRL_BIT_IMMEDIATE_STOP);
714 outl(tmp, dev->iobase + ME4000_AI_CTRL_REG);
716 /* Clear the control register */
717 outl(0x0, dev->iobase + ME4000_AI_CTRL_REG);
722 static int ai_check_chanlist(struct comedi_device *dev,
723 struct comedi_subdevice *s, struct comedi_cmd *cmd)
725 const struct me4000_board *thisboard = comedi_board(dev);
729 /* Check whether a channel list is available */
730 if (!cmd->chanlist_len) {
732 "comedi%d: me4000: ai_check_chanlist(): "
733 "No channel list available\n", dev->minor);
737 /* Check the channel list size */
738 if (cmd->chanlist_len > ME4000_AI_CHANNEL_LIST_COUNT) {
740 "comedi%d: me4000: ai_check_chanlist(): "
741 "Channel list is to large\n", dev->minor);
745 /* Check the pointer */
746 if (!cmd->chanlist) {
748 "comedi%d: me4000: ai_check_chanlist(): "
749 "NULL pointer to channel list\n", dev->minor);
753 /* Check whether aref is equal for all entries */
754 aref = CR_AREF(cmd->chanlist[0]);
755 for (i = 0; i < cmd->chanlist_len; i++) {
756 if (CR_AREF(cmd->chanlist[i]) != aref) {
758 "comedi%d: me4000: ai_check_chanlist(): "
759 "Mode is not equal for all entries\n",
765 /* Check whether channels are available for this ending */
766 if (aref == SDF_DIFF) {
767 for (i = 0; i < cmd->chanlist_len; i++) {
768 if (CR_CHAN(cmd->chanlist[i]) >=
769 thisboard->ai_diff_nchan) {
771 "comedi%d: me4000: ai_check_chanlist():"
772 " Channel number to high\n", dev->minor);
777 for (i = 0; i < cmd->chanlist_len; i++) {
778 if (CR_CHAN(cmd->chanlist[i]) >= thisboard->ai_nchan) {
780 "comedi%d: me4000: ai_check_chanlist(): "
781 "Channel number to high\n", dev->minor);
787 /* Check if bipolar is set for all entries when in differential mode */
788 if (aref == SDF_DIFF) {
789 for (i = 0; i < cmd->chanlist_len; i++) {
790 if (CR_RANGE(cmd->chanlist[i]) != 1 &&
791 CR_RANGE(cmd->chanlist[i]) != 2) {
793 "comedi%d: me4000: ai_check_chanlist(): "
794 "Bipolar is not selected in "
795 "differential mode\n",
805 static int ai_round_cmd_args(struct comedi_device *dev,
806 struct comedi_subdevice *s,
807 struct comedi_cmd *cmd,
808 unsigned int *init_ticks,
809 unsigned int *scan_ticks, unsigned int *chan_ticks)
818 if (cmd->start_arg) {
819 *init_ticks = (cmd->start_arg * 33) / 1000;
820 rest = (cmd->start_arg * 33) % 1000;
822 if ((cmd->flags & TRIG_ROUND_MASK) == TRIG_ROUND_NEAREST) {
825 } else if ((cmd->flags & TRIG_ROUND_MASK) == TRIG_ROUND_UP) {
831 if (cmd->scan_begin_arg) {
832 *scan_ticks = (cmd->scan_begin_arg * 33) / 1000;
833 rest = (cmd->scan_begin_arg * 33) % 1000;
835 if ((cmd->flags & TRIG_ROUND_MASK) == TRIG_ROUND_NEAREST) {
838 } else if ((cmd->flags & TRIG_ROUND_MASK) == TRIG_ROUND_UP) {
844 if (cmd->convert_arg) {
845 *chan_ticks = (cmd->convert_arg * 33) / 1000;
846 rest = (cmd->convert_arg * 33) % 1000;
848 if ((cmd->flags & TRIG_ROUND_MASK) == TRIG_ROUND_NEAREST) {
851 } else if ((cmd->flags & TRIG_ROUND_MASK) == TRIG_ROUND_UP) {
860 static void ai_write_timer(struct comedi_device *dev,
861 unsigned int init_ticks,
862 unsigned int scan_ticks, unsigned int chan_ticks)
864 outl(init_ticks - 1, dev->iobase + ME4000_AI_SCAN_PRE_TIMER_LOW_REG);
865 outl(0x0, dev->iobase + ME4000_AI_SCAN_PRE_TIMER_HIGH_REG);
868 outl(scan_ticks - 1, dev->iobase + ME4000_AI_SCAN_TIMER_LOW_REG);
869 outl(0x0, dev->iobase + ME4000_AI_SCAN_TIMER_HIGH_REG);
872 outl(chan_ticks - 1, dev->iobase + ME4000_AI_CHAN_PRE_TIMER_REG);
873 outl(chan_ticks - 1, dev->iobase + ME4000_AI_CHAN_TIMER_REG);
876 static int ai_prepare(struct comedi_device *dev,
877 struct comedi_subdevice *s,
878 struct comedi_cmd *cmd,
879 unsigned int init_ticks,
880 unsigned int scan_ticks, unsigned int chan_ticks)
883 unsigned long tmp = 0;
885 /* Write timer arguments */
886 ai_write_timer(dev, init_ticks, scan_ticks, chan_ticks);
888 /* Reset control register */
889 outl(tmp, dev->iobase + ME4000_AI_CTRL_REG);
892 if ((cmd->start_src == TRIG_EXT &&
893 cmd->scan_begin_src == TRIG_TIMER &&
894 cmd->convert_src == TRIG_TIMER) ||
895 (cmd->start_src == TRIG_EXT &&
896 cmd->scan_begin_src == TRIG_FOLLOW &&
897 cmd->convert_src == TRIG_TIMER)) {
898 tmp = ME4000_AI_CTRL_BIT_MODE_1 |
899 ME4000_AI_CTRL_BIT_CHANNEL_FIFO |
900 ME4000_AI_CTRL_BIT_DATA_FIFO;
901 } else if (cmd->start_src == TRIG_EXT &&
902 cmd->scan_begin_src == TRIG_EXT &&
903 cmd->convert_src == TRIG_TIMER) {
904 tmp = ME4000_AI_CTRL_BIT_MODE_2 |
905 ME4000_AI_CTRL_BIT_CHANNEL_FIFO |
906 ME4000_AI_CTRL_BIT_DATA_FIFO;
907 } else if (cmd->start_src == TRIG_EXT &&
908 cmd->scan_begin_src == TRIG_EXT &&
909 cmd->convert_src == TRIG_EXT) {
910 tmp = ME4000_AI_CTRL_BIT_MODE_0 |
911 ME4000_AI_CTRL_BIT_MODE_1 |
912 ME4000_AI_CTRL_BIT_CHANNEL_FIFO |
913 ME4000_AI_CTRL_BIT_DATA_FIFO;
915 tmp = ME4000_AI_CTRL_BIT_MODE_0 |
916 ME4000_AI_CTRL_BIT_CHANNEL_FIFO |
917 ME4000_AI_CTRL_BIT_DATA_FIFO;
921 if (cmd->stop_src == TRIG_COUNT) {
922 outl(cmd->chanlist_len * cmd->stop_arg,
923 dev->iobase + ME4000_AI_SAMPLE_COUNTER_REG);
924 tmp |= ME4000_AI_CTRL_BIT_HF_IRQ | ME4000_AI_CTRL_BIT_SC_IRQ;
925 } else if (cmd->stop_src == TRIG_NONE &&
926 cmd->scan_end_src == TRIG_COUNT) {
927 outl(cmd->scan_end_arg,
928 dev->iobase + ME4000_AI_SAMPLE_COUNTER_REG);
929 tmp |= ME4000_AI_CTRL_BIT_HF_IRQ | ME4000_AI_CTRL_BIT_SC_IRQ;
931 tmp |= ME4000_AI_CTRL_BIT_HF_IRQ;
934 /* Write the setup to the control register */
935 outl(tmp, dev->iobase + ME4000_AI_CTRL_REG);
937 /* Write the channel list */
938 ai_write_chanlist(dev, s, cmd);
943 static int ai_write_chanlist(struct comedi_device *dev,
944 struct comedi_subdevice *s, struct comedi_cmd *cmd)
952 for (i = 0; i < cmd->chanlist_len; i++) {
953 chan = CR_CHAN(cmd->chanlist[i]);
954 rang = CR_RANGE(cmd->chanlist[i]);
955 aref = CR_AREF(cmd->chanlist[i]);
960 entry |= ME4000_AI_LIST_RANGE_UNIPOLAR_2_5;
962 entry |= ME4000_AI_LIST_RANGE_UNIPOLAR_10;
964 entry |= ME4000_AI_LIST_RANGE_BIPOLAR_2_5;
966 entry |= ME4000_AI_LIST_RANGE_BIPOLAR_10;
968 if (aref == SDF_DIFF)
969 entry |= ME4000_AI_LIST_INPUT_DIFFERENTIAL;
971 entry |= ME4000_AI_LIST_INPUT_SINGLE_ENDED;
973 outl(entry, dev->iobase + ME4000_AI_CHANNEL_LIST_REG);
979 static int me4000_ai_do_cmd(struct comedi_device *dev,
980 struct comedi_subdevice *s)
983 unsigned int init_ticks = 0;
984 unsigned int scan_ticks = 0;
985 unsigned int chan_ticks = 0;
986 struct comedi_cmd *cmd = &s->async->cmd;
988 /* Reset the analog input */
989 err = me4000_ai_cancel(dev, s);
993 /* Round the timer arguments */
994 err = ai_round_cmd_args(dev,
995 s, cmd, &init_ticks, &scan_ticks, &chan_ticks);
999 /* Prepare the AI for acquisition */
1000 err = ai_prepare(dev, s, cmd, init_ticks, scan_ticks, chan_ticks);
1004 /* Start acquistion by dummy read */
1005 inl(dev->iobase + ME4000_AI_START_REG);
1011 * me4000_ai_do_cmd_test():
1013 * The demo cmd.c in ./comedilib/demo specifies 6 return values:
1017 * - invalid argument
1018 * - argument conflict
1019 * - invalid chanlist
1020 * So I tried to adopt this scheme.
1022 static int me4000_ai_do_cmd_test(struct comedi_device *dev,
1023 struct comedi_subdevice *s,
1024 struct comedi_cmd *cmd)
1027 unsigned int init_ticks;
1028 unsigned int chan_ticks;
1029 unsigned int scan_ticks;
1032 /* Only rounding flags are implemented */
1033 cmd->flags &= TRIG_ROUND_NEAREST | TRIG_ROUND_UP | TRIG_ROUND_DOWN;
1035 /* Round the timer arguments */
1036 ai_round_cmd_args(dev, s, cmd, &init_ticks, &scan_ticks, &chan_ticks);
1039 * Stage 1. Check if the trigger sources are generally valid.
1041 switch (cmd->start_src) {
1046 cmd->start_src &= TRIG_NOW | TRIG_EXT;
1051 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1052 "Invalid start source\n", dev->minor);
1053 cmd->start_src = TRIG_NOW;
1056 switch (cmd->scan_begin_src) {
1062 cmd->scan_begin_src &= TRIG_FOLLOW | TRIG_TIMER | TRIG_EXT;
1067 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1068 "Invalid scan begin source\n", dev->minor);
1069 cmd->scan_begin_src = TRIG_FOLLOW;
1072 switch (cmd->convert_src) {
1077 cmd->convert_src &= TRIG_TIMER | TRIG_EXT;
1082 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1083 "Invalid convert source\n", dev->minor);
1084 cmd->convert_src = TRIG_TIMER;
1087 switch (cmd->scan_end_src) {
1092 cmd->scan_end_src &= TRIG_NONE | TRIG_COUNT;
1097 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1098 "Invalid scan end source\n", dev->minor);
1099 cmd->scan_end_src = TRIG_NONE;
1102 switch (cmd->stop_src) {
1107 cmd->stop_src &= TRIG_NONE | TRIG_COUNT;
1112 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1113 "Invalid stop source\n", dev->minor);
1114 cmd->stop_src = TRIG_NONE;
1121 * Stage 2. Check for trigger source conflicts.
1123 if (cmd->start_src == TRIG_NOW &&
1124 cmd->scan_begin_src == TRIG_TIMER &&
1125 cmd->convert_src == TRIG_TIMER) {
1126 } else if (cmd->start_src == TRIG_NOW &&
1127 cmd->scan_begin_src == TRIG_FOLLOW &&
1128 cmd->convert_src == TRIG_TIMER) {
1129 } else if (cmd->start_src == TRIG_EXT &&
1130 cmd->scan_begin_src == TRIG_TIMER &&
1131 cmd->convert_src == TRIG_TIMER) {
1132 } else if (cmd->start_src == TRIG_EXT &&
1133 cmd->scan_begin_src == TRIG_FOLLOW &&
1134 cmd->convert_src == TRIG_TIMER) {
1135 } else if (cmd->start_src == TRIG_EXT &&
1136 cmd->scan_begin_src == TRIG_EXT &&
1137 cmd->convert_src == TRIG_TIMER) {
1138 } else if (cmd->start_src == TRIG_EXT &&
1139 cmd->scan_begin_src == TRIG_EXT &&
1140 cmd->convert_src == TRIG_EXT) {
1143 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1144 "Invalid start trigger combination\n", dev->minor);
1145 cmd->start_src = TRIG_NOW;
1146 cmd->scan_begin_src = TRIG_FOLLOW;
1147 cmd->convert_src = TRIG_TIMER;
1151 if (cmd->stop_src == TRIG_NONE && cmd->scan_end_src == TRIG_NONE) {
1152 } else if (cmd->stop_src == TRIG_COUNT &&
1153 cmd->scan_end_src == TRIG_NONE) {
1154 } else if (cmd->stop_src == TRIG_NONE &&
1155 cmd->scan_end_src == TRIG_COUNT) {
1156 } else if (cmd->stop_src == TRIG_COUNT &&
1157 cmd->scan_end_src == TRIG_COUNT) {
1160 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1161 "Invalid stop trigger combination\n", dev->minor);
1162 cmd->stop_src = TRIG_NONE;
1163 cmd->scan_end_src = TRIG_NONE;
1170 * Stage 3. Check if arguments are generally valid.
1172 if (cmd->chanlist_len < 1) {
1174 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1175 "No channel list\n", dev->minor);
1176 cmd->chanlist_len = 1;
1179 if (init_ticks < 66) {
1181 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1182 "Start arg to low\n", dev->minor);
1183 cmd->start_arg = 2000;
1186 if (scan_ticks && scan_ticks < 67) {
1188 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1189 "Scan begin arg to low\n", dev->minor);
1190 cmd->scan_begin_arg = 2031;
1193 if (chan_ticks < 66) {
1195 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1196 "Convert arg to low\n", dev->minor);
1197 cmd->convert_arg = 2000;
1205 * Stage 4. Check for argument conflicts.
1207 if (cmd->start_src == TRIG_NOW &&
1208 cmd->scan_begin_src == TRIG_TIMER &&
1209 cmd->convert_src == TRIG_TIMER) {
1211 /* Check timer arguments */
1212 if (init_ticks < ME4000_AI_MIN_TICKS) {
1214 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1215 "Invalid start arg\n", dev->minor);
1216 cmd->start_arg = 2000; /* 66 ticks at least */
1219 if (chan_ticks < ME4000_AI_MIN_TICKS) {
1221 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1222 "Invalid convert arg\n", dev->minor);
1223 cmd->convert_arg = 2000; /* 66 ticks at least */
1226 if (scan_ticks <= cmd->chanlist_len * chan_ticks) {
1228 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1229 "Invalid scan end arg\n", dev->minor);
1231 /* At least one tick more */
1232 cmd->scan_end_arg = 2000 * cmd->chanlist_len + 31;
1235 } else if (cmd->start_src == TRIG_NOW &&
1236 cmd->scan_begin_src == TRIG_FOLLOW &&
1237 cmd->convert_src == TRIG_TIMER) {
1239 /* Check timer arguments */
1240 if (init_ticks < ME4000_AI_MIN_TICKS) {
1242 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1243 "Invalid start arg\n", dev->minor);
1244 cmd->start_arg = 2000; /* 66 ticks at least */
1247 if (chan_ticks < ME4000_AI_MIN_TICKS) {
1249 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1250 "Invalid convert arg\n", dev->minor);
1251 cmd->convert_arg = 2000; /* 66 ticks at least */
1254 } else if (cmd->start_src == TRIG_EXT &&
1255 cmd->scan_begin_src == TRIG_TIMER &&
1256 cmd->convert_src == TRIG_TIMER) {
1258 /* Check timer arguments */
1259 if (init_ticks < ME4000_AI_MIN_TICKS) {
1261 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1262 "Invalid start arg\n", dev->minor);
1263 cmd->start_arg = 2000; /* 66 ticks at least */
1266 if (chan_ticks < ME4000_AI_MIN_TICKS) {
1268 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1269 "Invalid convert arg\n", dev->minor);
1270 cmd->convert_arg = 2000; /* 66 ticks at least */
1273 if (scan_ticks <= cmd->chanlist_len * chan_ticks) {
1275 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1276 "Invalid scan end arg\n", dev->minor);
1278 /* At least one tick more */
1279 cmd->scan_end_arg = 2000 * cmd->chanlist_len + 31;
1282 } else if (cmd->start_src == TRIG_EXT &&
1283 cmd->scan_begin_src == TRIG_FOLLOW &&
1284 cmd->convert_src == TRIG_TIMER) {
1286 /* Check timer arguments */
1287 if (init_ticks < ME4000_AI_MIN_TICKS) {
1289 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1290 "Invalid start arg\n", dev->minor);
1291 cmd->start_arg = 2000; /* 66 ticks at least */
1294 if (chan_ticks < ME4000_AI_MIN_TICKS) {
1296 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1297 "Invalid convert arg\n", dev->minor);
1298 cmd->convert_arg = 2000; /* 66 ticks at least */
1301 } else if (cmd->start_src == TRIG_EXT &&
1302 cmd->scan_begin_src == TRIG_EXT &&
1303 cmd->convert_src == TRIG_TIMER) {
1305 /* Check timer arguments */
1306 if (init_ticks < ME4000_AI_MIN_TICKS) {
1308 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1309 "Invalid start arg\n", dev->minor);
1310 cmd->start_arg = 2000; /* 66 ticks at least */
1313 if (chan_ticks < ME4000_AI_MIN_TICKS) {
1315 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1316 "Invalid convert arg\n", dev->minor);
1317 cmd->convert_arg = 2000; /* 66 ticks at least */
1320 } else if (cmd->start_src == TRIG_EXT &&
1321 cmd->scan_begin_src == TRIG_EXT &&
1322 cmd->convert_src == TRIG_EXT) {
1324 /* Check timer arguments */
1325 if (init_ticks < ME4000_AI_MIN_TICKS) {
1327 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1328 "Invalid start arg\n", dev->minor);
1329 cmd->start_arg = 2000; /* 66 ticks at least */
1333 if (cmd->stop_src == TRIG_COUNT) {
1334 if (cmd->stop_arg == 0) {
1336 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1337 "Invalid stop arg\n", dev->minor);
1342 if (cmd->scan_end_src == TRIG_COUNT) {
1343 if (cmd->scan_end_arg == 0) {
1345 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1346 "Invalid scan end arg\n", dev->minor);
1347 cmd->scan_end_arg = 1;
1356 * Stage 5. Check the channel list.
1358 if (ai_check_chanlist(dev, s, cmd))
1364 static irqreturn_t me4000_ai_isr(int irq, void *dev_id)
1367 struct comedi_device *dev = dev_id;
1368 struct comedi_subdevice *s = &dev->subdevices[0];
1376 /* Reset all events */
1377 s->async->events = 0;
1379 /* Check if irq number is right */
1380 if (irq != info->irq) {
1382 "comedi%d: me4000: me4000_ai_isr(): "
1383 "Incorrect interrupt num: %d\n", dev->minor, irq);
1387 if (inl(dev->iobase + ME4000_IRQ_STATUS_REG) &
1388 ME4000_IRQ_STATUS_BIT_AI_HF) {
1389 /* Read status register to find out what happened */
1390 tmp = inl(dev->iobase + ME4000_AI_CTRL_REG);
1392 if (!(tmp & ME4000_AI_STATUS_BIT_FF_DATA) &&
1393 !(tmp & ME4000_AI_STATUS_BIT_HF_DATA) &&
1394 (tmp & ME4000_AI_STATUS_BIT_EF_DATA)) {
1395 c = ME4000_AI_FIFO_COUNT;
1398 * FIFO overflow, so stop conversion
1399 * and disable all interrupts
1401 tmp |= ME4000_AI_CTRL_BIT_IMMEDIATE_STOP;
1402 tmp &= ~(ME4000_AI_CTRL_BIT_HF_IRQ |
1403 ME4000_AI_CTRL_BIT_SC_IRQ);
1404 outl(tmp, dev->iobase + ME4000_AI_CTRL_REG);
1406 s->async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
1409 "comedi%d: me4000: me4000_ai_isr(): "
1410 "FIFO overflow\n", dev->minor);
1411 } else if ((tmp & ME4000_AI_STATUS_BIT_FF_DATA)
1412 && !(tmp & ME4000_AI_STATUS_BIT_HF_DATA)
1413 && (tmp & ME4000_AI_STATUS_BIT_EF_DATA)) {
1414 s->async->events |= COMEDI_CB_BLOCK;
1416 c = ME4000_AI_FIFO_COUNT / 2;
1419 "comedi%d: me4000: me4000_ai_isr(): "
1420 "Can't determine state of fifo\n", dev->minor);
1424 * Undefined state, so stop conversion
1425 * and disable all interrupts
1427 tmp |= ME4000_AI_CTRL_BIT_IMMEDIATE_STOP;
1428 tmp &= ~(ME4000_AI_CTRL_BIT_HF_IRQ |
1429 ME4000_AI_CTRL_BIT_SC_IRQ);
1430 outl(tmp, dev->iobase + ME4000_AI_CTRL_REG);
1432 s->async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
1435 "comedi%d: me4000: me4000_ai_isr(): "
1436 "Undefined FIFO state\n", dev->minor);
1439 for (i = 0; i < c; i++) {
1440 /* Read value from data fifo */
1441 lval = inl(dev->iobase + ME4000_AI_DATA_REG) & 0xFFFF;
1444 if (!comedi_buf_put(s->async, lval)) {
1446 * Buffer overflow, so stop conversion
1447 * and disable all interrupts
1449 tmp |= ME4000_AI_CTRL_BIT_IMMEDIATE_STOP;
1450 tmp &= ~(ME4000_AI_CTRL_BIT_HF_IRQ |
1451 ME4000_AI_CTRL_BIT_SC_IRQ);
1452 outl(tmp, dev->iobase + ME4000_AI_CTRL_REG);
1454 s->async->events |= COMEDI_CB_OVERFLOW;
1457 "comedi%d: me4000: me4000_ai_isr(): "
1458 "Buffer overflow\n", dev->minor);
1464 /* Work is done, so reset the interrupt */
1465 tmp |= ME4000_AI_CTRL_BIT_HF_IRQ_RESET;
1466 outl(tmp, dev->iobase + ME4000_AI_CTRL_REG);
1467 tmp &= ~ME4000_AI_CTRL_BIT_HF_IRQ_RESET;
1468 outl(tmp, dev->iobase + ME4000_AI_CTRL_REG);
1471 if (inl(dev->iobase + ME4000_IRQ_STATUS_REG) &
1472 ME4000_IRQ_STATUS_BIT_SC) {
1473 s->async->events |= COMEDI_CB_BLOCK | COMEDI_CB_EOA;
1476 * Acquisition is complete, so stop
1477 * conversion and disable all interrupts
1479 tmp = inl(dev->iobase + ME4000_AI_CTRL_REG);
1480 tmp |= ME4000_AI_CTRL_BIT_IMMEDIATE_STOP;
1481 tmp &= ~(ME4000_AI_CTRL_BIT_HF_IRQ | ME4000_AI_CTRL_BIT_SC_IRQ);
1482 outl(tmp, dev->iobase + ME4000_AI_CTRL_REG);
1484 /* Poll data until fifo empty */
1485 while (inl(dev->iobase + ME4000_AI_CTRL_REG) &
1486 ME4000_AI_STATUS_BIT_EF_DATA) {
1487 /* Read value from data fifo */
1488 lval = inl(dev->iobase + ME4000_AI_DATA_REG) & 0xFFFF;
1491 if (!comedi_buf_put(s->async, lval)) {
1493 "comedi%d: me4000: me4000_ai_isr(): "
1494 "Buffer overflow\n", dev->minor);
1495 s->async->events |= COMEDI_CB_OVERFLOW;
1500 /* Work is done, so reset the interrupt */
1501 tmp |= ME4000_AI_CTRL_BIT_SC_IRQ_RESET;
1502 outl(tmp, dev->iobase + ME4000_AI_CTRL_REG);
1503 tmp &= ~ME4000_AI_CTRL_BIT_SC_IRQ_RESET;
1504 outl(tmp, dev->iobase + ME4000_AI_CTRL_REG);
1507 if (s->async->events)
1508 comedi_event(dev, s);
1513 /*=============================================================================
1514 Analog output section
1515 ===========================================================================*/
1517 static int me4000_ao_insn_write(struct comedi_device *dev,
1518 struct comedi_subdevice *s,
1519 struct comedi_insn *insn, unsigned int *data)
1521 const struct me4000_board *thisboard = comedi_board(dev);
1522 int chan = CR_CHAN(insn->chanspec);
1523 int rang = CR_RANGE(insn->chanspec);
1524 int aref = CR_AREF(insn->chanspec);
1529 } else if (insn->n > 1) {
1531 "comedi%d: me4000: me4000_ao_insn_write(): "
1532 "Invalid instruction length %d\n", dev->minor, insn->n);
1536 if (chan >= thisboard->ao_nchan) {
1538 "comedi%d: me4000: me4000_ao_insn_write(): "
1539 "Invalid channel %d\n", dev->minor, insn->n);
1545 "comedi%d: me4000: me4000_ao_insn_write(): "
1546 "Invalid range %d\n", dev->minor, insn->n);
1550 if (aref != AREF_GROUND && aref != AREF_COMMON) {
1552 "comedi%d: me4000: me4000_ao_insn_write(): "
1553 "Invalid aref %d\n", dev->minor, insn->n);
1557 /* Stop any running conversion */
1558 tmp = inl(info->ao_context[chan].ctrl_reg);
1559 tmp |= ME4000_AO_CTRL_BIT_IMMEDIATE_STOP;
1560 outl(tmp, info->ao_context[chan].ctrl_reg);
1562 /* Clear control register and set to single mode */
1563 outl(0x0, info->ao_context[chan].ctrl_reg);
1565 /* Write data value */
1566 outl(data[0], info->ao_context[chan].single_reg);
1568 /* Store in the mirror */
1569 info->ao_context[chan].mirror = data[0];
1574 static int me4000_ao_insn_read(struct comedi_device *dev,
1575 struct comedi_subdevice *s,
1576 struct comedi_insn *insn, unsigned int *data)
1578 int chan = CR_CHAN(insn->chanspec);
1582 } else if (insn->n > 1) {
1584 ("comedi%d: me4000: me4000_ao_insn_read(): "
1585 "Invalid instruction length\n", dev->minor);
1589 data[0] = info->ao_context[chan].mirror;
1594 /*=============================================================================
1596 ===========================================================================*/
1598 static int me4000_dio_insn_bits(struct comedi_device *dev,
1599 struct comedi_subdevice *s,
1600 struct comedi_insn *insn, unsigned int *data)
1603 * The insn data consists of a mask in data[0] and the new data
1604 * in data[1]. The mask defines which bits we are concerning about.
1605 * The new data must be anded with the mask.
1606 * Each channel corresponds to a bit.
1609 /* Check if requested ports are configured for output */
1610 if ((s->io_bits & data[0]) != data[0])
1613 s->state &= ~data[0];
1614 s->state |= data[0] & data[1];
1616 /* Write out the new digital output lines */
1617 outl((s->state >> 0) & 0xFF,
1618 dev->iobase + ME4000_DIO_PORT_0_REG);
1619 outl((s->state >> 8) & 0xFF,
1620 dev->iobase + ME4000_DIO_PORT_1_REG);
1621 outl((s->state >> 16) & 0xFF,
1622 dev->iobase + ME4000_DIO_PORT_2_REG);
1623 outl((s->state >> 24) & 0xFF,
1624 dev->iobase + ME4000_DIO_PORT_3_REG);
1627 /* On return, data[1] contains the value of
1628 the digital input and output lines. */
1629 data[1] = ((inl(dev->iobase + ME4000_DIO_PORT_0_REG) & 0xFF) << 0) |
1630 ((inl(dev->iobase + ME4000_DIO_PORT_1_REG) & 0xFF) << 8) |
1631 ((inl(dev->iobase + ME4000_DIO_PORT_2_REG) & 0xFF) << 16) |
1632 ((inl(dev->iobase + ME4000_DIO_PORT_3_REG) & 0xFF) << 24);
1637 static int me4000_dio_insn_config(struct comedi_device *dev,
1638 struct comedi_subdevice *s,
1639 struct comedi_insn *insn, unsigned int *data)
1642 int chan = CR_CHAN(insn->chanspec);
1647 case INSN_CONFIG_DIO_QUERY:
1649 (s->io_bits & (1 << chan)) ? COMEDI_OUTPUT : COMEDI_INPUT;
1651 case INSN_CONFIG_DIO_INPUT:
1652 case INSN_CONFIG_DIO_OUTPUT:
1657 * The input or output configuration of each digital line is
1658 * configured by a special insn_config instruction. chanspec
1659 * contains the channel to be changed, and data[0] contains the
1660 * value INSN_CONFIG_DIO_INPUT or INSN_CONFIG_DIO_OUTPUT.
1661 * On the ME-4000 it is only possible to switch port wise (8 bit)
1664 tmp = inl(dev->iobase + ME4000_DIO_CTRL_REG);
1666 if (data[0] == INSN_CONFIG_DIO_OUTPUT) {
1669 tmp &= ~(ME4000_DIO_CTRL_BIT_MODE_0 |
1670 ME4000_DIO_CTRL_BIT_MODE_1);
1671 tmp |= ME4000_DIO_CTRL_BIT_MODE_0;
1672 } else if (chan < 16) {
1674 * Chech for optoisolated ME-4000 version.
1675 * If one the first port is a fixed output
1676 * port and the second is a fixed input port.
1678 if (!inl(dev->iobase + ME4000_DIO_DIR_REG))
1681 s->io_bits |= 0xFF00;
1682 tmp &= ~(ME4000_DIO_CTRL_BIT_MODE_2 |
1683 ME4000_DIO_CTRL_BIT_MODE_3);
1684 tmp |= ME4000_DIO_CTRL_BIT_MODE_2;
1685 } else if (chan < 24) {
1686 s->io_bits |= 0xFF0000;
1687 tmp &= ~(ME4000_DIO_CTRL_BIT_MODE_4 |
1688 ME4000_DIO_CTRL_BIT_MODE_5);
1689 tmp |= ME4000_DIO_CTRL_BIT_MODE_4;
1690 } else if (chan < 32) {
1691 s->io_bits |= 0xFF000000;
1692 tmp &= ~(ME4000_DIO_CTRL_BIT_MODE_6 |
1693 ME4000_DIO_CTRL_BIT_MODE_7);
1694 tmp |= ME4000_DIO_CTRL_BIT_MODE_6;
1701 * Chech for optoisolated ME-4000 version.
1702 * If one the first port is a fixed output
1703 * port and the second is a fixed input port.
1705 if (!inl(dev->iobase + ME4000_DIO_DIR_REG))
1708 s->io_bits &= ~0xFF;
1709 tmp &= ~(ME4000_DIO_CTRL_BIT_MODE_0 |
1710 ME4000_DIO_CTRL_BIT_MODE_1);
1711 } else if (chan < 16) {
1712 s->io_bits &= ~0xFF00;
1713 tmp &= ~(ME4000_DIO_CTRL_BIT_MODE_2 |
1714 ME4000_DIO_CTRL_BIT_MODE_3);
1715 } else if (chan < 24) {
1716 s->io_bits &= ~0xFF0000;
1717 tmp &= ~(ME4000_DIO_CTRL_BIT_MODE_4 |
1718 ME4000_DIO_CTRL_BIT_MODE_5);
1719 } else if (chan < 32) {
1720 s->io_bits &= ~0xFF000000;
1721 tmp &= ~(ME4000_DIO_CTRL_BIT_MODE_6 |
1722 ME4000_DIO_CTRL_BIT_MODE_7);
1728 outl(tmp, dev->iobase + ME4000_DIO_CTRL_REG);
1733 /*=============================================================================
1735 ===========================================================================*/
1737 static int cnt_reset(struct comedi_device *dev, unsigned int channel)
1741 outb(0x30, info->timer_regbase + ME4000_CNT_CTRL_REG);
1742 outb(0x00, info->timer_regbase + ME4000_CNT_COUNTER_0_REG);
1743 outb(0x00, info->timer_regbase + ME4000_CNT_COUNTER_0_REG);
1746 outb(0x70, info->timer_regbase + ME4000_CNT_CTRL_REG);
1747 outb(0x00, info->timer_regbase + ME4000_CNT_COUNTER_1_REG);
1748 outb(0x00, info->timer_regbase + ME4000_CNT_COUNTER_1_REG);
1751 outb(0xB0, info->timer_regbase + ME4000_CNT_CTRL_REG);
1752 outb(0x00, info->timer_regbase + ME4000_CNT_COUNTER_2_REG);
1753 outb(0x00, info->timer_regbase + ME4000_CNT_COUNTER_2_REG);
1757 "comedi%d: me4000: cnt_reset(): Invalid channel\n",
1765 static int cnt_config(struct comedi_device *dev, unsigned int channel,
1772 tmp |= ME4000_CNT_COUNTER_0;
1775 tmp |= ME4000_CNT_COUNTER_1;
1778 tmp |= ME4000_CNT_COUNTER_2;
1782 "comedi%d: me4000: cnt_config(): Invalid channel\n",
1789 tmp |= ME4000_CNT_MODE_0;
1792 tmp |= ME4000_CNT_MODE_1;
1795 tmp |= ME4000_CNT_MODE_2;
1798 tmp |= ME4000_CNT_MODE_3;
1801 tmp |= ME4000_CNT_MODE_4;
1804 tmp |= ME4000_CNT_MODE_5;
1808 "comedi%d: me4000: cnt_config(): Invalid counter mode\n",
1813 /* Write the control word */
1815 outb(tmp, info->timer_regbase + ME4000_CNT_CTRL_REG);
1820 static int me4000_cnt_insn_config(struct comedi_device *dev,
1821 struct comedi_subdevice *s,
1822 struct comedi_insn *insn, unsigned int *data)
1831 "comedi%d: me4000: me4000_cnt_insn_config(): "
1832 "Invalid instruction length%d\n",
1833 dev->minor, insn->n);
1837 err = cnt_reset(dev, insn->chanspec);
1841 case GPCT_SET_OPERATION:
1844 "comedi%d: me4000: me4000_cnt_insn_config(): "
1845 "Invalid instruction length%d\n",
1846 dev->minor, insn->n);
1850 err = cnt_config(dev, insn->chanspec, data[1]);
1856 "comedi%d: me4000: me4000_cnt_insn_config(): "
1857 "Invalid instruction\n", dev->minor);
1864 static int me4000_cnt_insn_read(struct comedi_device *dev,
1865 struct comedi_subdevice *s,
1866 struct comedi_insn *insn, unsigned int *data)
1876 "comedi%d: me4000: me4000_cnt_insn_read(): "
1877 "Invalid instruction length %d\n",
1878 dev->minor, insn->n);
1882 switch (insn->chanspec) {
1884 tmp = inb(info->timer_regbase + ME4000_CNT_COUNTER_0_REG);
1886 tmp = inb(info->timer_regbase + ME4000_CNT_COUNTER_0_REG);
1887 data[0] |= tmp << 8;
1890 tmp = inb(info->timer_regbase + ME4000_CNT_COUNTER_1_REG);
1892 tmp = inb(info->timer_regbase + ME4000_CNT_COUNTER_1_REG);
1893 data[0] |= tmp << 8;
1896 tmp = inb(info->timer_regbase + ME4000_CNT_COUNTER_2_REG);
1898 tmp = inb(info->timer_regbase + ME4000_CNT_COUNTER_2_REG);
1899 data[0] |= tmp << 8;
1903 "comedi%d: me4000: me4000_cnt_insn_read(): "
1904 "Invalid channel %d\n",
1905 dev->minor, insn->chanspec);
1912 static int me4000_cnt_insn_write(struct comedi_device *dev,
1913 struct comedi_subdevice *s,
1914 struct comedi_insn *insn, unsigned int *data)
1921 } else if (insn->n > 1) {
1923 "comedi%d: me4000: me4000_cnt_insn_write(): "
1924 "Invalid instruction length %d\n",
1925 dev->minor, insn->n);
1929 switch (insn->chanspec) {
1931 tmp = data[0] & 0xFF;
1932 outb(tmp, info->timer_regbase + ME4000_CNT_COUNTER_0_REG);
1933 tmp = (data[0] >> 8) & 0xFF;
1934 outb(tmp, info->timer_regbase + ME4000_CNT_COUNTER_0_REG);
1937 tmp = data[0] & 0xFF;
1938 outb(tmp, info->timer_regbase + ME4000_CNT_COUNTER_1_REG);
1939 tmp = (data[0] >> 8) & 0xFF;
1940 outb(tmp, info->timer_regbase + ME4000_CNT_COUNTER_1_REG);
1943 tmp = data[0] & 0xFF;
1944 outb(tmp, info->timer_regbase + ME4000_CNT_COUNTER_2_REG);
1945 tmp = (data[0] >> 8) & 0xFF;
1946 outb(tmp, info->timer_regbase + ME4000_CNT_COUNTER_2_REG);
1950 "comedi%d: me4000: me4000_cnt_insn_write(): "
1951 "Invalid channel %d\n",
1952 dev->minor, insn->chanspec);
1959 static int me4000_attach(struct comedi_device *dev, struct comedi_devconfig *it)
1961 const struct me4000_board *thisboard;
1962 struct comedi_subdevice *s;
1965 result = me4000_probe(dev, it);
1968 thisboard = comedi_board(dev);
1970 result = comedi_alloc_subdevices(dev, 4);
1974 /*=========================================================================
1975 Analog input subdevice
1976 ========================================================================*/
1978 s = &dev->subdevices[0];
1980 if (thisboard->ai_nchan) {
1981 s->type = COMEDI_SUBD_AI;
1983 SDF_READABLE | SDF_COMMON | SDF_GROUND | SDF_DIFF;
1984 s->n_chan = thisboard->ai_nchan;
1985 s->maxdata = 0xFFFF; /* 16 bit ADC */
1986 s->len_chanlist = ME4000_AI_CHANNEL_LIST_COUNT;
1987 s->range_table = &me4000_ai_range;
1988 s->insn_read = me4000_ai_insn_read;
1990 if (info->irq > 0) {
1991 if (request_irq(info->irq, me4000_ai_isr,
1992 IRQF_SHARED, "ME-4000", dev)) {
1994 ("comedi%d: me4000: me4000_attach(): "
1995 "Unable to allocate irq\n", dev->minor);
1997 dev->read_subdev = s;
1998 s->subdev_flags |= SDF_CMD_READ;
1999 s->cancel = me4000_ai_cancel;
2000 s->do_cmdtest = me4000_ai_do_cmd_test;
2001 s->do_cmd = me4000_ai_do_cmd;
2005 "comedi%d: me4000: me4000_attach(): "
2006 "No interrupt available\n", dev->minor);
2009 s->type = COMEDI_SUBD_UNUSED;
2012 /*=========================================================================
2013 Analog output subdevice
2014 ========================================================================*/
2016 s = &dev->subdevices[1];
2018 if (thisboard->ao_nchan) {
2019 s->type = COMEDI_SUBD_AO;
2020 s->subdev_flags = SDF_WRITEABLE | SDF_COMMON | SDF_GROUND;
2021 s->n_chan = thisboard->ao_nchan;
2022 s->maxdata = 0xFFFF; /* 16 bit DAC */
2023 s->range_table = &me4000_ao_range;
2024 s->insn_write = me4000_ao_insn_write;
2025 s->insn_read = me4000_ao_insn_read;
2027 s->type = COMEDI_SUBD_UNUSED;
2030 /*=========================================================================
2031 Digital I/O subdevice
2032 ========================================================================*/
2034 s = &dev->subdevices[2];
2036 if (thisboard->dio_nchan) {
2037 s->type = COMEDI_SUBD_DIO;
2038 s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
2039 s->n_chan = thisboard->dio_nchan;
2041 s->range_table = &range_digital;
2042 s->insn_bits = me4000_dio_insn_bits;
2043 s->insn_config = me4000_dio_insn_config;
2045 s->type = COMEDI_SUBD_UNUSED;
2049 * Check for optoisolated ME-4000 version. If one the first
2050 * port is a fixed output port and the second is a fixed input port.
2052 if (!inl(dev->iobase + ME4000_DIO_DIR_REG)) {
2054 outl(ME4000_DIO_CTRL_BIT_MODE_0,
2055 dev->iobase + ME4000_DIO_DIR_REG);
2058 /*=========================================================================
2060 ========================================================================*/
2062 s = &dev->subdevices[3];
2064 if (thisboard->has_counter) {
2065 s->type = COMEDI_SUBD_COUNTER;
2066 s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
2068 s->maxdata = 0xFFFF; /* 16 bit counters */
2069 s->insn_read = me4000_cnt_insn_read;
2070 s->insn_write = me4000_cnt_insn_write;
2071 s->insn_config = me4000_cnt_insn_config;
2073 s->type = COMEDI_SUBD_UNUSED;
2079 static void me4000_detach(struct comedi_device *dev)
2082 if (info->pci_dev_p) {
2084 if (info->plx_regbase)
2085 comedi_pci_disable(info->pci_dev_p);
2086 pci_dev_put(info->pci_dev_p);
2091 static struct comedi_driver me4000_driver = {
2092 .driver_name = "me4000",
2093 .module = THIS_MODULE,
2094 .attach = me4000_attach,
2095 .detach = me4000_detach,
2098 static int __devinit me4000_pci_probe(struct pci_dev *dev,
2099 const struct pci_device_id *ent)
2101 return comedi_pci_auto_config(dev, &me4000_driver);
2104 static void __devexit me4000_pci_remove(struct pci_dev *dev)
2106 comedi_pci_auto_unconfig(dev);
2109 static DEFINE_PCI_DEVICE_TABLE(me4000_pci_table) = {
2110 {PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4650)},
2111 {PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4660)},
2112 {PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4660I)},
2113 {PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4660S)},
2114 {PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4660IS)},
2115 {PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4670)},
2116 {PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4670I)},
2117 {PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4670S)},
2118 {PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4670IS)},
2119 {PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4680)},
2120 {PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4680I)},
2121 {PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4680S)},
2122 {PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4680IS)},
2125 MODULE_DEVICE_TABLE(pci, me4000_pci_table);
2127 static struct pci_driver me4000_pci_driver = {
2129 .id_table = me4000_pci_table,
2130 .probe = me4000_pci_probe,
2131 .remove = __devexit_p(me4000_pci_remove),
2133 module_comedi_pci_driver(me4000_driver, me4000_pci_driver);
2135 MODULE_AUTHOR("Comedi http://www.comedi.org");
2136 MODULE_DESCRIPTION("Comedi low-level driver");
2137 MODULE_LICENSE("GPL");