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 get_registers(struct comedi_device *dev, struct pci_dev *pci_dev_p);
219 static int init_board_info(struct comedi_device *dev,
220 struct pci_dev *pci_dev_p);
221 static int init_ao_context(struct comedi_device *dev);
222 static int init_ai_context(struct comedi_device *dev);
223 static int init_dio_context(struct comedi_device *dev);
224 static int xilinx_download(struct comedi_device *dev);
225 static int reset_board(struct comedi_device *dev);
227 static int ai_write_chanlist(struct comedi_device *dev,
228 struct comedi_subdevice *s,
229 struct comedi_cmd *cmd);
231 static const struct comedi_lrange me4000_ai_range = {
241 static const struct comedi_lrange me4000_ao_range = {
248 static int me4000_probe(struct comedi_device *dev, struct comedi_devconfig *it)
250 struct pci_dev *pci_device = NULL;
252 const struct me4000_board *board;
254 /* Allocate private memory */
255 if (alloc_private(dev, sizeof(struct me4000_info)) < 0)
259 * Probe the device to determine what device in the series it is.
261 for_each_pci_dev(pci_device) {
262 if (pci_device->vendor == PCI_VENDOR_ID_MEILHAUS) {
263 for (i = 0; i < ARRAY_SIZE(me4000_boards); i++) {
264 if (me4000_boards[i].device_id ==
265 pci_device->device) {
268 * bus/slot requested?
270 if ((it->options[0] != 0)
271 || (it->options[1] != 0)) {
273 * Are we on the wrong
276 if (pci_device->bus->number !=
279 PCI_SLOT(pci_device->devfn)
284 dev->board_ptr = me4000_boards + i;
285 board = comedi_board(dev);
286 info->pci_dev_p = pci_device;
294 "comedi%d: me4000: me4000_probe(): "
295 "No supported board found (req. bus/slot : %d/%d)\n",
296 dev->minor, it->options[0], it->options[1]);
302 "comedi%d: me4000: me4000_probe(): "
303 "Found %s at PCI bus %d, slot %d\n",
304 dev->minor, me4000_boards[i].name, pci_device->bus->number,
305 PCI_SLOT(pci_device->devfn));
307 /* Set data in device structure */
308 dev->board_name = board->name;
310 /* Enable PCI device and request regions */
311 result = comedi_pci_enable(pci_device, dev->board_name);
314 "comedi%d: me4000: me4000_probe(): Cannot enable PCI "
315 "device and request I/O regions\n", dev->minor);
319 /* Get the PCI base registers */
320 result = get_registers(dev, pci_device);
323 "comedi%d: me4000: me4000_probe(): "
324 "Cannot get registers\n", dev->minor);
327 /* Initialize board info */
328 result = init_board_info(dev, pci_device);
331 "comedi%d: me4000: me4000_probe(): "
332 "Cannot init baord info\n", dev->minor);
336 /* Init analog output context */
337 result = init_ao_context(dev);
340 "comedi%d: me4000: me4000_probe(): "
341 "Cannot init ao context\n", dev->minor);
345 /* Init analog input context */
346 result = init_ai_context(dev);
349 "comedi%d: me4000: me4000_probe(): "
350 "Cannot init ai context\n", dev->minor);
354 /* Init digital I/O context */
355 result = init_dio_context(dev);
358 "comedi%d: me4000: me4000_probe(): "
359 "Cannot init dio context\n", dev->minor);
363 /* Download the xilinx firmware */
364 result = xilinx_download(dev);
367 "comedi%d: me4000: me4000_probe(): "
368 "Can't download firmware\n", dev->minor);
372 /* Make a hardware reset */
373 result = reset_board(dev);
376 "comedi%d: me4000: me4000_probe(): Can't reset board\n",
384 static int get_registers(struct comedi_device *dev, struct pci_dev *pci_dev_p)
386 /*--------------------------- plx regbase -------------------------------*/
388 info->plx_regbase = pci_resource_start(pci_dev_p, 1);
389 if (info->plx_regbase == 0) {
391 "comedi%d: me4000: get_registers(): "
392 "PCI base address 1 is not available\n", dev->minor);
395 info->plx_regbase_size = pci_resource_len(pci_dev_p, 1);
397 /*--------------------------- me4000 regbase ----------------------------*/
399 info->me4000_regbase = pci_resource_start(pci_dev_p, 2);
400 if (info->me4000_regbase == 0) {
402 "comedi%d: me4000: get_registers(): "
403 "PCI base address 2 is not available\n", dev->minor);
406 info->me4000_regbase_size = pci_resource_len(pci_dev_p, 2);
408 /*--------------------------- timer regbase ------------------------------*/
410 info->timer_regbase = pci_resource_start(pci_dev_p, 3);
411 if (info->timer_regbase == 0) {
413 "comedi%d: me4000: get_registers(): "
414 "PCI base address 3 is not available\n", dev->minor);
417 info->timer_regbase_size = pci_resource_len(pci_dev_p, 3);
419 /*--------------------------- program regbase ----------------------------*/
421 info->program_regbase = pci_resource_start(pci_dev_p, 5);
422 if (info->program_regbase == 0) {
424 "comedi%d: me4000: get_registers(): "
425 "PCI base address 5 is not available\n", dev->minor);
428 info->program_regbase_size = pci_resource_len(pci_dev_p, 5);
433 static int init_board_info(struct comedi_device *dev, struct pci_dev *pci_dev_p)
437 /* Init spin locks */
438 /* spin_lock_init(&info->preload_lock); */
439 /* spin_lock_init(&info->ai_ctrl_lock); */
441 /* Get the serial number */
442 result = pci_read_config_dword(pci_dev_p, 0x2C, &info->serial_no);
443 if (result != PCIBIOS_SUCCESSFUL)
446 /* Get the hardware revision */
447 result = pci_read_config_byte(pci_dev_p, 0x08, &info->hw_revision);
448 if (result != PCIBIOS_SUCCESSFUL)
451 /* Get the vendor id */
452 info->vendor_id = pci_dev_p->vendor;
454 /* Get the device id */
455 info->device_id = pci_dev_p->device;
457 /* Get the irq assigned to the board */
458 info->irq = pci_dev_p->irq;
463 static int init_ao_context(struct comedi_device *dev)
465 const struct me4000_board *thisboard = comedi_board(dev);
468 for (i = 0; i < thisboard->ao_nchan; i++) {
469 /* spin_lock_init(&info->ao_context[i].use_lock); */
470 info->ao_context[i].irq = info->irq;
474 info->ao_context[i].ctrl_reg =
475 info->me4000_regbase + ME4000_AO_00_CTRL_REG;
476 info->ao_context[i].status_reg =
477 info->me4000_regbase + ME4000_AO_00_STATUS_REG;
478 info->ao_context[i].fifo_reg =
479 info->me4000_regbase + ME4000_AO_00_FIFO_REG;
480 info->ao_context[i].single_reg =
481 info->me4000_regbase + ME4000_AO_00_SINGLE_REG;
482 info->ao_context[i].timer_reg =
483 info->me4000_regbase + ME4000_AO_00_TIMER_REG;
484 info->ao_context[i].irq_status_reg =
485 info->me4000_regbase + ME4000_IRQ_STATUS_REG;
486 info->ao_context[i].preload_reg =
487 info->me4000_regbase + ME4000_AO_LOADSETREG_XX;
490 info->ao_context[i].ctrl_reg =
491 info->me4000_regbase + ME4000_AO_01_CTRL_REG;
492 info->ao_context[i].status_reg =
493 info->me4000_regbase + ME4000_AO_01_STATUS_REG;
494 info->ao_context[i].fifo_reg =
495 info->me4000_regbase + ME4000_AO_01_FIFO_REG;
496 info->ao_context[i].single_reg =
497 info->me4000_regbase + ME4000_AO_01_SINGLE_REG;
498 info->ao_context[i].timer_reg =
499 info->me4000_regbase + ME4000_AO_01_TIMER_REG;
500 info->ao_context[i].irq_status_reg =
501 info->me4000_regbase + ME4000_IRQ_STATUS_REG;
502 info->ao_context[i].preload_reg =
503 info->me4000_regbase + ME4000_AO_LOADSETREG_XX;
506 info->ao_context[i].ctrl_reg =
507 info->me4000_regbase + ME4000_AO_02_CTRL_REG;
508 info->ao_context[i].status_reg =
509 info->me4000_regbase + ME4000_AO_02_STATUS_REG;
510 info->ao_context[i].fifo_reg =
511 info->me4000_regbase + ME4000_AO_02_FIFO_REG;
512 info->ao_context[i].single_reg =
513 info->me4000_regbase + ME4000_AO_02_SINGLE_REG;
514 info->ao_context[i].timer_reg =
515 info->me4000_regbase + ME4000_AO_02_TIMER_REG;
516 info->ao_context[i].irq_status_reg =
517 info->me4000_regbase + ME4000_IRQ_STATUS_REG;
518 info->ao_context[i].preload_reg =
519 info->me4000_regbase + ME4000_AO_LOADSETREG_XX;
522 info->ao_context[i].ctrl_reg =
523 info->me4000_regbase + ME4000_AO_03_CTRL_REG;
524 info->ao_context[i].status_reg =
525 info->me4000_regbase + ME4000_AO_03_STATUS_REG;
526 info->ao_context[i].fifo_reg =
527 info->me4000_regbase + ME4000_AO_03_FIFO_REG;
528 info->ao_context[i].single_reg =
529 info->me4000_regbase + ME4000_AO_03_SINGLE_REG;
530 info->ao_context[i].timer_reg =
531 info->me4000_regbase + ME4000_AO_03_TIMER_REG;
532 info->ao_context[i].irq_status_reg =
533 info->me4000_regbase + ME4000_IRQ_STATUS_REG;
534 info->ao_context[i].preload_reg =
535 info->me4000_regbase + ME4000_AO_LOADSETREG_XX;
545 static int init_ai_context(struct comedi_device *dev)
547 info->ai_context.irq = info->irq;
549 info->ai_context.ctrl_reg = info->me4000_regbase + ME4000_AI_CTRL_REG;
550 info->ai_context.status_reg =
551 info->me4000_regbase + ME4000_AI_STATUS_REG;
552 info->ai_context.channel_list_reg =
553 info->me4000_regbase + ME4000_AI_CHANNEL_LIST_REG;
554 info->ai_context.data_reg = info->me4000_regbase + ME4000_AI_DATA_REG;
555 info->ai_context.chan_timer_reg =
556 info->me4000_regbase + ME4000_AI_CHAN_TIMER_REG;
557 info->ai_context.chan_pre_timer_reg =
558 info->me4000_regbase + ME4000_AI_CHAN_PRE_TIMER_REG;
559 info->ai_context.scan_timer_low_reg =
560 info->me4000_regbase + ME4000_AI_SCAN_TIMER_LOW_REG;
561 info->ai_context.scan_timer_high_reg =
562 info->me4000_regbase + ME4000_AI_SCAN_TIMER_HIGH_REG;
563 info->ai_context.scan_pre_timer_low_reg =
564 info->me4000_regbase + ME4000_AI_SCAN_PRE_TIMER_LOW_REG;
565 info->ai_context.scan_pre_timer_high_reg =
566 info->me4000_regbase + ME4000_AI_SCAN_PRE_TIMER_HIGH_REG;
567 info->ai_context.start_reg = info->me4000_regbase + ME4000_AI_START_REG;
568 info->ai_context.irq_status_reg =
569 info->me4000_regbase + ME4000_IRQ_STATUS_REG;
570 info->ai_context.sample_counter_reg =
571 info->me4000_regbase + ME4000_AI_SAMPLE_COUNTER_REG;
576 static int init_dio_context(struct comedi_device *dev)
578 info->dio_context.dir_reg = info->me4000_regbase + ME4000_DIO_DIR_REG;
579 info->dio_context.ctrl_reg = info->me4000_regbase + ME4000_DIO_CTRL_REG;
580 info->dio_context.port_0_reg =
581 info->me4000_regbase + ME4000_DIO_PORT_0_REG;
582 info->dio_context.port_1_reg =
583 info->me4000_regbase + ME4000_DIO_PORT_1_REG;
584 info->dio_context.port_2_reg =
585 info->me4000_regbase + ME4000_DIO_PORT_2_REG;
586 info->dio_context.port_3_reg =
587 info->me4000_regbase + ME4000_DIO_PORT_3_REG;
592 #define FIRMWARE_NOT_AVAILABLE 1
593 #if FIRMWARE_NOT_AVAILABLE
594 extern unsigned char *xilinx_firm;
597 static int xilinx_download(struct comedi_device *dev)
600 wait_queue_head_t queue;
604 init_waitqueue_head(&queue);
607 * Set PLX local interrupt 2 polarity to high.
608 * Interrupt is thrown by init pin of xilinx.
610 outl(0x10, info->plx_regbase + PLX_INTCSR);
612 /* Set /CS and /WRITE of the Xilinx */
613 value = inl(info->plx_regbase + PLX_ICR);
615 outl(value, info->plx_regbase + PLX_ICR);
617 /* Init Xilinx with CS1 */
618 inb(info->program_regbase + 0xC8);
620 /* Wait until /INIT pin is set */
622 if (!(inl(info->plx_regbase + PLX_INTCSR) & 0x20)) {
624 "comedi%d: me4000: xilinx_download(): "
625 "Can't init Xilinx\n", dev->minor);
629 /* Reset /CS and /WRITE of the Xilinx */
630 value = inl(info->plx_regbase + PLX_ICR);
632 outl(value, info->plx_regbase + PLX_ICR);
633 if (FIRMWARE_NOT_AVAILABLE) {
634 comedi_error(dev, "xilinx firmware unavailable "
635 "due to licensing, aborting");
638 /* Download Xilinx firmware */
639 size = (xilinx_firm[0] << 24) + (xilinx_firm[1] << 16) +
640 (xilinx_firm[2] << 8) + xilinx_firm[3];
643 for (idx = 0; idx < size; idx++) {
644 outb(xilinx_firm[16 + idx], info->program_regbase);
647 /* Check if BUSY flag is low */
648 if (inl(info->plx_regbase + PLX_ICR) & 0x20) {
650 "comedi%d: me4000: xilinx_download(): "
651 "Xilinx is still busy (idx = %d)\n",
658 /* If done flag is high download was successful */
659 if (inl(info->plx_regbase + PLX_ICR) & 0x4) {
662 "comedi%d: me4000: xilinx_download(): "
663 "DONE flag is not set\n", dev->minor);
665 "comedi%d: me4000: xilinx_download(): "
666 "Download not successful\n", dev->minor);
670 /* Set /CS and /WRITE */
671 value = inl(info->plx_regbase + PLX_ICR);
673 outl(value, info->plx_regbase + PLX_ICR);
678 static int reset_board(struct comedi_device *dev)
682 /* Make a hardware reset */
683 icr = inl(info->plx_regbase + PLX_ICR);
685 outl(icr, info->plx_regbase + PLX_ICR);
687 outl(icr, info->plx_regbase + PLX_ICR);
689 /* 0x8000 to the DACs means an output voltage of 0V */
690 outl(0x8000, info->me4000_regbase + ME4000_AO_00_SINGLE_REG);
691 outl(0x8000, info->me4000_regbase + ME4000_AO_01_SINGLE_REG);
692 outl(0x8000, info->me4000_regbase + ME4000_AO_02_SINGLE_REG);
693 outl(0x8000, info->me4000_regbase + ME4000_AO_03_SINGLE_REG);
695 /* Set both stop bits in the analog input control register */
696 outl(ME4000_AI_CTRL_BIT_IMMEDIATE_STOP | ME4000_AI_CTRL_BIT_STOP,
697 info->me4000_regbase + ME4000_AI_CTRL_REG);
699 /* Set both stop bits in the analog output control register */
700 outl(ME4000_AO_CTRL_BIT_IMMEDIATE_STOP | ME4000_AO_CTRL_BIT_STOP,
701 info->me4000_regbase + ME4000_AO_00_CTRL_REG);
702 outl(ME4000_AO_CTRL_BIT_IMMEDIATE_STOP | ME4000_AO_CTRL_BIT_STOP,
703 info->me4000_regbase + ME4000_AO_01_CTRL_REG);
704 outl(ME4000_AO_CTRL_BIT_IMMEDIATE_STOP | ME4000_AO_CTRL_BIT_STOP,
705 info->me4000_regbase + ME4000_AO_02_CTRL_REG);
706 outl(ME4000_AO_CTRL_BIT_IMMEDIATE_STOP | ME4000_AO_CTRL_BIT_STOP,
707 info->me4000_regbase + ME4000_AO_03_CTRL_REG);
709 /* Enable interrupts on the PLX */
710 outl(0x43, info->plx_regbase + PLX_INTCSR);
712 /* Set the adustment register for AO demux */
713 outl(ME4000_AO_DEMUX_ADJUST_VALUE,
714 info->me4000_regbase + ME4000_AO_DEMUX_ADJUST_REG);
717 * Set digital I/O direction for port 0
718 * to output on isolated versions
720 if (!(inl(info->me4000_regbase + ME4000_DIO_DIR_REG) & 0x1))
721 outl(0x1, info->me4000_regbase + ME4000_DIO_CTRL_REG);
726 /*=============================================================================
728 ===========================================================================*/
730 static int me4000_ai_insn_read(struct comedi_device *dev,
731 struct comedi_subdevice *subdevice,
732 struct comedi_insn *insn, unsigned int *data)
734 const struct me4000_board *thisboard = comedi_board(dev);
735 int chan = CR_CHAN(insn->chanspec);
736 int rang = CR_RANGE(insn->chanspec);
737 int aref = CR_AREF(insn->chanspec);
739 unsigned long entry = 0;
745 } else if (insn->n > 1) {
747 "comedi%d: me4000: me4000_ai_insn_read(): "
748 "Invalid instruction length %d\n", dev->minor, insn->n);
754 entry |= ME4000_AI_LIST_RANGE_UNIPOLAR_2_5;
757 entry |= ME4000_AI_LIST_RANGE_UNIPOLAR_10;
760 entry |= ME4000_AI_LIST_RANGE_BIPOLAR_2_5;
763 entry |= ME4000_AI_LIST_RANGE_BIPOLAR_10;
767 "comedi%d: me4000: me4000_ai_insn_read(): "
768 "Invalid range specified\n", dev->minor);
775 if (chan >= thisboard->ai_nchan) {
777 "comedi%d: me4000: me4000_ai_insn_read(): "
778 "Analog input is not available\n", dev->minor);
781 entry |= ME4000_AI_LIST_INPUT_SINGLE_ENDED | chan;
785 if (rang == 0 || rang == 1) {
787 "comedi%d: me4000: me4000_ai_insn_read(): "
788 "Range must be bipolar when aref = diff\n",
793 if (chan >= thisboard->ai_diff_nchan) {
795 "comedi%d: me4000: me4000_ai_insn_read(): "
796 "Analog input is not available\n", dev->minor);
799 entry |= ME4000_AI_LIST_INPUT_DIFFERENTIAL | chan;
803 "comedi%d: me4000: me4000_ai_insn_read(): "
804 "Invalid aref specified\n", dev->minor);
808 entry |= ME4000_AI_LIST_LAST_ENTRY;
810 /* Clear channel list, data fifo and both stop bits */
811 tmp = inl(info->ai_context.ctrl_reg);
812 tmp &= ~(ME4000_AI_CTRL_BIT_CHANNEL_FIFO |
813 ME4000_AI_CTRL_BIT_DATA_FIFO |
814 ME4000_AI_CTRL_BIT_STOP | ME4000_AI_CTRL_BIT_IMMEDIATE_STOP);
815 outl(tmp, info->ai_context.ctrl_reg);
817 /* Set the acquisition mode to single */
818 tmp &= ~(ME4000_AI_CTRL_BIT_MODE_0 | ME4000_AI_CTRL_BIT_MODE_1 |
819 ME4000_AI_CTRL_BIT_MODE_2);
820 outl(tmp, info->ai_context.ctrl_reg);
822 /* Enable channel list and data fifo */
823 tmp |= ME4000_AI_CTRL_BIT_CHANNEL_FIFO | ME4000_AI_CTRL_BIT_DATA_FIFO;
824 outl(tmp, info->ai_context.ctrl_reg);
826 /* Generate channel list entry */
827 outl(entry, info->ai_context.channel_list_reg);
829 /* Set the timer to maximum sample rate */
830 outl(ME4000_AI_MIN_TICKS, info->ai_context.chan_timer_reg);
831 outl(ME4000_AI_MIN_TICKS, info->ai_context.chan_pre_timer_reg);
833 /* Start conversion by dummy read */
834 inl(info->ai_context.start_reg);
836 /* Wait until ready */
838 if (!(inl(info->ai_context.status_reg) &
839 ME4000_AI_STATUS_BIT_EF_DATA)) {
841 "comedi%d: me4000: me4000_ai_insn_read(): "
842 "Value not available after wait\n", dev->minor);
846 /* Read value from data fifo */
847 lval = inl(info->ai_context.data_reg) & 0xFFFF;
848 data[0] = lval ^ 0x8000;
853 static int me4000_ai_cancel(struct comedi_device *dev,
854 struct comedi_subdevice *s)
858 /* Stop any running conversion */
859 tmp = inl(info->ai_context.ctrl_reg);
860 tmp &= ~(ME4000_AI_CTRL_BIT_STOP | ME4000_AI_CTRL_BIT_IMMEDIATE_STOP);
861 outl(tmp, info->ai_context.ctrl_reg);
863 /* Clear the control register */
864 outl(0x0, info->ai_context.ctrl_reg);
869 static int ai_check_chanlist(struct comedi_device *dev,
870 struct comedi_subdevice *s, struct comedi_cmd *cmd)
872 const struct me4000_board *thisboard = comedi_board(dev);
876 /* Check whether a channel list is available */
877 if (!cmd->chanlist_len) {
879 "comedi%d: me4000: ai_check_chanlist(): "
880 "No channel list available\n", dev->minor);
884 /* Check the channel list size */
885 if (cmd->chanlist_len > ME4000_AI_CHANNEL_LIST_COUNT) {
887 "comedi%d: me4000: ai_check_chanlist(): "
888 "Channel list is to large\n", dev->minor);
892 /* Check the pointer */
893 if (!cmd->chanlist) {
895 "comedi%d: me4000: ai_check_chanlist(): "
896 "NULL pointer to channel list\n", dev->minor);
900 /* Check whether aref is equal for all entries */
901 aref = CR_AREF(cmd->chanlist[0]);
902 for (i = 0; i < cmd->chanlist_len; i++) {
903 if (CR_AREF(cmd->chanlist[i]) != aref) {
905 "comedi%d: me4000: ai_check_chanlist(): "
906 "Mode is not equal for all entries\n",
912 /* Check whether channels are available for this ending */
913 if (aref == SDF_DIFF) {
914 for (i = 0; i < cmd->chanlist_len; i++) {
915 if (CR_CHAN(cmd->chanlist[i]) >=
916 thisboard->ai_diff_nchan) {
918 "comedi%d: me4000: ai_check_chanlist():"
919 " Channel number to high\n", dev->minor);
924 for (i = 0; i < cmd->chanlist_len; i++) {
925 if (CR_CHAN(cmd->chanlist[i]) >= thisboard->ai_nchan) {
927 "comedi%d: me4000: ai_check_chanlist(): "
928 "Channel number to high\n", dev->minor);
934 /* Check if bipolar is set for all entries when in differential mode */
935 if (aref == SDF_DIFF) {
936 for (i = 0; i < cmd->chanlist_len; i++) {
937 if (CR_RANGE(cmd->chanlist[i]) != 1 &&
938 CR_RANGE(cmd->chanlist[i]) != 2) {
940 "comedi%d: me4000: ai_check_chanlist(): "
941 "Bipolar is not selected in "
942 "differential mode\n",
952 static int ai_round_cmd_args(struct comedi_device *dev,
953 struct comedi_subdevice *s,
954 struct comedi_cmd *cmd,
955 unsigned int *init_ticks,
956 unsigned int *scan_ticks, unsigned int *chan_ticks)
965 if (cmd->start_arg) {
966 *init_ticks = (cmd->start_arg * 33) / 1000;
967 rest = (cmd->start_arg * 33) % 1000;
969 if ((cmd->flags & TRIG_ROUND_MASK) == TRIG_ROUND_NEAREST) {
972 } else if ((cmd->flags & TRIG_ROUND_MASK) == TRIG_ROUND_UP) {
978 if (cmd->scan_begin_arg) {
979 *scan_ticks = (cmd->scan_begin_arg * 33) / 1000;
980 rest = (cmd->scan_begin_arg * 33) % 1000;
982 if ((cmd->flags & TRIG_ROUND_MASK) == TRIG_ROUND_NEAREST) {
985 } else if ((cmd->flags & TRIG_ROUND_MASK) == TRIG_ROUND_UP) {
991 if (cmd->convert_arg) {
992 *chan_ticks = (cmd->convert_arg * 33) / 1000;
993 rest = (cmd->convert_arg * 33) % 1000;
995 if ((cmd->flags & TRIG_ROUND_MASK) == TRIG_ROUND_NEAREST) {
998 } else if ((cmd->flags & TRIG_ROUND_MASK) == TRIG_ROUND_UP) {
1007 static void ai_write_timer(struct comedi_device *dev,
1008 unsigned int init_ticks,
1009 unsigned int scan_ticks, unsigned int chan_ticks)
1011 outl(init_ticks - 1, info->ai_context.scan_pre_timer_low_reg);
1012 outl(0x0, info->ai_context.scan_pre_timer_high_reg);
1015 outl(scan_ticks - 1, info->ai_context.scan_timer_low_reg);
1016 outl(0x0, info->ai_context.scan_timer_high_reg);
1019 outl(chan_ticks - 1, info->ai_context.chan_pre_timer_reg);
1020 outl(chan_ticks - 1, info->ai_context.chan_timer_reg);
1023 static int ai_prepare(struct comedi_device *dev,
1024 struct comedi_subdevice *s,
1025 struct comedi_cmd *cmd,
1026 unsigned int init_ticks,
1027 unsigned int scan_ticks, unsigned int chan_ticks)
1030 unsigned long tmp = 0;
1032 /* Write timer arguments */
1033 ai_write_timer(dev, init_ticks, scan_ticks, chan_ticks);
1035 /* Reset control register */
1036 outl(tmp, info->ai_context.ctrl_reg);
1039 if ((cmd->start_src == TRIG_EXT &&
1040 cmd->scan_begin_src == TRIG_TIMER &&
1041 cmd->convert_src == TRIG_TIMER) ||
1042 (cmd->start_src == TRIG_EXT &&
1043 cmd->scan_begin_src == TRIG_FOLLOW &&
1044 cmd->convert_src == TRIG_TIMER)) {
1045 tmp = ME4000_AI_CTRL_BIT_MODE_1 |
1046 ME4000_AI_CTRL_BIT_CHANNEL_FIFO |
1047 ME4000_AI_CTRL_BIT_DATA_FIFO;
1048 } else if (cmd->start_src == TRIG_EXT &&
1049 cmd->scan_begin_src == TRIG_EXT &&
1050 cmd->convert_src == TRIG_TIMER) {
1051 tmp = ME4000_AI_CTRL_BIT_MODE_2 |
1052 ME4000_AI_CTRL_BIT_CHANNEL_FIFO |
1053 ME4000_AI_CTRL_BIT_DATA_FIFO;
1054 } else if (cmd->start_src == TRIG_EXT &&
1055 cmd->scan_begin_src == TRIG_EXT &&
1056 cmd->convert_src == TRIG_EXT) {
1057 tmp = ME4000_AI_CTRL_BIT_MODE_0 |
1058 ME4000_AI_CTRL_BIT_MODE_1 |
1059 ME4000_AI_CTRL_BIT_CHANNEL_FIFO |
1060 ME4000_AI_CTRL_BIT_DATA_FIFO;
1062 tmp = ME4000_AI_CTRL_BIT_MODE_0 |
1063 ME4000_AI_CTRL_BIT_CHANNEL_FIFO |
1064 ME4000_AI_CTRL_BIT_DATA_FIFO;
1068 if (cmd->stop_src == TRIG_COUNT) {
1069 outl(cmd->chanlist_len * cmd->stop_arg,
1070 info->ai_context.sample_counter_reg);
1071 tmp |= ME4000_AI_CTRL_BIT_HF_IRQ | ME4000_AI_CTRL_BIT_SC_IRQ;
1072 } else if (cmd->stop_src == TRIG_NONE &&
1073 cmd->scan_end_src == TRIG_COUNT) {
1074 outl(cmd->scan_end_arg,
1075 info->ai_context.sample_counter_reg);
1076 tmp |= ME4000_AI_CTRL_BIT_HF_IRQ | ME4000_AI_CTRL_BIT_SC_IRQ;
1078 tmp |= ME4000_AI_CTRL_BIT_HF_IRQ;
1081 /* Write the setup to the control register */
1082 outl(tmp, info->ai_context.ctrl_reg);
1084 /* Write the channel list */
1085 ai_write_chanlist(dev, s, cmd);
1090 static int ai_write_chanlist(struct comedi_device *dev,
1091 struct comedi_subdevice *s, struct comedi_cmd *cmd)
1099 for (i = 0; i < cmd->chanlist_len; i++) {
1100 chan = CR_CHAN(cmd->chanlist[i]);
1101 rang = CR_RANGE(cmd->chanlist[i]);
1102 aref = CR_AREF(cmd->chanlist[i]);
1107 entry |= ME4000_AI_LIST_RANGE_UNIPOLAR_2_5;
1109 entry |= ME4000_AI_LIST_RANGE_UNIPOLAR_10;
1111 entry |= ME4000_AI_LIST_RANGE_BIPOLAR_2_5;
1113 entry |= ME4000_AI_LIST_RANGE_BIPOLAR_10;
1115 if (aref == SDF_DIFF)
1116 entry |= ME4000_AI_LIST_INPUT_DIFFERENTIAL;
1118 entry |= ME4000_AI_LIST_INPUT_SINGLE_ENDED;
1120 outl(entry, info->ai_context.channel_list_reg);
1126 static int me4000_ai_do_cmd(struct comedi_device *dev,
1127 struct comedi_subdevice *s)
1130 unsigned int init_ticks = 0;
1131 unsigned int scan_ticks = 0;
1132 unsigned int chan_ticks = 0;
1133 struct comedi_cmd *cmd = &s->async->cmd;
1135 /* Reset the analog input */
1136 err = me4000_ai_cancel(dev, s);
1140 /* Round the timer arguments */
1141 err = ai_round_cmd_args(dev,
1142 s, cmd, &init_ticks, &scan_ticks, &chan_ticks);
1146 /* Prepare the AI for acquisition */
1147 err = ai_prepare(dev, s, cmd, init_ticks, scan_ticks, chan_ticks);
1151 /* Start acquistion by dummy read */
1152 inl(info->ai_context.start_reg);
1158 * me4000_ai_do_cmd_test():
1160 * The demo cmd.c in ./comedilib/demo specifies 6 return values:
1164 * - invalid argument
1165 * - argument conflict
1166 * - invalid chanlist
1167 * So I tried to adopt this scheme.
1169 static int me4000_ai_do_cmd_test(struct comedi_device *dev,
1170 struct comedi_subdevice *s,
1171 struct comedi_cmd *cmd)
1174 unsigned int init_ticks;
1175 unsigned int chan_ticks;
1176 unsigned int scan_ticks;
1179 /* Only rounding flags are implemented */
1180 cmd->flags &= TRIG_ROUND_NEAREST | TRIG_ROUND_UP | TRIG_ROUND_DOWN;
1182 /* Round the timer arguments */
1183 ai_round_cmd_args(dev, s, cmd, &init_ticks, &scan_ticks, &chan_ticks);
1186 * Stage 1. Check if the trigger sources are generally valid.
1188 switch (cmd->start_src) {
1193 cmd->start_src &= TRIG_NOW | TRIG_EXT;
1198 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1199 "Invalid start source\n", dev->minor);
1200 cmd->start_src = TRIG_NOW;
1203 switch (cmd->scan_begin_src) {
1209 cmd->scan_begin_src &= TRIG_FOLLOW | TRIG_TIMER | TRIG_EXT;
1214 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1215 "Invalid scan begin source\n", dev->minor);
1216 cmd->scan_begin_src = TRIG_FOLLOW;
1219 switch (cmd->convert_src) {
1224 cmd->convert_src &= TRIG_TIMER | TRIG_EXT;
1229 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1230 "Invalid convert source\n", dev->minor);
1231 cmd->convert_src = TRIG_TIMER;
1234 switch (cmd->scan_end_src) {
1239 cmd->scan_end_src &= TRIG_NONE | TRIG_COUNT;
1244 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1245 "Invalid scan end source\n", dev->minor);
1246 cmd->scan_end_src = TRIG_NONE;
1249 switch (cmd->stop_src) {
1254 cmd->stop_src &= TRIG_NONE | TRIG_COUNT;
1259 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1260 "Invalid stop source\n", dev->minor);
1261 cmd->stop_src = TRIG_NONE;
1268 * Stage 2. Check for trigger source conflicts.
1270 if (cmd->start_src == TRIG_NOW &&
1271 cmd->scan_begin_src == TRIG_TIMER &&
1272 cmd->convert_src == TRIG_TIMER) {
1273 } else if (cmd->start_src == TRIG_NOW &&
1274 cmd->scan_begin_src == TRIG_FOLLOW &&
1275 cmd->convert_src == TRIG_TIMER) {
1276 } else if (cmd->start_src == TRIG_EXT &&
1277 cmd->scan_begin_src == TRIG_TIMER &&
1278 cmd->convert_src == TRIG_TIMER) {
1279 } else if (cmd->start_src == TRIG_EXT &&
1280 cmd->scan_begin_src == TRIG_FOLLOW &&
1281 cmd->convert_src == TRIG_TIMER) {
1282 } else if (cmd->start_src == TRIG_EXT &&
1283 cmd->scan_begin_src == TRIG_EXT &&
1284 cmd->convert_src == TRIG_TIMER) {
1285 } else if (cmd->start_src == TRIG_EXT &&
1286 cmd->scan_begin_src == TRIG_EXT &&
1287 cmd->convert_src == TRIG_EXT) {
1290 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1291 "Invalid start trigger combination\n", dev->minor);
1292 cmd->start_src = TRIG_NOW;
1293 cmd->scan_begin_src = TRIG_FOLLOW;
1294 cmd->convert_src = TRIG_TIMER;
1298 if (cmd->stop_src == TRIG_NONE && cmd->scan_end_src == TRIG_NONE) {
1299 } else if (cmd->stop_src == TRIG_COUNT &&
1300 cmd->scan_end_src == TRIG_NONE) {
1301 } else if (cmd->stop_src == TRIG_NONE &&
1302 cmd->scan_end_src == TRIG_COUNT) {
1303 } else if (cmd->stop_src == TRIG_COUNT &&
1304 cmd->scan_end_src == TRIG_COUNT) {
1307 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1308 "Invalid stop trigger combination\n", dev->minor);
1309 cmd->stop_src = TRIG_NONE;
1310 cmd->scan_end_src = TRIG_NONE;
1317 * Stage 3. Check if arguments are generally valid.
1319 if (cmd->chanlist_len < 1) {
1321 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1322 "No channel list\n", dev->minor);
1323 cmd->chanlist_len = 1;
1326 if (init_ticks < 66) {
1328 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1329 "Start arg to low\n", dev->minor);
1330 cmd->start_arg = 2000;
1333 if (scan_ticks && scan_ticks < 67) {
1335 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1336 "Scan begin arg to low\n", dev->minor);
1337 cmd->scan_begin_arg = 2031;
1340 if (chan_ticks < 66) {
1342 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1343 "Convert arg to low\n", dev->minor);
1344 cmd->convert_arg = 2000;
1352 * Stage 4. Check for argument conflicts.
1354 if (cmd->start_src == TRIG_NOW &&
1355 cmd->scan_begin_src == TRIG_TIMER &&
1356 cmd->convert_src == TRIG_TIMER) {
1358 /* Check timer arguments */
1359 if (init_ticks < ME4000_AI_MIN_TICKS) {
1361 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1362 "Invalid start arg\n", dev->minor);
1363 cmd->start_arg = 2000; /* 66 ticks at least */
1366 if (chan_ticks < ME4000_AI_MIN_TICKS) {
1368 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1369 "Invalid convert arg\n", dev->minor);
1370 cmd->convert_arg = 2000; /* 66 ticks at least */
1373 if (scan_ticks <= cmd->chanlist_len * chan_ticks) {
1375 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1376 "Invalid scan end arg\n", dev->minor);
1378 /* At least one tick more */
1379 cmd->scan_end_arg = 2000 * cmd->chanlist_len + 31;
1382 } else if (cmd->start_src == TRIG_NOW &&
1383 cmd->scan_begin_src == TRIG_FOLLOW &&
1384 cmd->convert_src == TRIG_TIMER) {
1386 /* Check timer arguments */
1387 if (init_ticks < ME4000_AI_MIN_TICKS) {
1389 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1390 "Invalid start arg\n", dev->minor);
1391 cmd->start_arg = 2000; /* 66 ticks at least */
1394 if (chan_ticks < ME4000_AI_MIN_TICKS) {
1396 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1397 "Invalid convert arg\n", dev->minor);
1398 cmd->convert_arg = 2000; /* 66 ticks at least */
1401 } else if (cmd->start_src == TRIG_EXT &&
1402 cmd->scan_begin_src == TRIG_TIMER &&
1403 cmd->convert_src == TRIG_TIMER) {
1405 /* Check timer arguments */
1406 if (init_ticks < ME4000_AI_MIN_TICKS) {
1408 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1409 "Invalid start arg\n", dev->minor);
1410 cmd->start_arg = 2000; /* 66 ticks at least */
1413 if (chan_ticks < ME4000_AI_MIN_TICKS) {
1415 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1416 "Invalid convert arg\n", dev->minor);
1417 cmd->convert_arg = 2000; /* 66 ticks at least */
1420 if (scan_ticks <= cmd->chanlist_len * chan_ticks) {
1422 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1423 "Invalid scan end arg\n", dev->minor);
1425 /* At least one tick more */
1426 cmd->scan_end_arg = 2000 * cmd->chanlist_len + 31;
1429 } else if (cmd->start_src == TRIG_EXT &&
1430 cmd->scan_begin_src == TRIG_FOLLOW &&
1431 cmd->convert_src == TRIG_TIMER) {
1433 /* Check timer arguments */
1434 if (init_ticks < ME4000_AI_MIN_TICKS) {
1436 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1437 "Invalid start arg\n", dev->minor);
1438 cmd->start_arg = 2000; /* 66 ticks at least */
1441 if (chan_ticks < ME4000_AI_MIN_TICKS) {
1443 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1444 "Invalid convert arg\n", dev->minor);
1445 cmd->convert_arg = 2000; /* 66 ticks at least */
1448 } else if (cmd->start_src == TRIG_EXT &&
1449 cmd->scan_begin_src == TRIG_EXT &&
1450 cmd->convert_src == TRIG_TIMER) {
1452 /* Check timer arguments */
1453 if (init_ticks < ME4000_AI_MIN_TICKS) {
1455 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1456 "Invalid start arg\n", dev->minor);
1457 cmd->start_arg = 2000; /* 66 ticks at least */
1460 if (chan_ticks < ME4000_AI_MIN_TICKS) {
1462 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1463 "Invalid convert arg\n", dev->minor);
1464 cmd->convert_arg = 2000; /* 66 ticks at least */
1467 } else if (cmd->start_src == TRIG_EXT &&
1468 cmd->scan_begin_src == TRIG_EXT &&
1469 cmd->convert_src == TRIG_EXT) {
1471 /* Check timer arguments */
1472 if (init_ticks < ME4000_AI_MIN_TICKS) {
1474 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1475 "Invalid start arg\n", dev->minor);
1476 cmd->start_arg = 2000; /* 66 ticks at least */
1480 if (cmd->stop_src == TRIG_COUNT) {
1481 if (cmd->stop_arg == 0) {
1483 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1484 "Invalid stop arg\n", dev->minor);
1489 if (cmd->scan_end_src == TRIG_COUNT) {
1490 if (cmd->scan_end_arg == 0) {
1492 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1493 "Invalid scan end arg\n", dev->minor);
1494 cmd->scan_end_arg = 1;
1503 * Stage 5. Check the channel list.
1505 if (ai_check_chanlist(dev, s, cmd))
1511 static irqreturn_t me4000_ai_isr(int irq, void *dev_id)
1514 struct comedi_device *dev = dev_id;
1515 struct comedi_subdevice *s = &dev->subdevices[0];
1516 struct me4000_ai_context *ai_context = &info->ai_context;
1524 /* Reset all events */
1525 s->async->events = 0;
1527 /* Check if irq number is right */
1528 if (irq != ai_context->irq) {
1530 "comedi%d: me4000: me4000_ai_isr(): "
1531 "Incorrect interrupt num: %d\n", dev->minor, irq);
1535 if (inl(ai_context->irq_status_reg) &
1536 ME4000_IRQ_STATUS_BIT_AI_HF) {
1537 /* Read status register to find out what happened */
1538 tmp = inl(ai_context->ctrl_reg);
1540 if (!(tmp & ME4000_AI_STATUS_BIT_FF_DATA) &&
1541 !(tmp & ME4000_AI_STATUS_BIT_HF_DATA) &&
1542 (tmp & ME4000_AI_STATUS_BIT_EF_DATA)) {
1543 c = ME4000_AI_FIFO_COUNT;
1546 * FIFO overflow, so stop conversion
1547 * and disable all interrupts
1549 tmp |= ME4000_AI_CTRL_BIT_IMMEDIATE_STOP;
1550 tmp &= ~(ME4000_AI_CTRL_BIT_HF_IRQ |
1551 ME4000_AI_CTRL_BIT_SC_IRQ);
1552 outl(tmp, ai_context->ctrl_reg);
1554 s->async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
1557 "comedi%d: me4000: me4000_ai_isr(): "
1558 "FIFO overflow\n", dev->minor);
1559 } else if ((tmp & ME4000_AI_STATUS_BIT_FF_DATA)
1560 && !(tmp & ME4000_AI_STATUS_BIT_HF_DATA)
1561 && (tmp & ME4000_AI_STATUS_BIT_EF_DATA)) {
1562 s->async->events |= COMEDI_CB_BLOCK;
1564 c = ME4000_AI_FIFO_COUNT / 2;
1567 "comedi%d: me4000: me4000_ai_isr(): "
1568 "Can't determine state of fifo\n", dev->minor);
1572 * Undefined state, so stop conversion
1573 * and disable all interrupts
1575 tmp |= ME4000_AI_CTRL_BIT_IMMEDIATE_STOP;
1576 tmp &= ~(ME4000_AI_CTRL_BIT_HF_IRQ |
1577 ME4000_AI_CTRL_BIT_SC_IRQ);
1578 outl(tmp, ai_context->ctrl_reg);
1580 s->async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
1583 "comedi%d: me4000: me4000_ai_isr(): "
1584 "Undefined FIFO state\n", dev->minor);
1587 for (i = 0; i < c; i++) {
1588 /* Read value from data fifo */
1589 lval = inl(ai_context->data_reg) & 0xFFFF;
1592 if (!comedi_buf_put(s->async, lval)) {
1594 * Buffer overflow, so stop conversion
1595 * and disable all interrupts
1597 tmp |= ME4000_AI_CTRL_BIT_IMMEDIATE_STOP;
1598 tmp &= ~(ME4000_AI_CTRL_BIT_HF_IRQ |
1599 ME4000_AI_CTRL_BIT_SC_IRQ);
1600 outl(tmp, ai_context->ctrl_reg);
1602 s->async->events |= COMEDI_CB_OVERFLOW;
1605 "comedi%d: me4000: me4000_ai_isr(): "
1606 "Buffer overflow\n", dev->minor);
1612 /* Work is done, so reset the interrupt */
1613 tmp |= ME4000_AI_CTRL_BIT_HF_IRQ_RESET;
1614 outl(tmp, ai_context->ctrl_reg);
1615 tmp &= ~ME4000_AI_CTRL_BIT_HF_IRQ_RESET;
1616 outl(tmp, ai_context->ctrl_reg);
1619 if (inl(ai_context->irq_status_reg) & ME4000_IRQ_STATUS_BIT_SC) {
1620 s->async->events |= COMEDI_CB_BLOCK | COMEDI_CB_EOA;
1623 * Acquisition is complete, so stop
1624 * conversion and disable all interrupts
1626 tmp = inl(ai_context->ctrl_reg);
1627 tmp |= ME4000_AI_CTRL_BIT_IMMEDIATE_STOP;
1628 tmp &= ~(ME4000_AI_CTRL_BIT_HF_IRQ | ME4000_AI_CTRL_BIT_SC_IRQ);
1629 outl(tmp, ai_context->ctrl_reg);
1631 /* Poll data until fifo empty */
1632 while (inl(ai_context->ctrl_reg) & ME4000_AI_STATUS_BIT_EF_DATA) {
1633 /* Read value from data fifo */
1634 lval = inl(ai_context->data_reg) & 0xFFFF;
1637 if (!comedi_buf_put(s->async, lval)) {
1639 "comedi%d: me4000: me4000_ai_isr(): "
1640 "Buffer overflow\n", dev->minor);
1641 s->async->events |= COMEDI_CB_OVERFLOW;
1646 /* Work is done, so reset the interrupt */
1647 tmp |= ME4000_AI_CTRL_BIT_SC_IRQ_RESET;
1648 outl(tmp, ai_context->ctrl_reg);
1649 tmp &= ~ME4000_AI_CTRL_BIT_SC_IRQ_RESET;
1650 outl(tmp, ai_context->ctrl_reg);
1653 if (s->async->events)
1654 comedi_event(dev, s);
1659 /*=============================================================================
1660 Analog output section
1661 ===========================================================================*/
1663 static int me4000_ao_insn_write(struct comedi_device *dev,
1664 struct comedi_subdevice *s,
1665 struct comedi_insn *insn, unsigned int *data)
1667 const struct me4000_board *thisboard = comedi_board(dev);
1668 int chan = CR_CHAN(insn->chanspec);
1669 int rang = CR_RANGE(insn->chanspec);
1670 int aref = CR_AREF(insn->chanspec);
1675 } else if (insn->n > 1) {
1677 "comedi%d: me4000: me4000_ao_insn_write(): "
1678 "Invalid instruction length %d\n", dev->minor, insn->n);
1682 if (chan >= thisboard->ao_nchan) {
1684 "comedi%d: me4000: me4000_ao_insn_write(): "
1685 "Invalid channel %d\n", dev->minor, insn->n);
1691 "comedi%d: me4000: me4000_ao_insn_write(): "
1692 "Invalid range %d\n", dev->minor, insn->n);
1696 if (aref != AREF_GROUND && aref != AREF_COMMON) {
1698 "comedi%d: me4000: me4000_ao_insn_write(): "
1699 "Invalid aref %d\n", dev->minor, insn->n);
1703 /* Stop any running conversion */
1704 tmp = inl(info->ao_context[chan].ctrl_reg);
1705 tmp |= ME4000_AO_CTRL_BIT_IMMEDIATE_STOP;
1706 outl(tmp, info->ao_context[chan].ctrl_reg);
1708 /* Clear control register and set to single mode */
1709 outl(0x0, info->ao_context[chan].ctrl_reg);
1711 /* Write data value */
1712 outl(data[0], info->ao_context[chan].single_reg);
1714 /* Store in the mirror */
1715 info->ao_context[chan].mirror = data[0];
1720 static int me4000_ao_insn_read(struct comedi_device *dev,
1721 struct comedi_subdevice *s,
1722 struct comedi_insn *insn, unsigned int *data)
1724 int chan = CR_CHAN(insn->chanspec);
1728 } else if (insn->n > 1) {
1730 ("comedi%d: me4000: me4000_ao_insn_read(): "
1731 "Invalid instruction length\n", dev->minor);
1735 data[0] = info->ao_context[chan].mirror;
1740 /*=============================================================================
1742 ===========================================================================*/
1744 static int me4000_dio_insn_bits(struct comedi_device *dev,
1745 struct comedi_subdevice *s,
1746 struct comedi_insn *insn, unsigned int *data)
1749 * The insn data consists of a mask in data[0] and the new data
1750 * in data[1]. The mask defines which bits we are concerning about.
1751 * The new data must be anded with the mask.
1752 * Each channel corresponds to a bit.
1755 /* Check if requested ports are configured for output */
1756 if ((s->io_bits & data[0]) != data[0])
1759 s->state &= ~data[0];
1760 s->state |= data[0] & data[1];
1762 /* Write out the new digital output lines */
1763 outl((s->state >> 0) & 0xFF,
1764 info->dio_context.port_0_reg);
1765 outl((s->state >> 8) & 0xFF,
1766 info->dio_context.port_1_reg);
1767 outl((s->state >> 16) & 0xFF,
1768 info->dio_context.port_2_reg);
1769 outl((s->state >> 24) & 0xFF,
1770 info->dio_context.port_3_reg);
1773 /* On return, data[1] contains the value of
1774 the digital input and output lines. */
1775 data[1] = ((inl(info->dio_context.port_0_reg) & 0xFF) << 0) |
1776 ((inl(info->dio_context.port_1_reg) & 0xFF) << 8) |
1777 ((inl(info->dio_context.port_2_reg) & 0xFF) << 16) |
1778 ((inl(info->dio_context.port_3_reg) & 0xFF) << 24);
1783 static int me4000_dio_insn_config(struct comedi_device *dev,
1784 struct comedi_subdevice *s,
1785 struct comedi_insn *insn, unsigned int *data)
1788 int chan = CR_CHAN(insn->chanspec);
1793 case INSN_CONFIG_DIO_QUERY:
1795 (s->io_bits & (1 << chan)) ? COMEDI_OUTPUT : COMEDI_INPUT;
1797 case INSN_CONFIG_DIO_INPUT:
1798 case INSN_CONFIG_DIO_OUTPUT:
1803 * The input or output configuration of each digital line is
1804 * configured by a special insn_config instruction. chanspec
1805 * contains the channel to be changed, and data[0] contains the
1806 * value INSN_CONFIG_DIO_INPUT or INSN_CONFIG_DIO_OUTPUT.
1807 * On the ME-4000 it is only possible to switch port wise (8 bit)
1810 tmp = inl(info->dio_context.ctrl_reg);
1812 if (data[0] == INSN_CONFIG_DIO_OUTPUT) {
1815 tmp &= ~(ME4000_DIO_CTRL_BIT_MODE_0 |
1816 ME4000_DIO_CTRL_BIT_MODE_1);
1817 tmp |= ME4000_DIO_CTRL_BIT_MODE_0;
1818 } else if (chan < 16) {
1820 * Chech for optoisolated ME-4000 version.
1821 * If one the first port is a fixed output
1822 * port and the second is a fixed input port.
1824 if (!inl(info->dio_context.dir_reg))
1827 s->io_bits |= 0xFF00;
1828 tmp &= ~(ME4000_DIO_CTRL_BIT_MODE_2 |
1829 ME4000_DIO_CTRL_BIT_MODE_3);
1830 tmp |= ME4000_DIO_CTRL_BIT_MODE_2;
1831 } else if (chan < 24) {
1832 s->io_bits |= 0xFF0000;
1833 tmp &= ~(ME4000_DIO_CTRL_BIT_MODE_4 |
1834 ME4000_DIO_CTRL_BIT_MODE_5);
1835 tmp |= ME4000_DIO_CTRL_BIT_MODE_4;
1836 } else if (chan < 32) {
1837 s->io_bits |= 0xFF000000;
1838 tmp &= ~(ME4000_DIO_CTRL_BIT_MODE_6 |
1839 ME4000_DIO_CTRL_BIT_MODE_7);
1840 tmp |= ME4000_DIO_CTRL_BIT_MODE_6;
1847 * Chech for optoisolated ME-4000 version.
1848 * If one the first port is a fixed output
1849 * port and the second is a fixed input port.
1851 if (!inl(info->dio_context.dir_reg))
1854 s->io_bits &= ~0xFF;
1855 tmp &= ~(ME4000_DIO_CTRL_BIT_MODE_0 |
1856 ME4000_DIO_CTRL_BIT_MODE_1);
1857 } else if (chan < 16) {
1858 s->io_bits &= ~0xFF00;
1859 tmp &= ~(ME4000_DIO_CTRL_BIT_MODE_2 |
1860 ME4000_DIO_CTRL_BIT_MODE_3);
1861 } else if (chan < 24) {
1862 s->io_bits &= ~0xFF0000;
1863 tmp &= ~(ME4000_DIO_CTRL_BIT_MODE_4 |
1864 ME4000_DIO_CTRL_BIT_MODE_5);
1865 } else if (chan < 32) {
1866 s->io_bits &= ~0xFF000000;
1867 tmp &= ~(ME4000_DIO_CTRL_BIT_MODE_6 |
1868 ME4000_DIO_CTRL_BIT_MODE_7);
1874 outl(tmp, info->dio_context.ctrl_reg);
1879 /*=============================================================================
1881 ===========================================================================*/
1883 static int cnt_reset(struct comedi_device *dev, unsigned int channel)
1887 outb(0x30, info->timer_regbase + ME4000_CNT_CTRL_REG);
1888 outb(0x00, info->timer_regbase + ME4000_CNT_COUNTER_0_REG);
1889 outb(0x00, info->timer_regbase + ME4000_CNT_COUNTER_0_REG);
1892 outb(0x70, info->timer_regbase + ME4000_CNT_CTRL_REG);
1893 outb(0x00, info->timer_regbase + ME4000_CNT_COUNTER_1_REG);
1894 outb(0x00, info->timer_regbase + ME4000_CNT_COUNTER_1_REG);
1897 outb(0xB0, info->timer_regbase + ME4000_CNT_CTRL_REG);
1898 outb(0x00, info->timer_regbase + ME4000_CNT_COUNTER_2_REG);
1899 outb(0x00, info->timer_regbase + ME4000_CNT_COUNTER_2_REG);
1903 "comedi%d: me4000: cnt_reset(): Invalid channel\n",
1911 static int cnt_config(struct comedi_device *dev, unsigned int channel,
1918 tmp |= ME4000_CNT_COUNTER_0;
1921 tmp |= ME4000_CNT_COUNTER_1;
1924 tmp |= ME4000_CNT_COUNTER_2;
1928 "comedi%d: me4000: cnt_config(): Invalid channel\n",
1935 tmp |= ME4000_CNT_MODE_0;
1938 tmp |= ME4000_CNT_MODE_1;
1941 tmp |= ME4000_CNT_MODE_2;
1944 tmp |= ME4000_CNT_MODE_3;
1947 tmp |= ME4000_CNT_MODE_4;
1950 tmp |= ME4000_CNT_MODE_5;
1954 "comedi%d: me4000: cnt_config(): Invalid counter mode\n",
1959 /* Write the control word */
1961 outb(tmp, info->timer_regbase + ME4000_CNT_CTRL_REG);
1966 static int me4000_cnt_insn_config(struct comedi_device *dev,
1967 struct comedi_subdevice *s,
1968 struct comedi_insn *insn, unsigned int *data)
1977 "comedi%d: me4000: me4000_cnt_insn_config(): "
1978 "Invalid instruction length%d\n",
1979 dev->minor, insn->n);
1983 err = cnt_reset(dev, insn->chanspec);
1987 case GPCT_SET_OPERATION:
1990 "comedi%d: me4000: me4000_cnt_insn_config(): "
1991 "Invalid instruction length%d\n",
1992 dev->minor, insn->n);
1996 err = cnt_config(dev, insn->chanspec, data[1]);
2002 "comedi%d: me4000: me4000_cnt_insn_config(): "
2003 "Invalid instruction\n", dev->minor);
2010 static int me4000_cnt_insn_read(struct comedi_device *dev,
2011 struct comedi_subdevice *s,
2012 struct comedi_insn *insn, unsigned int *data)
2022 "comedi%d: me4000: me4000_cnt_insn_read(): "
2023 "Invalid instruction length %d\n",
2024 dev->minor, insn->n);
2028 switch (insn->chanspec) {
2030 tmp = inb(info->timer_regbase + ME4000_CNT_COUNTER_0_REG);
2032 tmp = inb(info->timer_regbase + ME4000_CNT_COUNTER_0_REG);
2033 data[0] |= tmp << 8;
2036 tmp = inb(info->timer_regbase + ME4000_CNT_COUNTER_1_REG);
2038 tmp = inb(info->timer_regbase + ME4000_CNT_COUNTER_1_REG);
2039 data[0] |= tmp << 8;
2042 tmp = inb(info->timer_regbase + ME4000_CNT_COUNTER_2_REG);
2044 tmp = inb(info->timer_regbase + ME4000_CNT_COUNTER_2_REG);
2045 data[0] |= tmp << 8;
2049 "comedi%d: me4000: me4000_cnt_insn_read(): "
2050 "Invalid channel %d\n",
2051 dev->minor, insn->chanspec);
2058 static int me4000_cnt_insn_write(struct comedi_device *dev,
2059 struct comedi_subdevice *s,
2060 struct comedi_insn *insn, unsigned int *data)
2067 } else if (insn->n > 1) {
2069 "comedi%d: me4000: me4000_cnt_insn_write(): "
2070 "Invalid instruction length %d\n",
2071 dev->minor, insn->n);
2075 switch (insn->chanspec) {
2077 tmp = data[0] & 0xFF;
2078 outb(tmp, info->timer_regbase + ME4000_CNT_COUNTER_0_REG);
2079 tmp = (data[0] >> 8) & 0xFF;
2080 outb(tmp, info->timer_regbase + ME4000_CNT_COUNTER_0_REG);
2083 tmp = data[0] & 0xFF;
2084 outb(tmp, info->timer_regbase + ME4000_CNT_COUNTER_1_REG);
2085 tmp = (data[0] >> 8) & 0xFF;
2086 outb(tmp, info->timer_regbase + ME4000_CNT_COUNTER_1_REG);
2089 tmp = data[0] & 0xFF;
2090 outb(tmp, info->timer_regbase + ME4000_CNT_COUNTER_2_REG);
2091 tmp = (data[0] >> 8) & 0xFF;
2092 outb(tmp, info->timer_regbase + ME4000_CNT_COUNTER_2_REG);
2096 "comedi%d: me4000: me4000_cnt_insn_write(): "
2097 "Invalid channel %d\n",
2098 dev->minor, insn->chanspec);
2105 static int me4000_attach(struct comedi_device *dev, struct comedi_devconfig *it)
2107 const struct me4000_board *thisboard;
2108 struct comedi_subdevice *s;
2111 result = me4000_probe(dev, it);
2114 thisboard = comedi_board(dev);
2116 result = comedi_alloc_subdevices(dev, 4);
2120 /*=========================================================================
2121 Analog input subdevice
2122 ========================================================================*/
2124 s = &dev->subdevices[0];
2126 if (thisboard->ai_nchan) {
2127 s->type = COMEDI_SUBD_AI;
2129 SDF_READABLE | SDF_COMMON | SDF_GROUND | SDF_DIFF;
2130 s->n_chan = thisboard->ai_nchan;
2131 s->maxdata = 0xFFFF; /* 16 bit ADC */
2132 s->len_chanlist = ME4000_AI_CHANNEL_LIST_COUNT;
2133 s->range_table = &me4000_ai_range;
2134 s->insn_read = me4000_ai_insn_read;
2136 if (info->irq > 0) {
2137 if (request_irq(info->irq, me4000_ai_isr,
2138 IRQF_SHARED, "ME-4000", dev)) {
2140 ("comedi%d: me4000: me4000_attach(): "
2141 "Unable to allocate irq\n", dev->minor);
2143 dev->read_subdev = s;
2144 s->subdev_flags |= SDF_CMD_READ;
2145 s->cancel = me4000_ai_cancel;
2146 s->do_cmdtest = me4000_ai_do_cmd_test;
2147 s->do_cmd = me4000_ai_do_cmd;
2151 "comedi%d: me4000: me4000_attach(): "
2152 "No interrupt available\n", dev->minor);
2155 s->type = COMEDI_SUBD_UNUSED;
2158 /*=========================================================================
2159 Analog output subdevice
2160 ========================================================================*/
2162 s = &dev->subdevices[1];
2164 if (thisboard->ao_nchan) {
2165 s->type = COMEDI_SUBD_AO;
2166 s->subdev_flags = SDF_WRITEABLE | SDF_COMMON | SDF_GROUND;
2167 s->n_chan = thisboard->ao_nchan;
2168 s->maxdata = 0xFFFF; /* 16 bit DAC */
2169 s->range_table = &me4000_ao_range;
2170 s->insn_write = me4000_ao_insn_write;
2171 s->insn_read = me4000_ao_insn_read;
2173 s->type = COMEDI_SUBD_UNUSED;
2176 /*=========================================================================
2177 Digital I/O subdevice
2178 ========================================================================*/
2180 s = &dev->subdevices[2];
2182 if (thisboard->dio_nchan) {
2183 s->type = COMEDI_SUBD_DIO;
2184 s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
2185 s->n_chan = thisboard->dio_nchan;
2187 s->range_table = &range_digital;
2188 s->insn_bits = me4000_dio_insn_bits;
2189 s->insn_config = me4000_dio_insn_config;
2191 s->type = COMEDI_SUBD_UNUSED;
2195 * Check for optoisolated ME-4000 version. If one the first
2196 * port is a fixed output port and the second is a fixed input port.
2198 if (!inl(info->dio_context.dir_reg)) {
2200 outl(ME4000_DIO_CTRL_BIT_MODE_0, info->dio_context.dir_reg);
2203 /*=========================================================================
2205 ========================================================================*/
2207 s = &dev->subdevices[3];
2209 if (thisboard->has_counter) {
2210 s->type = COMEDI_SUBD_COUNTER;
2211 s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
2213 s->maxdata = 0xFFFF; /* 16 bit counters */
2214 s->insn_read = me4000_cnt_insn_read;
2215 s->insn_write = me4000_cnt_insn_write;
2216 s->insn_config = me4000_cnt_insn_config;
2218 s->type = COMEDI_SUBD_UNUSED;
2224 static void me4000_detach(struct comedi_device *dev)
2227 if (info->pci_dev_p) {
2229 if (info->plx_regbase)
2230 comedi_pci_disable(info->pci_dev_p);
2231 pci_dev_put(info->pci_dev_p);
2236 static struct comedi_driver me4000_driver = {
2237 .driver_name = "me4000",
2238 .module = THIS_MODULE,
2239 .attach = me4000_attach,
2240 .detach = me4000_detach,
2243 static int __devinit me4000_pci_probe(struct pci_dev *dev,
2244 const struct pci_device_id *ent)
2246 return comedi_pci_auto_config(dev, &me4000_driver);
2249 static void __devexit me4000_pci_remove(struct pci_dev *dev)
2251 comedi_pci_auto_unconfig(dev);
2254 static DEFINE_PCI_DEVICE_TABLE(me4000_pci_table) = {
2255 {PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4650)},
2256 {PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4660)},
2257 {PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4660I)},
2258 {PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4660S)},
2259 {PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4660IS)},
2260 {PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4670)},
2261 {PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4670I)},
2262 {PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4670S)},
2263 {PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4670IS)},
2264 {PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4680)},
2265 {PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4680I)},
2266 {PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4680S)},
2267 {PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4680IS)},
2270 MODULE_DEVICE_TABLE(pci, me4000_pci_table);
2272 static struct pci_driver me4000_pci_driver = {
2274 .id_table = me4000_pci_table,
2275 .probe = me4000_pci_probe,
2276 .remove = __devexit_p(me4000_pci_remove),
2278 module_comedi_pci_driver(me4000_driver, me4000_pci_driver);
2280 MODULE_AUTHOR("Comedi http://www.comedi.org");
2281 MODULE_DESCRIPTION("Comedi low-level driver");
2282 MODULE_LICENSE("GPL");