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 static const struct me4000_board me4000_boards[] = {
68 {"ME-4650", 0x4650, {0, 0}, {16, 0, 0, 0}, {4}, {0} },
70 {"ME-4660", 0x4660, {0, 0}, {32, 0, 16, 0}, {4}, {3} },
71 {"ME-4660i", 0x4661, {0, 0}, {32, 0, 16, 0}, {4}, {3} },
72 {"ME-4660s", 0x4662, {0, 0}, {32, 8, 16, 0}, {4}, {3} },
73 {"ME-4660is", 0x4663, {0, 0}, {32, 8, 16, 0}, {4}, {3} },
75 {"ME-4670", 0x4670, {4, 0}, {32, 0, 16, 1}, {4}, {3} },
76 {"ME-4670i", 0x4671, {4, 0}, {32, 0, 16, 1}, {4}, {3} },
77 {"ME-4670s", 0x4672, {4, 0}, {32, 8, 16, 1}, {4}, {3} },
78 {"ME-4670is", 0x4673, {4, 0}, {32, 8, 16, 1}, {4}, {3} },
80 {"ME-4680", 0x4680, {4, 4}, {32, 0, 16, 1}, {4}, {3} },
81 {"ME-4680i", 0x4681, {4, 4}, {32, 0, 16, 1}, {4}, {3} },
82 {"ME-4680s", 0x4682, {4, 4}, {32, 8, 16, 1}, {4}, {3} },
83 {"ME-4680is", 0x4683, {4, 4}, {32, 8, 16, 1}, {4}, {3} },
88 #define ME4000_BOARD_VERSIONS (ARRAY_SIZE(me4000_boards) - 1)
90 /*-----------------------------------------------------------------------------
91 Meilhaus function prototypes
92 ---------------------------------------------------------------------------*/
93 static int get_registers(struct comedi_device *dev, struct pci_dev *pci_dev_p);
94 static int init_board_info(struct comedi_device *dev,
95 struct pci_dev *pci_dev_p);
96 static int init_ao_context(struct comedi_device *dev);
97 static int init_ai_context(struct comedi_device *dev);
98 static int init_dio_context(struct comedi_device *dev);
99 static int init_cnt_context(struct comedi_device *dev);
100 static int xilinx_download(struct comedi_device *dev);
101 static int reset_board(struct comedi_device *dev);
103 static int ai_write_chanlist(struct comedi_device *dev,
104 struct comedi_subdevice *s,
105 struct comedi_cmd *cmd);
107 static const struct comedi_lrange me4000_ai_range = {
117 static const struct comedi_lrange me4000_ao_range = {
124 static int me4000_probe(struct comedi_device *dev, struct comedi_devconfig *it)
126 struct pci_dev *pci_device = NULL;
128 struct me4000_board *board;
130 /* Allocate private memory */
131 if (alloc_private(dev, sizeof(struct me4000_info)) < 0)
135 * Probe the device to determine what device in the series it is.
137 for_each_pci_dev(pci_device) {
138 if (pci_device->vendor == PCI_VENDOR_ID_MEILHAUS) {
139 for (i = 0; i < ME4000_BOARD_VERSIONS; i++) {
140 if (me4000_boards[i].device_id ==
141 pci_device->device) {
144 * bus/slot requested?
146 if ((it->options[0] != 0)
147 || (it->options[1] != 0)) {
149 * Are we on the wrong
152 if (pci_device->bus->number !=
155 PCI_SLOT(pci_device->devfn)
160 dev->board_ptr = me4000_boards + i;
162 (struct me4000_board *)
164 info->pci_dev_p = pci_device;
172 "comedi%d: me4000: me4000_probe(): "
173 "No supported board found (req. bus/slot : %d/%d)\n",
174 dev->minor, it->options[0], it->options[1]);
180 "comedi%d: me4000: me4000_probe(): "
181 "Found %s at PCI bus %d, slot %d\n",
182 dev->minor, me4000_boards[i].name, pci_device->bus->number,
183 PCI_SLOT(pci_device->devfn));
185 /* Set data in device structure */
186 dev->board_name = board->name;
188 /* Enable PCI device and request regions */
189 result = comedi_pci_enable(pci_device, dev->board_name);
192 "comedi%d: me4000: me4000_probe(): Cannot enable PCI "
193 "device and request I/O regions\n", dev->minor);
197 /* Get the PCI base registers */
198 result = get_registers(dev, pci_device);
201 "comedi%d: me4000: me4000_probe(): "
202 "Cannot get registers\n", dev->minor);
205 /* Initialize board info */
206 result = init_board_info(dev, pci_device);
209 "comedi%d: me4000: me4000_probe(): "
210 "Cannot init baord info\n", dev->minor);
214 /* Init analog output context */
215 result = init_ao_context(dev);
218 "comedi%d: me4000: me4000_probe(): "
219 "Cannot init ao context\n", dev->minor);
223 /* Init analog input context */
224 result = init_ai_context(dev);
227 "comedi%d: me4000: me4000_probe(): "
228 "Cannot init ai context\n", dev->minor);
232 /* Init digital I/O context */
233 result = init_dio_context(dev);
236 "comedi%d: me4000: me4000_probe(): "
237 "Cannot init dio context\n", dev->minor);
241 /* Init counter context */
242 result = init_cnt_context(dev);
245 "comedi%d: me4000: me4000_probe(): "
246 "Cannot init cnt context\n", dev->minor);
250 /* Download the xilinx firmware */
251 result = xilinx_download(dev);
254 "comedi%d: me4000: me4000_probe(): "
255 "Can't download firmware\n", dev->minor);
259 /* Make a hardware reset */
260 result = reset_board(dev);
263 "comedi%d: me4000: me4000_probe(): Can't reset board\n",
271 static int get_registers(struct comedi_device *dev, struct pci_dev *pci_dev_p)
273 /*--------------------------- plx regbase -------------------------------*/
275 info->plx_regbase = pci_resource_start(pci_dev_p, 1);
276 if (info->plx_regbase == 0) {
278 "comedi%d: me4000: get_registers(): "
279 "PCI base address 1 is not available\n", dev->minor);
282 info->plx_regbase_size = pci_resource_len(pci_dev_p, 1);
284 /*--------------------------- me4000 regbase ----------------------------*/
286 info->me4000_regbase = pci_resource_start(pci_dev_p, 2);
287 if (info->me4000_regbase == 0) {
289 "comedi%d: me4000: get_registers(): "
290 "PCI base address 2 is not available\n", dev->minor);
293 info->me4000_regbase_size = pci_resource_len(pci_dev_p, 2);
295 /*--------------------------- timer regbase ------------------------------*/
297 info->timer_regbase = pci_resource_start(pci_dev_p, 3);
298 if (info->timer_regbase == 0) {
300 "comedi%d: me4000: get_registers(): "
301 "PCI base address 3 is not available\n", dev->minor);
304 info->timer_regbase_size = pci_resource_len(pci_dev_p, 3);
306 /*--------------------------- program regbase ----------------------------*/
308 info->program_regbase = pci_resource_start(pci_dev_p, 5);
309 if (info->program_regbase == 0) {
311 "comedi%d: me4000: get_registers(): "
312 "PCI base address 5 is not available\n", dev->minor);
315 info->program_regbase_size = pci_resource_len(pci_dev_p, 5);
320 static int init_board_info(struct comedi_device *dev, struct pci_dev *pci_dev_p)
324 /* Init spin locks */
325 /* spin_lock_init(&info->preload_lock); */
326 /* spin_lock_init(&info->ai_ctrl_lock); */
328 /* Get the serial number */
329 result = pci_read_config_dword(pci_dev_p, 0x2C, &info->serial_no);
330 if (result != PCIBIOS_SUCCESSFUL)
333 /* Get the hardware revision */
334 result = pci_read_config_byte(pci_dev_p, 0x08, &info->hw_revision);
335 if (result != PCIBIOS_SUCCESSFUL)
338 /* Get the vendor id */
339 info->vendor_id = pci_dev_p->vendor;
341 /* Get the device id */
342 info->device_id = pci_dev_p->device;
344 /* Get the irq assigned to the board */
345 info->irq = pci_dev_p->irq;
350 static int init_ao_context(struct comedi_device *dev)
354 for (i = 0; i < thisboard->ao.count; i++) {
355 /* spin_lock_init(&info->ao_context[i].use_lock); */
356 info->ao_context[i].irq = info->irq;
360 info->ao_context[i].ctrl_reg =
361 info->me4000_regbase + ME4000_AO_00_CTRL_REG;
362 info->ao_context[i].status_reg =
363 info->me4000_regbase + ME4000_AO_00_STATUS_REG;
364 info->ao_context[i].fifo_reg =
365 info->me4000_regbase + ME4000_AO_00_FIFO_REG;
366 info->ao_context[i].single_reg =
367 info->me4000_regbase + ME4000_AO_00_SINGLE_REG;
368 info->ao_context[i].timer_reg =
369 info->me4000_regbase + ME4000_AO_00_TIMER_REG;
370 info->ao_context[i].irq_status_reg =
371 info->me4000_regbase + ME4000_IRQ_STATUS_REG;
372 info->ao_context[i].preload_reg =
373 info->me4000_regbase + ME4000_AO_LOADSETREG_XX;
376 info->ao_context[i].ctrl_reg =
377 info->me4000_regbase + ME4000_AO_01_CTRL_REG;
378 info->ao_context[i].status_reg =
379 info->me4000_regbase + ME4000_AO_01_STATUS_REG;
380 info->ao_context[i].fifo_reg =
381 info->me4000_regbase + ME4000_AO_01_FIFO_REG;
382 info->ao_context[i].single_reg =
383 info->me4000_regbase + ME4000_AO_01_SINGLE_REG;
384 info->ao_context[i].timer_reg =
385 info->me4000_regbase + ME4000_AO_01_TIMER_REG;
386 info->ao_context[i].irq_status_reg =
387 info->me4000_regbase + ME4000_IRQ_STATUS_REG;
388 info->ao_context[i].preload_reg =
389 info->me4000_regbase + ME4000_AO_LOADSETREG_XX;
392 info->ao_context[i].ctrl_reg =
393 info->me4000_regbase + ME4000_AO_02_CTRL_REG;
394 info->ao_context[i].status_reg =
395 info->me4000_regbase + ME4000_AO_02_STATUS_REG;
396 info->ao_context[i].fifo_reg =
397 info->me4000_regbase + ME4000_AO_02_FIFO_REG;
398 info->ao_context[i].single_reg =
399 info->me4000_regbase + ME4000_AO_02_SINGLE_REG;
400 info->ao_context[i].timer_reg =
401 info->me4000_regbase + ME4000_AO_02_TIMER_REG;
402 info->ao_context[i].irq_status_reg =
403 info->me4000_regbase + ME4000_IRQ_STATUS_REG;
404 info->ao_context[i].preload_reg =
405 info->me4000_regbase + ME4000_AO_LOADSETREG_XX;
408 info->ao_context[i].ctrl_reg =
409 info->me4000_regbase + ME4000_AO_03_CTRL_REG;
410 info->ao_context[i].status_reg =
411 info->me4000_regbase + ME4000_AO_03_STATUS_REG;
412 info->ao_context[i].fifo_reg =
413 info->me4000_regbase + ME4000_AO_03_FIFO_REG;
414 info->ao_context[i].single_reg =
415 info->me4000_regbase + ME4000_AO_03_SINGLE_REG;
416 info->ao_context[i].timer_reg =
417 info->me4000_regbase + ME4000_AO_03_TIMER_REG;
418 info->ao_context[i].irq_status_reg =
419 info->me4000_regbase + ME4000_IRQ_STATUS_REG;
420 info->ao_context[i].preload_reg =
421 info->me4000_regbase + ME4000_AO_LOADSETREG_XX;
431 static int init_ai_context(struct comedi_device *dev)
433 info->ai_context.irq = info->irq;
435 info->ai_context.ctrl_reg = info->me4000_regbase + ME4000_AI_CTRL_REG;
436 info->ai_context.status_reg =
437 info->me4000_regbase + ME4000_AI_STATUS_REG;
438 info->ai_context.channel_list_reg =
439 info->me4000_regbase + ME4000_AI_CHANNEL_LIST_REG;
440 info->ai_context.data_reg = info->me4000_regbase + ME4000_AI_DATA_REG;
441 info->ai_context.chan_timer_reg =
442 info->me4000_regbase + ME4000_AI_CHAN_TIMER_REG;
443 info->ai_context.chan_pre_timer_reg =
444 info->me4000_regbase + ME4000_AI_CHAN_PRE_TIMER_REG;
445 info->ai_context.scan_timer_low_reg =
446 info->me4000_regbase + ME4000_AI_SCAN_TIMER_LOW_REG;
447 info->ai_context.scan_timer_high_reg =
448 info->me4000_regbase + ME4000_AI_SCAN_TIMER_HIGH_REG;
449 info->ai_context.scan_pre_timer_low_reg =
450 info->me4000_regbase + ME4000_AI_SCAN_PRE_TIMER_LOW_REG;
451 info->ai_context.scan_pre_timer_high_reg =
452 info->me4000_regbase + ME4000_AI_SCAN_PRE_TIMER_HIGH_REG;
453 info->ai_context.start_reg = info->me4000_regbase + ME4000_AI_START_REG;
454 info->ai_context.irq_status_reg =
455 info->me4000_regbase + ME4000_IRQ_STATUS_REG;
456 info->ai_context.sample_counter_reg =
457 info->me4000_regbase + ME4000_AI_SAMPLE_COUNTER_REG;
462 static int init_dio_context(struct comedi_device *dev)
464 info->dio_context.dir_reg = info->me4000_regbase + ME4000_DIO_DIR_REG;
465 info->dio_context.ctrl_reg = info->me4000_regbase + ME4000_DIO_CTRL_REG;
466 info->dio_context.port_0_reg =
467 info->me4000_regbase + ME4000_DIO_PORT_0_REG;
468 info->dio_context.port_1_reg =
469 info->me4000_regbase + ME4000_DIO_PORT_1_REG;
470 info->dio_context.port_2_reg =
471 info->me4000_regbase + ME4000_DIO_PORT_2_REG;
472 info->dio_context.port_3_reg =
473 info->me4000_regbase + ME4000_DIO_PORT_3_REG;
478 static int init_cnt_context(struct comedi_device *dev)
480 info->cnt_context.ctrl_reg = info->timer_regbase + ME4000_CNT_CTRL_REG;
481 info->cnt_context.counter_0_reg =
482 info->timer_regbase + ME4000_CNT_COUNTER_0_REG;
483 info->cnt_context.counter_1_reg =
484 info->timer_regbase + ME4000_CNT_COUNTER_1_REG;
485 info->cnt_context.counter_2_reg =
486 info->timer_regbase + ME4000_CNT_COUNTER_2_REG;
491 #define FIRMWARE_NOT_AVAILABLE 1
492 #if FIRMWARE_NOT_AVAILABLE
493 extern unsigned char *xilinx_firm;
496 static int xilinx_download(struct comedi_device *dev)
499 wait_queue_head_t queue;
503 init_waitqueue_head(&queue);
506 * Set PLX local interrupt 2 polarity to high.
507 * Interrupt is thrown by init pin of xilinx.
509 outl(0x10, info->plx_regbase + PLX_INTCSR);
511 /* Set /CS and /WRITE of the Xilinx */
512 value = inl(info->plx_regbase + PLX_ICR);
514 outl(value, info->plx_regbase + PLX_ICR);
516 /* Init Xilinx with CS1 */
517 inb(info->program_regbase + 0xC8);
519 /* Wait until /INIT pin is set */
521 if (!(inl(info->plx_regbase + PLX_INTCSR) & 0x20)) {
523 "comedi%d: me4000: xilinx_download(): "
524 "Can't init Xilinx\n", dev->minor);
528 /* Reset /CS and /WRITE of the Xilinx */
529 value = inl(info->plx_regbase + PLX_ICR);
531 outl(value, info->plx_regbase + PLX_ICR);
532 if (FIRMWARE_NOT_AVAILABLE) {
533 comedi_error(dev, "xilinx firmware unavailable "
534 "due to licensing, aborting");
537 /* Download Xilinx firmware */
538 size = (xilinx_firm[0] << 24) + (xilinx_firm[1] << 16) +
539 (xilinx_firm[2] << 8) + xilinx_firm[3];
542 for (idx = 0; idx < size; idx++) {
543 outb(xilinx_firm[16 + idx], info->program_regbase);
546 /* Check if BUSY flag is low */
547 if (inl(info->plx_regbase + PLX_ICR) & 0x20) {
549 "comedi%d: me4000: xilinx_download(): "
550 "Xilinx is still busy (idx = %d)\n",
557 /* If done flag is high download was successful */
558 if (inl(info->plx_regbase + PLX_ICR) & 0x4) {
561 "comedi%d: me4000: xilinx_download(): "
562 "DONE flag is not set\n", dev->minor);
564 "comedi%d: me4000: xilinx_download(): "
565 "Download not successful\n", dev->minor);
569 /* Set /CS and /WRITE */
570 value = inl(info->plx_regbase + PLX_ICR);
572 outl(value, info->plx_regbase + PLX_ICR);
577 static int reset_board(struct comedi_device *dev)
581 /* Make a hardware reset */
582 icr = inl(info->plx_regbase + PLX_ICR);
584 outl(icr, info->plx_regbase + PLX_ICR);
586 outl(icr, info->plx_regbase + PLX_ICR);
588 /* 0x8000 to the DACs means an output voltage of 0V */
589 outl(0x8000, info->me4000_regbase + ME4000_AO_00_SINGLE_REG);
590 outl(0x8000, info->me4000_regbase + ME4000_AO_01_SINGLE_REG);
591 outl(0x8000, info->me4000_regbase + ME4000_AO_02_SINGLE_REG);
592 outl(0x8000, info->me4000_regbase + ME4000_AO_03_SINGLE_REG);
594 /* Set both stop bits in the analog input control register */
595 outl(ME4000_AI_CTRL_BIT_IMMEDIATE_STOP | ME4000_AI_CTRL_BIT_STOP,
596 info->me4000_regbase + ME4000_AI_CTRL_REG);
598 /* Set both stop bits in the analog output control register */
599 outl(ME4000_AO_CTRL_BIT_IMMEDIATE_STOP | ME4000_AO_CTRL_BIT_STOP,
600 info->me4000_regbase + ME4000_AO_00_CTRL_REG);
601 outl(ME4000_AO_CTRL_BIT_IMMEDIATE_STOP | ME4000_AO_CTRL_BIT_STOP,
602 info->me4000_regbase + ME4000_AO_01_CTRL_REG);
603 outl(ME4000_AO_CTRL_BIT_IMMEDIATE_STOP | ME4000_AO_CTRL_BIT_STOP,
604 info->me4000_regbase + ME4000_AO_02_CTRL_REG);
605 outl(ME4000_AO_CTRL_BIT_IMMEDIATE_STOP | ME4000_AO_CTRL_BIT_STOP,
606 info->me4000_regbase + ME4000_AO_03_CTRL_REG);
608 /* Enable interrupts on the PLX */
609 outl(0x43, info->plx_regbase + PLX_INTCSR);
611 /* Set the adustment register for AO demux */
612 outl(ME4000_AO_DEMUX_ADJUST_VALUE,
613 info->me4000_regbase + ME4000_AO_DEMUX_ADJUST_REG);
616 * Set digital I/O direction for port 0
617 * to output on isolated versions
619 if (!(inl(info->me4000_regbase + ME4000_DIO_DIR_REG) & 0x1))
620 outl(0x1, info->me4000_regbase + ME4000_DIO_CTRL_REG);
625 /*=============================================================================
627 ===========================================================================*/
629 static int me4000_ai_insn_read(struct comedi_device *dev,
630 struct comedi_subdevice *subdevice,
631 struct comedi_insn *insn, unsigned int *data)
634 int chan = CR_CHAN(insn->chanspec);
635 int rang = CR_RANGE(insn->chanspec);
636 int aref = CR_AREF(insn->chanspec);
638 unsigned long entry = 0;
644 } else if (insn->n > 1) {
646 "comedi%d: me4000: me4000_ai_insn_read(): "
647 "Invalid instruction length %d\n", dev->minor, insn->n);
653 entry |= ME4000_AI_LIST_RANGE_UNIPOLAR_2_5;
656 entry |= ME4000_AI_LIST_RANGE_UNIPOLAR_10;
659 entry |= ME4000_AI_LIST_RANGE_BIPOLAR_2_5;
662 entry |= ME4000_AI_LIST_RANGE_BIPOLAR_10;
666 "comedi%d: me4000: me4000_ai_insn_read(): "
667 "Invalid range specified\n", dev->minor);
674 if (chan >= thisboard->ai.count) {
676 "comedi%d: me4000: me4000_ai_insn_read(): "
677 "Analog input is not available\n", dev->minor);
680 entry |= ME4000_AI_LIST_INPUT_SINGLE_ENDED | chan;
684 if (rang == 0 || rang == 1) {
686 "comedi%d: me4000: me4000_ai_insn_read(): "
687 "Range must be bipolar when aref = diff\n",
692 if (chan >= thisboard->ai.diff_count) {
694 "comedi%d: me4000: me4000_ai_insn_read(): "
695 "Analog input is not available\n", dev->minor);
698 entry |= ME4000_AI_LIST_INPUT_DIFFERENTIAL | chan;
702 "comedi%d: me4000: me4000_ai_insn_read(): "
703 "Invalid aref specified\n", dev->minor);
707 entry |= ME4000_AI_LIST_LAST_ENTRY;
709 /* Clear channel list, data fifo and both stop bits */
710 tmp = inl(info->ai_context.ctrl_reg);
711 tmp &= ~(ME4000_AI_CTRL_BIT_CHANNEL_FIFO |
712 ME4000_AI_CTRL_BIT_DATA_FIFO |
713 ME4000_AI_CTRL_BIT_STOP | ME4000_AI_CTRL_BIT_IMMEDIATE_STOP);
714 outl(tmp, info->ai_context.ctrl_reg);
716 /* Set the acquisition mode to single */
717 tmp &= ~(ME4000_AI_CTRL_BIT_MODE_0 | ME4000_AI_CTRL_BIT_MODE_1 |
718 ME4000_AI_CTRL_BIT_MODE_2);
719 outl(tmp, info->ai_context.ctrl_reg);
721 /* Enable channel list and data fifo */
722 tmp |= ME4000_AI_CTRL_BIT_CHANNEL_FIFO | ME4000_AI_CTRL_BIT_DATA_FIFO;
723 outl(tmp, info->ai_context.ctrl_reg);
725 /* Generate channel list entry */
726 outl(entry, info->ai_context.channel_list_reg);
728 /* Set the timer to maximum sample rate */
729 outl(ME4000_AI_MIN_TICKS, info->ai_context.chan_timer_reg);
730 outl(ME4000_AI_MIN_TICKS, info->ai_context.chan_pre_timer_reg);
732 /* Start conversion by dummy read */
733 inl(info->ai_context.start_reg);
735 /* Wait until ready */
737 if (!(inl(info->ai_context.status_reg) &
738 ME4000_AI_STATUS_BIT_EF_DATA)) {
740 "comedi%d: me4000: me4000_ai_insn_read(): "
741 "Value not available after wait\n", dev->minor);
745 /* Read value from data fifo */
746 lval = inl(info->ai_context.data_reg) & 0xFFFF;
747 data[0] = lval ^ 0x8000;
752 static int me4000_ai_cancel(struct comedi_device *dev,
753 struct comedi_subdevice *s)
757 /* Stop any running conversion */
758 tmp = inl(info->ai_context.ctrl_reg);
759 tmp &= ~(ME4000_AI_CTRL_BIT_STOP | ME4000_AI_CTRL_BIT_IMMEDIATE_STOP);
760 outl(tmp, info->ai_context.ctrl_reg);
762 /* Clear the control register */
763 outl(0x0, info->ai_context.ctrl_reg);
768 static int ai_check_chanlist(struct comedi_device *dev,
769 struct comedi_subdevice *s, struct comedi_cmd *cmd)
774 /* Check whether a channel list is available */
775 if (!cmd->chanlist_len) {
777 "comedi%d: me4000: ai_check_chanlist(): "
778 "No channel list available\n", dev->minor);
782 /* Check the channel list size */
783 if (cmd->chanlist_len > ME4000_AI_CHANNEL_LIST_COUNT) {
785 "comedi%d: me4000: ai_check_chanlist(): "
786 "Channel list is to large\n", dev->minor);
790 /* Check the pointer */
791 if (!cmd->chanlist) {
793 "comedi%d: me4000: ai_check_chanlist(): "
794 "NULL pointer to channel list\n", dev->minor);
798 /* Check whether aref is equal for all entries */
799 aref = CR_AREF(cmd->chanlist[0]);
800 for (i = 0; i < cmd->chanlist_len; i++) {
801 if (CR_AREF(cmd->chanlist[i]) != aref) {
803 "comedi%d: me4000: ai_check_chanlist(): "
804 "Mode is not equal for all entries\n",
810 /* Check whether channels are available for this ending */
811 if (aref == SDF_DIFF) {
812 for (i = 0; i < cmd->chanlist_len; i++) {
813 if (CR_CHAN(cmd->chanlist[i]) >=
814 thisboard->ai.diff_count) {
816 "comedi%d: me4000: ai_check_chanlist():"
817 " Channel number to high\n", dev->minor);
822 for (i = 0; i < cmd->chanlist_len; i++) {
823 if (CR_CHAN(cmd->chanlist[i]) >= thisboard->ai.count) {
825 "comedi%d: me4000: ai_check_chanlist(): "
826 "Channel number to high\n", dev->minor);
832 /* Check if bipolar is set for all entries when in differential mode */
833 if (aref == SDF_DIFF) {
834 for (i = 0; i < cmd->chanlist_len; i++) {
835 if (CR_RANGE(cmd->chanlist[i]) != 1 &&
836 CR_RANGE(cmd->chanlist[i]) != 2) {
838 "comedi%d: me4000: ai_check_chanlist(): "
839 "Bipolar is not selected in "
840 "differential mode\n",
850 static int ai_round_cmd_args(struct comedi_device *dev,
851 struct comedi_subdevice *s,
852 struct comedi_cmd *cmd,
853 unsigned int *init_ticks,
854 unsigned int *scan_ticks, unsigned int *chan_ticks)
863 if (cmd->start_arg) {
864 *init_ticks = (cmd->start_arg * 33) / 1000;
865 rest = (cmd->start_arg * 33) % 1000;
867 if ((cmd->flags & TRIG_ROUND_MASK) == TRIG_ROUND_NEAREST) {
870 } else if ((cmd->flags & TRIG_ROUND_MASK) == TRIG_ROUND_UP) {
876 if (cmd->scan_begin_arg) {
877 *scan_ticks = (cmd->scan_begin_arg * 33) / 1000;
878 rest = (cmd->scan_begin_arg * 33) % 1000;
880 if ((cmd->flags & TRIG_ROUND_MASK) == TRIG_ROUND_NEAREST) {
883 } else if ((cmd->flags & TRIG_ROUND_MASK) == TRIG_ROUND_UP) {
889 if (cmd->convert_arg) {
890 *chan_ticks = (cmd->convert_arg * 33) / 1000;
891 rest = (cmd->convert_arg * 33) % 1000;
893 if ((cmd->flags & TRIG_ROUND_MASK) == TRIG_ROUND_NEAREST) {
896 } else if ((cmd->flags & TRIG_ROUND_MASK) == TRIG_ROUND_UP) {
905 static void ai_write_timer(struct comedi_device *dev,
906 unsigned int init_ticks,
907 unsigned int scan_ticks, unsigned int chan_ticks)
909 outl(init_ticks - 1, info->ai_context.scan_pre_timer_low_reg);
910 outl(0x0, info->ai_context.scan_pre_timer_high_reg);
913 outl(scan_ticks - 1, info->ai_context.scan_timer_low_reg);
914 outl(0x0, info->ai_context.scan_timer_high_reg);
917 outl(chan_ticks - 1, info->ai_context.chan_pre_timer_reg);
918 outl(chan_ticks - 1, info->ai_context.chan_timer_reg);
921 static int ai_prepare(struct comedi_device *dev,
922 struct comedi_subdevice *s,
923 struct comedi_cmd *cmd,
924 unsigned int init_ticks,
925 unsigned int scan_ticks, unsigned int chan_ticks)
928 unsigned long tmp = 0;
930 /* Write timer arguments */
931 ai_write_timer(dev, init_ticks, scan_ticks, chan_ticks);
933 /* Reset control register */
934 outl(tmp, info->ai_context.ctrl_reg);
937 if ((cmd->start_src == TRIG_EXT &&
938 cmd->scan_begin_src == TRIG_TIMER &&
939 cmd->convert_src == TRIG_TIMER) ||
940 (cmd->start_src == TRIG_EXT &&
941 cmd->scan_begin_src == TRIG_FOLLOW &&
942 cmd->convert_src == TRIG_TIMER)) {
943 tmp = ME4000_AI_CTRL_BIT_MODE_1 |
944 ME4000_AI_CTRL_BIT_CHANNEL_FIFO |
945 ME4000_AI_CTRL_BIT_DATA_FIFO;
946 } else if (cmd->start_src == TRIG_EXT &&
947 cmd->scan_begin_src == TRIG_EXT &&
948 cmd->convert_src == TRIG_TIMER) {
949 tmp = ME4000_AI_CTRL_BIT_MODE_2 |
950 ME4000_AI_CTRL_BIT_CHANNEL_FIFO |
951 ME4000_AI_CTRL_BIT_DATA_FIFO;
952 } else if (cmd->start_src == TRIG_EXT &&
953 cmd->scan_begin_src == TRIG_EXT &&
954 cmd->convert_src == TRIG_EXT) {
955 tmp = ME4000_AI_CTRL_BIT_MODE_0 |
956 ME4000_AI_CTRL_BIT_MODE_1 |
957 ME4000_AI_CTRL_BIT_CHANNEL_FIFO |
958 ME4000_AI_CTRL_BIT_DATA_FIFO;
960 tmp = ME4000_AI_CTRL_BIT_MODE_0 |
961 ME4000_AI_CTRL_BIT_CHANNEL_FIFO |
962 ME4000_AI_CTRL_BIT_DATA_FIFO;
966 if (cmd->stop_src == TRIG_COUNT) {
967 outl(cmd->chanlist_len * cmd->stop_arg,
968 info->ai_context.sample_counter_reg);
969 tmp |= ME4000_AI_CTRL_BIT_HF_IRQ | ME4000_AI_CTRL_BIT_SC_IRQ;
970 } else if (cmd->stop_src == TRIG_NONE &&
971 cmd->scan_end_src == TRIG_COUNT) {
972 outl(cmd->scan_end_arg,
973 info->ai_context.sample_counter_reg);
974 tmp |= ME4000_AI_CTRL_BIT_HF_IRQ | ME4000_AI_CTRL_BIT_SC_IRQ;
976 tmp |= ME4000_AI_CTRL_BIT_HF_IRQ;
979 /* Write the setup to the control register */
980 outl(tmp, info->ai_context.ctrl_reg);
982 /* Write the channel list */
983 ai_write_chanlist(dev, s, cmd);
988 static int ai_write_chanlist(struct comedi_device *dev,
989 struct comedi_subdevice *s, struct comedi_cmd *cmd)
997 for (i = 0; i < cmd->chanlist_len; i++) {
998 chan = CR_CHAN(cmd->chanlist[i]);
999 rang = CR_RANGE(cmd->chanlist[i]);
1000 aref = CR_AREF(cmd->chanlist[i]);
1005 entry |= ME4000_AI_LIST_RANGE_UNIPOLAR_2_5;
1007 entry |= ME4000_AI_LIST_RANGE_UNIPOLAR_10;
1009 entry |= ME4000_AI_LIST_RANGE_BIPOLAR_2_5;
1011 entry |= ME4000_AI_LIST_RANGE_BIPOLAR_10;
1013 if (aref == SDF_DIFF)
1014 entry |= ME4000_AI_LIST_INPUT_DIFFERENTIAL;
1016 entry |= ME4000_AI_LIST_INPUT_SINGLE_ENDED;
1018 outl(entry, info->ai_context.channel_list_reg);
1024 static int me4000_ai_do_cmd(struct comedi_device *dev,
1025 struct comedi_subdevice *s)
1028 unsigned int init_ticks = 0;
1029 unsigned int scan_ticks = 0;
1030 unsigned int chan_ticks = 0;
1031 struct comedi_cmd *cmd = &s->async->cmd;
1033 /* Reset the analog input */
1034 err = me4000_ai_cancel(dev, s);
1038 /* Round the timer arguments */
1039 err = ai_round_cmd_args(dev,
1040 s, cmd, &init_ticks, &scan_ticks, &chan_ticks);
1044 /* Prepare the AI for acquisition */
1045 err = ai_prepare(dev, s, cmd, init_ticks, scan_ticks, chan_ticks);
1049 /* Start acquistion by dummy read */
1050 inl(info->ai_context.start_reg);
1056 * me4000_ai_do_cmd_test():
1058 * The demo cmd.c in ./comedilib/demo specifies 6 return values:
1062 * - invalid argument
1063 * - argument conflict
1064 * - invalid chanlist
1065 * So I tried to adopt this scheme.
1067 static int me4000_ai_do_cmd_test(struct comedi_device *dev,
1068 struct comedi_subdevice *s,
1069 struct comedi_cmd *cmd)
1072 unsigned int init_ticks;
1073 unsigned int chan_ticks;
1074 unsigned int scan_ticks;
1077 /* Only rounding flags are implemented */
1078 cmd->flags &= TRIG_ROUND_NEAREST | TRIG_ROUND_UP | TRIG_ROUND_DOWN;
1080 /* Round the timer arguments */
1081 ai_round_cmd_args(dev, s, cmd, &init_ticks, &scan_ticks, &chan_ticks);
1084 * Stage 1. Check if the trigger sources are generally valid.
1086 switch (cmd->start_src) {
1091 cmd->start_src &= TRIG_NOW | TRIG_EXT;
1096 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1097 "Invalid start source\n", dev->minor);
1098 cmd->start_src = TRIG_NOW;
1101 switch (cmd->scan_begin_src) {
1107 cmd->scan_begin_src &= TRIG_FOLLOW | TRIG_TIMER | TRIG_EXT;
1112 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1113 "Invalid scan begin source\n", dev->minor);
1114 cmd->scan_begin_src = TRIG_FOLLOW;
1117 switch (cmd->convert_src) {
1122 cmd->convert_src &= TRIG_TIMER | TRIG_EXT;
1127 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1128 "Invalid convert source\n", dev->minor);
1129 cmd->convert_src = TRIG_TIMER;
1132 switch (cmd->scan_end_src) {
1137 cmd->scan_end_src &= TRIG_NONE | TRIG_COUNT;
1142 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1143 "Invalid scan end source\n", dev->minor);
1144 cmd->scan_end_src = TRIG_NONE;
1147 switch (cmd->stop_src) {
1152 cmd->stop_src &= TRIG_NONE | TRIG_COUNT;
1157 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1158 "Invalid stop source\n", dev->minor);
1159 cmd->stop_src = TRIG_NONE;
1166 * Stage 2. Check for trigger source conflicts.
1168 if (cmd->start_src == TRIG_NOW &&
1169 cmd->scan_begin_src == TRIG_TIMER &&
1170 cmd->convert_src == TRIG_TIMER) {
1171 } else if (cmd->start_src == TRIG_NOW &&
1172 cmd->scan_begin_src == TRIG_FOLLOW &&
1173 cmd->convert_src == TRIG_TIMER) {
1174 } else if (cmd->start_src == TRIG_EXT &&
1175 cmd->scan_begin_src == TRIG_TIMER &&
1176 cmd->convert_src == TRIG_TIMER) {
1177 } else if (cmd->start_src == TRIG_EXT &&
1178 cmd->scan_begin_src == TRIG_FOLLOW &&
1179 cmd->convert_src == TRIG_TIMER) {
1180 } else if (cmd->start_src == TRIG_EXT &&
1181 cmd->scan_begin_src == TRIG_EXT &&
1182 cmd->convert_src == TRIG_TIMER) {
1183 } else if (cmd->start_src == TRIG_EXT &&
1184 cmd->scan_begin_src == TRIG_EXT &&
1185 cmd->convert_src == TRIG_EXT) {
1188 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1189 "Invalid start trigger combination\n", dev->minor);
1190 cmd->start_src = TRIG_NOW;
1191 cmd->scan_begin_src = TRIG_FOLLOW;
1192 cmd->convert_src = TRIG_TIMER;
1196 if (cmd->stop_src == TRIG_NONE && cmd->scan_end_src == TRIG_NONE) {
1197 } else if (cmd->stop_src == TRIG_COUNT &&
1198 cmd->scan_end_src == TRIG_NONE) {
1199 } else if (cmd->stop_src == TRIG_NONE &&
1200 cmd->scan_end_src == TRIG_COUNT) {
1201 } else if (cmd->stop_src == TRIG_COUNT &&
1202 cmd->scan_end_src == TRIG_COUNT) {
1205 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1206 "Invalid stop trigger combination\n", dev->minor);
1207 cmd->stop_src = TRIG_NONE;
1208 cmd->scan_end_src = TRIG_NONE;
1215 * Stage 3. Check if arguments are generally valid.
1217 if (cmd->chanlist_len < 1) {
1219 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1220 "No channel list\n", dev->minor);
1221 cmd->chanlist_len = 1;
1224 if (init_ticks < 66) {
1226 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1227 "Start arg to low\n", dev->minor);
1228 cmd->start_arg = 2000;
1231 if (scan_ticks && scan_ticks < 67) {
1233 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1234 "Scan begin arg to low\n", dev->minor);
1235 cmd->scan_begin_arg = 2031;
1238 if (chan_ticks < 66) {
1240 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1241 "Convert arg to low\n", dev->minor);
1242 cmd->convert_arg = 2000;
1250 * Stage 4. Check for argument conflicts.
1252 if (cmd->start_src == TRIG_NOW &&
1253 cmd->scan_begin_src == TRIG_TIMER &&
1254 cmd->convert_src == TRIG_TIMER) {
1256 /* Check timer arguments */
1257 if (init_ticks < ME4000_AI_MIN_TICKS) {
1259 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1260 "Invalid start arg\n", dev->minor);
1261 cmd->start_arg = 2000; /* 66 ticks at least */
1264 if (chan_ticks < ME4000_AI_MIN_TICKS) {
1266 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1267 "Invalid convert arg\n", dev->minor);
1268 cmd->convert_arg = 2000; /* 66 ticks at least */
1271 if (scan_ticks <= cmd->chanlist_len * chan_ticks) {
1273 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1274 "Invalid scan end arg\n", dev->minor);
1276 /* At least one tick more */
1277 cmd->scan_end_arg = 2000 * cmd->chanlist_len + 31;
1280 } else if (cmd->start_src == TRIG_NOW &&
1281 cmd->scan_begin_src == TRIG_FOLLOW &&
1282 cmd->convert_src == TRIG_TIMER) {
1284 /* Check timer arguments */
1285 if (init_ticks < ME4000_AI_MIN_TICKS) {
1287 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1288 "Invalid start arg\n", dev->minor);
1289 cmd->start_arg = 2000; /* 66 ticks at least */
1292 if (chan_ticks < ME4000_AI_MIN_TICKS) {
1294 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1295 "Invalid convert arg\n", dev->minor);
1296 cmd->convert_arg = 2000; /* 66 ticks at least */
1299 } else if (cmd->start_src == TRIG_EXT &&
1300 cmd->scan_begin_src == TRIG_TIMER &&
1301 cmd->convert_src == TRIG_TIMER) {
1303 /* Check timer arguments */
1304 if (init_ticks < ME4000_AI_MIN_TICKS) {
1306 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1307 "Invalid start arg\n", dev->minor);
1308 cmd->start_arg = 2000; /* 66 ticks at least */
1311 if (chan_ticks < ME4000_AI_MIN_TICKS) {
1313 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1314 "Invalid convert arg\n", dev->minor);
1315 cmd->convert_arg = 2000; /* 66 ticks at least */
1318 if (scan_ticks <= cmd->chanlist_len * chan_ticks) {
1320 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1321 "Invalid scan end arg\n", dev->minor);
1323 /* At least one tick more */
1324 cmd->scan_end_arg = 2000 * cmd->chanlist_len + 31;
1327 } else if (cmd->start_src == TRIG_EXT &&
1328 cmd->scan_begin_src == TRIG_FOLLOW &&
1329 cmd->convert_src == TRIG_TIMER) {
1331 /* Check timer arguments */
1332 if (init_ticks < ME4000_AI_MIN_TICKS) {
1334 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1335 "Invalid start arg\n", dev->minor);
1336 cmd->start_arg = 2000; /* 66 ticks at least */
1339 if (chan_ticks < ME4000_AI_MIN_TICKS) {
1341 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1342 "Invalid convert arg\n", dev->minor);
1343 cmd->convert_arg = 2000; /* 66 ticks at least */
1346 } else if (cmd->start_src == TRIG_EXT &&
1347 cmd->scan_begin_src == TRIG_EXT &&
1348 cmd->convert_src == TRIG_TIMER) {
1350 /* Check timer arguments */
1351 if (init_ticks < ME4000_AI_MIN_TICKS) {
1353 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1354 "Invalid start arg\n", dev->minor);
1355 cmd->start_arg = 2000; /* 66 ticks at least */
1358 if (chan_ticks < ME4000_AI_MIN_TICKS) {
1360 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1361 "Invalid convert arg\n", dev->minor);
1362 cmd->convert_arg = 2000; /* 66 ticks at least */
1365 } else if (cmd->start_src == TRIG_EXT &&
1366 cmd->scan_begin_src == TRIG_EXT &&
1367 cmd->convert_src == TRIG_EXT) {
1369 /* Check timer arguments */
1370 if (init_ticks < ME4000_AI_MIN_TICKS) {
1372 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1373 "Invalid start arg\n", dev->minor);
1374 cmd->start_arg = 2000; /* 66 ticks at least */
1378 if (cmd->stop_src == TRIG_COUNT) {
1379 if (cmd->stop_arg == 0) {
1381 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1382 "Invalid stop arg\n", dev->minor);
1387 if (cmd->scan_end_src == TRIG_COUNT) {
1388 if (cmd->scan_end_arg == 0) {
1390 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1391 "Invalid scan end arg\n", dev->minor);
1392 cmd->scan_end_arg = 1;
1401 * Stage 5. Check the channel list.
1403 if (ai_check_chanlist(dev, s, cmd))
1409 static irqreturn_t me4000_ai_isr(int irq, void *dev_id)
1412 struct comedi_device *dev = dev_id;
1413 struct comedi_subdevice *s = dev->subdevices;
1414 struct me4000_ai_context *ai_context = &info->ai_context;
1422 /* Reset all events */
1423 s->async->events = 0;
1425 /* Check if irq number is right */
1426 if (irq != ai_context->irq) {
1428 "comedi%d: me4000: me4000_ai_isr(): "
1429 "Incorrect interrupt num: %d\n", dev->minor, irq);
1433 if (inl(ai_context->irq_status_reg) &
1434 ME4000_IRQ_STATUS_BIT_AI_HF) {
1435 /* Read status register to find out what happened */
1436 tmp = inl(ai_context->ctrl_reg);
1438 if (!(tmp & ME4000_AI_STATUS_BIT_FF_DATA) &&
1439 !(tmp & ME4000_AI_STATUS_BIT_HF_DATA) &&
1440 (tmp & ME4000_AI_STATUS_BIT_EF_DATA)) {
1441 c = ME4000_AI_FIFO_COUNT;
1444 * FIFO overflow, so stop conversion
1445 * and disable all interrupts
1447 tmp |= ME4000_AI_CTRL_BIT_IMMEDIATE_STOP;
1448 tmp &= ~(ME4000_AI_CTRL_BIT_HF_IRQ |
1449 ME4000_AI_CTRL_BIT_SC_IRQ);
1450 outl(tmp, ai_context->ctrl_reg);
1452 s->async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
1455 "comedi%d: me4000: me4000_ai_isr(): "
1456 "FIFO overflow\n", dev->minor);
1457 } else if ((tmp & ME4000_AI_STATUS_BIT_FF_DATA)
1458 && !(tmp & ME4000_AI_STATUS_BIT_HF_DATA)
1459 && (tmp & ME4000_AI_STATUS_BIT_EF_DATA)) {
1460 s->async->events |= COMEDI_CB_BLOCK;
1462 c = ME4000_AI_FIFO_COUNT / 2;
1465 "comedi%d: me4000: me4000_ai_isr(): "
1466 "Can't determine state of fifo\n", dev->minor);
1470 * Undefined state, so stop conversion
1471 * and disable all interrupts
1473 tmp |= ME4000_AI_CTRL_BIT_IMMEDIATE_STOP;
1474 tmp &= ~(ME4000_AI_CTRL_BIT_HF_IRQ |
1475 ME4000_AI_CTRL_BIT_SC_IRQ);
1476 outl(tmp, ai_context->ctrl_reg);
1478 s->async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
1481 "comedi%d: me4000: me4000_ai_isr(): "
1482 "Undefined FIFO state\n", dev->minor);
1485 for (i = 0; i < c; i++) {
1486 /* Read value from data fifo */
1487 lval = inl(ai_context->data_reg) & 0xFFFF;
1490 if (!comedi_buf_put(s->async, lval)) {
1492 * Buffer overflow, so stop conversion
1493 * and disable all interrupts
1495 tmp |= ME4000_AI_CTRL_BIT_IMMEDIATE_STOP;
1496 tmp &= ~(ME4000_AI_CTRL_BIT_HF_IRQ |
1497 ME4000_AI_CTRL_BIT_SC_IRQ);
1498 outl(tmp, ai_context->ctrl_reg);
1500 s->async->events |= COMEDI_CB_OVERFLOW;
1503 "comedi%d: me4000: me4000_ai_isr(): "
1504 "Buffer overflow\n", dev->minor);
1510 /* Work is done, so reset the interrupt */
1511 tmp |= ME4000_AI_CTRL_BIT_HF_IRQ_RESET;
1512 outl(tmp, ai_context->ctrl_reg);
1513 tmp &= ~ME4000_AI_CTRL_BIT_HF_IRQ_RESET;
1514 outl(tmp, ai_context->ctrl_reg);
1517 if (inl(ai_context->irq_status_reg) & ME4000_IRQ_STATUS_BIT_SC) {
1518 s->async->events |= COMEDI_CB_BLOCK | COMEDI_CB_EOA;
1521 * Acquisition is complete, so stop
1522 * conversion and disable all interrupts
1524 tmp = inl(ai_context->ctrl_reg);
1525 tmp |= ME4000_AI_CTRL_BIT_IMMEDIATE_STOP;
1526 tmp &= ~(ME4000_AI_CTRL_BIT_HF_IRQ | ME4000_AI_CTRL_BIT_SC_IRQ);
1527 outl(tmp, ai_context->ctrl_reg);
1529 /* Poll data until fifo empty */
1530 while (inl(ai_context->ctrl_reg) & ME4000_AI_STATUS_BIT_EF_DATA) {
1531 /* Read value from data fifo */
1532 lval = inl(ai_context->data_reg) & 0xFFFF;
1535 if (!comedi_buf_put(s->async, lval)) {
1537 "comedi%d: me4000: me4000_ai_isr(): "
1538 "Buffer overflow\n", dev->minor);
1539 s->async->events |= COMEDI_CB_OVERFLOW;
1544 /* Work is done, so reset the interrupt */
1545 tmp |= ME4000_AI_CTRL_BIT_SC_IRQ_RESET;
1546 outl(tmp, ai_context->ctrl_reg);
1547 tmp &= ~ME4000_AI_CTRL_BIT_SC_IRQ_RESET;
1548 outl(tmp, ai_context->ctrl_reg);
1551 if (s->async->events)
1552 comedi_event(dev, s);
1557 /*=============================================================================
1558 Analog output section
1559 ===========================================================================*/
1561 static int me4000_ao_insn_write(struct comedi_device *dev,
1562 struct comedi_subdevice *s,
1563 struct comedi_insn *insn, unsigned int *data)
1566 int chan = CR_CHAN(insn->chanspec);
1567 int rang = CR_RANGE(insn->chanspec);
1568 int aref = CR_AREF(insn->chanspec);
1573 } else if (insn->n > 1) {
1575 "comedi%d: me4000: me4000_ao_insn_write(): "
1576 "Invalid instruction length %d\n", dev->minor, insn->n);
1580 if (chan >= thisboard->ao.count) {
1582 "comedi%d: me4000: me4000_ao_insn_write(): "
1583 "Invalid channel %d\n", dev->minor, insn->n);
1589 "comedi%d: me4000: me4000_ao_insn_write(): "
1590 "Invalid range %d\n", dev->minor, insn->n);
1594 if (aref != AREF_GROUND && aref != AREF_COMMON) {
1596 "comedi%d: me4000: me4000_ao_insn_write(): "
1597 "Invalid aref %d\n", dev->minor, insn->n);
1601 /* Stop any running conversion */
1602 tmp = inl(info->ao_context[chan].ctrl_reg);
1603 tmp |= ME4000_AO_CTRL_BIT_IMMEDIATE_STOP;
1604 outl(tmp, info->ao_context[chan].ctrl_reg);
1606 /* Clear control register and set to single mode */
1607 outl(0x0, info->ao_context[chan].ctrl_reg);
1609 /* Write data value */
1610 outl(data[0], info->ao_context[chan].single_reg);
1612 /* Store in the mirror */
1613 info->ao_context[chan].mirror = data[0];
1618 static int me4000_ao_insn_read(struct comedi_device *dev,
1619 struct comedi_subdevice *s,
1620 struct comedi_insn *insn, unsigned int *data)
1622 int chan = CR_CHAN(insn->chanspec);
1626 } else if (insn->n > 1) {
1628 ("comedi%d: me4000: me4000_ao_insn_read(): "
1629 "Invalid instruction length\n", dev->minor);
1633 data[0] = info->ao_context[chan].mirror;
1638 /*=============================================================================
1640 ===========================================================================*/
1642 static int me4000_dio_insn_bits(struct comedi_device *dev,
1643 struct comedi_subdevice *s,
1644 struct comedi_insn *insn, unsigned int *data)
1647 * The insn data consists of a mask in data[0] and the new data
1648 * in data[1]. The mask defines which bits we are concerning about.
1649 * The new data must be anded with the mask.
1650 * Each channel corresponds to a bit.
1653 /* Check if requested ports are configured for output */
1654 if ((s->io_bits & data[0]) != data[0])
1657 s->state &= ~data[0];
1658 s->state |= data[0] & data[1];
1660 /* Write out the new digital output lines */
1661 outl((s->state >> 0) & 0xFF,
1662 info->dio_context.port_0_reg);
1663 outl((s->state >> 8) & 0xFF,
1664 info->dio_context.port_1_reg);
1665 outl((s->state >> 16) & 0xFF,
1666 info->dio_context.port_2_reg);
1667 outl((s->state >> 24) & 0xFF,
1668 info->dio_context.port_3_reg);
1671 /* On return, data[1] contains the value of
1672 the digital input and output lines. */
1673 data[1] = ((inl(info->dio_context.port_0_reg) & 0xFF) << 0) |
1674 ((inl(info->dio_context.port_1_reg) & 0xFF) << 8) |
1675 ((inl(info->dio_context.port_2_reg) & 0xFF) << 16) |
1676 ((inl(info->dio_context.port_3_reg) & 0xFF) << 24);
1681 static int me4000_dio_insn_config(struct comedi_device *dev,
1682 struct comedi_subdevice *s,
1683 struct comedi_insn *insn, unsigned int *data)
1686 int chan = CR_CHAN(insn->chanspec);
1691 case INSN_CONFIG_DIO_QUERY:
1693 (s->io_bits & (1 << chan)) ? COMEDI_OUTPUT : COMEDI_INPUT;
1695 case INSN_CONFIG_DIO_INPUT:
1696 case INSN_CONFIG_DIO_OUTPUT:
1701 * The input or output configuration of each digital line is
1702 * configured by a special insn_config instruction. chanspec
1703 * contains the channel to be changed, and data[0] contains the
1704 * value INSN_CONFIG_DIO_INPUT or INSN_CONFIG_DIO_OUTPUT.
1705 * On the ME-4000 it is only possible to switch port wise (8 bit)
1708 tmp = inl(info->dio_context.ctrl_reg);
1710 if (data[0] == INSN_CONFIG_DIO_OUTPUT) {
1713 tmp &= ~(ME4000_DIO_CTRL_BIT_MODE_0 |
1714 ME4000_DIO_CTRL_BIT_MODE_1);
1715 tmp |= ME4000_DIO_CTRL_BIT_MODE_0;
1716 } else if (chan < 16) {
1718 * Chech for optoisolated ME-4000 version.
1719 * If one the first port is a fixed output
1720 * port and the second is a fixed input port.
1722 if (!inl(info->dio_context.dir_reg))
1725 s->io_bits |= 0xFF00;
1726 tmp &= ~(ME4000_DIO_CTRL_BIT_MODE_2 |
1727 ME4000_DIO_CTRL_BIT_MODE_3);
1728 tmp |= ME4000_DIO_CTRL_BIT_MODE_2;
1729 } else if (chan < 24) {
1730 s->io_bits |= 0xFF0000;
1731 tmp &= ~(ME4000_DIO_CTRL_BIT_MODE_4 |
1732 ME4000_DIO_CTRL_BIT_MODE_5);
1733 tmp |= ME4000_DIO_CTRL_BIT_MODE_4;
1734 } else if (chan < 32) {
1735 s->io_bits |= 0xFF000000;
1736 tmp &= ~(ME4000_DIO_CTRL_BIT_MODE_6 |
1737 ME4000_DIO_CTRL_BIT_MODE_7);
1738 tmp |= ME4000_DIO_CTRL_BIT_MODE_6;
1745 * Chech for optoisolated ME-4000 version.
1746 * If one the first port is a fixed output
1747 * port and the second is a fixed input port.
1749 if (!inl(info->dio_context.dir_reg))
1752 s->io_bits &= ~0xFF;
1753 tmp &= ~(ME4000_DIO_CTRL_BIT_MODE_0 |
1754 ME4000_DIO_CTRL_BIT_MODE_1);
1755 } else if (chan < 16) {
1756 s->io_bits &= ~0xFF00;
1757 tmp &= ~(ME4000_DIO_CTRL_BIT_MODE_2 |
1758 ME4000_DIO_CTRL_BIT_MODE_3);
1759 } else if (chan < 24) {
1760 s->io_bits &= ~0xFF0000;
1761 tmp &= ~(ME4000_DIO_CTRL_BIT_MODE_4 |
1762 ME4000_DIO_CTRL_BIT_MODE_5);
1763 } else if (chan < 32) {
1764 s->io_bits &= ~0xFF000000;
1765 tmp &= ~(ME4000_DIO_CTRL_BIT_MODE_6 |
1766 ME4000_DIO_CTRL_BIT_MODE_7);
1772 outl(tmp, info->dio_context.ctrl_reg);
1777 /*=============================================================================
1779 ===========================================================================*/
1781 static int cnt_reset(struct comedi_device *dev, unsigned int channel)
1785 outb(0x30, info->cnt_context.ctrl_reg);
1786 outb(0x00, info->cnt_context.counter_0_reg);
1787 outb(0x00, info->cnt_context.counter_0_reg);
1790 outb(0x70, info->cnt_context.ctrl_reg);
1791 outb(0x00, info->cnt_context.counter_1_reg);
1792 outb(0x00, info->cnt_context.counter_1_reg);
1795 outb(0xB0, info->cnt_context.ctrl_reg);
1796 outb(0x00, info->cnt_context.counter_2_reg);
1797 outb(0x00, info->cnt_context.counter_2_reg);
1801 "comedi%d: me4000: cnt_reset(): Invalid channel\n",
1809 static int cnt_config(struct comedi_device *dev, unsigned int channel,
1816 tmp |= ME4000_CNT_COUNTER_0;
1819 tmp |= ME4000_CNT_COUNTER_1;
1822 tmp |= ME4000_CNT_COUNTER_2;
1826 "comedi%d: me4000: cnt_config(): Invalid channel\n",
1833 tmp |= ME4000_CNT_MODE_0;
1836 tmp |= ME4000_CNT_MODE_1;
1839 tmp |= ME4000_CNT_MODE_2;
1842 tmp |= ME4000_CNT_MODE_3;
1845 tmp |= ME4000_CNT_MODE_4;
1848 tmp |= ME4000_CNT_MODE_5;
1852 "comedi%d: me4000: cnt_config(): Invalid counter mode\n",
1857 /* Write the control word */
1859 outb(tmp, info->cnt_context.ctrl_reg);
1864 static int me4000_cnt_insn_config(struct comedi_device *dev,
1865 struct comedi_subdevice *s,
1866 struct comedi_insn *insn, unsigned int *data)
1875 "comedi%d: me4000: me4000_cnt_insn_config(): "
1876 "Invalid instruction length%d\n",
1877 dev->minor, insn->n);
1881 err = cnt_reset(dev, insn->chanspec);
1885 case GPCT_SET_OPERATION:
1888 "comedi%d: me4000: me4000_cnt_insn_config(): "
1889 "Invalid instruction length%d\n",
1890 dev->minor, insn->n);
1894 err = cnt_config(dev, insn->chanspec, data[1]);
1900 "comedi%d: me4000: me4000_cnt_insn_config(): "
1901 "Invalid instruction\n", dev->minor);
1908 static int me4000_cnt_insn_read(struct comedi_device *dev,
1909 struct comedi_subdevice *s,
1910 struct comedi_insn *insn, unsigned int *data)
1920 "comedi%d: me4000: me4000_cnt_insn_read(): "
1921 "Invalid instruction length %d\n",
1922 dev->minor, insn->n);
1926 switch (insn->chanspec) {
1928 tmp = inb(info->cnt_context.counter_0_reg);
1930 tmp = inb(info->cnt_context.counter_0_reg);
1931 data[0] |= tmp << 8;
1934 tmp = inb(info->cnt_context.counter_1_reg);
1936 tmp = inb(info->cnt_context.counter_1_reg);
1937 data[0] |= tmp << 8;
1940 tmp = inb(info->cnt_context.counter_2_reg);
1942 tmp = inb(info->cnt_context.counter_2_reg);
1943 data[0] |= tmp << 8;
1947 "comedi%d: me4000: me4000_cnt_insn_read(): "
1948 "Invalid channel %d\n",
1949 dev->minor, insn->chanspec);
1956 static int me4000_cnt_insn_write(struct comedi_device *dev,
1957 struct comedi_subdevice *s,
1958 struct comedi_insn *insn, unsigned int *data)
1965 } else if (insn->n > 1) {
1967 "comedi%d: me4000: me4000_cnt_insn_write(): "
1968 "Invalid instruction length %d\n",
1969 dev->minor, insn->n);
1973 switch (insn->chanspec) {
1975 tmp = data[0] & 0xFF;
1976 outb(tmp, info->cnt_context.counter_0_reg);
1977 tmp = (data[0] >> 8) & 0xFF;
1978 outb(tmp, info->cnt_context.counter_0_reg);
1981 tmp = data[0] & 0xFF;
1982 outb(tmp, info->cnt_context.counter_1_reg);
1983 tmp = (data[0] >> 8) & 0xFF;
1984 outb(tmp, info->cnt_context.counter_1_reg);
1987 tmp = data[0] & 0xFF;
1988 outb(tmp, info->cnt_context.counter_2_reg);
1989 tmp = (data[0] >> 8) & 0xFF;
1990 outb(tmp, info->cnt_context.counter_2_reg);
1994 "comedi%d: me4000: me4000_cnt_insn_write(): "
1995 "Invalid channel %d\n",
1996 dev->minor, insn->chanspec);
2003 static int me4000_attach(struct comedi_device *dev, struct comedi_devconfig *it)
2005 struct comedi_subdevice *s;
2008 result = me4000_probe(dev, it);
2012 result = comedi_alloc_subdevices(dev, 4);
2016 /*=========================================================================
2017 Analog input subdevice
2018 ========================================================================*/
2020 s = dev->subdevices + 0;
2022 if (thisboard->ai.count) {
2023 s->type = COMEDI_SUBD_AI;
2025 SDF_READABLE | SDF_COMMON | SDF_GROUND | SDF_DIFF;
2026 s->n_chan = thisboard->ai.count;
2027 s->maxdata = 0xFFFF; /* 16 bit ADC */
2028 s->len_chanlist = ME4000_AI_CHANNEL_LIST_COUNT;
2029 s->range_table = &me4000_ai_range;
2030 s->insn_read = me4000_ai_insn_read;
2032 if (info->irq > 0) {
2033 if (request_irq(info->irq, me4000_ai_isr,
2034 IRQF_SHARED, "ME-4000", dev)) {
2036 ("comedi%d: me4000: me4000_attach(): "
2037 "Unable to allocate irq\n", dev->minor);
2039 dev->read_subdev = s;
2040 s->subdev_flags |= SDF_CMD_READ;
2041 s->cancel = me4000_ai_cancel;
2042 s->do_cmdtest = me4000_ai_do_cmd_test;
2043 s->do_cmd = me4000_ai_do_cmd;
2047 "comedi%d: me4000: me4000_attach(): "
2048 "No interrupt available\n", dev->minor);
2051 s->type = COMEDI_SUBD_UNUSED;
2054 /*=========================================================================
2055 Analog output subdevice
2056 ========================================================================*/
2058 s = dev->subdevices + 1;
2060 if (thisboard->ao.count) {
2061 s->type = COMEDI_SUBD_AO;
2062 s->subdev_flags = SDF_WRITEABLE | SDF_COMMON | SDF_GROUND;
2063 s->n_chan = thisboard->ao.count;
2064 s->maxdata = 0xFFFF; /* 16 bit DAC */
2065 s->range_table = &me4000_ao_range;
2066 s->insn_write = me4000_ao_insn_write;
2067 s->insn_read = me4000_ao_insn_read;
2069 s->type = COMEDI_SUBD_UNUSED;
2072 /*=========================================================================
2073 Digital I/O subdevice
2074 ========================================================================*/
2076 s = dev->subdevices + 2;
2078 if (thisboard->dio.count) {
2079 s->type = COMEDI_SUBD_DIO;
2080 s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
2081 s->n_chan = thisboard->dio.count * 8;
2083 s->range_table = &range_digital;
2084 s->insn_bits = me4000_dio_insn_bits;
2085 s->insn_config = me4000_dio_insn_config;
2087 s->type = COMEDI_SUBD_UNUSED;
2091 * Check for optoisolated ME-4000 version. If one the first
2092 * port is a fixed output port and the second is a fixed input port.
2094 if (!inl(info->dio_context.dir_reg)) {
2096 outl(ME4000_DIO_CTRL_BIT_MODE_0, info->dio_context.dir_reg);
2099 /*=========================================================================
2101 ========================================================================*/
2103 s = dev->subdevices + 3;
2105 if (thisboard->cnt.count) {
2106 s->type = COMEDI_SUBD_COUNTER;
2107 s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
2108 s->n_chan = thisboard->cnt.count;
2109 s->maxdata = 0xFFFF; /* 16 bit counters */
2110 s->insn_read = me4000_cnt_insn_read;
2111 s->insn_write = me4000_cnt_insn_write;
2112 s->insn_config = me4000_cnt_insn_config;
2114 s->type = COMEDI_SUBD_UNUSED;
2120 static void me4000_detach(struct comedi_device *dev)
2123 if (info->pci_dev_p) {
2125 if (info->plx_regbase)
2126 comedi_pci_disable(info->pci_dev_p);
2127 pci_dev_put(info->pci_dev_p);
2132 static struct comedi_driver me4000_driver = {
2133 .driver_name = "me4000",
2134 .module = THIS_MODULE,
2135 .attach = me4000_attach,
2136 .detach = me4000_detach,
2139 static int __devinit me4000_pci_probe(struct pci_dev *dev,
2140 const struct pci_device_id *ent)
2142 return comedi_pci_auto_config(dev, &me4000_driver);
2145 static void __devexit me4000_pci_remove(struct pci_dev *dev)
2147 comedi_pci_auto_unconfig(dev);
2150 static DEFINE_PCI_DEVICE_TABLE(me4000_pci_table) = {
2151 { PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, 0x4650) },
2152 { PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, 0x4660) },
2153 { PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, 0x4661) },
2154 { PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, 0x4662) },
2155 { PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, 0x4663) },
2156 { PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, 0x4670) },
2157 { PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, 0x4671) },
2158 { PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, 0x4672) },
2159 { PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, 0x4673) },
2160 { PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, 0x4680) },
2161 { PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, 0x4681) },
2162 { PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, 0x4682) },
2163 { PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, 0x4683) },
2166 MODULE_DEVICE_TABLE(pci, me4000_pci_table);
2168 static struct pci_driver me4000_pci_driver = {
2170 .id_table = me4000_pci_table,
2171 .probe = me4000_pci_probe,
2172 .remove = __devexit_p(me4000_pci_remove),
2174 module_comedi_pci_driver(me4000_driver, me4000_pci_driver);
2176 MODULE_AUTHOR("Comedi http://www.comedi.org");
2177 MODULE_DESCRIPTION("Comedi low-level driver");
2178 MODULE_LICENSE("GPL");