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 init_ai_context(struct comedi_device *dev);
222 static int init_dio_context(struct comedi_device *dev);
223 static int xilinx_download(struct comedi_device *dev);
224 static int reset_board(struct comedi_device *dev);
226 static int ai_write_chanlist(struct comedi_device *dev,
227 struct comedi_subdevice *s,
228 struct comedi_cmd *cmd);
230 static const struct comedi_lrange me4000_ai_range = {
240 static const struct comedi_lrange me4000_ao_range = {
247 static int me4000_probe(struct comedi_device *dev, struct comedi_devconfig *it)
249 struct pci_dev *pci_device = NULL;
251 const struct me4000_board *board;
253 /* Allocate private memory */
254 if (alloc_private(dev, sizeof(struct me4000_info)) < 0)
258 * Probe the device to determine what device in the series it is.
260 for_each_pci_dev(pci_device) {
261 if (pci_device->vendor == PCI_VENDOR_ID_MEILHAUS) {
262 for (i = 0; i < ARRAY_SIZE(me4000_boards); i++) {
263 if (me4000_boards[i].device_id ==
264 pci_device->device) {
267 * bus/slot requested?
269 if ((it->options[0] != 0)
270 || (it->options[1] != 0)) {
272 * Are we on the wrong
275 if (pci_device->bus->number !=
278 PCI_SLOT(pci_device->devfn)
283 dev->board_ptr = me4000_boards + i;
284 board = comedi_board(dev);
285 info->pci_dev_p = pci_device;
294 dev->board_name = board->name;
296 result = comedi_pci_enable(pci_device, dev->board_name);
300 info->plx_regbase = pci_resource_start(pci_device, 1);
301 if (!info->plx_regbase)
304 dev->iobase = pci_resource_start(pci_device, 2);
308 info->timer_regbase = pci_resource_start(pci_device, 3);
309 if (!info->timer_regbase)
312 info->program_regbase = pci_resource_start(pci_device, 5);
313 if (!info->program_regbase)
316 result = init_board_info(dev, pci_device);
320 result = init_ao_context(dev);
324 result = init_ai_context(dev);
328 result = init_dio_context(dev);
332 result = xilinx_download(dev);
336 result = reset_board(dev);
343 static int init_board_info(struct comedi_device *dev, struct pci_dev *pci_dev_p)
347 /* Init spin locks */
348 /* spin_lock_init(&info->preload_lock); */
349 /* spin_lock_init(&info->ai_ctrl_lock); */
351 /* Get the serial number */
352 result = pci_read_config_dword(pci_dev_p, 0x2C, &info->serial_no);
353 if (result != PCIBIOS_SUCCESSFUL)
356 /* Get the hardware revision */
357 result = pci_read_config_byte(pci_dev_p, 0x08, &info->hw_revision);
358 if (result != PCIBIOS_SUCCESSFUL)
361 /* Get the vendor id */
362 info->vendor_id = pci_dev_p->vendor;
364 /* Get the device id */
365 info->device_id = pci_dev_p->device;
367 /* Get the irq assigned to the board */
368 info->irq = pci_dev_p->irq;
373 static int init_ao_context(struct comedi_device *dev)
375 const struct me4000_board *thisboard = comedi_board(dev);
378 for (i = 0; i < thisboard->ao_nchan; i++) {
379 /* spin_lock_init(&info->ao_context[i].use_lock); */
380 info->ao_context[i].irq = info->irq;
384 info->ao_context[i].ctrl_reg =
385 dev->iobase + ME4000_AO_00_CTRL_REG;
386 info->ao_context[i].status_reg =
387 dev->iobase + ME4000_AO_00_STATUS_REG;
388 info->ao_context[i].fifo_reg =
389 dev->iobase + ME4000_AO_00_FIFO_REG;
390 info->ao_context[i].single_reg =
391 dev->iobase + ME4000_AO_00_SINGLE_REG;
392 info->ao_context[i].timer_reg =
393 dev->iobase + ME4000_AO_00_TIMER_REG;
394 info->ao_context[i].irq_status_reg =
395 dev->iobase + ME4000_IRQ_STATUS_REG;
396 info->ao_context[i].preload_reg =
397 dev->iobase + ME4000_AO_LOADSETREG_XX;
400 info->ao_context[i].ctrl_reg =
401 dev->iobase + ME4000_AO_01_CTRL_REG;
402 info->ao_context[i].status_reg =
403 dev->iobase + ME4000_AO_01_STATUS_REG;
404 info->ao_context[i].fifo_reg =
405 dev->iobase + ME4000_AO_01_FIFO_REG;
406 info->ao_context[i].single_reg =
407 dev->iobase + ME4000_AO_01_SINGLE_REG;
408 info->ao_context[i].timer_reg =
409 dev->iobase + ME4000_AO_01_TIMER_REG;
410 info->ao_context[i].irq_status_reg =
411 dev->iobase + ME4000_IRQ_STATUS_REG;
412 info->ao_context[i].preload_reg =
413 dev->iobase + ME4000_AO_LOADSETREG_XX;
416 info->ao_context[i].ctrl_reg =
417 dev->iobase + ME4000_AO_02_CTRL_REG;
418 info->ao_context[i].status_reg =
419 dev->iobase + ME4000_AO_02_STATUS_REG;
420 info->ao_context[i].fifo_reg =
421 dev->iobase + ME4000_AO_02_FIFO_REG;
422 info->ao_context[i].single_reg =
423 dev->iobase + ME4000_AO_02_SINGLE_REG;
424 info->ao_context[i].timer_reg =
425 dev->iobase + ME4000_AO_02_TIMER_REG;
426 info->ao_context[i].irq_status_reg =
427 dev->iobase + ME4000_IRQ_STATUS_REG;
428 info->ao_context[i].preload_reg =
429 dev->iobase + ME4000_AO_LOADSETREG_XX;
432 info->ao_context[i].ctrl_reg =
433 dev->iobase + ME4000_AO_03_CTRL_REG;
434 info->ao_context[i].status_reg =
435 dev->iobase + ME4000_AO_03_STATUS_REG;
436 info->ao_context[i].fifo_reg =
437 dev->iobase + ME4000_AO_03_FIFO_REG;
438 info->ao_context[i].single_reg =
439 dev->iobase + ME4000_AO_03_SINGLE_REG;
440 info->ao_context[i].timer_reg =
441 dev->iobase + ME4000_AO_03_TIMER_REG;
442 info->ao_context[i].irq_status_reg =
443 dev->iobase + ME4000_IRQ_STATUS_REG;
444 info->ao_context[i].preload_reg =
445 dev->iobase + ME4000_AO_LOADSETREG_XX;
455 static int init_ai_context(struct comedi_device *dev)
457 info->ai_context.irq = info->irq;
459 info->ai_context.ctrl_reg = dev->iobase + ME4000_AI_CTRL_REG;
460 info->ai_context.status_reg =
461 dev->iobase + ME4000_AI_STATUS_REG;
462 info->ai_context.channel_list_reg =
463 dev->iobase + ME4000_AI_CHANNEL_LIST_REG;
464 info->ai_context.data_reg = dev->iobase + ME4000_AI_DATA_REG;
465 info->ai_context.chan_timer_reg =
466 dev->iobase + ME4000_AI_CHAN_TIMER_REG;
467 info->ai_context.chan_pre_timer_reg =
468 dev->iobase + ME4000_AI_CHAN_PRE_TIMER_REG;
469 info->ai_context.scan_timer_low_reg =
470 dev->iobase + ME4000_AI_SCAN_TIMER_LOW_REG;
471 info->ai_context.scan_timer_high_reg =
472 dev->iobase + ME4000_AI_SCAN_TIMER_HIGH_REG;
473 info->ai_context.scan_pre_timer_low_reg =
474 dev->iobase + ME4000_AI_SCAN_PRE_TIMER_LOW_REG;
475 info->ai_context.scan_pre_timer_high_reg =
476 dev->iobase + ME4000_AI_SCAN_PRE_TIMER_HIGH_REG;
477 info->ai_context.start_reg = dev->iobase + ME4000_AI_START_REG;
478 info->ai_context.irq_status_reg =
479 dev->iobase + ME4000_IRQ_STATUS_REG;
480 info->ai_context.sample_counter_reg =
481 dev->iobase + ME4000_AI_SAMPLE_COUNTER_REG;
486 static int init_dio_context(struct comedi_device *dev)
488 info->dio_context.dir_reg = dev->iobase + ME4000_DIO_DIR_REG;
489 info->dio_context.ctrl_reg = dev->iobase + ME4000_DIO_CTRL_REG;
490 info->dio_context.port_0_reg =
491 dev->iobase + ME4000_DIO_PORT_0_REG;
492 info->dio_context.port_1_reg =
493 dev->iobase + ME4000_DIO_PORT_1_REG;
494 info->dio_context.port_2_reg =
495 dev->iobase + ME4000_DIO_PORT_2_REG;
496 info->dio_context.port_3_reg =
497 dev->iobase + ME4000_DIO_PORT_3_REG;
502 #define FIRMWARE_NOT_AVAILABLE 1
503 #if FIRMWARE_NOT_AVAILABLE
504 extern unsigned char *xilinx_firm;
507 static int xilinx_download(struct comedi_device *dev)
510 wait_queue_head_t queue;
514 init_waitqueue_head(&queue);
517 * Set PLX local interrupt 2 polarity to high.
518 * Interrupt is thrown by init pin of xilinx.
520 outl(0x10, info->plx_regbase + PLX_INTCSR);
522 /* Set /CS and /WRITE of the Xilinx */
523 value = inl(info->plx_regbase + PLX_ICR);
525 outl(value, info->plx_regbase + PLX_ICR);
527 /* Init Xilinx with CS1 */
528 inb(info->program_regbase + 0xC8);
530 /* Wait until /INIT pin is set */
532 if (!(inl(info->plx_regbase + PLX_INTCSR) & 0x20)) {
534 "comedi%d: me4000: xilinx_download(): "
535 "Can't init Xilinx\n", dev->minor);
539 /* Reset /CS and /WRITE of the Xilinx */
540 value = inl(info->plx_regbase + PLX_ICR);
542 outl(value, info->plx_regbase + PLX_ICR);
543 if (FIRMWARE_NOT_AVAILABLE) {
544 comedi_error(dev, "xilinx firmware unavailable "
545 "due to licensing, aborting");
548 /* Download Xilinx firmware */
549 size = (xilinx_firm[0] << 24) + (xilinx_firm[1] << 16) +
550 (xilinx_firm[2] << 8) + xilinx_firm[3];
553 for (idx = 0; idx < size; idx++) {
554 outb(xilinx_firm[16 + idx], info->program_regbase);
557 /* Check if BUSY flag is low */
558 if (inl(info->plx_regbase + PLX_ICR) & 0x20) {
560 "comedi%d: me4000: xilinx_download(): "
561 "Xilinx is still busy (idx = %d)\n",
568 /* If done flag is high download was successful */
569 if (inl(info->plx_regbase + PLX_ICR) & 0x4) {
572 "comedi%d: me4000: xilinx_download(): "
573 "DONE flag is not set\n", dev->minor);
575 "comedi%d: me4000: xilinx_download(): "
576 "Download not successful\n", dev->minor);
580 /* Set /CS and /WRITE */
581 value = inl(info->plx_regbase + PLX_ICR);
583 outl(value, info->plx_regbase + PLX_ICR);
588 static int reset_board(struct comedi_device *dev)
592 /* Make a hardware reset */
593 icr = inl(info->plx_regbase + PLX_ICR);
595 outl(icr, info->plx_regbase + PLX_ICR);
597 outl(icr, info->plx_regbase + PLX_ICR);
599 /* 0x8000 to the DACs means an output voltage of 0V */
600 outl(0x8000, dev->iobase + ME4000_AO_00_SINGLE_REG);
601 outl(0x8000, dev->iobase + ME4000_AO_01_SINGLE_REG);
602 outl(0x8000, dev->iobase + ME4000_AO_02_SINGLE_REG);
603 outl(0x8000, dev->iobase + ME4000_AO_03_SINGLE_REG);
605 /* Set both stop bits in the analog input control register */
606 outl(ME4000_AI_CTRL_BIT_IMMEDIATE_STOP | ME4000_AI_CTRL_BIT_STOP,
607 dev->iobase + ME4000_AI_CTRL_REG);
609 /* Set both stop bits in the analog output control register */
610 outl(ME4000_AO_CTRL_BIT_IMMEDIATE_STOP | ME4000_AO_CTRL_BIT_STOP,
611 dev->iobase + ME4000_AO_00_CTRL_REG);
612 outl(ME4000_AO_CTRL_BIT_IMMEDIATE_STOP | ME4000_AO_CTRL_BIT_STOP,
613 dev->iobase + ME4000_AO_01_CTRL_REG);
614 outl(ME4000_AO_CTRL_BIT_IMMEDIATE_STOP | ME4000_AO_CTRL_BIT_STOP,
615 dev->iobase + ME4000_AO_02_CTRL_REG);
616 outl(ME4000_AO_CTRL_BIT_IMMEDIATE_STOP | ME4000_AO_CTRL_BIT_STOP,
617 dev->iobase + ME4000_AO_03_CTRL_REG);
619 /* Enable interrupts on the PLX */
620 outl(0x43, info->plx_regbase + PLX_INTCSR);
622 /* Set the adustment register for AO demux */
623 outl(ME4000_AO_DEMUX_ADJUST_VALUE,
624 dev->iobase + ME4000_AO_DEMUX_ADJUST_REG);
627 * Set digital I/O direction for port 0
628 * to output on isolated versions
630 if (!(inl(dev->iobase + ME4000_DIO_DIR_REG) & 0x1))
631 outl(0x1, dev->iobase + ME4000_DIO_CTRL_REG);
636 /*=============================================================================
638 ===========================================================================*/
640 static int me4000_ai_insn_read(struct comedi_device *dev,
641 struct comedi_subdevice *subdevice,
642 struct comedi_insn *insn, unsigned int *data)
644 const struct me4000_board *thisboard = comedi_board(dev);
645 int chan = CR_CHAN(insn->chanspec);
646 int rang = CR_RANGE(insn->chanspec);
647 int aref = CR_AREF(insn->chanspec);
649 unsigned long entry = 0;
655 } else if (insn->n > 1) {
657 "comedi%d: me4000: me4000_ai_insn_read(): "
658 "Invalid instruction length %d\n", dev->minor, insn->n);
664 entry |= ME4000_AI_LIST_RANGE_UNIPOLAR_2_5;
667 entry |= ME4000_AI_LIST_RANGE_UNIPOLAR_10;
670 entry |= ME4000_AI_LIST_RANGE_BIPOLAR_2_5;
673 entry |= ME4000_AI_LIST_RANGE_BIPOLAR_10;
677 "comedi%d: me4000: me4000_ai_insn_read(): "
678 "Invalid range specified\n", dev->minor);
685 if (chan >= thisboard->ai_nchan) {
687 "comedi%d: me4000: me4000_ai_insn_read(): "
688 "Analog input is not available\n", dev->minor);
691 entry |= ME4000_AI_LIST_INPUT_SINGLE_ENDED | chan;
695 if (rang == 0 || rang == 1) {
697 "comedi%d: me4000: me4000_ai_insn_read(): "
698 "Range must be bipolar when aref = diff\n",
703 if (chan >= thisboard->ai_diff_nchan) {
705 "comedi%d: me4000: me4000_ai_insn_read(): "
706 "Analog input is not available\n", dev->minor);
709 entry |= ME4000_AI_LIST_INPUT_DIFFERENTIAL | chan;
713 "comedi%d: me4000: me4000_ai_insn_read(): "
714 "Invalid aref specified\n", dev->minor);
718 entry |= ME4000_AI_LIST_LAST_ENTRY;
720 /* Clear channel list, data fifo and both stop bits */
721 tmp = inl(info->ai_context.ctrl_reg);
722 tmp &= ~(ME4000_AI_CTRL_BIT_CHANNEL_FIFO |
723 ME4000_AI_CTRL_BIT_DATA_FIFO |
724 ME4000_AI_CTRL_BIT_STOP | ME4000_AI_CTRL_BIT_IMMEDIATE_STOP);
725 outl(tmp, info->ai_context.ctrl_reg);
727 /* Set the acquisition mode to single */
728 tmp &= ~(ME4000_AI_CTRL_BIT_MODE_0 | ME4000_AI_CTRL_BIT_MODE_1 |
729 ME4000_AI_CTRL_BIT_MODE_2);
730 outl(tmp, info->ai_context.ctrl_reg);
732 /* Enable channel list and data fifo */
733 tmp |= ME4000_AI_CTRL_BIT_CHANNEL_FIFO | ME4000_AI_CTRL_BIT_DATA_FIFO;
734 outl(tmp, info->ai_context.ctrl_reg);
736 /* Generate channel list entry */
737 outl(entry, info->ai_context.channel_list_reg);
739 /* Set the timer to maximum sample rate */
740 outl(ME4000_AI_MIN_TICKS, info->ai_context.chan_timer_reg);
741 outl(ME4000_AI_MIN_TICKS, info->ai_context.chan_pre_timer_reg);
743 /* Start conversion by dummy read */
744 inl(info->ai_context.start_reg);
746 /* Wait until ready */
748 if (!(inl(info->ai_context.status_reg) &
749 ME4000_AI_STATUS_BIT_EF_DATA)) {
751 "comedi%d: me4000: me4000_ai_insn_read(): "
752 "Value not available after wait\n", dev->minor);
756 /* Read value from data fifo */
757 lval = inl(info->ai_context.data_reg) & 0xFFFF;
758 data[0] = lval ^ 0x8000;
763 static int me4000_ai_cancel(struct comedi_device *dev,
764 struct comedi_subdevice *s)
768 /* Stop any running conversion */
769 tmp = inl(info->ai_context.ctrl_reg);
770 tmp &= ~(ME4000_AI_CTRL_BIT_STOP | ME4000_AI_CTRL_BIT_IMMEDIATE_STOP);
771 outl(tmp, info->ai_context.ctrl_reg);
773 /* Clear the control register */
774 outl(0x0, info->ai_context.ctrl_reg);
779 static int ai_check_chanlist(struct comedi_device *dev,
780 struct comedi_subdevice *s, struct comedi_cmd *cmd)
782 const struct me4000_board *thisboard = comedi_board(dev);
786 /* Check whether a channel list is available */
787 if (!cmd->chanlist_len) {
789 "comedi%d: me4000: ai_check_chanlist(): "
790 "No channel list available\n", dev->minor);
794 /* Check the channel list size */
795 if (cmd->chanlist_len > ME4000_AI_CHANNEL_LIST_COUNT) {
797 "comedi%d: me4000: ai_check_chanlist(): "
798 "Channel list is to large\n", dev->minor);
802 /* Check the pointer */
803 if (!cmd->chanlist) {
805 "comedi%d: me4000: ai_check_chanlist(): "
806 "NULL pointer to channel list\n", dev->minor);
810 /* Check whether aref is equal for all entries */
811 aref = CR_AREF(cmd->chanlist[0]);
812 for (i = 0; i < cmd->chanlist_len; i++) {
813 if (CR_AREF(cmd->chanlist[i]) != aref) {
815 "comedi%d: me4000: ai_check_chanlist(): "
816 "Mode is not equal for all entries\n",
822 /* Check whether channels are available for this ending */
823 if (aref == SDF_DIFF) {
824 for (i = 0; i < cmd->chanlist_len; i++) {
825 if (CR_CHAN(cmd->chanlist[i]) >=
826 thisboard->ai_diff_nchan) {
828 "comedi%d: me4000: ai_check_chanlist():"
829 " Channel number to high\n", dev->minor);
834 for (i = 0; i < cmd->chanlist_len; i++) {
835 if (CR_CHAN(cmd->chanlist[i]) >= thisboard->ai_nchan) {
837 "comedi%d: me4000: ai_check_chanlist(): "
838 "Channel number to high\n", dev->minor);
844 /* Check if bipolar is set for all entries when in differential mode */
845 if (aref == SDF_DIFF) {
846 for (i = 0; i < cmd->chanlist_len; i++) {
847 if (CR_RANGE(cmd->chanlist[i]) != 1 &&
848 CR_RANGE(cmd->chanlist[i]) != 2) {
850 "comedi%d: me4000: ai_check_chanlist(): "
851 "Bipolar is not selected in "
852 "differential mode\n",
862 static int ai_round_cmd_args(struct comedi_device *dev,
863 struct comedi_subdevice *s,
864 struct comedi_cmd *cmd,
865 unsigned int *init_ticks,
866 unsigned int *scan_ticks, unsigned int *chan_ticks)
875 if (cmd->start_arg) {
876 *init_ticks = (cmd->start_arg * 33) / 1000;
877 rest = (cmd->start_arg * 33) % 1000;
879 if ((cmd->flags & TRIG_ROUND_MASK) == TRIG_ROUND_NEAREST) {
882 } else if ((cmd->flags & TRIG_ROUND_MASK) == TRIG_ROUND_UP) {
888 if (cmd->scan_begin_arg) {
889 *scan_ticks = (cmd->scan_begin_arg * 33) / 1000;
890 rest = (cmd->scan_begin_arg * 33) % 1000;
892 if ((cmd->flags & TRIG_ROUND_MASK) == TRIG_ROUND_NEAREST) {
895 } else if ((cmd->flags & TRIG_ROUND_MASK) == TRIG_ROUND_UP) {
901 if (cmd->convert_arg) {
902 *chan_ticks = (cmd->convert_arg * 33) / 1000;
903 rest = (cmd->convert_arg * 33) % 1000;
905 if ((cmd->flags & TRIG_ROUND_MASK) == TRIG_ROUND_NEAREST) {
908 } else if ((cmd->flags & TRIG_ROUND_MASK) == TRIG_ROUND_UP) {
917 static void ai_write_timer(struct comedi_device *dev,
918 unsigned int init_ticks,
919 unsigned int scan_ticks, unsigned int chan_ticks)
921 outl(init_ticks - 1, info->ai_context.scan_pre_timer_low_reg);
922 outl(0x0, info->ai_context.scan_pre_timer_high_reg);
925 outl(scan_ticks - 1, info->ai_context.scan_timer_low_reg);
926 outl(0x0, info->ai_context.scan_timer_high_reg);
929 outl(chan_ticks - 1, info->ai_context.chan_pre_timer_reg);
930 outl(chan_ticks - 1, info->ai_context.chan_timer_reg);
933 static int ai_prepare(struct comedi_device *dev,
934 struct comedi_subdevice *s,
935 struct comedi_cmd *cmd,
936 unsigned int init_ticks,
937 unsigned int scan_ticks, unsigned int chan_ticks)
940 unsigned long tmp = 0;
942 /* Write timer arguments */
943 ai_write_timer(dev, init_ticks, scan_ticks, chan_ticks);
945 /* Reset control register */
946 outl(tmp, info->ai_context.ctrl_reg);
949 if ((cmd->start_src == TRIG_EXT &&
950 cmd->scan_begin_src == TRIG_TIMER &&
951 cmd->convert_src == TRIG_TIMER) ||
952 (cmd->start_src == TRIG_EXT &&
953 cmd->scan_begin_src == TRIG_FOLLOW &&
954 cmd->convert_src == TRIG_TIMER)) {
955 tmp = ME4000_AI_CTRL_BIT_MODE_1 |
956 ME4000_AI_CTRL_BIT_CHANNEL_FIFO |
957 ME4000_AI_CTRL_BIT_DATA_FIFO;
958 } else if (cmd->start_src == TRIG_EXT &&
959 cmd->scan_begin_src == TRIG_EXT &&
960 cmd->convert_src == TRIG_TIMER) {
961 tmp = ME4000_AI_CTRL_BIT_MODE_2 |
962 ME4000_AI_CTRL_BIT_CHANNEL_FIFO |
963 ME4000_AI_CTRL_BIT_DATA_FIFO;
964 } else if (cmd->start_src == TRIG_EXT &&
965 cmd->scan_begin_src == TRIG_EXT &&
966 cmd->convert_src == TRIG_EXT) {
967 tmp = ME4000_AI_CTRL_BIT_MODE_0 |
968 ME4000_AI_CTRL_BIT_MODE_1 |
969 ME4000_AI_CTRL_BIT_CHANNEL_FIFO |
970 ME4000_AI_CTRL_BIT_DATA_FIFO;
972 tmp = ME4000_AI_CTRL_BIT_MODE_0 |
973 ME4000_AI_CTRL_BIT_CHANNEL_FIFO |
974 ME4000_AI_CTRL_BIT_DATA_FIFO;
978 if (cmd->stop_src == TRIG_COUNT) {
979 outl(cmd->chanlist_len * cmd->stop_arg,
980 info->ai_context.sample_counter_reg);
981 tmp |= ME4000_AI_CTRL_BIT_HF_IRQ | ME4000_AI_CTRL_BIT_SC_IRQ;
982 } else if (cmd->stop_src == TRIG_NONE &&
983 cmd->scan_end_src == TRIG_COUNT) {
984 outl(cmd->scan_end_arg,
985 info->ai_context.sample_counter_reg);
986 tmp |= ME4000_AI_CTRL_BIT_HF_IRQ | ME4000_AI_CTRL_BIT_SC_IRQ;
988 tmp |= ME4000_AI_CTRL_BIT_HF_IRQ;
991 /* Write the setup to the control register */
992 outl(tmp, info->ai_context.ctrl_reg);
994 /* Write the channel list */
995 ai_write_chanlist(dev, s, cmd);
1000 static int ai_write_chanlist(struct comedi_device *dev,
1001 struct comedi_subdevice *s, struct comedi_cmd *cmd)
1009 for (i = 0; i < cmd->chanlist_len; i++) {
1010 chan = CR_CHAN(cmd->chanlist[i]);
1011 rang = CR_RANGE(cmd->chanlist[i]);
1012 aref = CR_AREF(cmd->chanlist[i]);
1017 entry |= ME4000_AI_LIST_RANGE_UNIPOLAR_2_5;
1019 entry |= ME4000_AI_LIST_RANGE_UNIPOLAR_10;
1021 entry |= ME4000_AI_LIST_RANGE_BIPOLAR_2_5;
1023 entry |= ME4000_AI_LIST_RANGE_BIPOLAR_10;
1025 if (aref == SDF_DIFF)
1026 entry |= ME4000_AI_LIST_INPUT_DIFFERENTIAL;
1028 entry |= ME4000_AI_LIST_INPUT_SINGLE_ENDED;
1030 outl(entry, info->ai_context.channel_list_reg);
1036 static int me4000_ai_do_cmd(struct comedi_device *dev,
1037 struct comedi_subdevice *s)
1040 unsigned int init_ticks = 0;
1041 unsigned int scan_ticks = 0;
1042 unsigned int chan_ticks = 0;
1043 struct comedi_cmd *cmd = &s->async->cmd;
1045 /* Reset the analog input */
1046 err = me4000_ai_cancel(dev, s);
1050 /* Round the timer arguments */
1051 err = ai_round_cmd_args(dev,
1052 s, cmd, &init_ticks, &scan_ticks, &chan_ticks);
1056 /* Prepare the AI for acquisition */
1057 err = ai_prepare(dev, s, cmd, init_ticks, scan_ticks, chan_ticks);
1061 /* Start acquistion by dummy read */
1062 inl(info->ai_context.start_reg);
1068 * me4000_ai_do_cmd_test():
1070 * The demo cmd.c in ./comedilib/demo specifies 6 return values:
1074 * - invalid argument
1075 * - argument conflict
1076 * - invalid chanlist
1077 * So I tried to adopt this scheme.
1079 static int me4000_ai_do_cmd_test(struct comedi_device *dev,
1080 struct comedi_subdevice *s,
1081 struct comedi_cmd *cmd)
1084 unsigned int init_ticks;
1085 unsigned int chan_ticks;
1086 unsigned int scan_ticks;
1089 /* Only rounding flags are implemented */
1090 cmd->flags &= TRIG_ROUND_NEAREST | TRIG_ROUND_UP | TRIG_ROUND_DOWN;
1092 /* Round the timer arguments */
1093 ai_round_cmd_args(dev, s, cmd, &init_ticks, &scan_ticks, &chan_ticks);
1096 * Stage 1. Check if the trigger sources are generally valid.
1098 switch (cmd->start_src) {
1103 cmd->start_src &= TRIG_NOW | TRIG_EXT;
1108 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1109 "Invalid start source\n", dev->minor);
1110 cmd->start_src = TRIG_NOW;
1113 switch (cmd->scan_begin_src) {
1119 cmd->scan_begin_src &= TRIG_FOLLOW | TRIG_TIMER | TRIG_EXT;
1124 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1125 "Invalid scan begin source\n", dev->minor);
1126 cmd->scan_begin_src = TRIG_FOLLOW;
1129 switch (cmd->convert_src) {
1134 cmd->convert_src &= TRIG_TIMER | TRIG_EXT;
1139 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1140 "Invalid convert source\n", dev->minor);
1141 cmd->convert_src = TRIG_TIMER;
1144 switch (cmd->scan_end_src) {
1149 cmd->scan_end_src &= TRIG_NONE | TRIG_COUNT;
1154 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1155 "Invalid scan end source\n", dev->minor);
1156 cmd->scan_end_src = TRIG_NONE;
1159 switch (cmd->stop_src) {
1164 cmd->stop_src &= TRIG_NONE | TRIG_COUNT;
1169 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1170 "Invalid stop source\n", dev->minor);
1171 cmd->stop_src = TRIG_NONE;
1178 * Stage 2. Check for trigger source conflicts.
1180 if (cmd->start_src == TRIG_NOW &&
1181 cmd->scan_begin_src == TRIG_TIMER &&
1182 cmd->convert_src == TRIG_TIMER) {
1183 } else if (cmd->start_src == TRIG_NOW &&
1184 cmd->scan_begin_src == TRIG_FOLLOW &&
1185 cmd->convert_src == TRIG_TIMER) {
1186 } else if (cmd->start_src == TRIG_EXT &&
1187 cmd->scan_begin_src == TRIG_TIMER &&
1188 cmd->convert_src == TRIG_TIMER) {
1189 } else if (cmd->start_src == TRIG_EXT &&
1190 cmd->scan_begin_src == TRIG_FOLLOW &&
1191 cmd->convert_src == TRIG_TIMER) {
1192 } else if (cmd->start_src == TRIG_EXT &&
1193 cmd->scan_begin_src == TRIG_EXT &&
1194 cmd->convert_src == TRIG_TIMER) {
1195 } else if (cmd->start_src == TRIG_EXT &&
1196 cmd->scan_begin_src == TRIG_EXT &&
1197 cmd->convert_src == TRIG_EXT) {
1200 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1201 "Invalid start trigger combination\n", dev->minor);
1202 cmd->start_src = TRIG_NOW;
1203 cmd->scan_begin_src = TRIG_FOLLOW;
1204 cmd->convert_src = TRIG_TIMER;
1208 if (cmd->stop_src == TRIG_NONE && cmd->scan_end_src == TRIG_NONE) {
1209 } else if (cmd->stop_src == TRIG_COUNT &&
1210 cmd->scan_end_src == TRIG_NONE) {
1211 } else if (cmd->stop_src == TRIG_NONE &&
1212 cmd->scan_end_src == TRIG_COUNT) {
1213 } else if (cmd->stop_src == TRIG_COUNT &&
1214 cmd->scan_end_src == TRIG_COUNT) {
1217 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1218 "Invalid stop trigger combination\n", dev->minor);
1219 cmd->stop_src = TRIG_NONE;
1220 cmd->scan_end_src = TRIG_NONE;
1227 * Stage 3. Check if arguments are generally valid.
1229 if (cmd->chanlist_len < 1) {
1231 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1232 "No channel list\n", dev->minor);
1233 cmd->chanlist_len = 1;
1236 if (init_ticks < 66) {
1238 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1239 "Start arg to low\n", dev->minor);
1240 cmd->start_arg = 2000;
1243 if (scan_ticks && scan_ticks < 67) {
1245 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1246 "Scan begin arg to low\n", dev->minor);
1247 cmd->scan_begin_arg = 2031;
1250 if (chan_ticks < 66) {
1252 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1253 "Convert arg to low\n", dev->minor);
1254 cmd->convert_arg = 2000;
1262 * Stage 4. Check for argument conflicts.
1264 if (cmd->start_src == TRIG_NOW &&
1265 cmd->scan_begin_src == TRIG_TIMER &&
1266 cmd->convert_src == TRIG_TIMER) {
1268 /* Check timer arguments */
1269 if (init_ticks < ME4000_AI_MIN_TICKS) {
1271 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1272 "Invalid start arg\n", dev->minor);
1273 cmd->start_arg = 2000; /* 66 ticks at least */
1276 if (chan_ticks < ME4000_AI_MIN_TICKS) {
1278 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1279 "Invalid convert arg\n", dev->minor);
1280 cmd->convert_arg = 2000; /* 66 ticks at least */
1283 if (scan_ticks <= cmd->chanlist_len * chan_ticks) {
1285 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1286 "Invalid scan end arg\n", dev->minor);
1288 /* At least one tick more */
1289 cmd->scan_end_arg = 2000 * cmd->chanlist_len + 31;
1292 } else if (cmd->start_src == TRIG_NOW &&
1293 cmd->scan_begin_src == TRIG_FOLLOW &&
1294 cmd->convert_src == TRIG_TIMER) {
1296 /* Check timer arguments */
1297 if (init_ticks < ME4000_AI_MIN_TICKS) {
1299 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1300 "Invalid start arg\n", dev->minor);
1301 cmd->start_arg = 2000; /* 66 ticks at least */
1304 if (chan_ticks < ME4000_AI_MIN_TICKS) {
1306 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1307 "Invalid convert arg\n", dev->minor);
1308 cmd->convert_arg = 2000; /* 66 ticks at least */
1311 } else if (cmd->start_src == TRIG_EXT &&
1312 cmd->scan_begin_src == TRIG_TIMER &&
1313 cmd->convert_src == TRIG_TIMER) {
1315 /* Check timer arguments */
1316 if (init_ticks < ME4000_AI_MIN_TICKS) {
1318 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1319 "Invalid start arg\n", dev->minor);
1320 cmd->start_arg = 2000; /* 66 ticks at least */
1323 if (chan_ticks < ME4000_AI_MIN_TICKS) {
1325 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1326 "Invalid convert arg\n", dev->minor);
1327 cmd->convert_arg = 2000; /* 66 ticks at least */
1330 if (scan_ticks <= cmd->chanlist_len * chan_ticks) {
1332 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1333 "Invalid scan end arg\n", dev->minor);
1335 /* At least one tick more */
1336 cmd->scan_end_arg = 2000 * cmd->chanlist_len + 31;
1339 } else if (cmd->start_src == TRIG_EXT &&
1340 cmd->scan_begin_src == TRIG_FOLLOW &&
1341 cmd->convert_src == TRIG_TIMER) {
1343 /* Check timer arguments */
1344 if (init_ticks < ME4000_AI_MIN_TICKS) {
1346 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1347 "Invalid start arg\n", dev->minor);
1348 cmd->start_arg = 2000; /* 66 ticks at least */
1351 if (chan_ticks < ME4000_AI_MIN_TICKS) {
1353 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1354 "Invalid convert arg\n", dev->minor);
1355 cmd->convert_arg = 2000; /* 66 ticks at least */
1358 } else if (cmd->start_src == TRIG_EXT &&
1359 cmd->scan_begin_src == TRIG_EXT &&
1360 cmd->convert_src == TRIG_TIMER) {
1362 /* Check timer arguments */
1363 if (init_ticks < ME4000_AI_MIN_TICKS) {
1365 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1366 "Invalid start arg\n", dev->minor);
1367 cmd->start_arg = 2000; /* 66 ticks at least */
1370 if (chan_ticks < ME4000_AI_MIN_TICKS) {
1372 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1373 "Invalid convert arg\n", dev->minor);
1374 cmd->convert_arg = 2000; /* 66 ticks at least */
1377 } else if (cmd->start_src == TRIG_EXT &&
1378 cmd->scan_begin_src == TRIG_EXT &&
1379 cmd->convert_src == TRIG_EXT) {
1381 /* Check timer arguments */
1382 if (init_ticks < ME4000_AI_MIN_TICKS) {
1384 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1385 "Invalid start arg\n", dev->minor);
1386 cmd->start_arg = 2000; /* 66 ticks at least */
1390 if (cmd->stop_src == TRIG_COUNT) {
1391 if (cmd->stop_arg == 0) {
1393 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1394 "Invalid stop arg\n", dev->minor);
1399 if (cmd->scan_end_src == TRIG_COUNT) {
1400 if (cmd->scan_end_arg == 0) {
1402 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1403 "Invalid scan end arg\n", dev->minor);
1404 cmd->scan_end_arg = 1;
1413 * Stage 5. Check the channel list.
1415 if (ai_check_chanlist(dev, s, cmd))
1421 static irqreturn_t me4000_ai_isr(int irq, void *dev_id)
1424 struct comedi_device *dev = dev_id;
1425 struct comedi_subdevice *s = &dev->subdevices[0];
1426 struct me4000_ai_context *ai_context = &info->ai_context;
1434 /* Reset all events */
1435 s->async->events = 0;
1437 /* Check if irq number is right */
1438 if (irq != ai_context->irq) {
1440 "comedi%d: me4000: me4000_ai_isr(): "
1441 "Incorrect interrupt num: %d\n", dev->minor, irq);
1445 if (inl(ai_context->irq_status_reg) &
1446 ME4000_IRQ_STATUS_BIT_AI_HF) {
1447 /* Read status register to find out what happened */
1448 tmp = inl(ai_context->ctrl_reg);
1450 if (!(tmp & ME4000_AI_STATUS_BIT_FF_DATA) &&
1451 !(tmp & ME4000_AI_STATUS_BIT_HF_DATA) &&
1452 (tmp & ME4000_AI_STATUS_BIT_EF_DATA)) {
1453 c = ME4000_AI_FIFO_COUNT;
1456 * FIFO overflow, so stop conversion
1457 * and disable all interrupts
1459 tmp |= ME4000_AI_CTRL_BIT_IMMEDIATE_STOP;
1460 tmp &= ~(ME4000_AI_CTRL_BIT_HF_IRQ |
1461 ME4000_AI_CTRL_BIT_SC_IRQ);
1462 outl(tmp, ai_context->ctrl_reg);
1464 s->async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
1467 "comedi%d: me4000: me4000_ai_isr(): "
1468 "FIFO overflow\n", dev->minor);
1469 } else if ((tmp & ME4000_AI_STATUS_BIT_FF_DATA)
1470 && !(tmp & ME4000_AI_STATUS_BIT_HF_DATA)
1471 && (tmp & ME4000_AI_STATUS_BIT_EF_DATA)) {
1472 s->async->events |= COMEDI_CB_BLOCK;
1474 c = ME4000_AI_FIFO_COUNT / 2;
1477 "comedi%d: me4000: me4000_ai_isr(): "
1478 "Can't determine state of fifo\n", dev->minor);
1482 * Undefined state, so stop conversion
1483 * and disable all interrupts
1485 tmp |= ME4000_AI_CTRL_BIT_IMMEDIATE_STOP;
1486 tmp &= ~(ME4000_AI_CTRL_BIT_HF_IRQ |
1487 ME4000_AI_CTRL_BIT_SC_IRQ);
1488 outl(tmp, ai_context->ctrl_reg);
1490 s->async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
1493 "comedi%d: me4000: me4000_ai_isr(): "
1494 "Undefined FIFO state\n", dev->minor);
1497 for (i = 0; i < c; i++) {
1498 /* Read value from data fifo */
1499 lval = inl(ai_context->data_reg) & 0xFFFF;
1502 if (!comedi_buf_put(s->async, lval)) {
1504 * Buffer overflow, so stop conversion
1505 * and disable all interrupts
1507 tmp |= ME4000_AI_CTRL_BIT_IMMEDIATE_STOP;
1508 tmp &= ~(ME4000_AI_CTRL_BIT_HF_IRQ |
1509 ME4000_AI_CTRL_BIT_SC_IRQ);
1510 outl(tmp, ai_context->ctrl_reg);
1512 s->async->events |= COMEDI_CB_OVERFLOW;
1515 "comedi%d: me4000: me4000_ai_isr(): "
1516 "Buffer overflow\n", dev->minor);
1522 /* Work is done, so reset the interrupt */
1523 tmp |= ME4000_AI_CTRL_BIT_HF_IRQ_RESET;
1524 outl(tmp, ai_context->ctrl_reg);
1525 tmp &= ~ME4000_AI_CTRL_BIT_HF_IRQ_RESET;
1526 outl(tmp, ai_context->ctrl_reg);
1529 if (inl(ai_context->irq_status_reg) & ME4000_IRQ_STATUS_BIT_SC) {
1530 s->async->events |= COMEDI_CB_BLOCK | COMEDI_CB_EOA;
1533 * Acquisition is complete, so stop
1534 * conversion and disable all interrupts
1536 tmp = inl(ai_context->ctrl_reg);
1537 tmp |= ME4000_AI_CTRL_BIT_IMMEDIATE_STOP;
1538 tmp &= ~(ME4000_AI_CTRL_BIT_HF_IRQ | ME4000_AI_CTRL_BIT_SC_IRQ);
1539 outl(tmp, ai_context->ctrl_reg);
1541 /* Poll data until fifo empty */
1542 while (inl(ai_context->ctrl_reg) & ME4000_AI_STATUS_BIT_EF_DATA) {
1543 /* Read value from data fifo */
1544 lval = inl(ai_context->data_reg) & 0xFFFF;
1547 if (!comedi_buf_put(s->async, lval)) {
1549 "comedi%d: me4000: me4000_ai_isr(): "
1550 "Buffer overflow\n", dev->minor);
1551 s->async->events |= COMEDI_CB_OVERFLOW;
1556 /* Work is done, so reset the interrupt */
1557 tmp |= ME4000_AI_CTRL_BIT_SC_IRQ_RESET;
1558 outl(tmp, ai_context->ctrl_reg);
1559 tmp &= ~ME4000_AI_CTRL_BIT_SC_IRQ_RESET;
1560 outl(tmp, ai_context->ctrl_reg);
1563 if (s->async->events)
1564 comedi_event(dev, s);
1569 /*=============================================================================
1570 Analog output section
1571 ===========================================================================*/
1573 static int me4000_ao_insn_write(struct comedi_device *dev,
1574 struct comedi_subdevice *s,
1575 struct comedi_insn *insn, unsigned int *data)
1577 const struct me4000_board *thisboard = comedi_board(dev);
1578 int chan = CR_CHAN(insn->chanspec);
1579 int rang = CR_RANGE(insn->chanspec);
1580 int aref = CR_AREF(insn->chanspec);
1585 } else if (insn->n > 1) {
1587 "comedi%d: me4000: me4000_ao_insn_write(): "
1588 "Invalid instruction length %d\n", dev->minor, insn->n);
1592 if (chan >= thisboard->ao_nchan) {
1594 "comedi%d: me4000: me4000_ao_insn_write(): "
1595 "Invalid channel %d\n", dev->minor, insn->n);
1601 "comedi%d: me4000: me4000_ao_insn_write(): "
1602 "Invalid range %d\n", dev->minor, insn->n);
1606 if (aref != AREF_GROUND && aref != AREF_COMMON) {
1608 "comedi%d: me4000: me4000_ao_insn_write(): "
1609 "Invalid aref %d\n", dev->minor, insn->n);
1613 /* Stop any running conversion */
1614 tmp = inl(info->ao_context[chan].ctrl_reg);
1615 tmp |= ME4000_AO_CTRL_BIT_IMMEDIATE_STOP;
1616 outl(tmp, info->ao_context[chan].ctrl_reg);
1618 /* Clear control register and set to single mode */
1619 outl(0x0, info->ao_context[chan].ctrl_reg);
1621 /* Write data value */
1622 outl(data[0], info->ao_context[chan].single_reg);
1624 /* Store in the mirror */
1625 info->ao_context[chan].mirror = data[0];
1630 static int me4000_ao_insn_read(struct comedi_device *dev,
1631 struct comedi_subdevice *s,
1632 struct comedi_insn *insn, unsigned int *data)
1634 int chan = CR_CHAN(insn->chanspec);
1638 } else if (insn->n > 1) {
1640 ("comedi%d: me4000: me4000_ao_insn_read(): "
1641 "Invalid instruction length\n", dev->minor);
1645 data[0] = info->ao_context[chan].mirror;
1650 /*=============================================================================
1652 ===========================================================================*/
1654 static int me4000_dio_insn_bits(struct comedi_device *dev,
1655 struct comedi_subdevice *s,
1656 struct comedi_insn *insn, unsigned int *data)
1659 * The insn data consists of a mask in data[0] and the new data
1660 * in data[1]. The mask defines which bits we are concerning about.
1661 * The new data must be anded with the mask.
1662 * Each channel corresponds to a bit.
1665 /* Check if requested ports are configured for output */
1666 if ((s->io_bits & data[0]) != data[0])
1669 s->state &= ~data[0];
1670 s->state |= data[0] & data[1];
1672 /* Write out the new digital output lines */
1673 outl((s->state >> 0) & 0xFF,
1674 info->dio_context.port_0_reg);
1675 outl((s->state >> 8) & 0xFF,
1676 info->dio_context.port_1_reg);
1677 outl((s->state >> 16) & 0xFF,
1678 info->dio_context.port_2_reg);
1679 outl((s->state >> 24) & 0xFF,
1680 info->dio_context.port_3_reg);
1683 /* On return, data[1] contains the value of
1684 the digital input and output lines. */
1685 data[1] = ((inl(info->dio_context.port_0_reg) & 0xFF) << 0) |
1686 ((inl(info->dio_context.port_1_reg) & 0xFF) << 8) |
1687 ((inl(info->dio_context.port_2_reg) & 0xFF) << 16) |
1688 ((inl(info->dio_context.port_3_reg) & 0xFF) << 24);
1693 static int me4000_dio_insn_config(struct comedi_device *dev,
1694 struct comedi_subdevice *s,
1695 struct comedi_insn *insn, unsigned int *data)
1698 int chan = CR_CHAN(insn->chanspec);
1703 case INSN_CONFIG_DIO_QUERY:
1705 (s->io_bits & (1 << chan)) ? COMEDI_OUTPUT : COMEDI_INPUT;
1707 case INSN_CONFIG_DIO_INPUT:
1708 case INSN_CONFIG_DIO_OUTPUT:
1713 * The input or output configuration of each digital line is
1714 * configured by a special insn_config instruction. chanspec
1715 * contains the channel to be changed, and data[0] contains the
1716 * value INSN_CONFIG_DIO_INPUT or INSN_CONFIG_DIO_OUTPUT.
1717 * On the ME-4000 it is only possible to switch port wise (8 bit)
1720 tmp = inl(info->dio_context.ctrl_reg);
1722 if (data[0] == INSN_CONFIG_DIO_OUTPUT) {
1725 tmp &= ~(ME4000_DIO_CTRL_BIT_MODE_0 |
1726 ME4000_DIO_CTRL_BIT_MODE_1);
1727 tmp |= ME4000_DIO_CTRL_BIT_MODE_0;
1728 } else if (chan < 16) {
1730 * Chech for optoisolated ME-4000 version.
1731 * If one the first port is a fixed output
1732 * port and the second is a fixed input port.
1734 if (!inl(info->dio_context.dir_reg))
1737 s->io_bits |= 0xFF00;
1738 tmp &= ~(ME4000_DIO_CTRL_BIT_MODE_2 |
1739 ME4000_DIO_CTRL_BIT_MODE_3);
1740 tmp |= ME4000_DIO_CTRL_BIT_MODE_2;
1741 } else if (chan < 24) {
1742 s->io_bits |= 0xFF0000;
1743 tmp &= ~(ME4000_DIO_CTRL_BIT_MODE_4 |
1744 ME4000_DIO_CTRL_BIT_MODE_5);
1745 tmp |= ME4000_DIO_CTRL_BIT_MODE_4;
1746 } else if (chan < 32) {
1747 s->io_bits |= 0xFF000000;
1748 tmp &= ~(ME4000_DIO_CTRL_BIT_MODE_6 |
1749 ME4000_DIO_CTRL_BIT_MODE_7);
1750 tmp |= ME4000_DIO_CTRL_BIT_MODE_6;
1757 * Chech for optoisolated ME-4000 version.
1758 * If one the first port is a fixed output
1759 * port and the second is a fixed input port.
1761 if (!inl(info->dio_context.dir_reg))
1764 s->io_bits &= ~0xFF;
1765 tmp &= ~(ME4000_DIO_CTRL_BIT_MODE_0 |
1766 ME4000_DIO_CTRL_BIT_MODE_1);
1767 } else if (chan < 16) {
1768 s->io_bits &= ~0xFF00;
1769 tmp &= ~(ME4000_DIO_CTRL_BIT_MODE_2 |
1770 ME4000_DIO_CTRL_BIT_MODE_3);
1771 } else if (chan < 24) {
1772 s->io_bits &= ~0xFF0000;
1773 tmp &= ~(ME4000_DIO_CTRL_BIT_MODE_4 |
1774 ME4000_DIO_CTRL_BIT_MODE_5);
1775 } else if (chan < 32) {
1776 s->io_bits &= ~0xFF000000;
1777 tmp &= ~(ME4000_DIO_CTRL_BIT_MODE_6 |
1778 ME4000_DIO_CTRL_BIT_MODE_7);
1784 outl(tmp, info->dio_context.ctrl_reg);
1789 /*=============================================================================
1791 ===========================================================================*/
1793 static int cnt_reset(struct comedi_device *dev, unsigned int channel)
1797 outb(0x30, info->timer_regbase + ME4000_CNT_CTRL_REG);
1798 outb(0x00, info->timer_regbase + ME4000_CNT_COUNTER_0_REG);
1799 outb(0x00, info->timer_regbase + ME4000_CNT_COUNTER_0_REG);
1802 outb(0x70, info->timer_regbase + ME4000_CNT_CTRL_REG);
1803 outb(0x00, info->timer_regbase + ME4000_CNT_COUNTER_1_REG);
1804 outb(0x00, info->timer_regbase + ME4000_CNT_COUNTER_1_REG);
1807 outb(0xB0, info->timer_regbase + ME4000_CNT_CTRL_REG);
1808 outb(0x00, info->timer_regbase + ME4000_CNT_COUNTER_2_REG);
1809 outb(0x00, info->timer_regbase + ME4000_CNT_COUNTER_2_REG);
1813 "comedi%d: me4000: cnt_reset(): Invalid channel\n",
1821 static int cnt_config(struct comedi_device *dev, unsigned int channel,
1828 tmp |= ME4000_CNT_COUNTER_0;
1831 tmp |= ME4000_CNT_COUNTER_1;
1834 tmp |= ME4000_CNT_COUNTER_2;
1838 "comedi%d: me4000: cnt_config(): Invalid channel\n",
1845 tmp |= ME4000_CNT_MODE_0;
1848 tmp |= ME4000_CNT_MODE_1;
1851 tmp |= ME4000_CNT_MODE_2;
1854 tmp |= ME4000_CNT_MODE_3;
1857 tmp |= ME4000_CNT_MODE_4;
1860 tmp |= ME4000_CNT_MODE_5;
1864 "comedi%d: me4000: cnt_config(): Invalid counter mode\n",
1869 /* Write the control word */
1871 outb(tmp, info->timer_regbase + ME4000_CNT_CTRL_REG);
1876 static int me4000_cnt_insn_config(struct comedi_device *dev,
1877 struct comedi_subdevice *s,
1878 struct comedi_insn *insn, unsigned int *data)
1887 "comedi%d: me4000: me4000_cnt_insn_config(): "
1888 "Invalid instruction length%d\n",
1889 dev->minor, insn->n);
1893 err = cnt_reset(dev, insn->chanspec);
1897 case GPCT_SET_OPERATION:
1900 "comedi%d: me4000: me4000_cnt_insn_config(): "
1901 "Invalid instruction length%d\n",
1902 dev->minor, insn->n);
1906 err = cnt_config(dev, insn->chanspec, data[1]);
1912 "comedi%d: me4000: me4000_cnt_insn_config(): "
1913 "Invalid instruction\n", dev->minor);
1920 static int me4000_cnt_insn_read(struct comedi_device *dev,
1921 struct comedi_subdevice *s,
1922 struct comedi_insn *insn, unsigned int *data)
1932 "comedi%d: me4000: me4000_cnt_insn_read(): "
1933 "Invalid instruction length %d\n",
1934 dev->minor, insn->n);
1938 switch (insn->chanspec) {
1940 tmp = inb(info->timer_regbase + ME4000_CNT_COUNTER_0_REG);
1942 tmp = inb(info->timer_regbase + ME4000_CNT_COUNTER_0_REG);
1943 data[0] |= tmp << 8;
1946 tmp = inb(info->timer_regbase + ME4000_CNT_COUNTER_1_REG);
1948 tmp = inb(info->timer_regbase + ME4000_CNT_COUNTER_1_REG);
1949 data[0] |= tmp << 8;
1952 tmp = inb(info->timer_regbase + ME4000_CNT_COUNTER_2_REG);
1954 tmp = inb(info->timer_regbase + ME4000_CNT_COUNTER_2_REG);
1955 data[0] |= tmp << 8;
1959 "comedi%d: me4000: me4000_cnt_insn_read(): "
1960 "Invalid channel %d\n",
1961 dev->minor, insn->chanspec);
1968 static int me4000_cnt_insn_write(struct comedi_device *dev,
1969 struct comedi_subdevice *s,
1970 struct comedi_insn *insn, unsigned int *data)
1977 } else if (insn->n > 1) {
1979 "comedi%d: me4000: me4000_cnt_insn_write(): "
1980 "Invalid instruction length %d\n",
1981 dev->minor, insn->n);
1985 switch (insn->chanspec) {
1987 tmp = data[0] & 0xFF;
1988 outb(tmp, info->timer_regbase + ME4000_CNT_COUNTER_0_REG);
1989 tmp = (data[0] >> 8) & 0xFF;
1990 outb(tmp, info->timer_regbase + ME4000_CNT_COUNTER_0_REG);
1993 tmp = data[0] & 0xFF;
1994 outb(tmp, info->timer_regbase + ME4000_CNT_COUNTER_1_REG);
1995 tmp = (data[0] >> 8) & 0xFF;
1996 outb(tmp, info->timer_regbase + ME4000_CNT_COUNTER_1_REG);
1999 tmp = data[0] & 0xFF;
2000 outb(tmp, info->timer_regbase + ME4000_CNT_COUNTER_2_REG);
2001 tmp = (data[0] >> 8) & 0xFF;
2002 outb(tmp, info->timer_regbase + ME4000_CNT_COUNTER_2_REG);
2006 "comedi%d: me4000: me4000_cnt_insn_write(): "
2007 "Invalid channel %d\n",
2008 dev->minor, insn->chanspec);
2015 static int me4000_attach(struct comedi_device *dev, struct comedi_devconfig *it)
2017 const struct me4000_board *thisboard;
2018 struct comedi_subdevice *s;
2021 result = me4000_probe(dev, it);
2024 thisboard = comedi_board(dev);
2026 result = comedi_alloc_subdevices(dev, 4);
2030 /*=========================================================================
2031 Analog input subdevice
2032 ========================================================================*/
2034 s = &dev->subdevices[0];
2036 if (thisboard->ai_nchan) {
2037 s->type = COMEDI_SUBD_AI;
2039 SDF_READABLE | SDF_COMMON | SDF_GROUND | SDF_DIFF;
2040 s->n_chan = thisboard->ai_nchan;
2041 s->maxdata = 0xFFFF; /* 16 bit ADC */
2042 s->len_chanlist = ME4000_AI_CHANNEL_LIST_COUNT;
2043 s->range_table = &me4000_ai_range;
2044 s->insn_read = me4000_ai_insn_read;
2046 if (info->irq > 0) {
2047 if (request_irq(info->irq, me4000_ai_isr,
2048 IRQF_SHARED, "ME-4000", dev)) {
2050 ("comedi%d: me4000: me4000_attach(): "
2051 "Unable to allocate irq\n", dev->minor);
2053 dev->read_subdev = s;
2054 s->subdev_flags |= SDF_CMD_READ;
2055 s->cancel = me4000_ai_cancel;
2056 s->do_cmdtest = me4000_ai_do_cmd_test;
2057 s->do_cmd = me4000_ai_do_cmd;
2061 "comedi%d: me4000: me4000_attach(): "
2062 "No interrupt available\n", dev->minor);
2065 s->type = COMEDI_SUBD_UNUSED;
2068 /*=========================================================================
2069 Analog output subdevice
2070 ========================================================================*/
2072 s = &dev->subdevices[1];
2074 if (thisboard->ao_nchan) {
2075 s->type = COMEDI_SUBD_AO;
2076 s->subdev_flags = SDF_WRITEABLE | SDF_COMMON | SDF_GROUND;
2077 s->n_chan = thisboard->ao_nchan;
2078 s->maxdata = 0xFFFF; /* 16 bit DAC */
2079 s->range_table = &me4000_ao_range;
2080 s->insn_write = me4000_ao_insn_write;
2081 s->insn_read = me4000_ao_insn_read;
2083 s->type = COMEDI_SUBD_UNUSED;
2086 /*=========================================================================
2087 Digital I/O subdevice
2088 ========================================================================*/
2090 s = &dev->subdevices[2];
2092 if (thisboard->dio_nchan) {
2093 s->type = COMEDI_SUBD_DIO;
2094 s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
2095 s->n_chan = thisboard->dio_nchan;
2097 s->range_table = &range_digital;
2098 s->insn_bits = me4000_dio_insn_bits;
2099 s->insn_config = me4000_dio_insn_config;
2101 s->type = COMEDI_SUBD_UNUSED;
2105 * Check for optoisolated ME-4000 version. If one the first
2106 * port is a fixed output port and the second is a fixed input port.
2108 if (!inl(info->dio_context.dir_reg)) {
2110 outl(ME4000_DIO_CTRL_BIT_MODE_0, info->dio_context.dir_reg);
2113 /*=========================================================================
2115 ========================================================================*/
2117 s = &dev->subdevices[3];
2119 if (thisboard->has_counter) {
2120 s->type = COMEDI_SUBD_COUNTER;
2121 s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
2123 s->maxdata = 0xFFFF; /* 16 bit counters */
2124 s->insn_read = me4000_cnt_insn_read;
2125 s->insn_write = me4000_cnt_insn_write;
2126 s->insn_config = me4000_cnt_insn_config;
2128 s->type = COMEDI_SUBD_UNUSED;
2134 static void me4000_detach(struct comedi_device *dev)
2137 if (info->pci_dev_p) {
2139 if (info->plx_regbase)
2140 comedi_pci_disable(info->pci_dev_p);
2141 pci_dev_put(info->pci_dev_p);
2146 static struct comedi_driver me4000_driver = {
2147 .driver_name = "me4000",
2148 .module = THIS_MODULE,
2149 .attach = me4000_attach,
2150 .detach = me4000_detach,
2153 static int __devinit me4000_pci_probe(struct pci_dev *dev,
2154 const struct pci_device_id *ent)
2156 return comedi_pci_auto_config(dev, &me4000_driver);
2159 static void __devexit me4000_pci_remove(struct pci_dev *dev)
2161 comedi_pci_auto_unconfig(dev);
2164 static DEFINE_PCI_DEVICE_TABLE(me4000_pci_table) = {
2165 {PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4650)},
2166 {PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4660)},
2167 {PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4660I)},
2168 {PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4660S)},
2169 {PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4660IS)},
2170 {PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4670)},
2171 {PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4670I)},
2172 {PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4670S)},
2173 {PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4670IS)},
2174 {PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4680)},
2175 {PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4680I)},
2176 {PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4680S)},
2177 {PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4680IS)},
2180 MODULE_DEVICE_TABLE(pci, me4000_pci_table);
2182 static struct pci_driver me4000_pci_driver = {
2184 .id_table = me4000_pci_table,
2185 .probe = me4000_pci_probe,
2186 .remove = __devexit_p(me4000_pci_remove),
2188 module_comedi_pci_driver(me4000_driver, me4000_pci_driver);
2190 MODULE_AUTHOR("Comedi http://www.comedi.org");
2191 MODULE_DESCRIPTION("Comedi low-level driver");
2192 MODULE_LICENSE("GPL");