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} },
86 /*-----------------------------------------------------------------------------
87 Meilhaus function prototypes
88 ---------------------------------------------------------------------------*/
89 static int get_registers(struct comedi_device *dev, struct pci_dev *pci_dev_p);
90 static int init_board_info(struct comedi_device *dev,
91 struct pci_dev *pci_dev_p);
92 static int init_ao_context(struct comedi_device *dev);
93 static int init_ai_context(struct comedi_device *dev);
94 static int init_dio_context(struct comedi_device *dev);
95 static int init_cnt_context(struct comedi_device *dev);
96 static int xilinx_download(struct comedi_device *dev);
97 static int reset_board(struct comedi_device *dev);
99 static int ai_write_chanlist(struct comedi_device *dev,
100 struct comedi_subdevice *s,
101 struct comedi_cmd *cmd);
103 static const struct comedi_lrange me4000_ai_range = {
113 static const struct comedi_lrange me4000_ao_range = {
120 static int me4000_probe(struct comedi_device *dev, struct comedi_devconfig *it)
122 struct pci_dev *pci_device = NULL;
124 struct me4000_board *board;
126 /* Allocate private memory */
127 if (alloc_private(dev, sizeof(struct me4000_info)) < 0)
131 * Probe the device to determine what device in the series it is.
133 for_each_pci_dev(pci_device) {
134 if (pci_device->vendor == PCI_VENDOR_ID_MEILHAUS) {
135 for (i = 0; i < ARRAY_SIZE(me4000_boards); i++) {
136 if (me4000_boards[i].device_id ==
137 pci_device->device) {
140 * bus/slot requested?
142 if ((it->options[0] != 0)
143 || (it->options[1] != 0)) {
145 * Are we on the wrong
148 if (pci_device->bus->number !=
151 PCI_SLOT(pci_device->devfn)
156 dev->board_ptr = me4000_boards + i;
158 (struct me4000_board *)
160 info->pci_dev_p = pci_device;
168 "comedi%d: me4000: me4000_probe(): "
169 "No supported board found (req. bus/slot : %d/%d)\n",
170 dev->minor, it->options[0], it->options[1]);
176 "comedi%d: me4000: me4000_probe(): "
177 "Found %s at PCI bus %d, slot %d\n",
178 dev->minor, me4000_boards[i].name, pci_device->bus->number,
179 PCI_SLOT(pci_device->devfn));
181 /* Set data in device structure */
182 dev->board_name = board->name;
184 /* Enable PCI device and request regions */
185 result = comedi_pci_enable(pci_device, dev->board_name);
188 "comedi%d: me4000: me4000_probe(): Cannot enable PCI "
189 "device and request I/O regions\n", dev->minor);
193 /* Get the PCI base registers */
194 result = get_registers(dev, pci_device);
197 "comedi%d: me4000: me4000_probe(): "
198 "Cannot get registers\n", dev->minor);
201 /* Initialize board info */
202 result = init_board_info(dev, pci_device);
205 "comedi%d: me4000: me4000_probe(): "
206 "Cannot init baord info\n", dev->minor);
210 /* Init analog output context */
211 result = init_ao_context(dev);
214 "comedi%d: me4000: me4000_probe(): "
215 "Cannot init ao context\n", dev->minor);
219 /* Init analog input context */
220 result = init_ai_context(dev);
223 "comedi%d: me4000: me4000_probe(): "
224 "Cannot init ai context\n", dev->minor);
228 /* Init digital I/O context */
229 result = init_dio_context(dev);
232 "comedi%d: me4000: me4000_probe(): "
233 "Cannot init dio context\n", dev->minor);
237 /* Init counter context */
238 result = init_cnt_context(dev);
241 "comedi%d: me4000: me4000_probe(): "
242 "Cannot init cnt context\n", dev->minor);
246 /* Download the xilinx firmware */
247 result = xilinx_download(dev);
250 "comedi%d: me4000: me4000_probe(): "
251 "Can't download firmware\n", dev->minor);
255 /* Make a hardware reset */
256 result = reset_board(dev);
259 "comedi%d: me4000: me4000_probe(): Can't reset board\n",
267 static int get_registers(struct comedi_device *dev, struct pci_dev *pci_dev_p)
269 /*--------------------------- plx regbase -------------------------------*/
271 info->plx_regbase = pci_resource_start(pci_dev_p, 1);
272 if (info->plx_regbase == 0) {
274 "comedi%d: me4000: get_registers(): "
275 "PCI base address 1 is not available\n", dev->minor);
278 info->plx_regbase_size = pci_resource_len(pci_dev_p, 1);
280 /*--------------------------- me4000 regbase ----------------------------*/
282 info->me4000_regbase = pci_resource_start(pci_dev_p, 2);
283 if (info->me4000_regbase == 0) {
285 "comedi%d: me4000: get_registers(): "
286 "PCI base address 2 is not available\n", dev->minor);
289 info->me4000_regbase_size = pci_resource_len(pci_dev_p, 2);
291 /*--------------------------- timer regbase ------------------------------*/
293 info->timer_regbase = pci_resource_start(pci_dev_p, 3);
294 if (info->timer_regbase == 0) {
296 "comedi%d: me4000: get_registers(): "
297 "PCI base address 3 is not available\n", dev->minor);
300 info->timer_regbase_size = pci_resource_len(pci_dev_p, 3);
302 /*--------------------------- program regbase ----------------------------*/
304 info->program_regbase = pci_resource_start(pci_dev_p, 5);
305 if (info->program_regbase == 0) {
307 "comedi%d: me4000: get_registers(): "
308 "PCI base address 5 is not available\n", dev->minor);
311 info->program_regbase_size = pci_resource_len(pci_dev_p, 5);
316 static int init_board_info(struct comedi_device *dev, struct pci_dev *pci_dev_p)
320 /* Init spin locks */
321 /* spin_lock_init(&info->preload_lock); */
322 /* spin_lock_init(&info->ai_ctrl_lock); */
324 /* Get the serial number */
325 result = pci_read_config_dword(pci_dev_p, 0x2C, &info->serial_no);
326 if (result != PCIBIOS_SUCCESSFUL)
329 /* Get the hardware revision */
330 result = pci_read_config_byte(pci_dev_p, 0x08, &info->hw_revision);
331 if (result != PCIBIOS_SUCCESSFUL)
334 /* Get the vendor id */
335 info->vendor_id = pci_dev_p->vendor;
337 /* Get the device id */
338 info->device_id = pci_dev_p->device;
340 /* Get the irq assigned to the board */
341 info->irq = pci_dev_p->irq;
346 static int init_ao_context(struct comedi_device *dev)
350 for (i = 0; i < thisboard->ao.count; i++) {
351 /* spin_lock_init(&info->ao_context[i].use_lock); */
352 info->ao_context[i].irq = info->irq;
356 info->ao_context[i].ctrl_reg =
357 info->me4000_regbase + ME4000_AO_00_CTRL_REG;
358 info->ao_context[i].status_reg =
359 info->me4000_regbase + ME4000_AO_00_STATUS_REG;
360 info->ao_context[i].fifo_reg =
361 info->me4000_regbase + ME4000_AO_00_FIFO_REG;
362 info->ao_context[i].single_reg =
363 info->me4000_regbase + ME4000_AO_00_SINGLE_REG;
364 info->ao_context[i].timer_reg =
365 info->me4000_regbase + ME4000_AO_00_TIMER_REG;
366 info->ao_context[i].irq_status_reg =
367 info->me4000_regbase + ME4000_IRQ_STATUS_REG;
368 info->ao_context[i].preload_reg =
369 info->me4000_regbase + ME4000_AO_LOADSETREG_XX;
372 info->ao_context[i].ctrl_reg =
373 info->me4000_regbase + ME4000_AO_01_CTRL_REG;
374 info->ao_context[i].status_reg =
375 info->me4000_regbase + ME4000_AO_01_STATUS_REG;
376 info->ao_context[i].fifo_reg =
377 info->me4000_regbase + ME4000_AO_01_FIFO_REG;
378 info->ao_context[i].single_reg =
379 info->me4000_regbase + ME4000_AO_01_SINGLE_REG;
380 info->ao_context[i].timer_reg =
381 info->me4000_regbase + ME4000_AO_01_TIMER_REG;
382 info->ao_context[i].irq_status_reg =
383 info->me4000_regbase + ME4000_IRQ_STATUS_REG;
384 info->ao_context[i].preload_reg =
385 info->me4000_regbase + ME4000_AO_LOADSETREG_XX;
388 info->ao_context[i].ctrl_reg =
389 info->me4000_regbase + ME4000_AO_02_CTRL_REG;
390 info->ao_context[i].status_reg =
391 info->me4000_regbase + ME4000_AO_02_STATUS_REG;
392 info->ao_context[i].fifo_reg =
393 info->me4000_regbase + ME4000_AO_02_FIFO_REG;
394 info->ao_context[i].single_reg =
395 info->me4000_regbase + ME4000_AO_02_SINGLE_REG;
396 info->ao_context[i].timer_reg =
397 info->me4000_regbase + ME4000_AO_02_TIMER_REG;
398 info->ao_context[i].irq_status_reg =
399 info->me4000_regbase + ME4000_IRQ_STATUS_REG;
400 info->ao_context[i].preload_reg =
401 info->me4000_regbase + ME4000_AO_LOADSETREG_XX;
404 info->ao_context[i].ctrl_reg =
405 info->me4000_regbase + ME4000_AO_03_CTRL_REG;
406 info->ao_context[i].status_reg =
407 info->me4000_regbase + ME4000_AO_03_STATUS_REG;
408 info->ao_context[i].fifo_reg =
409 info->me4000_regbase + ME4000_AO_03_FIFO_REG;
410 info->ao_context[i].single_reg =
411 info->me4000_regbase + ME4000_AO_03_SINGLE_REG;
412 info->ao_context[i].timer_reg =
413 info->me4000_regbase + ME4000_AO_03_TIMER_REG;
414 info->ao_context[i].irq_status_reg =
415 info->me4000_regbase + ME4000_IRQ_STATUS_REG;
416 info->ao_context[i].preload_reg =
417 info->me4000_regbase + ME4000_AO_LOADSETREG_XX;
427 static int init_ai_context(struct comedi_device *dev)
429 info->ai_context.irq = info->irq;
431 info->ai_context.ctrl_reg = info->me4000_regbase + ME4000_AI_CTRL_REG;
432 info->ai_context.status_reg =
433 info->me4000_regbase + ME4000_AI_STATUS_REG;
434 info->ai_context.channel_list_reg =
435 info->me4000_regbase + ME4000_AI_CHANNEL_LIST_REG;
436 info->ai_context.data_reg = info->me4000_regbase + ME4000_AI_DATA_REG;
437 info->ai_context.chan_timer_reg =
438 info->me4000_regbase + ME4000_AI_CHAN_TIMER_REG;
439 info->ai_context.chan_pre_timer_reg =
440 info->me4000_regbase + ME4000_AI_CHAN_PRE_TIMER_REG;
441 info->ai_context.scan_timer_low_reg =
442 info->me4000_regbase + ME4000_AI_SCAN_TIMER_LOW_REG;
443 info->ai_context.scan_timer_high_reg =
444 info->me4000_regbase + ME4000_AI_SCAN_TIMER_HIGH_REG;
445 info->ai_context.scan_pre_timer_low_reg =
446 info->me4000_regbase + ME4000_AI_SCAN_PRE_TIMER_LOW_REG;
447 info->ai_context.scan_pre_timer_high_reg =
448 info->me4000_regbase + ME4000_AI_SCAN_PRE_TIMER_HIGH_REG;
449 info->ai_context.start_reg = info->me4000_regbase + ME4000_AI_START_REG;
450 info->ai_context.irq_status_reg =
451 info->me4000_regbase + ME4000_IRQ_STATUS_REG;
452 info->ai_context.sample_counter_reg =
453 info->me4000_regbase + ME4000_AI_SAMPLE_COUNTER_REG;
458 static int init_dio_context(struct comedi_device *dev)
460 info->dio_context.dir_reg = info->me4000_regbase + ME4000_DIO_DIR_REG;
461 info->dio_context.ctrl_reg = info->me4000_regbase + ME4000_DIO_CTRL_REG;
462 info->dio_context.port_0_reg =
463 info->me4000_regbase + ME4000_DIO_PORT_0_REG;
464 info->dio_context.port_1_reg =
465 info->me4000_regbase + ME4000_DIO_PORT_1_REG;
466 info->dio_context.port_2_reg =
467 info->me4000_regbase + ME4000_DIO_PORT_2_REG;
468 info->dio_context.port_3_reg =
469 info->me4000_regbase + ME4000_DIO_PORT_3_REG;
474 static int init_cnt_context(struct comedi_device *dev)
476 info->cnt_context.ctrl_reg = info->timer_regbase + ME4000_CNT_CTRL_REG;
477 info->cnt_context.counter_0_reg =
478 info->timer_regbase + ME4000_CNT_COUNTER_0_REG;
479 info->cnt_context.counter_1_reg =
480 info->timer_regbase + ME4000_CNT_COUNTER_1_REG;
481 info->cnt_context.counter_2_reg =
482 info->timer_regbase + ME4000_CNT_COUNTER_2_REG;
487 #define FIRMWARE_NOT_AVAILABLE 1
488 #if FIRMWARE_NOT_AVAILABLE
489 extern unsigned char *xilinx_firm;
492 static int xilinx_download(struct comedi_device *dev)
495 wait_queue_head_t queue;
499 init_waitqueue_head(&queue);
502 * Set PLX local interrupt 2 polarity to high.
503 * Interrupt is thrown by init pin of xilinx.
505 outl(0x10, info->plx_regbase + PLX_INTCSR);
507 /* Set /CS and /WRITE of the Xilinx */
508 value = inl(info->plx_regbase + PLX_ICR);
510 outl(value, info->plx_regbase + PLX_ICR);
512 /* Init Xilinx with CS1 */
513 inb(info->program_regbase + 0xC8);
515 /* Wait until /INIT pin is set */
517 if (!(inl(info->plx_regbase + PLX_INTCSR) & 0x20)) {
519 "comedi%d: me4000: xilinx_download(): "
520 "Can't init Xilinx\n", dev->minor);
524 /* Reset /CS and /WRITE of the Xilinx */
525 value = inl(info->plx_regbase + PLX_ICR);
527 outl(value, info->plx_regbase + PLX_ICR);
528 if (FIRMWARE_NOT_AVAILABLE) {
529 comedi_error(dev, "xilinx firmware unavailable "
530 "due to licensing, aborting");
533 /* Download Xilinx firmware */
534 size = (xilinx_firm[0] << 24) + (xilinx_firm[1] << 16) +
535 (xilinx_firm[2] << 8) + xilinx_firm[3];
538 for (idx = 0; idx < size; idx++) {
539 outb(xilinx_firm[16 + idx], info->program_regbase);
542 /* Check if BUSY flag is low */
543 if (inl(info->plx_regbase + PLX_ICR) & 0x20) {
545 "comedi%d: me4000: xilinx_download(): "
546 "Xilinx is still busy (idx = %d)\n",
553 /* If done flag is high download was successful */
554 if (inl(info->plx_regbase + PLX_ICR) & 0x4) {
557 "comedi%d: me4000: xilinx_download(): "
558 "DONE flag is not set\n", dev->minor);
560 "comedi%d: me4000: xilinx_download(): "
561 "Download not successful\n", dev->minor);
565 /* Set /CS and /WRITE */
566 value = inl(info->plx_regbase + PLX_ICR);
568 outl(value, info->plx_regbase + PLX_ICR);
573 static int reset_board(struct comedi_device *dev)
577 /* Make a hardware reset */
578 icr = inl(info->plx_regbase + PLX_ICR);
580 outl(icr, info->plx_regbase + PLX_ICR);
582 outl(icr, info->plx_regbase + PLX_ICR);
584 /* 0x8000 to the DACs means an output voltage of 0V */
585 outl(0x8000, info->me4000_regbase + ME4000_AO_00_SINGLE_REG);
586 outl(0x8000, info->me4000_regbase + ME4000_AO_01_SINGLE_REG);
587 outl(0x8000, info->me4000_regbase + ME4000_AO_02_SINGLE_REG);
588 outl(0x8000, info->me4000_regbase + ME4000_AO_03_SINGLE_REG);
590 /* Set both stop bits in the analog input control register */
591 outl(ME4000_AI_CTRL_BIT_IMMEDIATE_STOP | ME4000_AI_CTRL_BIT_STOP,
592 info->me4000_regbase + ME4000_AI_CTRL_REG);
594 /* Set both stop bits in the analog output control register */
595 outl(ME4000_AO_CTRL_BIT_IMMEDIATE_STOP | ME4000_AO_CTRL_BIT_STOP,
596 info->me4000_regbase + ME4000_AO_00_CTRL_REG);
597 outl(ME4000_AO_CTRL_BIT_IMMEDIATE_STOP | ME4000_AO_CTRL_BIT_STOP,
598 info->me4000_regbase + ME4000_AO_01_CTRL_REG);
599 outl(ME4000_AO_CTRL_BIT_IMMEDIATE_STOP | ME4000_AO_CTRL_BIT_STOP,
600 info->me4000_regbase + ME4000_AO_02_CTRL_REG);
601 outl(ME4000_AO_CTRL_BIT_IMMEDIATE_STOP | ME4000_AO_CTRL_BIT_STOP,
602 info->me4000_regbase + ME4000_AO_03_CTRL_REG);
604 /* Enable interrupts on the PLX */
605 outl(0x43, info->plx_regbase + PLX_INTCSR);
607 /* Set the adustment register for AO demux */
608 outl(ME4000_AO_DEMUX_ADJUST_VALUE,
609 info->me4000_regbase + ME4000_AO_DEMUX_ADJUST_REG);
612 * Set digital I/O direction for port 0
613 * to output on isolated versions
615 if (!(inl(info->me4000_regbase + ME4000_DIO_DIR_REG) & 0x1))
616 outl(0x1, info->me4000_regbase + ME4000_DIO_CTRL_REG);
621 /*=============================================================================
623 ===========================================================================*/
625 static int me4000_ai_insn_read(struct comedi_device *dev,
626 struct comedi_subdevice *subdevice,
627 struct comedi_insn *insn, unsigned int *data)
630 int chan = CR_CHAN(insn->chanspec);
631 int rang = CR_RANGE(insn->chanspec);
632 int aref = CR_AREF(insn->chanspec);
634 unsigned long entry = 0;
640 } else if (insn->n > 1) {
642 "comedi%d: me4000: me4000_ai_insn_read(): "
643 "Invalid instruction length %d\n", dev->minor, insn->n);
649 entry |= ME4000_AI_LIST_RANGE_UNIPOLAR_2_5;
652 entry |= ME4000_AI_LIST_RANGE_UNIPOLAR_10;
655 entry |= ME4000_AI_LIST_RANGE_BIPOLAR_2_5;
658 entry |= ME4000_AI_LIST_RANGE_BIPOLAR_10;
662 "comedi%d: me4000: me4000_ai_insn_read(): "
663 "Invalid range specified\n", dev->minor);
670 if (chan >= thisboard->ai.count) {
672 "comedi%d: me4000: me4000_ai_insn_read(): "
673 "Analog input is not available\n", dev->minor);
676 entry |= ME4000_AI_LIST_INPUT_SINGLE_ENDED | chan;
680 if (rang == 0 || rang == 1) {
682 "comedi%d: me4000: me4000_ai_insn_read(): "
683 "Range must be bipolar when aref = diff\n",
688 if (chan >= thisboard->ai.diff_count) {
690 "comedi%d: me4000: me4000_ai_insn_read(): "
691 "Analog input is not available\n", dev->minor);
694 entry |= ME4000_AI_LIST_INPUT_DIFFERENTIAL | chan;
698 "comedi%d: me4000: me4000_ai_insn_read(): "
699 "Invalid aref specified\n", dev->minor);
703 entry |= ME4000_AI_LIST_LAST_ENTRY;
705 /* Clear channel list, data fifo and both stop bits */
706 tmp = inl(info->ai_context.ctrl_reg);
707 tmp &= ~(ME4000_AI_CTRL_BIT_CHANNEL_FIFO |
708 ME4000_AI_CTRL_BIT_DATA_FIFO |
709 ME4000_AI_CTRL_BIT_STOP | ME4000_AI_CTRL_BIT_IMMEDIATE_STOP);
710 outl(tmp, info->ai_context.ctrl_reg);
712 /* Set the acquisition mode to single */
713 tmp &= ~(ME4000_AI_CTRL_BIT_MODE_0 | ME4000_AI_CTRL_BIT_MODE_1 |
714 ME4000_AI_CTRL_BIT_MODE_2);
715 outl(tmp, info->ai_context.ctrl_reg);
717 /* Enable channel list and data fifo */
718 tmp |= ME4000_AI_CTRL_BIT_CHANNEL_FIFO | ME4000_AI_CTRL_BIT_DATA_FIFO;
719 outl(tmp, info->ai_context.ctrl_reg);
721 /* Generate channel list entry */
722 outl(entry, info->ai_context.channel_list_reg);
724 /* Set the timer to maximum sample rate */
725 outl(ME4000_AI_MIN_TICKS, info->ai_context.chan_timer_reg);
726 outl(ME4000_AI_MIN_TICKS, info->ai_context.chan_pre_timer_reg);
728 /* Start conversion by dummy read */
729 inl(info->ai_context.start_reg);
731 /* Wait until ready */
733 if (!(inl(info->ai_context.status_reg) &
734 ME4000_AI_STATUS_BIT_EF_DATA)) {
736 "comedi%d: me4000: me4000_ai_insn_read(): "
737 "Value not available after wait\n", dev->minor);
741 /* Read value from data fifo */
742 lval = inl(info->ai_context.data_reg) & 0xFFFF;
743 data[0] = lval ^ 0x8000;
748 static int me4000_ai_cancel(struct comedi_device *dev,
749 struct comedi_subdevice *s)
753 /* Stop any running conversion */
754 tmp = inl(info->ai_context.ctrl_reg);
755 tmp &= ~(ME4000_AI_CTRL_BIT_STOP | ME4000_AI_CTRL_BIT_IMMEDIATE_STOP);
756 outl(tmp, info->ai_context.ctrl_reg);
758 /* Clear the control register */
759 outl(0x0, info->ai_context.ctrl_reg);
764 static int ai_check_chanlist(struct comedi_device *dev,
765 struct comedi_subdevice *s, struct comedi_cmd *cmd)
770 /* Check whether a channel list is available */
771 if (!cmd->chanlist_len) {
773 "comedi%d: me4000: ai_check_chanlist(): "
774 "No channel list available\n", dev->minor);
778 /* Check the channel list size */
779 if (cmd->chanlist_len > ME4000_AI_CHANNEL_LIST_COUNT) {
781 "comedi%d: me4000: ai_check_chanlist(): "
782 "Channel list is to large\n", dev->minor);
786 /* Check the pointer */
787 if (!cmd->chanlist) {
789 "comedi%d: me4000: ai_check_chanlist(): "
790 "NULL pointer to channel list\n", dev->minor);
794 /* Check whether aref is equal for all entries */
795 aref = CR_AREF(cmd->chanlist[0]);
796 for (i = 0; i < cmd->chanlist_len; i++) {
797 if (CR_AREF(cmd->chanlist[i]) != aref) {
799 "comedi%d: me4000: ai_check_chanlist(): "
800 "Mode is not equal for all entries\n",
806 /* Check whether channels are available for this ending */
807 if (aref == SDF_DIFF) {
808 for (i = 0; i < cmd->chanlist_len; i++) {
809 if (CR_CHAN(cmd->chanlist[i]) >=
810 thisboard->ai.diff_count) {
812 "comedi%d: me4000: ai_check_chanlist():"
813 " Channel number to high\n", dev->minor);
818 for (i = 0; i < cmd->chanlist_len; i++) {
819 if (CR_CHAN(cmd->chanlist[i]) >= thisboard->ai.count) {
821 "comedi%d: me4000: ai_check_chanlist(): "
822 "Channel number to high\n", dev->minor);
828 /* Check if bipolar is set for all entries when in differential mode */
829 if (aref == SDF_DIFF) {
830 for (i = 0; i < cmd->chanlist_len; i++) {
831 if (CR_RANGE(cmd->chanlist[i]) != 1 &&
832 CR_RANGE(cmd->chanlist[i]) != 2) {
834 "comedi%d: me4000: ai_check_chanlist(): "
835 "Bipolar is not selected in "
836 "differential mode\n",
846 static int ai_round_cmd_args(struct comedi_device *dev,
847 struct comedi_subdevice *s,
848 struct comedi_cmd *cmd,
849 unsigned int *init_ticks,
850 unsigned int *scan_ticks, unsigned int *chan_ticks)
859 if (cmd->start_arg) {
860 *init_ticks = (cmd->start_arg * 33) / 1000;
861 rest = (cmd->start_arg * 33) % 1000;
863 if ((cmd->flags & TRIG_ROUND_MASK) == TRIG_ROUND_NEAREST) {
866 } else if ((cmd->flags & TRIG_ROUND_MASK) == TRIG_ROUND_UP) {
872 if (cmd->scan_begin_arg) {
873 *scan_ticks = (cmd->scan_begin_arg * 33) / 1000;
874 rest = (cmd->scan_begin_arg * 33) % 1000;
876 if ((cmd->flags & TRIG_ROUND_MASK) == TRIG_ROUND_NEAREST) {
879 } else if ((cmd->flags & TRIG_ROUND_MASK) == TRIG_ROUND_UP) {
885 if (cmd->convert_arg) {
886 *chan_ticks = (cmd->convert_arg * 33) / 1000;
887 rest = (cmd->convert_arg * 33) % 1000;
889 if ((cmd->flags & TRIG_ROUND_MASK) == TRIG_ROUND_NEAREST) {
892 } else if ((cmd->flags & TRIG_ROUND_MASK) == TRIG_ROUND_UP) {
901 static void ai_write_timer(struct comedi_device *dev,
902 unsigned int init_ticks,
903 unsigned int scan_ticks, unsigned int chan_ticks)
905 outl(init_ticks - 1, info->ai_context.scan_pre_timer_low_reg);
906 outl(0x0, info->ai_context.scan_pre_timer_high_reg);
909 outl(scan_ticks - 1, info->ai_context.scan_timer_low_reg);
910 outl(0x0, info->ai_context.scan_timer_high_reg);
913 outl(chan_ticks - 1, info->ai_context.chan_pre_timer_reg);
914 outl(chan_ticks - 1, info->ai_context.chan_timer_reg);
917 static int ai_prepare(struct comedi_device *dev,
918 struct comedi_subdevice *s,
919 struct comedi_cmd *cmd,
920 unsigned int init_ticks,
921 unsigned int scan_ticks, unsigned int chan_ticks)
924 unsigned long tmp = 0;
926 /* Write timer arguments */
927 ai_write_timer(dev, init_ticks, scan_ticks, chan_ticks);
929 /* Reset control register */
930 outl(tmp, info->ai_context.ctrl_reg);
933 if ((cmd->start_src == TRIG_EXT &&
934 cmd->scan_begin_src == TRIG_TIMER &&
935 cmd->convert_src == TRIG_TIMER) ||
936 (cmd->start_src == TRIG_EXT &&
937 cmd->scan_begin_src == TRIG_FOLLOW &&
938 cmd->convert_src == TRIG_TIMER)) {
939 tmp = ME4000_AI_CTRL_BIT_MODE_1 |
940 ME4000_AI_CTRL_BIT_CHANNEL_FIFO |
941 ME4000_AI_CTRL_BIT_DATA_FIFO;
942 } else if (cmd->start_src == TRIG_EXT &&
943 cmd->scan_begin_src == TRIG_EXT &&
944 cmd->convert_src == TRIG_TIMER) {
945 tmp = ME4000_AI_CTRL_BIT_MODE_2 |
946 ME4000_AI_CTRL_BIT_CHANNEL_FIFO |
947 ME4000_AI_CTRL_BIT_DATA_FIFO;
948 } else if (cmd->start_src == TRIG_EXT &&
949 cmd->scan_begin_src == TRIG_EXT &&
950 cmd->convert_src == TRIG_EXT) {
951 tmp = ME4000_AI_CTRL_BIT_MODE_0 |
952 ME4000_AI_CTRL_BIT_MODE_1 |
953 ME4000_AI_CTRL_BIT_CHANNEL_FIFO |
954 ME4000_AI_CTRL_BIT_DATA_FIFO;
956 tmp = ME4000_AI_CTRL_BIT_MODE_0 |
957 ME4000_AI_CTRL_BIT_CHANNEL_FIFO |
958 ME4000_AI_CTRL_BIT_DATA_FIFO;
962 if (cmd->stop_src == TRIG_COUNT) {
963 outl(cmd->chanlist_len * cmd->stop_arg,
964 info->ai_context.sample_counter_reg);
965 tmp |= ME4000_AI_CTRL_BIT_HF_IRQ | ME4000_AI_CTRL_BIT_SC_IRQ;
966 } else if (cmd->stop_src == TRIG_NONE &&
967 cmd->scan_end_src == TRIG_COUNT) {
968 outl(cmd->scan_end_arg,
969 info->ai_context.sample_counter_reg);
970 tmp |= ME4000_AI_CTRL_BIT_HF_IRQ | ME4000_AI_CTRL_BIT_SC_IRQ;
972 tmp |= ME4000_AI_CTRL_BIT_HF_IRQ;
975 /* Write the setup to the control register */
976 outl(tmp, info->ai_context.ctrl_reg);
978 /* Write the channel list */
979 ai_write_chanlist(dev, s, cmd);
984 static int ai_write_chanlist(struct comedi_device *dev,
985 struct comedi_subdevice *s, struct comedi_cmd *cmd)
993 for (i = 0; i < cmd->chanlist_len; i++) {
994 chan = CR_CHAN(cmd->chanlist[i]);
995 rang = CR_RANGE(cmd->chanlist[i]);
996 aref = CR_AREF(cmd->chanlist[i]);
1001 entry |= ME4000_AI_LIST_RANGE_UNIPOLAR_2_5;
1003 entry |= ME4000_AI_LIST_RANGE_UNIPOLAR_10;
1005 entry |= ME4000_AI_LIST_RANGE_BIPOLAR_2_5;
1007 entry |= ME4000_AI_LIST_RANGE_BIPOLAR_10;
1009 if (aref == SDF_DIFF)
1010 entry |= ME4000_AI_LIST_INPUT_DIFFERENTIAL;
1012 entry |= ME4000_AI_LIST_INPUT_SINGLE_ENDED;
1014 outl(entry, info->ai_context.channel_list_reg);
1020 static int me4000_ai_do_cmd(struct comedi_device *dev,
1021 struct comedi_subdevice *s)
1024 unsigned int init_ticks = 0;
1025 unsigned int scan_ticks = 0;
1026 unsigned int chan_ticks = 0;
1027 struct comedi_cmd *cmd = &s->async->cmd;
1029 /* Reset the analog input */
1030 err = me4000_ai_cancel(dev, s);
1034 /* Round the timer arguments */
1035 err = ai_round_cmd_args(dev,
1036 s, cmd, &init_ticks, &scan_ticks, &chan_ticks);
1040 /* Prepare the AI for acquisition */
1041 err = ai_prepare(dev, s, cmd, init_ticks, scan_ticks, chan_ticks);
1045 /* Start acquistion by dummy read */
1046 inl(info->ai_context.start_reg);
1052 * me4000_ai_do_cmd_test():
1054 * The demo cmd.c in ./comedilib/demo specifies 6 return values:
1058 * - invalid argument
1059 * - argument conflict
1060 * - invalid chanlist
1061 * So I tried to adopt this scheme.
1063 static int me4000_ai_do_cmd_test(struct comedi_device *dev,
1064 struct comedi_subdevice *s,
1065 struct comedi_cmd *cmd)
1068 unsigned int init_ticks;
1069 unsigned int chan_ticks;
1070 unsigned int scan_ticks;
1073 /* Only rounding flags are implemented */
1074 cmd->flags &= TRIG_ROUND_NEAREST | TRIG_ROUND_UP | TRIG_ROUND_DOWN;
1076 /* Round the timer arguments */
1077 ai_round_cmd_args(dev, s, cmd, &init_ticks, &scan_ticks, &chan_ticks);
1080 * Stage 1. Check if the trigger sources are generally valid.
1082 switch (cmd->start_src) {
1087 cmd->start_src &= TRIG_NOW | TRIG_EXT;
1092 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1093 "Invalid start source\n", dev->minor);
1094 cmd->start_src = TRIG_NOW;
1097 switch (cmd->scan_begin_src) {
1103 cmd->scan_begin_src &= TRIG_FOLLOW | TRIG_TIMER | TRIG_EXT;
1108 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1109 "Invalid scan begin source\n", dev->minor);
1110 cmd->scan_begin_src = TRIG_FOLLOW;
1113 switch (cmd->convert_src) {
1118 cmd->convert_src &= TRIG_TIMER | TRIG_EXT;
1123 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1124 "Invalid convert source\n", dev->minor);
1125 cmd->convert_src = TRIG_TIMER;
1128 switch (cmd->scan_end_src) {
1133 cmd->scan_end_src &= TRIG_NONE | TRIG_COUNT;
1138 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1139 "Invalid scan end source\n", dev->minor);
1140 cmd->scan_end_src = TRIG_NONE;
1143 switch (cmd->stop_src) {
1148 cmd->stop_src &= TRIG_NONE | TRIG_COUNT;
1153 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1154 "Invalid stop source\n", dev->minor);
1155 cmd->stop_src = TRIG_NONE;
1162 * Stage 2. Check for trigger source conflicts.
1164 if (cmd->start_src == TRIG_NOW &&
1165 cmd->scan_begin_src == TRIG_TIMER &&
1166 cmd->convert_src == TRIG_TIMER) {
1167 } else if (cmd->start_src == TRIG_NOW &&
1168 cmd->scan_begin_src == TRIG_FOLLOW &&
1169 cmd->convert_src == TRIG_TIMER) {
1170 } else if (cmd->start_src == TRIG_EXT &&
1171 cmd->scan_begin_src == TRIG_TIMER &&
1172 cmd->convert_src == TRIG_TIMER) {
1173 } else if (cmd->start_src == TRIG_EXT &&
1174 cmd->scan_begin_src == TRIG_FOLLOW &&
1175 cmd->convert_src == TRIG_TIMER) {
1176 } else if (cmd->start_src == TRIG_EXT &&
1177 cmd->scan_begin_src == TRIG_EXT &&
1178 cmd->convert_src == TRIG_TIMER) {
1179 } else if (cmd->start_src == TRIG_EXT &&
1180 cmd->scan_begin_src == TRIG_EXT &&
1181 cmd->convert_src == TRIG_EXT) {
1184 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1185 "Invalid start trigger combination\n", dev->minor);
1186 cmd->start_src = TRIG_NOW;
1187 cmd->scan_begin_src = TRIG_FOLLOW;
1188 cmd->convert_src = TRIG_TIMER;
1192 if (cmd->stop_src == TRIG_NONE && cmd->scan_end_src == TRIG_NONE) {
1193 } else if (cmd->stop_src == TRIG_COUNT &&
1194 cmd->scan_end_src == TRIG_NONE) {
1195 } else if (cmd->stop_src == TRIG_NONE &&
1196 cmd->scan_end_src == TRIG_COUNT) {
1197 } else if (cmd->stop_src == TRIG_COUNT &&
1198 cmd->scan_end_src == TRIG_COUNT) {
1201 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1202 "Invalid stop trigger combination\n", dev->minor);
1203 cmd->stop_src = TRIG_NONE;
1204 cmd->scan_end_src = TRIG_NONE;
1211 * Stage 3. Check if arguments are generally valid.
1213 if (cmd->chanlist_len < 1) {
1215 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1216 "No channel list\n", dev->minor);
1217 cmd->chanlist_len = 1;
1220 if (init_ticks < 66) {
1222 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1223 "Start arg to low\n", dev->minor);
1224 cmd->start_arg = 2000;
1227 if (scan_ticks && scan_ticks < 67) {
1229 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1230 "Scan begin arg to low\n", dev->minor);
1231 cmd->scan_begin_arg = 2031;
1234 if (chan_ticks < 66) {
1236 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1237 "Convert arg to low\n", dev->minor);
1238 cmd->convert_arg = 2000;
1246 * Stage 4. Check for argument conflicts.
1248 if (cmd->start_src == TRIG_NOW &&
1249 cmd->scan_begin_src == TRIG_TIMER &&
1250 cmd->convert_src == TRIG_TIMER) {
1252 /* Check timer arguments */
1253 if (init_ticks < ME4000_AI_MIN_TICKS) {
1255 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1256 "Invalid start arg\n", dev->minor);
1257 cmd->start_arg = 2000; /* 66 ticks at least */
1260 if (chan_ticks < ME4000_AI_MIN_TICKS) {
1262 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1263 "Invalid convert arg\n", dev->minor);
1264 cmd->convert_arg = 2000; /* 66 ticks at least */
1267 if (scan_ticks <= cmd->chanlist_len * chan_ticks) {
1269 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1270 "Invalid scan end arg\n", dev->minor);
1272 /* At least one tick more */
1273 cmd->scan_end_arg = 2000 * cmd->chanlist_len + 31;
1276 } else if (cmd->start_src == TRIG_NOW &&
1277 cmd->scan_begin_src == TRIG_FOLLOW &&
1278 cmd->convert_src == TRIG_TIMER) {
1280 /* Check timer arguments */
1281 if (init_ticks < ME4000_AI_MIN_TICKS) {
1283 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1284 "Invalid start arg\n", dev->minor);
1285 cmd->start_arg = 2000; /* 66 ticks at least */
1288 if (chan_ticks < ME4000_AI_MIN_TICKS) {
1290 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1291 "Invalid convert arg\n", dev->minor);
1292 cmd->convert_arg = 2000; /* 66 ticks at least */
1295 } else if (cmd->start_src == TRIG_EXT &&
1296 cmd->scan_begin_src == TRIG_TIMER &&
1297 cmd->convert_src == TRIG_TIMER) {
1299 /* Check timer arguments */
1300 if (init_ticks < ME4000_AI_MIN_TICKS) {
1302 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1303 "Invalid start arg\n", dev->minor);
1304 cmd->start_arg = 2000; /* 66 ticks at least */
1307 if (chan_ticks < ME4000_AI_MIN_TICKS) {
1309 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1310 "Invalid convert arg\n", dev->minor);
1311 cmd->convert_arg = 2000; /* 66 ticks at least */
1314 if (scan_ticks <= cmd->chanlist_len * chan_ticks) {
1316 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1317 "Invalid scan end arg\n", dev->minor);
1319 /* At least one tick more */
1320 cmd->scan_end_arg = 2000 * cmd->chanlist_len + 31;
1323 } else if (cmd->start_src == TRIG_EXT &&
1324 cmd->scan_begin_src == TRIG_FOLLOW &&
1325 cmd->convert_src == TRIG_TIMER) {
1327 /* Check timer arguments */
1328 if (init_ticks < ME4000_AI_MIN_TICKS) {
1330 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1331 "Invalid start arg\n", dev->minor);
1332 cmd->start_arg = 2000; /* 66 ticks at least */
1335 if (chan_ticks < ME4000_AI_MIN_TICKS) {
1337 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1338 "Invalid convert arg\n", dev->minor);
1339 cmd->convert_arg = 2000; /* 66 ticks at least */
1342 } else if (cmd->start_src == TRIG_EXT &&
1343 cmd->scan_begin_src == TRIG_EXT &&
1344 cmd->convert_src == TRIG_TIMER) {
1346 /* Check timer arguments */
1347 if (init_ticks < ME4000_AI_MIN_TICKS) {
1349 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1350 "Invalid start arg\n", dev->minor);
1351 cmd->start_arg = 2000; /* 66 ticks at least */
1354 if (chan_ticks < ME4000_AI_MIN_TICKS) {
1356 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1357 "Invalid convert arg\n", dev->minor);
1358 cmd->convert_arg = 2000; /* 66 ticks at least */
1361 } else if (cmd->start_src == TRIG_EXT &&
1362 cmd->scan_begin_src == TRIG_EXT &&
1363 cmd->convert_src == TRIG_EXT) {
1365 /* Check timer arguments */
1366 if (init_ticks < ME4000_AI_MIN_TICKS) {
1368 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1369 "Invalid start arg\n", dev->minor);
1370 cmd->start_arg = 2000; /* 66 ticks at least */
1374 if (cmd->stop_src == TRIG_COUNT) {
1375 if (cmd->stop_arg == 0) {
1377 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1378 "Invalid stop arg\n", dev->minor);
1383 if (cmd->scan_end_src == TRIG_COUNT) {
1384 if (cmd->scan_end_arg == 0) {
1386 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1387 "Invalid scan end arg\n", dev->minor);
1388 cmd->scan_end_arg = 1;
1397 * Stage 5. Check the channel list.
1399 if (ai_check_chanlist(dev, s, cmd))
1405 static irqreturn_t me4000_ai_isr(int irq, void *dev_id)
1408 struct comedi_device *dev = dev_id;
1409 struct comedi_subdevice *s = &dev->subdevices[0];
1410 struct me4000_ai_context *ai_context = &info->ai_context;
1418 /* Reset all events */
1419 s->async->events = 0;
1421 /* Check if irq number is right */
1422 if (irq != ai_context->irq) {
1424 "comedi%d: me4000: me4000_ai_isr(): "
1425 "Incorrect interrupt num: %d\n", dev->minor, irq);
1429 if (inl(ai_context->irq_status_reg) &
1430 ME4000_IRQ_STATUS_BIT_AI_HF) {
1431 /* Read status register to find out what happened */
1432 tmp = inl(ai_context->ctrl_reg);
1434 if (!(tmp & ME4000_AI_STATUS_BIT_FF_DATA) &&
1435 !(tmp & ME4000_AI_STATUS_BIT_HF_DATA) &&
1436 (tmp & ME4000_AI_STATUS_BIT_EF_DATA)) {
1437 c = ME4000_AI_FIFO_COUNT;
1440 * FIFO overflow, so stop conversion
1441 * and disable all interrupts
1443 tmp |= ME4000_AI_CTRL_BIT_IMMEDIATE_STOP;
1444 tmp &= ~(ME4000_AI_CTRL_BIT_HF_IRQ |
1445 ME4000_AI_CTRL_BIT_SC_IRQ);
1446 outl(tmp, ai_context->ctrl_reg);
1448 s->async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
1451 "comedi%d: me4000: me4000_ai_isr(): "
1452 "FIFO overflow\n", dev->minor);
1453 } else if ((tmp & ME4000_AI_STATUS_BIT_FF_DATA)
1454 && !(tmp & ME4000_AI_STATUS_BIT_HF_DATA)
1455 && (tmp & ME4000_AI_STATUS_BIT_EF_DATA)) {
1456 s->async->events |= COMEDI_CB_BLOCK;
1458 c = ME4000_AI_FIFO_COUNT / 2;
1461 "comedi%d: me4000: me4000_ai_isr(): "
1462 "Can't determine state of fifo\n", dev->minor);
1466 * Undefined state, so stop conversion
1467 * and disable all interrupts
1469 tmp |= ME4000_AI_CTRL_BIT_IMMEDIATE_STOP;
1470 tmp &= ~(ME4000_AI_CTRL_BIT_HF_IRQ |
1471 ME4000_AI_CTRL_BIT_SC_IRQ);
1472 outl(tmp, ai_context->ctrl_reg);
1474 s->async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
1477 "comedi%d: me4000: me4000_ai_isr(): "
1478 "Undefined FIFO state\n", dev->minor);
1481 for (i = 0; i < c; i++) {
1482 /* Read value from data fifo */
1483 lval = inl(ai_context->data_reg) & 0xFFFF;
1486 if (!comedi_buf_put(s->async, lval)) {
1488 * Buffer overflow, so stop conversion
1489 * and disable all interrupts
1491 tmp |= ME4000_AI_CTRL_BIT_IMMEDIATE_STOP;
1492 tmp &= ~(ME4000_AI_CTRL_BIT_HF_IRQ |
1493 ME4000_AI_CTRL_BIT_SC_IRQ);
1494 outl(tmp, ai_context->ctrl_reg);
1496 s->async->events |= COMEDI_CB_OVERFLOW;
1499 "comedi%d: me4000: me4000_ai_isr(): "
1500 "Buffer overflow\n", dev->minor);
1506 /* Work is done, so reset the interrupt */
1507 tmp |= ME4000_AI_CTRL_BIT_HF_IRQ_RESET;
1508 outl(tmp, ai_context->ctrl_reg);
1509 tmp &= ~ME4000_AI_CTRL_BIT_HF_IRQ_RESET;
1510 outl(tmp, ai_context->ctrl_reg);
1513 if (inl(ai_context->irq_status_reg) & ME4000_IRQ_STATUS_BIT_SC) {
1514 s->async->events |= COMEDI_CB_BLOCK | COMEDI_CB_EOA;
1517 * Acquisition is complete, so stop
1518 * conversion and disable all interrupts
1520 tmp = inl(ai_context->ctrl_reg);
1521 tmp |= ME4000_AI_CTRL_BIT_IMMEDIATE_STOP;
1522 tmp &= ~(ME4000_AI_CTRL_BIT_HF_IRQ | ME4000_AI_CTRL_BIT_SC_IRQ);
1523 outl(tmp, ai_context->ctrl_reg);
1525 /* Poll data until fifo empty */
1526 while (inl(ai_context->ctrl_reg) & ME4000_AI_STATUS_BIT_EF_DATA) {
1527 /* Read value from data fifo */
1528 lval = inl(ai_context->data_reg) & 0xFFFF;
1531 if (!comedi_buf_put(s->async, lval)) {
1533 "comedi%d: me4000: me4000_ai_isr(): "
1534 "Buffer overflow\n", dev->minor);
1535 s->async->events |= COMEDI_CB_OVERFLOW;
1540 /* Work is done, so reset the interrupt */
1541 tmp |= ME4000_AI_CTRL_BIT_SC_IRQ_RESET;
1542 outl(tmp, ai_context->ctrl_reg);
1543 tmp &= ~ME4000_AI_CTRL_BIT_SC_IRQ_RESET;
1544 outl(tmp, ai_context->ctrl_reg);
1547 if (s->async->events)
1548 comedi_event(dev, s);
1553 /*=============================================================================
1554 Analog output section
1555 ===========================================================================*/
1557 static int me4000_ao_insn_write(struct comedi_device *dev,
1558 struct comedi_subdevice *s,
1559 struct comedi_insn *insn, unsigned int *data)
1562 int chan = CR_CHAN(insn->chanspec);
1563 int rang = CR_RANGE(insn->chanspec);
1564 int aref = CR_AREF(insn->chanspec);
1569 } else if (insn->n > 1) {
1571 "comedi%d: me4000: me4000_ao_insn_write(): "
1572 "Invalid instruction length %d\n", dev->minor, insn->n);
1576 if (chan >= thisboard->ao.count) {
1578 "comedi%d: me4000: me4000_ao_insn_write(): "
1579 "Invalid channel %d\n", dev->minor, insn->n);
1585 "comedi%d: me4000: me4000_ao_insn_write(): "
1586 "Invalid range %d\n", dev->minor, insn->n);
1590 if (aref != AREF_GROUND && aref != AREF_COMMON) {
1592 "comedi%d: me4000: me4000_ao_insn_write(): "
1593 "Invalid aref %d\n", dev->minor, insn->n);
1597 /* Stop any running conversion */
1598 tmp = inl(info->ao_context[chan].ctrl_reg);
1599 tmp |= ME4000_AO_CTRL_BIT_IMMEDIATE_STOP;
1600 outl(tmp, info->ao_context[chan].ctrl_reg);
1602 /* Clear control register and set to single mode */
1603 outl(0x0, info->ao_context[chan].ctrl_reg);
1605 /* Write data value */
1606 outl(data[0], info->ao_context[chan].single_reg);
1608 /* Store in the mirror */
1609 info->ao_context[chan].mirror = data[0];
1614 static int me4000_ao_insn_read(struct comedi_device *dev,
1615 struct comedi_subdevice *s,
1616 struct comedi_insn *insn, unsigned int *data)
1618 int chan = CR_CHAN(insn->chanspec);
1622 } else if (insn->n > 1) {
1624 ("comedi%d: me4000: me4000_ao_insn_read(): "
1625 "Invalid instruction length\n", dev->minor);
1629 data[0] = info->ao_context[chan].mirror;
1634 /*=============================================================================
1636 ===========================================================================*/
1638 static int me4000_dio_insn_bits(struct comedi_device *dev,
1639 struct comedi_subdevice *s,
1640 struct comedi_insn *insn, unsigned int *data)
1643 * The insn data consists of a mask in data[0] and the new data
1644 * in data[1]. The mask defines which bits we are concerning about.
1645 * The new data must be anded with the mask.
1646 * Each channel corresponds to a bit.
1649 /* Check if requested ports are configured for output */
1650 if ((s->io_bits & data[0]) != data[0])
1653 s->state &= ~data[0];
1654 s->state |= data[0] & data[1];
1656 /* Write out the new digital output lines */
1657 outl((s->state >> 0) & 0xFF,
1658 info->dio_context.port_0_reg);
1659 outl((s->state >> 8) & 0xFF,
1660 info->dio_context.port_1_reg);
1661 outl((s->state >> 16) & 0xFF,
1662 info->dio_context.port_2_reg);
1663 outl((s->state >> 24) & 0xFF,
1664 info->dio_context.port_3_reg);
1667 /* On return, data[1] contains the value of
1668 the digital input and output lines. */
1669 data[1] = ((inl(info->dio_context.port_0_reg) & 0xFF) << 0) |
1670 ((inl(info->dio_context.port_1_reg) & 0xFF) << 8) |
1671 ((inl(info->dio_context.port_2_reg) & 0xFF) << 16) |
1672 ((inl(info->dio_context.port_3_reg) & 0xFF) << 24);
1677 static int me4000_dio_insn_config(struct comedi_device *dev,
1678 struct comedi_subdevice *s,
1679 struct comedi_insn *insn, unsigned int *data)
1682 int chan = CR_CHAN(insn->chanspec);
1687 case INSN_CONFIG_DIO_QUERY:
1689 (s->io_bits & (1 << chan)) ? COMEDI_OUTPUT : COMEDI_INPUT;
1691 case INSN_CONFIG_DIO_INPUT:
1692 case INSN_CONFIG_DIO_OUTPUT:
1697 * The input or output configuration of each digital line is
1698 * configured by a special insn_config instruction. chanspec
1699 * contains the channel to be changed, and data[0] contains the
1700 * value INSN_CONFIG_DIO_INPUT or INSN_CONFIG_DIO_OUTPUT.
1701 * On the ME-4000 it is only possible to switch port wise (8 bit)
1704 tmp = inl(info->dio_context.ctrl_reg);
1706 if (data[0] == INSN_CONFIG_DIO_OUTPUT) {
1709 tmp &= ~(ME4000_DIO_CTRL_BIT_MODE_0 |
1710 ME4000_DIO_CTRL_BIT_MODE_1);
1711 tmp |= ME4000_DIO_CTRL_BIT_MODE_0;
1712 } else if (chan < 16) {
1714 * Chech for optoisolated ME-4000 version.
1715 * If one the first port is a fixed output
1716 * port and the second is a fixed input port.
1718 if (!inl(info->dio_context.dir_reg))
1721 s->io_bits |= 0xFF00;
1722 tmp &= ~(ME4000_DIO_CTRL_BIT_MODE_2 |
1723 ME4000_DIO_CTRL_BIT_MODE_3);
1724 tmp |= ME4000_DIO_CTRL_BIT_MODE_2;
1725 } else if (chan < 24) {
1726 s->io_bits |= 0xFF0000;
1727 tmp &= ~(ME4000_DIO_CTRL_BIT_MODE_4 |
1728 ME4000_DIO_CTRL_BIT_MODE_5);
1729 tmp |= ME4000_DIO_CTRL_BIT_MODE_4;
1730 } else if (chan < 32) {
1731 s->io_bits |= 0xFF000000;
1732 tmp &= ~(ME4000_DIO_CTRL_BIT_MODE_6 |
1733 ME4000_DIO_CTRL_BIT_MODE_7);
1734 tmp |= ME4000_DIO_CTRL_BIT_MODE_6;
1741 * Chech for optoisolated ME-4000 version.
1742 * If one the first port is a fixed output
1743 * port and the second is a fixed input port.
1745 if (!inl(info->dio_context.dir_reg))
1748 s->io_bits &= ~0xFF;
1749 tmp &= ~(ME4000_DIO_CTRL_BIT_MODE_0 |
1750 ME4000_DIO_CTRL_BIT_MODE_1);
1751 } else if (chan < 16) {
1752 s->io_bits &= ~0xFF00;
1753 tmp &= ~(ME4000_DIO_CTRL_BIT_MODE_2 |
1754 ME4000_DIO_CTRL_BIT_MODE_3);
1755 } else if (chan < 24) {
1756 s->io_bits &= ~0xFF0000;
1757 tmp &= ~(ME4000_DIO_CTRL_BIT_MODE_4 |
1758 ME4000_DIO_CTRL_BIT_MODE_5);
1759 } else if (chan < 32) {
1760 s->io_bits &= ~0xFF000000;
1761 tmp &= ~(ME4000_DIO_CTRL_BIT_MODE_6 |
1762 ME4000_DIO_CTRL_BIT_MODE_7);
1768 outl(tmp, info->dio_context.ctrl_reg);
1773 /*=============================================================================
1775 ===========================================================================*/
1777 static int cnt_reset(struct comedi_device *dev, unsigned int channel)
1781 outb(0x30, info->cnt_context.ctrl_reg);
1782 outb(0x00, info->cnt_context.counter_0_reg);
1783 outb(0x00, info->cnt_context.counter_0_reg);
1786 outb(0x70, info->cnt_context.ctrl_reg);
1787 outb(0x00, info->cnt_context.counter_1_reg);
1788 outb(0x00, info->cnt_context.counter_1_reg);
1791 outb(0xB0, info->cnt_context.ctrl_reg);
1792 outb(0x00, info->cnt_context.counter_2_reg);
1793 outb(0x00, info->cnt_context.counter_2_reg);
1797 "comedi%d: me4000: cnt_reset(): Invalid channel\n",
1805 static int cnt_config(struct comedi_device *dev, unsigned int channel,
1812 tmp |= ME4000_CNT_COUNTER_0;
1815 tmp |= ME4000_CNT_COUNTER_1;
1818 tmp |= ME4000_CNT_COUNTER_2;
1822 "comedi%d: me4000: cnt_config(): Invalid channel\n",
1829 tmp |= ME4000_CNT_MODE_0;
1832 tmp |= ME4000_CNT_MODE_1;
1835 tmp |= ME4000_CNT_MODE_2;
1838 tmp |= ME4000_CNT_MODE_3;
1841 tmp |= ME4000_CNT_MODE_4;
1844 tmp |= ME4000_CNT_MODE_5;
1848 "comedi%d: me4000: cnt_config(): Invalid counter mode\n",
1853 /* Write the control word */
1855 outb(tmp, info->cnt_context.ctrl_reg);
1860 static int me4000_cnt_insn_config(struct comedi_device *dev,
1861 struct comedi_subdevice *s,
1862 struct comedi_insn *insn, unsigned int *data)
1871 "comedi%d: me4000: me4000_cnt_insn_config(): "
1872 "Invalid instruction length%d\n",
1873 dev->minor, insn->n);
1877 err = cnt_reset(dev, insn->chanspec);
1881 case GPCT_SET_OPERATION:
1884 "comedi%d: me4000: me4000_cnt_insn_config(): "
1885 "Invalid instruction length%d\n",
1886 dev->minor, insn->n);
1890 err = cnt_config(dev, insn->chanspec, data[1]);
1896 "comedi%d: me4000: me4000_cnt_insn_config(): "
1897 "Invalid instruction\n", dev->minor);
1904 static int me4000_cnt_insn_read(struct comedi_device *dev,
1905 struct comedi_subdevice *s,
1906 struct comedi_insn *insn, unsigned int *data)
1916 "comedi%d: me4000: me4000_cnt_insn_read(): "
1917 "Invalid instruction length %d\n",
1918 dev->minor, insn->n);
1922 switch (insn->chanspec) {
1924 tmp = inb(info->cnt_context.counter_0_reg);
1926 tmp = inb(info->cnt_context.counter_0_reg);
1927 data[0] |= tmp << 8;
1930 tmp = inb(info->cnt_context.counter_1_reg);
1932 tmp = inb(info->cnt_context.counter_1_reg);
1933 data[0] |= tmp << 8;
1936 tmp = inb(info->cnt_context.counter_2_reg);
1938 tmp = inb(info->cnt_context.counter_2_reg);
1939 data[0] |= tmp << 8;
1943 "comedi%d: me4000: me4000_cnt_insn_read(): "
1944 "Invalid channel %d\n",
1945 dev->minor, insn->chanspec);
1952 static int me4000_cnt_insn_write(struct comedi_device *dev,
1953 struct comedi_subdevice *s,
1954 struct comedi_insn *insn, unsigned int *data)
1961 } else if (insn->n > 1) {
1963 "comedi%d: me4000: me4000_cnt_insn_write(): "
1964 "Invalid instruction length %d\n",
1965 dev->minor, insn->n);
1969 switch (insn->chanspec) {
1971 tmp = data[0] & 0xFF;
1972 outb(tmp, info->cnt_context.counter_0_reg);
1973 tmp = (data[0] >> 8) & 0xFF;
1974 outb(tmp, info->cnt_context.counter_0_reg);
1977 tmp = data[0] & 0xFF;
1978 outb(tmp, info->cnt_context.counter_1_reg);
1979 tmp = (data[0] >> 8) & 0xFF;
1980 outb(tmp, info->cnt_context.counter_1_reg);
1983 tmp = data[0] & 0xFF;
1984 outb(tmp, info->cnt_context.counter_2_reg);
1985 tmp = (data[0] >> 8) & 0xFF;
1986 outb(tmp, info->cnt_context.counter_2_reg);
1990 "comedi%d: me4000: me4000_cnt_insn_write(): "
1991 "Invalid channel %d\n",
1992 dev->minor, insn->chanspec);
1999 static int me4000_attach(struct comedi_device *dev, struct comedi_devconfig *it)
2001 struct comedi_subdevice *s;
2004 result = me4000_probe(dev, it);
2008 result = comedi_alloc_subdevices(dev, 4);
2012 /*=========================================================================
2013 Analog input subdevice
2014 ========================================================================*/
2016 s = &dev->subdevices[0];
2018 if (thisboard->ai.count) {
2019 s->type = COMEDI_SUBD_AI;
2021 SDF_READABLE | SDF_COMMON | SDF_GROUND | SDF_DIFF;
2022 s->n_chan = thisboard->ai.count;
2023 s->maxdata = 0xFFFF; /* 16 bit ADC */
2024 s->len_chanlist = ME4000_AI_CHANNEL_LIST_COUNT;
2025 s->range_table = &me4000_ai_range;
2026 s->insn_read = me4000_ai_insn_read;
2028 if (info->irq > 0) {
2029 if (request_irq(info->irq, me4000_ai_isr,
2030 IRQF_SHARED, "ME-4000", dev)) {
2032 ("comedi%d: me4000: me4000_attach(): "
2033 "Unable to allocate irq\n", dev->minor);
2035 dev->read_subdev = s;
2036 s->subdev_flags |= SDF_CMD_READ;
2037 s->cancel = me4000_ai_cancel;
2038 s->do_cmdtest = me4000_ai_do_cmd_test;
2039 s->do_cmd = me4000_ai_do_cmd;
2043 "comedi%d: me4000: me4000_attach(): "
2044 "No interrupt available\n", dev->minor);
2047 s->type = COMEDI_SUBD_UNUSED;
2050 /*=========================================================================
2051 Analog output subdevice
2052 ========================================================================*/
2054 s = &dev->subdevices[1];
2056 if (thisboard->ao.count) {
2057 s->type = COMEDI_SUBD_AO;
2058 s->subdev_flags = SDF_WRITEABLE | SDF_COMMON | SDF_GROUND;
2059 s->n_chan = thisboard->ao.count;
2060 s->maxdata = 0xFFFF; /* 16 bit DAC */
2061 s->range_table = &me4000_ao_range;
2062 s->insn_write = me4000_ao_insn_write;
2063 s->insn_read = me4000_ao_insn_read;
2065 s->type = COMEDI_SUBD_UNUSED;
2068 /*=========================================================================
2069 Digital I/O subdevice
2070 ========================================================================*/
2072 s = &dev->subdevices[2];
2074 if (thisboard->dio.count) {
2075 s->type = COMEDI_SUBD_DIO;
2076 s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
2077 s->n_chan = thisboard->dio.count * 8;
2079 s->range_table = &range_digital;
2080 s->insn_bits = me4000_dio_insn_bits;
2081 s->insn_config = me4000_dio_insn_config;
2083 s->type = COMEDI_SUBD_UNUSED;
2087 * Check for optoisolated ME-4000 version. If one the first
2088 * port is a fixed output port and the second is a fixed input port.
2090 if (!inl(info->dio_context.dir_reg)) {
2092 outl(ME4000_DIO_CTRL_BIT_MODE_0, info->dio_context.dir_reg);
2095 /*=========================================================================
2097 ========================================================================*/
2099 s = &dev->subdevices[3];
2101 if (thisboard->cnt.count) {
2102 s->type = COMEDI_SUBD_COUNTER;
2103 s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
2104 s->n_chan = thisboard->cnt.count;
2105 s->maxdata = 0xFFFF; /* 16 bit counters */
2106 s->insn_read = me4000_cnt_insn_read;
2107 s->insn_write = me4000_cnt_insn_write;
2108 s->insn_config = me4000_cnt_insn_config;
2110 s->type = COMEDI_SUBD_UNUSED;
2116 static void me4000_detach(struct comedi_device *dev)
2119 if (info->pci_dev_p) {
2121 if (info->plx_regbase)
2122 comedi_pci_disable(info->pci_dev_p);
2123 pci_dev_put(info->pci_dev_p);
2128 static struct comedi_driver me4000_driver = {
2129 .driver_name = "me4000",
2130 .module = THIS_MODULE,
2131 .attach = me4000_attach,
2132 .detach = me4000_detach,
2135 static int __devinit me4000_pci_probe(struct pci_dev *dev,
2136 const struct pci_device_id *ent)
2138 return comedi_pci_auto_config(dev, &me4000_driver);
2141 static void __devexit me4000_pci_remove(struct pci_dev *dev)
2143 comedi_pci_auto_unconfig(dev);
2146 static DEFINE_PCI_DEVICE_TABLE(me4000_pci_table) = {
2147 { PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, 0x4650) },
2148 { PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, 0x4660) },
2149 { PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, 0x4661) },
2150 { PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, 0x4662) },
2151 { PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, 0x4663) },
2152 { PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, 0x4670) },
2153 { PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, 0x4671) },
2154 { PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, 0x4672) },
2155 { PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, 0x4673) },
2156 { PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, 0x4680) },
2157 { PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, 0x4681) },
2158 { PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, 0x4682) },
2159 { PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, 0x4683) },
2162 MODULE_DEVICE_TABLE(pci, me4000_pci_table);
2164 static struct pci_driver me4000_pci_driver = {
2166 .id_table = me4000_pci_table,
2167 .probe = me4000_pci_probe,
2168 .remove = __devexit_p(me4000_pci_remove),
2170 module_comedi_pci_driver(me4000_driver, me4000_pci_driver);
2172 MODULE_AUTHOR("Comedi http://www.comedi.org");
2173 MODULE_DESCRIPTION("Comedi low-level driver");
2174 MODULE_LICENSE("GPL");