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 /*-----------------------------------------------------------------------------
108 Meilhaus inline functions
109 ---------------------------------------------------------------------------*/
111 static inline void me4000_outb(struct comedi_device *dev, unsigned char value,
114 PORT_PDEBUG("--> 0x%02X port 0x%04lX\n", value, port);
118 static inline void me4000_outl(struct comedi_device *dev, unsigned long value,
121 PORT_PDEBUG("--> 0x%08lX port 0x%04lX\n", value, port);
125 static inline unsigned long me4000_inl(struct comedi_device *dev,
130 PORT_PDEBUG("<-- 0x%08lX port 0x%04lX\n", value, port);
134 static inline unsigned char me4000_inb(struct comedi_device *dev,
139 PORT_PDEBUG("<-- 0x%08X port 0x%04lX\n", value, port);
143 static const struct comedi_lrange me4000_ai_range = {
153 static const struct comedi_lrange me4000_ao_range = {
160 static int me4000_probe(struct comedi_device *dev, struct comedi_devconfig *it)
162 struct pci_dev *pci_device = NULL;
164 struct me4000_board *board;
166 CALL_PDEBUG("In me4000_probe()\n");
168 /* Allocate private memory */
169 if (alloc_private(dev, sizeof(struct me4000_info)) < 0)
173 * Probe the device to determine what device in the series it is.
175 for_each_pci_dev(pci_device) {
176 if (pci_device->vendor == PCI_VENDOR_ID_MEILHAUS) {
177 for (i = 0; i < ME4000_BOARD_VERSIONS; i++) {
178 if (me4000_boards[i].device_id ==
179 pci_device->device) {
182 * bus/slot requested?
184 if ((it->options[0] != 0)
185 || (it->options[1] != 0)) {
187 * Are we on the wrong
190 if (pci_device->bus->number !=
193 PCI_SLOT(pci_device->devfn)
198 dev->board_ptr = me4000_boards + i;
200 (struct me4000_board *)
202 info->pci_dev_p = pci_device;
210 "comedi%d: me4000: me4000_probe(): "
211 "No supported board found (req. bus/slot : %d/%d)\n",
212 dev->minor, it->options[0], it->options[1]);
218 "comedi%d: me4000: me4000_probe(): "
219 "Found %s at PCI bus %d, slot %d\n",
220 dev->minor, me4000_boards[i].name, pci_device->bus->number,
221 PCI_SLOT(pci_device->devfn));
223 /* Set data in device structure */
224 dev->board_name = board->name;
226 /* Enable PCI device and request regions */
227 result = comedi_pci_enable(pci_device, dev->board_name);
230 "comedi%d: me4000: me4000_probe(): Cannot enable PCI "
231 "device and request I/O regions\n", dev->minor);
235 /* Get the PCI base registers */
236 result = get_registers(dev, pci_device);
239 "comedi%d: me4000: me4000_probe(): "
240 "Cannot get registers\n", dev->minor);
243 /* Initialize board info */
244 result = init_board_info(dev, pci_device);
247 "comedi%d: me4000: me4000_probe(): "
248 "Cannot init baord info\n", dev->minor);
252 /* Init analog output context */
253 result = init_ao_context(dev);
256 "comedi%d: me4000: me4000_probe(): "
257 "Cannot init ao context\n", dev->minor);
261 /* Init analog input context */
262 result = init_ai_context(dev);
265 "comedi%d: me4000: me4000_probe(): "
266 "Cannot init ai context\n", dev->minor);
270 /* Init digital I/O context */
271 result = init_dio_context(dev);
274 "comedi%d: me4000: me4000_probe(): "
275 "Cannot init dio context\n", dev->minor);
279 /* Init counter context */
280 result = init_cnt_context(dev);
283 "comedi%d: me4000: me4000_probe(): "
284 "Cannot init cnt context\n", dev->minor);
288 /* Download the xilinx firmware */
289 result = xilinx_download(dev);
292 "comedi%d: me4000: me4000_probe(): "
293 "Can't download firmware\n", dev->minor);
297 /* Make a hardware reset */
298 result = reset_board(dev);
301 "comedi%d: me4000: me4000_probe(): Can't reset board\n",
309 static int get_registers(struct comedi_device *dev, struct pci_dev *pci_dev_p)
312 CALL_PDEBUG("In get_registers()\n");
314 /*--------------------------- plx regbase -------------------------------*/
316 info->plx_regbase = pci_resource_start(pci_dev_p, 1);
317 if (info->plx_regbase == 0) {
319 "comedi%d: me4000: get_registers(): "
320 "PCI base address 1 is not available\n", dev->minor);
323 info->plx_regbase_size = pci_resource_len(pci_dev_p, 1);
325 /*--------------------------- me4000 regbase ----------------------------*/
327 info->me4000_regbase = pci_resource_start(pci_dev_p, 2);
328 if (info->me4000_regbase == 0) {
330 "comedi%d: me4000: get_registers(): "
331 "PCI base address 2 is not available\n", dev->minor);
334 info->me4000_regbase_size = pci_resource_len(pci_dev_p, 2);
336 /*--------------------------- timer regbase ------------------------------*/
338 info->timer_regbase = pci_resource_start(pci_dev_p, 3);
339 if (info->timer_regbase == 0) {
341 "comedi%d: me4000: get_registers(): "
342 "PCI base address 3 is not available\n", dev->minor);
345 info->timer_regbase_size = pci_resource_len(pci_dev_p, 3);
347 /*--------------------------- program regbase ----------------------------*/
349 info->program_regbase = pci_resource_start(pci_dev_p, 5);
350 if (info->program_regbase == 0) {
352 "comedi%d: me4000: get_registers(): "
353 "PCI base address 5 is not available\n", dev->minor);
356 info->program_regbase_size = pci_resource_len(pci_dev_p, 5);
361 static int init_board_info(struct comedi_device *dev, struct pci_dev *pci_dev_p)
365 CALL_PDEBUG("In init_board_info()\n");
367 /* Init spin locks */
368 /* spin_lock_init(&info->preload_lock); */
369 /* spin_lock_init(&info->ai_ctrl_lock); */
371 /* Get the serial number */
372 result = pci_read_config_dword(pci_dev_p, 0x2C, &info->serial_no);
373 if (result != PCIBIOS_SUCCESSFUL)
376 /* Get the hardware revision */
377 result = pci_read_config_byte(pci_dev_p, 0x08, &info->hw_revision);
378 if (result != PCIBIOS_SUCCESSFUL)
381 /* Get the vendor id */
382 info->vendor_id = pci_dev_p->vendor;
384 /* Get the device id */
385 info->device_id = pci_dev_p->device;
387 /* Get the irq assigned to the board */
388 info->irq = pci_dev_p->irq;
393 static int init_ao_context(struct comedi_device *dev)
397 CALL_PDEBUG("In init_ao_context()\n");
399 for (i = 0; i < thisboard->ao.count; i++) {
400 /* spin_lock_init(&info->ao_context[i].use_lock); */
401 info->ao_context[i].irq = info->irq;
405 info->ao_context[i].ctrl_reg =
406 info->me4000_regbase + ME4000_AO_00_CTRL_REG;
407 info->ao_context[i].status_reg =
408 info->me4000_regbase + ME4000_AO_00_STATUS_REG;
409 info->ao_context[i].fifo_reg =
410 info->me4000_regbase + ME4000_AO_00_FIFO_REG;
411 info->ao_context[i].single_reg =
412 info->me4000_regbase + ME4000_AO_00_SINGLE_REG;
413 info->ao_context[i].timer_reg =
414 info->me4000_regbase + ME4000_AO_00_TIMER_REG;
415 info->ao_context[i].irq_status_reg =
416 info->me4000_regbase + ME4000_IRQ_STATUS_REG;
417 info->ao_context[i].preload_reg =
418 info->me4000_regbase + ME4000_AO_LOADSETREG_XX;
421 info->ao_context[i].ctrl_reg =
422 info->me4000_regbase + ME4000_AO_01_CTRL_REG;
423 info->ao_context[i].status_reg =
424 info->me4000_regbase + ME4000_AO_01_STATUS_REG;
425 info->ao_context[i].fifo_reg =
426 info->me4000_regbase + ME4000_AO_01_FIFO_REG;
427 info->ao_context[i].single_reg =
428 info->me4000_regbase + ME4000_AO_01_SINGLE_REG;
429 info->ao_context[i].timer_reg =
430 info->me4000_regbase + ME4000_AO_01_TIMER_REG;
431 info->ao_context[i].irq_status_reg =
432 info->me4000_regbase + ME4000_IRQ_STATUS_REG;
433 info->ao_context[i].preload_reg =
434 info->me4000_regbase + ME4000_AO_LOADSETREG_XX;
437 info->ao_context[i].ctrl_reg =
438 info->me4000_regbase + ME4000_AO_02_CTRL_REG;
439 info->ao_context[i].status_reg =
440 info->me4000_regbase + ME4000_AO_02_STATUS_REG;
441 info->ao_context[i].fifo_reg =
442 info->me4000_regbase + ME4000_AO_02_FIFO_REG;
443 info->ao_context[i].single_reg =
444 info->me4000_regbase + ME4000_AO_02_SINGLE_REG;
445 info->ao_context[i].timer_reg =
446 info->me4000_regbase + ME4000_AO_02_TIMER_REG;
447 info->ao_context[i].irq_status_reg =
448 info->me4000_regbase + ME4000_IRQ_STATUS_REG;
449 info->ao_context[i].preload_reg =
450 info->me4000_regbase + ME4000_AO_LOADSETREG_XX;
453 info->ao_context[i].ctrl_reg =
454 info->me4000_regbase + ME4000_AO_03_CTRL_REG;
455 info->ao_context[i].status_reg =
456 info->me4000_regbase + ME4000_AO_03_STATUS_REG;
457 info->ao_context[i].fifo_reg =
458 info->me4000_regbase + ME4000_AO_03_FIFO_REG;
459 info->ao_context[i].single_reg =
460 info->me4000_regbase + ME4000_AO_03_SINGLE_REG;
461 info->ao_context[i].timer_reg =
462 info->me4000_regbase + ME4000_AO_03_TIMER_REG;
463 info->ao_context[i].irq_status_reg =
464 info->me4000_regbase + ME4000_IRQ_STATUS_REG;
465 info->ao_context[i].preload_reg =
466 info->me4000_regbase + ME4000_AO_LOADSETREG_XX;
476 static int init_ai_context(struct comedi_device *dev)
479 CALL_PDEBUG("In init_ai_context()\n");
481 info->ai_context.irq = info->irq;
483 info->ai_context.ctrl_reg = info->me4000_regbase + ME4000_AI_CTRL_REG;
484 info->ai_context.status_reg =
485 info->me4000_regbase + ME4000_AI_STATUS_REG;
486 info->ai_context.channel_list_reg =
487 info->me4000_regbase + ME4000_AI_CHANNEL_LIST_REG;
488 info->ai_context.data_reg = info->me4000_regbase + ME4000_AI_DATA_REG;
489 info->ai_context.chan_timer_reg =
490 info->me4000_regbase + ME4000_AI_CHAN_TIMER_REG;
491 info->ai_context.chan_pre_timer_reg =
492 info->me4000_regbase + ME4000_AI_CHAN_PRE_TIMER_REG;
493 info->ai_context.scan_timer_low_reg =
494 info->me4000_regbase + ME4000_AI_SCAN_TIMER_LOW_REG;
495 info->ai_context.scan_timer_high_reg =
496 info->me4000_regbase + ME4000_AI_SCAN_TIMER_HIGH_REG;
497 info->ai_context.scan_pre_timer_low_reg =
498 info->me4000_regbase + ME4000_AI_SCAN_PRE_TIMER_LOW_REG;
499 info->ai_context.scan_pre_timer_high_reg =
500 info->me4000_regbase + ME4000_AI_SCAN_PRE_TIMER_HIGH_REG;
501 info->ai_context.start_reg = info->me4000_regbase + ME4000_AI_START_REG;
502 info->ai_context.irq_status_reg =
503 info->me4000_regbase + ME4000_IRQ_STATUS_REG;
504 info->ai_context.sample_counter_reg =
505 info->me4000_regbase + ME4000_AI_SAMPLE_COUNTER_REG;
510 static int init_dio_context(struct comedi_device *dev)
513 CALL_PDEBUG("In init_dio_context()\n");
515 info->dio_context.dir_reg = info->me4000_regbase + ME4000_DIO_DIR_REG;
516 info->dio_context.ctrl_reg = info->me4000_regbase + ME4000_DIO_CTRL_REG;
517 info->dio_context.port_0_reg =
518 info->me4000_regbase + ME4000_DIO_PORT_0_REG;
519 info->dio_context.port_1_reg =
520 info->me4000_regbase + ME4000_DIO_PORT_1_REG;
521 info->dio_context.port_2_reg =
522 info->me4000_regbase + ME4000_DIO_PORT_2_REG;
523 info->dio_context.port_3_reg =
524 info->me4000_regbase + ME4000_DIO_PORT_3_REG;
529 static int init_cnt_context(struct comedi_device *dev)
532 CALL_PDEBUG("In init_cnt_context()\n");
534 info->cnt_context.ctrl_reg = info->timer_regbase + ME4000_CNT_CTRL_REG;
535 info->cnt_context.counter_0_reg =
536 info->timer_regbase + ME4000_CNT_COUNTER_0_REG;
537 info->cnt_context.counter_1_reg =
538 info->timer_regbase + ME4000_CNT_COUNTER_1_REG;
539 info->cnt_context.counter_2_reg =
540 info->timer_regbase + ME4000_CNT_COUNTER_2_REG;
545 #define FIRMWARE_NOT_AVAILABLE 1
546 #if FIRMWARE_NOT_AVAILABLE
547 extern unsigned char *xilinx_firm;
550 static int xilinx_download(struct comedi_device *dev)
553 wait_queue_head_t queue;
557 CALL_PDEBUG("In xilinx_download()\n");
559 init_waitqueue_head(&queue);
562 * Set PLX local interrupt 2 polarity to high.
563 * Interrupt is thrown by init pin of xilinx.
565 outl(0x10, info->plx_regbase + PLX_INTCSR);
567 /* Set /CS and /WRITE of the Xilinx */
568 value = inl(info->plx_regbase + PLX_ICR);
570 outl(value, info->plx_regbase + PLX_ICR);
572 /* Init Xilinx with CS1 */
573 inb(info->program_regbase + 0xC8);
575 /* Wait until /INIT pin is set */
577 if (!(inl(info->plx_regbase + PLX_INTCSR) & 0x20)) {
579 "comedi%d: me4000: xilinx_download(): "
580 "Can't init Xilinx\n", dev->minor);
584 /* Reset /CS and /WRITE of the Xilinx */
585 value = inl(info->plx_regbase + PLX_ICR);
587 outl(value, info->plx_regbase + PLX_ICR);
588 if (FIRMWARE_NOT_AVAILABLE) {
589 comedi_error(dev, "xilinx firmware unavailable "
590 "due to licensing, aborting");
593 /* Download Xilinx firmware */
594 size = (xilinx_firm[0] << 24) + (xilinx_firm[1] << 16) +
595 (xilinx_firm[2] << 8) + xilinx_firm[3];
598 for (idx = 0; idx < size; idx++) {
599 outb(xilinx_firm[16 + idx], info->program_regbase);
602 /* Check if BUSY flag is low */
603 if (inl(info->plx_regbase + PLX_ICR) & 0x20) {
605 "comedi%d: me4000: xilinx_download(): "
606 "Xilinx is still busy (idx = %d)\n",
613 /* If done flag is high download was successful */
614 if (inl(info->plx_regbase + PLX_ICR) & 0x4) {
617 "comedi%d: me4000: xilinx_download(): "
618 "DONE flag is not set\n", dev->minor);
620 "comedi%d: me4000: xilinx_download(): "
621 "Download not successful\n", dev->minor);
625 /* Set /CS and /WRITE */
626 value = inl(info->plx_regbase + PLX_ICR);
628 outl(value, info->plx_regbase + PLX_ICR);
633 static int reset_board(struct comedi_device *dev)
637 CALL_PDEBUG("In reset_board()\n");
639 /* Make a hardware reset */
640 icr = me4000_inl(dev, info->plx_regbase + PLX_ICR);
642 me4000_outl(dev, icr, info->plx_regbase + PLX_ICR);
644 me4000_outl(dev, icr, info->plx_regbase + PLX_ICR);
646 /* 0x8000 to the DACs means an output voltage of 0V */
647 me4000_outl(dev, 0x8000,
648 info->me4000_regbase + ME4000_AO_00_SINGLE_REG);
649 me4000_outl(dev, 0x8000,
650 info->me4000_regbase + ME4000_AO_01_SINGLE_REG);
651 me4000_outl(dev, 0x8000,
652 info->me4000_regbase + ME4000_AO_02_SINGLE_REG);
653 me4000_outl(dev, 0x8000,
654 info->me4000_regbase + ME4000_AO_03_SINGLE_REG);
656 /* Set both stop bits in the analog input control register */
658 ME4000_AI_CTRL_BIT_IMMEDIATE_STOP | ME4000_AI_CTRL_BIT_STOP,
659 info->me4000_regbase + ME4000_AI_CTRL_REG);
661 /* Set both stop bits in the analog output control register */
663 ME4000_AO_CTRL_BIT_IMMEDIATE_STOP | ME4000_AO_CTRL_BIT_STOP,
664 info->me4000_regbase + ME4000_AO_00_CTRL_REG);
666 ME4000_AO_CTRL_BIT_IMMEDIATE_STOP | ME4000_AO_CTRL_BIT_STOP,
667 info->me4000_regbase + ME4000_AO_01_CTRL_REG);
669 ME4000_AO_CTRL_BIT_IMMEDIATE_STOP | ME4000_AO_CTRL_BIT_STOP,
670 info->me4000_regbase + ME4000_AO_02_CTRL_REG);
672 ME4000_AO_CTRL_BIT_IMMEDIATE_STOP | ME4000_AO_CTRL_BIT_STOP,
673 info->me4000_regbase + ME4000_AO_03_CTRL_REG);
675 /* Enable interrupts on the PLX */
676 me4000_outl(dev, 0x43, info->plx_regbase + PLX_INTCSR);
678 /* Set the adustment register for AO demux */
679 me4000_outl(dev, ME4000_AO_DEMUX_ADJUST_VALUE,
680 info->me4000_regbase + ME4000_AO_DEMUX_ADJUST_REG);
683 * Set digital I/O direction for port 0
684 * to output on isolated versions
686 if (!(me4000_inl(dev, info->me4000_regbase + ME4000_DIO_DIR_REG) & 0x1)) {
687 me4000_outl(dev, 0x1,
688 info->me4000_regbase + ME4000_DIO_CTRL_REG);
694 /*=============================================================================
696 ===========================================================================*/
698 static int me4000_ai_insn_read(struct comedi_device *dev,
699 struct comedi_subdevice *subdevice,
700 struct comedi_insn *insn, unsigned int *data)
703 int chan = CR_CHAN(insn->chanspec);
704 int rang = CR_RANGE(insn->chanspec);
705 int aref = CR_AREF(insn->chanspec);
707 unsigned long entry = 0;
711 CALL_PDEBUG("In me4000_ai_insn_read()\n");
715 } else if (insn->n > 1) {
717 "comedi%d: me4000: me4000_ai_insn_read(): "
718 "Invalid instruction length %d\n", dev->minor, insn->n);
724 entry |= ME4000_AI_LIST_RANGE_UNIPOLAR_2_5;
727 entry |= ME4000_AI_LIST_RANGE_UNIPOLAR_10;
730 entry |= ME4000_AI_LIST_RANGE_BIPOLAR_2_5;
733 entry |= ME4000_AI_LIST_RANGE_BIPOLAR_10;
737 "comedi%d: me4000: me4000_ai_insn_read(): "
738 "Invalid range specified\n", dev->minor);
745 if (chan >= thisboard->ai.count) {
747 "comedi%d: me4000: me4000_ai_insn_read(): "
748 "Analog input is not available\n", dev->minor);
751 entry |= ME4000_AI_LIST_INPUT_SINGLE_ENDED | chan;
755 if (rang == 0 || rang == 1) {
757 "comedi%d: me4000: me4000_ai_insn_read(): "
758 "Range must be bipolar when aref = diff\n",
763 if (chan >= thisboard->ai.diff_count) {
765 "comedi%d: me4000: me4000_ai_insn_read(): "
766 "Analog input is not available\n", dev->minor);
769 entry |= ME4000_AI_LIST_INPUT_DIFFERENTIAL | chan;
773 "comedi%d: me4000: me4000_ai_insn_read(): "
774 "Invalid aref specified\n", dev->minor);
778 entry |= ME4000_AI_LIST_LAST_ENTRY;
780 /* Clear channel list, data fifo and both stop bits */
781 tmp = me4000_inl(dev, info->ai_context.ctrl_reg);
782 tmp &= ~(ME4000_AI_CTRL_BIT_CHANNEL_FIFO |
783 ME4000_AI_CTRL_BIT_DATA_FIFO |
784 ME4000_AI_CTRL_BIT_STOP | ME4000_AI_CTRL_BIT_IMMEDIATE_STOP);
785 me4000_outl(dev, tmp, info->ai_context.ctrl_reg);
787 /* Set the acquisition mode to single */
788 tmp &= ~(ME4000_AI_CTRL_BIT_MODE_0 | ME4000_AI_CTRL_BIT_MODE_1 |
789 ME4000_AI_CTRL_BIT_MODE_2);
790 me4000_outl(dev, tmp, info->ai_context.ctrl_reg);
792 /* Enable channel list and data fifo */
793 tmp |= ME4000_AI_CTRL_BIT_CHANNEL_FIFO | ME4000_AI_CTRL_BIT_DATA_FIFO;
794 me4000_outl(dev, tmp, info->ai_context.ctrl_reg);
796 /* Generate channel list entry */
797 me4000_outl(dev, entry, info->ai_context.channel_list_reg);
799 /* Set the timer to maximum sample rate */
800 me4000_outl(dev, ME4000_AI_MIN_TICKS, info->ai_context.chan_timer_reg);
801 me4000_outl(dev, ME4000_AI_MIN_TICKS,
802 info->ai_context.chan_pre_timer_reg);
804 /* Start conversion by dummy read */
805 me4000_inl(dev, info->ai_context.start_reg);
807 /* Wait until ready */
810 (me4000_inl(dev, info->ai_context.status_reg) &
811 ME4000_AI_STATUS_BIT_EF_DATA)) {
813 "comedi%d: me4000: me4000_ai_insn_read(): "
814 "Value not available after wait\n", dev->minor);
818 /* Read value from data fifo */
819 lval = me4000_inl(dev, info->ai_context.data_reg) & 0xFFFF;
820 data[0] = lval ^ 0x8000;
825 static int me4000_ai_cancel(struct comedi_device *dev,
826 struct comedi_subdevice *s)
830 CALL_PDEBUG("In me4000_ai_cancel()\n");
832 /* Stop any running conversion */
833 tmp = me4000_inl(dev, info->ai_context.ctrl_reg);
834 tmp &= ~(ME4000_AI_CTRL_BIT_STOP | ME4000_AI_CTRL_BIT_IMMEDIATE_STOP);
835 me4000_outl(dev, tmp, info->ai_context.ctrl_reg);
837 /* Clear the control register */
838 me4000_outl(dev, 0x0, info->ai_context.ctrl_reg);
843 static int ai_check_chanlist(struct comedi_device *dev,
844 struct comedi_subdevice *s, struct comedi_cmd *cmd)
849 CALL_PDEBUG("In ai_check_chanlist()\n");
851 /* Check whether a channel list is available */
852 if (!cmd->chanlist_len) {
854 "comedi%d: me4000: ai_check_chanlist(): "
855 "No channel list available\n", dev->minor);
859 /* Check the channel list size */
860 if (cmd->chanlist_len > ME4000_AI_CHANNEL_LIST_COUNT) {
862 "comedi%d: me4000: ai_check_chanlist(): "
863 "Channel list is to large\n", dev->minor);
867 /* Check the pointer */
868 if (!cmd->chanlist) {
870 "comedi%d: me4000: ai_check_chanlist(): "
871 "NULL pointer to channel list\n", dev->minor);
875 /* Check whether aref is equal for all entries */
876 aref = CR_AREF(cmd->chanlist[0]);
877 for (i = 0; i < cmd->chanlist_len; i++) {
878 if (CR_AREF(cmd->chanlist[i]) != aref) {
880 "comedi%d: me4000: ai_check_chanlist(): "
881 "Mode is not equal for all entries\n",
887 /* Check whether channels are available for this ending */
888 if (aref == SDF_DIFF) {
889 for (i = 0; i < cmd->chanlist_len; i++) {
890 if (CR_CHAN(cmd->chanlist[i]) >=
891 thisboard->ai.diff_count) {
893 "comedi%d: me4000: ai_check_chanlist():"
894 " Channel number to high\n", dev->minor);
899 for (i = 0; i < cmd->chanlist_len; i++) {
900 if (CR_CHAN(cmd->chanlist[i]) >= thisboard->ai.count) {
902 "comedi%d: me4000: ai_check_chanlist(): "
903 "Channel number to high\n", dev->minor);
909 /* Check if bipolar is set for all entries when in differential mode */
910 if (aref == SDF_DIFF) {
911 for (i = 0; i < cmd->chanlist_len; i++) {
912 if (CR_RANGE(cmd->chanlist[i]) != 1 &&
913 CR_RANGE(cmd->chanlist[i]) != 2) {
915 "comedi%d: me4000: ai_check_chanlist(): "
916 "Bipolar is not selected in "
917 "differential mode\n",
927 static int ai_round_cmd_args(struct comedi_device *dev,
928 struct comedi_subdevice *s,
929 struct comedi_cmd *cmd,
930 unsigned int *init_ticks,
931 unsigned int *scan_ticks, unsigned int *chan_ticks)
936 CALL_PDEBUG("In ai_round_cmd_args()\n");
942 PDEBUG("ai_round_cmd_arg(): start_arg = %d\n", cmd->start_arg);
943 PDEBUG("ai_round_cmd_arg(): scan_begin_arg = %d\n",
944 cmd->scan_begin_arg);
945 PDEBUG("ai_round_cmd_arg(): convert_arg = %d\n", cmd->convert_arg);
947 if (cmd->start_arg) {
948 *init_ticks = (cmd->start_arg * 33) / 1000;
949 rest = (cmd->start_arg * 33) % 1000;
951 if ((cmd->flags & TRIG_ROUND_MASK) == TRIG_ROUND_NEAREST) {
954 } else if ((cmd->flags & TRIG_ROUND_MASK) == TRIG_ROUND_UP) {
960 if (cmd->scan_begin_arg) {
961 *scan_ticks = (cmd->scan_begin_arg * 33) / 1000;
962 rest = (cmd->scan_begin_arg * 33) % 1000;
964 if ((cmd->flags & TRIG_ROUND_MASK) == TRIG_ROUND_NEAREST) {
967 } else if ((cmd->flags & TRIG_ROUND_MASK) == TRIG_ROUND_UP) {
973 if (cmd->convert_arg) {
974 *chan_ticks = (cmd->convert_arg * 33) / 1000;
975 rest = (cmd->convert_arg * 33) % 1000;
977 if ((cmd->flags & TRIG_ROUND_MASK) == TRIG_ROUND_NEAREST) {
980 } else if ((cmd->flags & TRIG_ROUND_MASK) == TRIG_ROUND_UP) {
986 PDEBUG("ai_round_cmd_args(): init_ticks = %d\n", *init_ticks);
987 PDEBUG("ai_round_cmd_args(): scan_ticks = %d\n", *scan_ticks);
988 PDEBUG("ai_round_cmd_args(): chan_ticks = %d\n", *chan_ticks);
993 static void ai_write_timer(struct comedi_device *dev,
994 unsigned int init_ticks,
995 unsigned int scan_ticks, unsigned int chan_ticks)
998 CALL_PDEBUG("In ai_write_timer()\n");
1000 me4000_outl(dev, init_ticks - 1,
1001 info->ai_context.scan_pre_timer_low_reg);
1002 me4000_outl(dev, 0x0, info->ai_context.scan_pre_timer_high_reg);
1005 me4000_outl(dev, scan_ticks - 1,
1006 info->ai_context.scan_timer_low_reg);
1007 me4000_outl(dev, 0x0, info->ai_context.scan_timer_high_reg);
1010 me4000_outl(dev, chan_ticks - 1, info->ai_context.chan_pre_timer_reg);
1011 me4000_outl(dev, chan_ticks - 1, info->ai_context.chan_timer_reg);
1014 static int ai_prepare(struct comedi_device *dev,
1015 struct comedi_subdevice *s,
1016 struct comedi_cmd *cmd,
1017 unsigned int init_ticks,
1018 unsigned int scan_ticks, unsigned int chan_ticks)
1021 unsigned long tmp = 0;
1023 CALL_PDEBUG("In ai_prepare()\n");
1025 /* Write timer arguments */
1026 ai_write_timer(dev, init_ticks, scan_ticks, chan_ticks);
1028 /* Reset control register */
1029 me4000_outl(dev, tmp, info->ai_context.ctrl_reg);
1032 if ((cmd->start_src == TRIG_EXT &&
1033 cmd->scan_begin_src == TRIG_TIMER &&
1034 cmd->convert_src == TRIG_TIMER) ||
1035 (cmd->start_src == TRIG_EXT &&
1036 cmd->scan_begin_src == TRIG_FOLLOW &&
1037 cmd->convert_src == TRIG_TIMER)) {
1038 tmp = ME4000_AI_CTRL_BIT_MODE_1 |
1039 ME4000_AI_CTRL_BIT_CHANNEL_FIFO |
1040 ME4000_AI_CTRL_BIT_DATA_FIFO;
1041 } else if (cmd->start_src == TRIG_EXT &&
1042 cmd->scan_begin_src == TRIG_EXT &&
1043 cmd->convert_src == TRIG_TIMER) {
1044 tmp = ME4000_AI_CTRL_BIT_MODE_2 |
1045 ME4000_AI_CTRL_BIT_CHANNEL_FIFO |
1046 ME4000_AI_CTRL_BIT_DATA_FIFO;
1047 } else if (cmd->start_src == TRIG_EXT &&
1048 cmd->scan_begin_src == TRIG_EXT &&
1049 cmd->convert_src == TRIG_EXT) {
1050 tmp = ME4000_AI_CTRL_BIT_MODE_0 |
1051 ME4000_AI_CTRL_BIT_MODE_1 |
1052 ME4000_AI_CTRL_BIT_CHANNEL_FIFO |
1053 ME4000_AI_CTRL_BIT_DATA_FIFO;
1055 tmp = ME4000_AI_CTRL_BIT_MODE_0 |
1056 ME4000_AI_CTRL_BIT_CHANNEL_FIFO |
1057 ME4000_AI_CTRL_BIT_DATA_FIFO;
1061 if (cmd->stop_src == TRIG_COUNT) {
1062 me4000_outl(dev, cmd->chanlist_len * cmd->stop_arg,
1063 info->ai_context.sample_counter_reg);
1064 tmp |= ME4000_AI_CTRL_BIT_HF_IRQ | ME4000_AI_CTRL_BIT_SC_IRQ;
1065 } else if (cmd->stop_src == TRIG_NONE &&
1066 cmd->scan_end_src == TRIG_COUNT) {
1067 me4000_outl(dev, cmd->scan_end_arg,
1068 info->ai_context.sample_counter_reg);
1069 tmp |= ME4000_AI_CTRL_BIT_HF_IRQ | ME4000_AI_CTRL_BIT_SC_IRQ;
1071 tmp |= ME4000_AI_CTRL_BIT_HF_IRQ;
1074 /* Write the setup to the control register */
1075 me4000_outl(dev, tmp, info->ai_context.ctrl_reg);
1077 /* Write the channel list */
1078 ai_write_chanlist(dev, s, cmd);
1083 static int ai_write_chanlist(struct comedi_device *dev,
1084 struct comedi_subdevice *s, struct comedi_cmd *cmd)
1092 CALL_PDEBUG("In ai_write_chanlist()\n");
1094 for (i = 0; i < cmd->chanlist_len; i++) {
1095 chan = CR_CHAN(cmd->chanlist[i]);
1096 rang = CR_RANGE(cmd->chanlist[i]);
1097 aref = CR_AREF(cmd->chanlist[i]);
1102 entry |= ME4000_AI_LIST_RANGE_UNIPOLAR_2_5;
1104 entry |= ME4000_AI_LIST_RANGE_UNIPOLAR_10;
1106 entry |= ME4000_AI_LIST_RANGE_BIPOLAR_2_5;
1108 entry |= ME4000_AI_LIST_RANGE_BIPOLAR_10;
1110 if (aref == SDF_DIFF)
1111 entry |= ME4000_AI_LIST_INPUT_DIFFERENTIAL;
1113 entry |= ME4000_AI_LIST_INPUT_SINGLE_ENDED;
1115 me4000_outl(dev, entry, info->ai_context.channel_list_reg);
1121 static int me4000_ai_do_cmd(struct comedi_device *dev,
1122 struct comedi_subdevice *s)
1125 unsigned int init_ticks = 0;
1126 unsigned int scan_ticks = 0;
1127 unsigned int chan_ticks = 0;
1128 struct comedi_cmd *cmd = &s->async->cmd;
1130 CALL_PDEBUG("In me4000_ai_do_cmd()\n");
1132 /* Reset the analog input */
1133 err = me4000_ai_cancel(dev, s);
1137 /* Round the timer arguments */
1138 err = ai_round_cmd_args(dev,
1139 s, cmd, &init_ticks, &scan_ticks, &chan_ticks);
1143 /* Prepare the AI for acquisition */
1144 err = ai_prepare(dev, s, cmd, init_ticks, scan_ticks, chan_ticks);
1148 /* Start acquistion by dummy read */
1149 me4000_inl(dev, info->ai_context.start_reg);
1155 * me4000_ai_do_cmd_test():
1157 * The demo cmd.c in ./comedilib/demo specifies 6 return values:
1161 * - invalid argument
1162 * - argument conflict
1163 * - invalid chanlist
1164 * So I tried to adopt this scheme.
1166 static int me4000_ai_do_cmd_test(struct comedi_device *dev,
1167 struct comedi_subdevice *s,
1168 struct comedi_cmd *cmd)
1171 unsigned int init_ticks;
1172 unsigned int chan_ticks;
1173 unsigned int scan_ticks;
1176 CALL_PDEBUG("In me4000_ai_do_cmd_test()\n");
1178 PDEBUG("me4000_ai_do_cmd_test(): subdev = %d\n", cmd->subdev);
1179 PDEBUG("me4000_ai_do_cmd_test(): flags = %08X\n", cmd->flags);
1180 PDEBUG("me4000_ai_do_cmd_test(): start_src = %08X\n",
1182 PDEBUG("me4000_ai_do_cmd_test(): start_arg = %d\n",
1184 PDEBUG("me4000_ai_do_cmd_test(): scan_begin_src = %08X\n",
1185 cmd->scan_begin_src);
1186 PDEBUG("me4000_ai_do_cmd_test(): scan_begin_arg = %d\n",
1187 cmd->scan_begin_arg);
1188 PDEBUG("me4000_ai_do_cmd_test(): convert_src = %08X\n",
1190 PDEBUG("me4000_ai_do_cmd_test(): convert_arg = %d\n",
1192 PDEBUG("me4000_ai_do_cmd_test(): scan_end_src = %08X\n",
1194 PDEBUG("me4000_ai_do_cmd_test(): scan_end_arg = %d\n",
1196 PDEBUG("me4000_ai_do_cmd_test(): stop_src = %08X\n",
1198 PDEBUG("me4000_ai_do_cmd_test(): stop_arg = %d\n", cmd->stop_arg);
1199 PDEBUG("me4000_ai_do_cmd_test(): chanlist = %d\n",
1200 (unsigned int)cmd->chanlist);
1201 PDEBUG("me4000_ai_do_cmd_test(): chanlist_len = %d\n",
1204 /* Only rounding flags are implemented */
1205 cmd->flags &= TRIG_ROUND_NEAREST | TRIG_ROUND_UP | TRIG_ROUND_DOWN;
1207 /* Round the timer arguments */
1208 ai_round_cmd_args(dev, s, cmd, &init_ticks, &scan_ticks, &chan_ticks);
1211 * Stage 1. Check if the trigger sources are generally valid.
1213 switch (cmd->start_src) {
1218 cmd->start_src &= TRIG_NOW | TRIG_EXT;
1223 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1224 "Invalid start source\n", dev->minor);
1225 cmd->start_src = TRIG_NOW;
1228 switch (cmd->scan_begin_src) {
1234 cmd->scan_begin_src &= TRIG_FOLLOW | TRIG_TIMER | TRIG_EXT;
1239 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1240 "Invalid scan begin source\n", dev->minor);
1241 cmd->scan_begin_src = TRIG_FOLLOW;
1244 switch (cmd->convert_src) {
1249 cmd->convert_src &= TRIG_TIMER | TRIG_EXT;
1254 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1255 "Invalid convert source\n", dev->minor);
1256 cmd->convert_src = TRIG_TIMER;
1259 switch (cmd->scan_end_src) {
1264 cmd->scan_end_src &= TRIG_NONE | TRIG_COUNT;
1269 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1270 "Invalid scan end source\n", dev->minor);
1271 cmd->scan_end_src = TRIG_NONE;
1274 switch (cmd->stop_src) {
1279 cmd->stop_src &= TRIG_NONE | TRIG_COUNT;
1284 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1285 "Invalid stop source\n", dev->minor);
1286 cmd->stop_src = TRIG_NONE;
1293 * Stage 2. Check for trigger source conflicts.
1295 if (cmd->start_src == TRIG_NOW &&
1296 cmd->scan_begin_src == TRIG_TIMER &&
1297 cmd->convert_src == TRIG_TIMER) {
1298 } else if (cmd->start_src == TRIG_NOW &&
1299 cmd->scan_begin_src == TRIG_FOLLOW &&
1300 cmd->convert_src == TRIG_TIMER) {
1301 } else if (cmd->start_src == TRIG_EXT &&
1302 cmd->scan_begin_src == TRIG_TIMER &&
1303 cmd->convert_src == TRIG_TIMER) {
1304 } else if (cmd->start_src == TRIG_EXT &&
1305 cmd->scan_begin_src == TRIG_FOLLOW &&
1306 cmd->convert_src == TRIG_TIMER) {
1307 } else if (cmd->start_src == TRIG_EXT &&
1308 cmd->scan_begin_src == TRIG_EXT &&
1309 cmd->convert_src == TRIG_TIMER) {
1310 } else if (cmd->start_src == TRIG_EXT &&
1311 cmd->scan_begin_src == TRIG_EXT &&
1312 cmd->convert_src == TRIG_EXT) {
1315 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1316 "Invalid start trigger combination\n", dev->minor);
1317 cmd->start_src = TRIG_NOW;
1318 cmd->scan_begin_src = TRIG_FOLLOW;
1319 cmd->convert_src = TRIG_TIMER;
1323 if (cmd->stop_src == TRIG_NONE && cmd->scan_end_src == TRIG_NONE) {
1324 } else if (cmd->stop_src == TRIG_COUNT &&
1325 cmd->scan_end_src == TRIG_NONE) {
1326 } else if (cmd->stop_src == TRIG_NONE &&
1327 cmd->scan_end_src == TRIG_COUNT) {
1328 } else if (cmd->stop_src == TRIG_COUNT &&
1329 cmd->scan_end_src == TRIG_COUNT) {
1332 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1333 "Invalid stop trigger combination\n", dev->minor);
1334 cmd->stop_src = TRIG_NONE;
1335 cmd->scan_end_src = TRIG_NONE;
1342 * Stage 3. Check if arguments are generally valid.
1344 if (cmd->chanlist_len < 1) {
1346 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1347 "No channel list\n", dev->minor);
1348 cmd->chanlist_len = 1;
1351 if (init_ticks < 66) {
1353 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1354 "Start arg to low\n", dev->minor);
1355 cmd->start_arg = 2000;
1358 if (scan_ticks && scan_ticks < 67) {
1360 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1361 "Scan begin arg to low\n", dev->minor);
1362 cmd->scan_begin_arg = 2031;
1365 if (chan_ticks < 66) {
1367 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1368 "Convert arg to low\n", dev->minor);
1369 cmd->convert_arg = 2000;
1377 * Stage 4. Check for argument conflicts.
1379 if (cmd->start_src == TRIG_NOW &&
1380 cmd->scan_begin_src == TRIG_TIMER &&
1381 cmd->convert_src == TRIG_TIMER) {
1383 /* Check timer arguments */
1384 if (init_ticks < ME4000_AI_MIN_TICKS) {
1386 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1387 "Invalid start arg\n", dev->minor);
1388 cmd->start_arg = 2000; /* 66 ticks at least */
1391 if (chan_ticks < ME4000_AI_MIN_TICKS) {
1393 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1394 "Invalid convert arg\n", dev->minor);
1395 cmd->convert_arg = 2000; /* 66 ticks at least */
1398 if (scan_ticks <= cmd->chanlist_len * chan_ticks) {
1400 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1401 "Invalid scan end arg\n", dev->minor);
1403 /* At least one tick more */
1404 cmd->scan_end_arg = 2000 * cmd->chanlist_len + 31;
1407 } else if (cmd->start_src == TRIG_NOW &&
1408 cmd->scan_begin_src == TRIG_FOLLOW &&
1409 cmd->convert_src == TRIG_TIMER) {
1411 /* Check timer arguments */
1412 if (init_ticks < ME4000_AI_MIN_TICKS) {
1414 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1415 "Invalid start arg\n", dev->minor);
1416 cmd->start_arg = 2000; /* 66 ticks at least */
1419 if (chan_ticks < ME4000_AI_MIN_TICKS) {
1421 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1422 "Invalid convert arg\n", dev->minor);
1423 cmd->convert_arg = 2000; /* 66 ticks at least */
1426 } else if (cmd->start_src == TRIG_EXT &&
1427 cmd->scan_begin_src == TRIG_TIMER &&
1428 cmd->convert_src == TRIG_TIMER) {
1430 /* Check timer arguments */
1431 if (init_ticks < ME4000_AI_MIN_TICKS) {
1433 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1434 "Invalid start arg\n", dev->minor);
1435 cmd->start_arg = 2000; /* 66 ticks at least */
1438 if (chan_ticks < ME4000_AI_MIN_TICKS) {
1440 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1441 "Invalid convert arg\n", dev->minor);
1442 cmd->convert_arg = 2000; /* 66 ticks at least */
1445 if (scan_ticks <= cmd->chanlist_len * chan_ticks) {
1447 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1448 "Invalid scan end arg\n", dev->minor);
1450 /* At least one tick more */
1451 cmd->scan_end_arg = 2000 * cmd->chanlist_len + 31;
1454 } else if (cmd->start_src == TRIG_EXT &&
1455 cmd->scan_begin_src == TRIG_FOLLOW &&
1456 cmd->convert_src == TRIG_TIMER) {
1458 /* Check timer arguments */
1459 if (init_ticks < ME4000_AI_MIN_TICKS) {
1461 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1462 "Invalid start arg\n", dev->minor);
1463 cmd->start_arg = 2000; /* 66 ticks at least */
1466 if (chan_ticks < ME4000_AI_MIN_TICKS) {
1468 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1469 "Invalid convert arg\n", dev->minor);
1470 cmd->convert_arg = 2000; /* 66 ticks at least */
1473 } else if (cmd->start_src == TRIG_EXT &&
1474 cmd->scan_begin_src == TRIG_EXT &&
1475 cmd->convert_src == TRIG_TIMER) {
1477 /* Check timer arguments */
1478 if (init_ticks < ME4000_AI_MIN_TICKS) {
1480 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1481 "Invalid start arg\n", dev->minor);
1482 cmd->start_arg = 2000; /* 66 ticks at least */
1485 if (chan_ticks < ME4000_AI_MIN_TICKS) {
1487 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1488 "Invalid convert arg\n", dev->minor);
1489 cmd->convert_arg = 2000; /* 66 ticks at least */
1492 } else if (cmd->start_src == TRIG_EXT &&
1493 cmd->scan_begin_src == TRIG_EXT &&
1494 cmd->convert_src == TRIG_EXT) {
1496 /* Check timer arguments */
1497 if (init_ticks < ME4000_AI_MIN_TICKS) {
1499 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1500 "Invalid start arg\n", dev->minor);
1501 cmd->start_arg = 2000; /* 66 ticks at least */
1505 if (cmd->stop_src == TRIG_COUNT) {
1506 if (cmd->stop_arg == 0) {
1508 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1509 "Invalid stop arg\n", dev->minor);
1514 if (cmd->scan_end_src == TRIG_COUNT) {
1515 if (cmd->scan_end_arg == 0) {
1517 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1518 "Invalid scan end arg\n", dev->minor);
1519 cmd->scan_end_arg = 1;
1528 * Stage 5. Check the channel list.
1530 if (ai_check_chanlist(dev, s, cmd))
1536 static irqreturn_t me4000_ai_isr(int irq, void *dev_id)
1539 struct comedi_device *dev = dev_id;
1540 struct comedi_subdevice *s = dev->subdevices;
1541 struct me4000_ai_context *ai_context = &info->ai_context;
1546 ISR_PDEBUG("me4000_ai_isr() is executed\n");
1548 if (!dev->attached) {
1549 ISR_PDEBUG("me4000_ai_isr() premature interrupt\n");
1553 /* Reset all events */
1554 s->async->events = 0;
1556 /* Check if irq number is right */
1557 if (irq != ai_context->irq) {
1559 "comedi%d: me4000: me4000_ai_isr(): "
1560 "Incorrect interrupt num: %d\n", dev->minor, irq);
1565 ai_context->irq_status_reg) &
1566 ME4000_IRQ_STATUS_BIT_AI_HF) {
1568 ("me4000_ai_isr(): Fifo half full interrupt occurred\n");
1570 /* Read status register to find out what happened */
1571 tmp = me4000_inl(dev, ai_context->ctrl_reg);
1573 if (!(tmp & ME4000_AI_STATUS_BIT_FF_DATA) &&
1574 !(tmp & ME4000_AI_STATUS_BIT_HF_DATA) &&
1575 (tmp & ME4000_AI_STATUS_BIT_EF_DATA)) {
1576 ISR_PDEBUG("me4000_ai_isr(): Fifo full\n");
1577 c = ME4000_AI_FIFO_COUNT;
1580 * FIFO overflow, so stop conversion
1581 * and disable all interrupts
1583 tmp |= ME4000_AI_CTRL_BIT_IMMEDIATE_STOP;
1584 tmp &= ~(ME4000_AI_CTRL_BIT_HF_IRQ |
1585 ME4000_AI_CTRL_BIT_SC_IRQ);
1586 me4000_outl(dev, tmp, ai_context->ctrl_reg);
1588 s->async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
1591 "comedi%d: me4000: me4000_ai_isr(): "
1592 "FIFO overflow\n", dev->minor);
1593 } else if ((tmp & ME4000_AI_STATUS_BIT_FF_DATA)
1594 && !(tmp & ME4000_AI_STATUS_BIT_HF_DATA)
1595 && (tmp & ME4000_AI_STATUS_BIT_EF_DATA)) {
1596 ISR_PDEBUG("me4000_ai_isr(): Fifo half full\n");
1598 s->async->events |= COMEDI_CB_BLOCK;
1600 c = ME4000_AI_FIFO_COUNT / 2;
1603 "comedi%d: me4000: me4000_ai_isr(): "
1604 "Can't determine state of fifo\n", dev->minor);
1608 * Undefined state, so stop conversion
1609 * and disable all interrupts
1611 tmp |= ME4000_AI_CTRL_BIT_IMMEDIATE_STOP;
1612 tmp &= ~(ME4000_AI_CTRL_BIT_HF_IRQ |
1613 ME4000_AI_CTRL_BIT_SC_IRQ);
1614 me4000_outl(dev, tmp, ai_context->ctrl_reg);
1616 s->async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
1619 "comedi%d: me4000: me4000_ai_isr(): "
1620 "Undefined FIFO state\n", dev->minor);
1623 ISR_PDEBUG("me4000_ai_isr(): Try to read %d values\n", c);
1625 for (i = 0; i < c; i++) {
1626 /* Read value from data fifo */
1627 lval = inl(ai_context->data_reg) & 0xFFFF;
1630 if (!comedi_buf_put(s->async, lval)) {
1632 * Buffer overflow, so stop conversion
1633 * and disable all interrupts
1635 tmp |= ME4000_AI_CTRL_BIT_IMMEDIATE_STOP;
1636 tmp &= ~(ME4000_AI_CTRL_BIT_HF_IRQ |
1637 ME4000_AI_CTRL_BIT_SC_IRQ);
1638 me4000_outl(dev, tmp, ai_context->ctrl_reg);
1640 s->async->events |= COMEDI_CB_OVERFLOW;
1643 "comedi%d: me4000: me4000_ai_isr(): "
1644 "Buffer overflow\n", dev->minor);
1650 /* Work is done, so reset the interrupt */
1651 ISR_PDEBUG("me4000_ai_isr(): Reset fifo half full interrupt\n");
1652 tmp |= ME4000_AI_CTRL_BIT_HF_IRQ_RESET;
1653 me4000_outl(dev, tmp, ai_context->ctrl_reg);
1654 tmp &= ~ME4000_AI_CTRL_BIT_HF_IRQ_RESET;
1655 me4000_outl(dev, tmp, ai_context->ctrl_reg);
1659 ai_context->irq_status_reg) & ME4000_IRQ_STATUS_BIT_SC) {
1661 ("me4000_ai_isr(): Sample counter interrupt occurred\n");
1663 s->async->events |= COMEDI_CB_BLOCK | COMEDI_CB_EOA;
1666 * Acquisition is complete, so stop
1667 * conversion and disable all interrupts
1669 tmp = me4000_inl(dev, ai_context->ctrl_reg);
1670 tmp |= ME4000_AI_CTRL_BIT_IMMEDIATE_STOP;
1671 tmp &= ~(ME4000_AI_CTRL_BIT_HF_IRQ | ME4000_AI_CTRL_BIT_SC_IRQ);
1672 me4000_outl(dev, tmp, ai_context->ctrl_reg);
1674 /* Poll data until fifo empty */
1675 while (inl(ai_context->ctrl_reg) & ME4000_AI_STATUS_BIT_EF_DATA) {
1676 /* Read value from data fifo */
1677 lval = inl(ai_context->data_reg) & 0xFFFF;
1680 if (!comedi_buf_put(s->async, lval)) {
1682 "comedi%d: me4000: me4000_ai_isr(): "
1683 "Buffer overflow\n", dev->minor);
1684 s->async->events |= COMEDI_CB_OVERFLOW;
1689 /* Work is done, so reset the interrupt */
1691 ("me4000_ai_isr(): Reset interrupt from sample counter\n");
1692 tmp |= ME4000_AI_CTRL_BIT_SC_IRQ_RESET;
1693 me4000_outl(dev, tmp, ai_context->ctrl_reg);
1694 tmp &= ~ME4000_AI_CTRL_BIT_SC_IRQ_RESET;
1695 me4000_outl(dev, tmp, ai_context->ctrl_reg);
1698 ISR_PDEBUG("me4000_ai_isr(): Events = 0x%X\n", s->async->events);
1700 if (s->async->events)
1701 comedi_event(dev, s);
1706 /*=============================================================================
1707 Analog output section
1708 ===========================================================================*/
1710 static int me4000_ao_insn_write(struct comedi_device *dev,
1711 struct comedi_subdevice *s,
1712 struct comedi_insn *insn, unsigned int *data)
1715 int chan = CR_CHAN(insn->chanspec);
1716 int rang = CR_RANGE(insn->chanspec);
1717 int aref = CR_AREF(insn->chanspec);
1720 CALL_PDEBUG("In me4000_ao_insn_write()\n");
1724 } else if (insn->n > 1) {
1726 "comedi%d: me4000: me4000_ao_insn_write(): "
1727 "Invalid instruction length %d\n", dev->minor, insn->n);
1731 if (chan >= thisboard->ao.count) {
1733 "comedi%d: me4000: me4000_ao_insn_write(): "
1734 "Invalid channel %d\n", dev->minor, insn->n);
1740 "comedi%d: me4000: me4000_ao_insn_write(): "
1741 "Invalid range %d\n", dev->minor, insn->n);
1745 if (aref != AREF_GROUND && aref != AREF_COMMON) {
1747 "comedi%d: me4000: me4000_ao_insn_write(): "
1748 "Invalid aref %d\n", dev->minor, insn->n);
1752 /* Stop any running conversion */
1753 tmp = me4000_inl(dev, info->ao_context[chan].ctrl_reg);
1754 tmp |= ME4000_AO_CTRL_BIT_IMMEDIATE_STOP;
1755 me4000_outl(dev, tmp, info->ao_context[chan].ctrl_reg);
1757 /* Clear control register and set to single mode */
1758 me4000_outl(dev, 0x0, info->ao_context[chan].ctrl_reg);
1760 /* Write data value */
1761 me4000_outl(dev, data[0], info->ao_context[chan].single_reg);
1763 /* Store in the mirror */
1764 info->ao_context[chan].mirror = data[0];
1769 static int me4000_ao_insn_read(struct comedi_device *dev,
1770 struct comedi_subdevice *s,
1771 struct comedi_insn *insn, unsigned int *data)
1773 int chan = CR_CHAN(insn->chanspec);
1777 } else if (insn->n > 1) {
1779 ("comedi%d: me4000: me4000_ao_insn_read(): "
1780 "Invalid instruction length\n", dev->minor);
1784 data[0] = info->ao_context[chan].mirror;
1789 /*=============================================================================
1791 ===========================================================================*/
1793 static int me4000_dio_insn_bits(struct comedi_device *dev,
1794 struct comedi_subdevice *s,
1795 struct comedi_insn *insn, unsigned int *data)
1798 CALL_PDEBUG("In me4000_dio_insn_bits()\n");
1800 /* Length of data must be 2 (mask and new data, see below) */
1806 ("comedi%d: me4000: me4000_dio_insn_bits(): "
1807 "Invalid instruction length\n", dev->minor);
1812 * The insn data consists of a mask in data[0] and the new data
1813 * in data[1]. The mask defines which bits we are concerning about.
1814 * The new data must be anded with the mask.
1815 * Each channel corresponds to a bit.
1818 /* Check if requested ports are configured for output */
1819 if ((s->io_bits & data[0]) != data[0])
1822 s->state &= ~data[0];
1823 s->state |= data[0] & data[1];
1825 /* Write out the new digital output lines */
1826 me4000_outl(dev, (s->state >> 0) & 0xFF,
1827 info->dio_context.port_0_reg);
1828 me4000_outl(dev, (s->state >> 8) & 0xFF,
1829 info->dio_context.port_1_reg);
1830 me4000_outl(dev, (s->state >> 16) & 0xFF,
1831 info->dio_context.port_2_reg);
1832 me4000_outl(dev, (s->state >> 24) & 0xFF,
1833 info->dio_context.port_3_reg);
1836 /* On return, data[1] contains the value of
1837 the digital input and output lines. */
1839 ((me4000_inl(dev, info->dio_context.port_0_reg) & 0xFF) << 0) |
1840 ((me4000_inl(dev, info->dio_context.port_1_reg) & 0xFF) << 8) |
1841 ((me4000_inl(dev, info->dio_context.port_2_reg) & 0xFF) << 16) |
1842 ((me4000_inl(dev, info->dio_context.port_3_reg) & 0xFF) << 24);
1847 static int me4000_dio_insn_config(struct comedi_device *dev,
1848 struct comedi_subdevice *s,
1849 struct comedi_insn *insn, unsigned int *data)
1852 int chan = CR_CHAN(insn->chanspec);
1854 CALL_PDEBUG("In me4000_dio_insn_config()\n");
1859 case INSN_CONFIG_DIO_QUERY:
1861 (s->io_bits & (1 << chan)) ? COMEDI_OUTPUT : COMEDI_INPUT;
1863 case INSN_CONFIG_DIO_INPUT:
1864 case INSN_CONFIG_DIO_OUTPUT:
1869 * The input or output configuration of each digital line is
1870 * configured by a special insn_config instruction. chanspec
1871 * contains the channel to be changed, and data[0] contains the
1872 * value INSN_CONFIG_DIO_INPUT or INSN_CONFIG_DIO_OUTPUT.
1873 * On the ME-4000 it is only possible to switch port wise (8 bit)
1876 tmp = me4000_inl(dev, info->dio_context.ctrl_reg);
1878 if (data[0] == INSN_CONFIG_DIO_OUTPUT) {
1881 tmp &= ~(ME4000_DIO_CTRL_BIT_MODE_0 |
1882 ME4000_DIO_CTRL_BIT_MODE_1);
1883 tmp |= ME4000_DIO_CTRL_BIT_MODE_0;
1884 } else if (chan < 16) {
1886 * Chech for optoisolated ME-4000 version.
1887 * If one the first port is a fixed output
1888 * port and the second is a fixed input port.
1890 if (!me4000_inl(dev, info->dio_context.dir_reg))
1893 s->io_bits |= 0xFF00;
1894 tmp &= ~(ME4000_DIO_CTRL_BIT_MODE_2 |
1895 ME4000_DIO_CTRL_BIT_MODE_3);
1896 tmp |= ME4000_DIO_CTRL_BIT_MODE_2;
1897 } else if (chan < 24) {
1898 s->io_bits |= 0xFF0000;
1899 tmp &= ~(ME4000_DIO_CTRL_BIT_MODE_4 |
1900 ME4000_DIO_CTRL_BIT_MODE_5);
1901 tmp |= ME4000_DIO_CTRL_BIT_MODE_4;
1902 } else if (chan < 32) {
1903 s->io_bits |= 0xFF000000;
1904 tmp &= ~(ME4000_DIO_CTRL_BIT_MODE_6 |
1905 ME4000_DIO_CTRL_BIT_MODE_7);
1906 tmp |= ME4000_DIO_CTRL_BIT_MODE_6;
1913 * Chech for optoisolated ME-4000 version.
1914 * If one the first port is a fixed output
1915 * port and the second is a fixed input port.
1917 if (!me4000_inl(dev, info->dio_context.dir_reg))
1920 s->io_bits &= ~0xFF;
1921 tmp &= ~(ME4000_DIO_CTRL_BIT_MODE_0 |
1922 ME4000_DIO_CTRL_BIT_MODE_1);
1923 } else if (chan < 16) {
1924 s->io_bits &= ~0xFF00;
1925 tmp &= ~(ME4000_DIO_CTRL_BIT_MODE_2 |
1926 ME4000_DIO_CTRL_BIT_MODE_3);
1927 } else if (chan < 24) {
1928 s->io_bits &= ~0xFF0000;
1929 tmp &= ~(ME4000_DIO_CTRL_BIT_MODE_4 |
1930 ME4000_DIO_CTRL_BIT_MODE_5);
1931 } else if (chan < 32) {
1932 s->io_bits &= ~0xFF000000;
1933 tmp &= ~(ME4000_DIO_CTRL_BIT_MODE_6 |
1934 ME4000_DIO_CTRL_BIT_MODE_7);
1940 me4000_outl(dev, tmp, info->dio_context.ctrl_reg);
1945 /*=============================================================================
1947 ===========================================================================*/
1949 static int cnt_reset(struct comedi_device *dev, unsigned int channel)
1952 CALL_PDEBUG("In cnt_reset()\n");
1956 me4000_outb(dev, 0x30, info->cnt_context.ctrl_reg);
1957 me4000_outb(dev, 0x00, info->cnt_context.counter_0_reg);
1958 me4000_outb(dev, 0x00, info->cnt_context.counter_0_reg);
1961 me4000_outb(dev, 0x70, info->cnt_context.ctrl_reg);
1962 me4000_outb(dev, 0x00, info->cnt_context.counter_1_reg);
1963 me4000_outb(dev, 0x00, info->cnt_context.counter_1_reg);
1966 me4000_outb(dev, 0xB0, info->cnt_context.ctrl_reg);
1967 me4000_outb(dev, 0x00, info->cnt_context.counter_2_reg);
1968 me4000_outb(dev, 0x00, info->cnt_context.counter_2_reg);
1972 "comedi%d: me4000: cnt_reset(): Invalid channel\n",
1980 static int cnt_config(struct comedi_device *dev, unsigned int channel,
1985 CALL_PDEBUG("In cnt_config()\n");
1989 tmp |= ME4000_CNT_COUNTER_0;
1992 tmp |= ME4000_CNT_COUNTER_1;
1995 tmp |= ME4000_CNT_COUNTER_2;
1999 "comedi%d: me4000: cnt_config(): Invalid channel\n",
2006 tmp |= ME4000_CNT_MODE_0;
2009 tmp |= ME4000_CNT_MODE_1;
2012 tmp |= ME4000_CNT_MODE_2;
2015 tmp |= ME4000_CNT_MODE_3;
2018 tmp |= ME4000_CNT_MODE_4;
2021 tmp |= ME4000_CNT_MODE_5;
2025 "comedi%d: me4000: cnt_config(): Invalid counter mode\n",
2030 /* Write the control word */
2032 me4000_outb(dev, tmp, info->cnt_context.ctrl_reg);
2037 static int me4000_cnt_insn_config(struct comedi_device *dev,
2038 struct comedi_subdevice *s,
2039 struct comedi_insn *insn, unsigned int *data)
2044 CALL_PDEBUG("In me4000_cnt_insn_config()\n");
2050 "comedi%d: me4000: me4000_cnt_insn_config(): "
2051 "Invalid instruction length%d\n",
2052 dev->minor, insn->n);
2056 err = cnt_reset(dev, insn->chanspec);
2060 case GPCT_SET_OPERATION:
2063 "comedi%d: me4000: me4000_cnt_insn_config(): "
2064 "Invalid instruction length%d\n",
2065 dev->minor, insn->n);
2069 err = cnt_config(dev, insn->chanspec, data[1]);
2075 "comedi%d: me4000: me4000_cnt_insn_config(): "
2076 "Invalid instruction\n", dev->minor);
2083 static int me4000_cnt_insn_read(struct comedi_device *dev,
2084 struct comedi_subdevice *s,
2085 struct comedi_insn *insn, unsigned int *data)
2090 CALL_PDEBUG("In me4000_cnt_insn_read()\n");
2097 "comedi%d: me4000: me4000_cnt_insn_read(): "
2098 "Invalid instruction length %d\n",
2099 dev->minor, insn->n);
2103 switch (insn->chanspec) {
2105 tmp = me4000_inb(dev, info->cnt_context.counter_0_reg);
2107 tmp = me4000_inb(dev, info->cnt_context.counter_0_reg);
2108 data[0] |= tmp << 8;
2111 tmp = me4000_inb(dev, info->cnt_context.counter_1_reg);
2113 tmp = me4000_inb(dev, info->cnt_context.counter_1_reg);
2114 data[0] |= tmp << 8;
2117 tmp = me4000_inb(dev, info->cnt_context.counter_2_reg);
2119 tmp = me4000_inb(dev, info->cnt_context.counter_2_reg);
2120 data[0] |= tmp << 8;
2124 "comedi%d: me4000: me4000_cnt_insn_read(): "
2125 "Invalid channel %d\n",
2126 dev->minor, insn->chanspec);
2133 static int me4000_cnt_insn_write(struct comedi_device *dev,
2134 struct comedi_subdevice *s,
2135 struct comedi_insn *insn, unsigned int *data)
2140 CALL_PDEBUG("In me4000_cnt_insn_write()\n");
2144 } else if (insn->n > 1) {
2146 "comedi%d: me4000: me4000_cnt_insn_write(): "
2147 "Invalid instruction length %d\n",
2148 dev->minor, insn->n);
2152 switch (insn->chanspec) {
2154 tmp = data[0] & 0xFF;
2155 me4000_outb(dev, tmp, info->cnt_context.counter_0_reg);
2156 tmp = (data[0] >> 8) & 0xFF;
2157 me4000_outb(dev, tmp, info->cnt_context.counter_0_reg);
2160 tmp = data[0] & 0xFF;
2161 me4000_outb(dev, tmp, info->cnt_context.counter_1_reg);
2162 tmp = (data[0] >> 8) & 0xFF;
2163 me4000_outb(dev, tmp, info->cnt_context.counter_1_reg);
2166 tmp = data[0] & 0xFF;
2167 me4000_outb(dev, tmp, info->cnt_context.counter_2_reg);
2168 tmp = (data[0] >> 8) & 0xFF;
2169 me4000_outb(dev, tmp, info->cnt_context.counter_2_reg);
2173 "comedi%d: me4000: me4000_cnt_insn_write(): "
2174 "Invalid channel %d\n",
2175 dev->minor, insn->chanspec);
2182 static int me4000_attach(struct comedi_device *dev, struct comedi_devconfig *it)
2184 struct comedi_subdevice *s;
2187 CALL_PDEBUG("In me4000_attach()\n");
2189 result = me4000_probe(dev, it);
2194 * Allocate the subdevice structures. alloc_subdevice() is a
2195 * convenient macro defined in comedidev.h. It relies on
2196 * n_subdevices being set correctly.
2198 if (comedi_alloc_subdevices(dev, 4) < 0)
2201 /*=========================================================================
2202 Analog input subdevice
2203 ========================================================================*/
2205 s = dev->subdevices + 0;
2207 if (thisboard->ai.count) {
2208 s->type = COMEDI_SUBD_AI;
2210 SDF_READABLE | SDF_COMMON | SDF_GROUND | SDF_DIFF;
2211 s->n_chan = thisboard->ai.count;
2212 s->maxdata = 0xFFFF; /* 16 bit ADC */
2213 s->len_chanlist = ME4000_AI_CHANNEL_LIST_COUNT;
2214 s->range_table = &me4000_ai_range;
2215 s->insn_read = me4000_ai_insn_read;
2217 if (info->irq > 0) {
2218 if (request_irq(info->irq, me4000_ai_isr,
2219 IRQF_SHARED, "ME-4000", dev)) {
2221 ("comedi%d: me4000: me4000_attach(): "
2222 "Unable to allocate irq\n", dev->minor);
2224 dev->read_subdev = s;
2225 s->subdev_flags |= SDF_CMD_READ;
2226 s->cancel = me4000_ai_cancel;
2227 s->do_cmdtest = me4000_ai_do_cmd_test;
2228 s->do_cmd = me4000_ai_do_cmd;
2232 "comedi%d: me4000: me4000_attach(): "
2233 "No interrupt available\n", dev->minor);
2236 s->type = COMEDI_SUBD_UNUSED;
2239 /*=========================================================================
2240 Analog output subdevice
2241 ========================================================================*/
2243 s = dev->subdevices + 1;
2245 if (thisboard->ao.count) {
2246 s->type = COMEDI_SUBD_AO;
2247 s->subdev_flags = SDF_WRITEABLE | SDF_COMMON | SDF_GROUND;
2248 s->n_chan = thisboard->ao.count;
2249 s->maxdata = 0xFFFF; /* 16 bit DAC */
2250 s->range_table = &me4000_ao_range;
2251 s->insn_write = me4000_ao_insn_write;
2252 s->insn_read = me4000_ao_insn_read;
2254 s->type = COMEDI_SUBD_UNUSED;
2257 /*=========================================================================
2258 Digital I/O subdevice
2259 ========================================================================*/
2261 s = dev->subdevices + 2;
2263 if (thisboard->dio.count) {
2264 s->type = COMEDI_SUBD_DIO;
2265 s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
2266 s->n_chan = thisboard->dio.count * 8;
2268 s->range_table = &range_digital;
2269 s->insn_bits = me4000_dio_insn_bits;
2270 s->insn_config = me4000_dio_insn_config;
2272 s->type = COMEDI_SUBD_UNUSED;
2276 * Check for optoisolated ME-4000 version. If one the first
2277 * port is a fixed output port and the second is a fixed input port.
2279 if (!me4000_inl(dev, info->dio_context.dir_reg)) {
2281 me4000_outl(dev, ME4000_DIO_CTRL_BIT_MODE_0,
2282 info->dio_context.dir_reg);
2285 /*=========================================================================
2287 ========================================================================*/
2289 s = dev->subdevices + 3;
2291 if (thisboard->cnt.count) {
2292 s->type = COMEDI_SUBD_COUNTER;
2293 s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
2294 s->n_chan = thisboard->cnt.count;
2295 s->maxdata = 0xFFFF; /* 16 bit counters */
2296 s->insn_read = me4000_cnt_insn_read;
2297 s->insn_write = me4000_cnt_insn_write;
2298 s->insn_config = me4000_cnt_insn_config;
2300 s->type = COMEDI_SUBD_UNUSED;
2306 static void me4000_detach(struct comedi_device *dev)
2309 if (info->pci_dev_p) {
2311 if (info->plx_regbase)
2312 comedi_pci_disable(info->pci_dev_p);
2313 pci_dev_put(info->pci_dev_p);
2318 static struct comedi_driver me4000_driver = {
2319 .driver_name = "me4000",
2320 .module = THIS_MODULE,
2321 .attach = me4000_attach,
2322 .detach = me4000_detach,
2325 static int __devinit me4000_pci_probe(struct pci_dev *dev,
2326 const struct pci_device_id *ent)
2328 return comedi_pci_auto_config(dev, &me4000_driver);
2331 static void __devexit me4000_pci_remove(struct pci_dev *dev)
2333 comedi_pci_auto_unconfig(dev);
2336 static DEFINE_PCI_DEVICE_TABLE(me4000_pci_table) = {
2337 { PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, 0x4650) },
2338 { PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, 0x4660) },
2339 { PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, 0x4661) },
2340 { PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, 0x4662) },
2341 { PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, 0x4663) },
2342 { PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, 0x4670) },
2343 { PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, 0x4671) },
2344 { PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, 0x4672) },
2345 { PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, 0x4673) },
2346 { PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, 0x4680) },
2347 { PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, 0x4681) },
2348 { PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, 0x4682) },
2349 { PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS, 0x4683) },
2352 MODULE_DEVICE_TABLE(pci, me4000_pci_table);
2354 static struct pci_driver me4000_pci_driver = {
2356 .id_table = me4000_pci_table,
2357 .probe = me4000_pci_probe,
2358 .remove = __devexit_p(me4000_pci_remove),
2360 module_comedi_pci_driver(me4000_driver, me4000_pci_driver);
2362 MODULE_AUTHOR("Comedi http://www.comedi.org");
2363 MODULE_DESCRIPTION("Comedi low-level driver");
2364 MODULE_LICENSE("GPL");