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>
61 #include "comedi_pci.h"
64 /* file removed due to GPL incompatibility */
65 #include "me4000_fw.h"
68 /*=============================================================================
70 This is used by modprobe to translate PCI IDs to drivers.
71 ===========================================================================*/
73 static DEFINE_PCI_DEVICE_TABLE(me4000_pci_table
) = {
74 { PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS
, 0x4650) },
75 { PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS
, 0x4660) },
76 { PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS
, 0x4661) },
77 { PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS
, 0x4662) },
78 { PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS
, 0x4663) },
79 { PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS
, 0x4670) },
80 { PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS
, 0x4671) },
81 { PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS
, 0x4672) },
82 { PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS
, 0x4673) },
83 { PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS
, 0x4680) },
84 { PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS
, 0x4681) },
85 { PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS
, 0x4682) },
86 { PCI_DEVICE(PCI_VENDOR_ID_MEILHAUS
, 0x4683) },
90 MODULE_DEVICE_TABLE(pci
, me4000_pci_table
);
92 static const struct me4000_board me4000_boards
[] = {
93 {"ME-4650", 0x4650, {0, 0}, {16, 0, 0, 0}, {4}, {0} },
95 {"ME-4660", 0x4660, {0, 0}, {32, 0, 16, 0}, {4}, {3} },
96 {"ME-4660i", 0x4661, {0, 0}, {32, 0, 16, 0}, {4}, {3} },
97 {"ME-4660s", 0x4662, {0, 0}, {32, 8, 16, 0}, {4}, {3} },
98 {"ME-4660is", 0x4663, {0, 0}, {32, 8, 16, 0}, {4}, {3} },
100 {"ME-4670", 0x4670, {4, 0}, {32, 0, 16, 1}, {4}, {3} },
101 {"ME-4670i", 0x4671, {4, 0}, {32, 0, 16, 1}, {4}, {3} },
102 {"ME-4670s", 0x4672, {4, 0}, {32, 8, 16, 1}, {4}, {3} },
103 {"ME-4670is", 0x4673, {4, 0}, {32, 8, 16, 1}, {4}, {3} },
105 {"ME-4680", 0x4680, {4, 4}, {32, 0, 16, 1}, {4}, {3} },
106 {"ME-4680i", 0x4681, {4, 4}, {32, 0, 16, 1}, {4}, {3} },
107 {"ME-4680s", 0x4682, {4, 4}, {32, 8, 16, 1}, {4}, {3} },
108 {"ME-4680is", 0x4683, {4, 4}, {32, 8, 16, 1}, {4}, {3} },
113 #define ME4000_BOARD_VERSIONS (ARRAY_SIZE(me4000_boards) - 1)
115 /*-----------------------------------------------------------------------------
116 Comedi function prototypes
117 ---------------------------------------------------------------------------*/
118 static int me4000_attach(struct comedi_device
*dev
,
119 struct comedi_devconfig
*it
);
120 static int me4000_detach(struct comedi_device
*dev
);
121 static struct comedi_driver driver_me4000
= {
122 .driver_name
= "me4000",
123 .module
= THIS_MODULE
,
124 .attach
= me4000_attach
,
125 .detach
= me4000_detach
,
128 /*-----------------------------------------------------------------------------
129 Meilhaus function prototypes
130 ---------------------------------------------------------------------------*/
131 static int me4000_probe(struct comedi_device
*dev
, struct comedi_devconfig
*it
);
132 static int get_registers(struct comedi_device
*dev
, struct pci_dev
*pci_dev_p
);
133 static int init_board_info(struct comedi_device
*dev
,
134 struct pci_dev
*pci_dev_p
);
135 static int init_ao_context(struct comedi_device
*dev
);
136 static int init_ai_context(struct comedi_device
*dev
);
137 static int init_dio_context(struct comedi_device
*dev
);
138 static int init_cnt_context(struct comedi_device
*dev
);
139 static int xilinx_download(struct comedi_device
*dev
);
140 static int reset_board(struct comedi_device
*dev
);
142 static int me4000_dio_insn_bits(struct comedi_device
*dev
,
143 struct comedi_subdevice
*s
,
144 struct comedi_insn
*insn
, unsigned int *data
);
146 static int me4000_dio_insn_config(struct comedi_device
*dev
,
147 struct comedi_subdevice
*s
,
148 struct comedi_insn
*insn
, unsigned int *data
);
150 static int cnt_reset(struct comedi_device
*dev
, unsigned int channel
);
152 static int cnt_config(struct comedi_device
*dev
,
153 unsigned int channel
, unsigned int mode
);
155 static int me4000_cnt_insn_config(struct comedi_device
*dev
,
156 struct comedi_subdevice
*s
,
157 struct comedi_insn
*insn
, unsigned int *data
);
159 static int me4000_cnt_insn_write(struct comedi_device
*dev
,
160 struct comedi_subdevice
*s
,
161 struct comedi_insn
*insn
, unsigned int *data
);
163 static int me4000_cnt_insn_read(struct comedi_device
*dev
,
164 struct comedi_subdevice
*s
,
165 struct comedi_insn
*insn
, unsigned int *data
);
167 static int me4000_ai_insn_read(struct comedi_device
*dev
,
168 struct comedi_subdevice
*subdevice
,
169 struct comedi_insn
*insn
, unsigned int *data
);
171 static int me4000_ai_cancel(struct comedi_device
*dev
,
172 struct comedi_subdevice
*s
);
174 static int ai_check_chanlist(struct comedi_device
*dev
,
175 struct comedi_subdevice
*s
,
176 struct comedi_cmd
*cmd
);
178 static int ai_round_cmd_args(struct comedi_device
*dev
,
179 struct comedi_subdevice
*s
,
180 struct comedi_cmd
*cmd
,
181 unsigned int *init_ticks
,
182 unsigned int *scan_ticks
,
183 unsigned int *chan_ticks
);
185 static int ai_prepare(struct comedi_device
*dev
,
186 struct comedi_subdevice
*s
,
187 struct comedi_cmd
*cmd
,
188 unsigned int init_ticks
,
189 unsigned int scan_ticks
, unsigned int chan_ticks
);
191 static int ai_write_chanlist(struct comedi_device
*dev
,
192 struct comedi_subdevice
*s
,
193 struct comedi_cmd
*cmd
);
195 static irqreturn_t
me4000_ai_isr(int irq
, void *dev_id
);
197 static int me4000_ai_do_cmd_test(struct comedi_device
*dev
,
198 struct comedi_subdevice
*s
,
199 struct comedi_cmd
*cmd
);
201 static int me4000_ai_do_cmd(struct comedi_device
*dev
,
202 struct comedi_subdevice
*s
);
204 static int me4000_ao_insn_write(struct comedi_device
*dev
,
205 struct comedi_subdevice
*s
,
206 struct comedi_insn
*insn
, unsigned int *data
);
208 static int me4000_ao_insn_read(struct comedi_device
*dev
,
209 struct comedi_subdevice
*s
,
210 struct comedi_insn
*insn
, unsigned int *data
);
212 /*-----------------------------------------------------------------------------
213 Meilhaus inline functions
214 ---------------------------------------------------------------------------*/
216 static inline void me4000_outb(struct comedi_device
*dev
, unsigned char value
,
219 PORT_PDEBUG("--> 0x%02X port 0x%04lX\n", value
, port
);
223 static inline void me4000_outl(struct comedi_device
*dev
, unsigned long value
,
226 PORT_PDEBUG("--> 0x%08lX port 0x%04lX\n", value
, port
);
230 static inline unsigned long me4000_inl(struct comedi_device
*dev
,
235 PORT_PDEBUG("<-- 0x%08lX port 0x%04lX\n", value
, port
);
239 static inline unsigned char me4000_inb(struct comedi_device
*dev
,
244 PORT_PDEBUG("<-- 0x%08X port 0x%04lX\n", value
, port
);
248 static const struct comedi_lrange me4000_ai_range
= {
258 static const struct comedi_lrange me4000_ao_range
= {
265 static int me4000_attach(struct comedi_device
*dev
, struct comedi_devconfig
*it
)
267 struct comedi_subdevice
*s
;
270 CALL_PDEBUG("In me4000_attach()\n");
272 result
= me4000_probe(dev
, it
);
277 * Allocate the subdevice structures. alloc_subdevice() is a
278 * convenient macro defined in comedidev.h. It relies on
279 * n_subdevices being set correctly.
281 if (alloc_subdevices(dev
, 4) < 0)
284 /*=========================================================================
285 Analog input subdevice
286 ========================================================================*/
288 s
= dev
->subdevices
+ 0;
290 if (thisboard
->ai
.count
) {
291 s
->type
= COMEDI_SUBD_AI
;
293 SDF_READABLE
| SDF_COMMON
| SDF_GROUND
| SDF_DIFF
;
294 s
->n_chan
= thisboard
->ai
.count
;
295 s
->maxdata
= 0xFFFF; /* 16 bit ADC */
296 s
->len_chanlist
= ME4000_AI_CHANNEL_LIST_COUNT
;
297 s
->range_table
= &me4000_ai_range
;
298 s
->insn_read
= me4000_ai_insn_read
;
301 if (request_irq(info
->irq
, me4000_ai_isr
,
302 IRQF_SHARED
, "ME-4000", dev
)) {
304 ("comedi%d: me4000: me4000_attach(): "
305 "Unable to allocate irq\n", dev
->minor
);
307 dev
->read_subdev
= s
;
308 s
->subdev_flags
|= SDF_CMD_READ
;
309 s
->cancel
= me4000_ai_cancel
;
310 s
->do_cmdtest
= me4000_ai_do_cmd_test
;
311 s
->do_cmd
= me4000_ai_do_cmd
;
315 "comedi%d: me4000: me4000_attach(): "
316 "No interrupt available\n", dev
->minor
);
319 s
->type
= COMEDI_SUBD_UNUSED
;
322 /*=========================================================================
323 Analog output subdevice
324 ========================================================================*/
326 s
= dev
->subdevices
+ 1;
328 if (thisboard
->ao
.count
) {
329 s
->type
= COMEDI_SUBD_AO
;
330 s
->subdev_flags
= SDF_WRITEABLE
| SDF_COMMON
| SDF_GROUND
;
331 s
->n_chan
= thisboard
->ao
.count
;
332 s
->maxdata
= 0xFFFF; /* 16 bit DAC */
333 s
->range_table
= &me4000_ao_range
;
334 s
->insn_write
= me4000_ao_insn_write
;
335 s
->insn_read
= me4000_ao_insn_read
;
337 s
->type
= COMEDI_SUBD_UNUSED
;
340 /*=========================================================================
341 Digital I/O subdevice
342 ========================================================================*/
344 s
= dev
->subdevices
+ 2;
346 if (thisboard
->dio
.count
) {
347 s
->type
= COMEDI_SUBD_DIO
;
348 s
->subdev_flags
= SDF_READABLE
| SDF_WRITABLE
;
349 s
->n_chan
= thisboard
->dio
.count
* 8;
351 s
->range_table
= &range_digital
;
352 s
->insn_bits
= me4000_dio_insn_bits
;
353 s
->insn_config
= me4000_dio_insn_config
;
355 s
->type
= COMEDI_SUBD_UNUSED
;
359 * Check for optoisolated ME-4000 version. If one the first
360 * port is a fixed output port and the second is a fixed input port.
362 if (!me4000_inl(dev
, info
->dio_context
.dir_reg
)) {
364 me4000_outl(dev
, ME4000_DIO_CTRL_BIT_MODE_0
,
365 info
->dio_context
.dir_reg
);
368 /*=========================================================================
370 ========================================================================*/
372 s
= dev
->subdevices
+ 3;
374 if (thisboard
->cnt
.count
) {
375 s
->type
= COMEDI_SUBD_COUNTER
;
376 s
->subdev_flags
= SDF_READABLE
| SDF_WRITABLE
;
377 s
->n_chan
= thisboard
->cnt
.count
;
378 s
->maxdata
= 0xFFFF; /* 16 bit counters */
379 s
->insn_read
= me4000_cnt_insn_read
;
380 s
->insn_write
= me4000_cnt_insn_write
;
381 s
->insn_config
= me4000_cnt_insn_config
;
383 s
->type
= COMEDI_SUBD_UNUSED
;
389 static int me4000_probe(struct comedi_device
*dev
, struct comedi_devconfig
*it
)
391 struct pci_dev
*pci_device
= NULL
;
393 struct me4000_board
*board
;
395 CALL_PDEBUG("In me4000_probe()\n");
397 /* Allocate private memory */
398 if (alloc_private(dev
, sizeof(struct me4000_info
)) < 0)
402 * Probe the device to determine what device in the series it is.
404 for_each_pci_dev(pci_device
) {
405 if (pci_device
->vendor
== PCI_VENDOR_ID_MEILHAUS
) {
406 for (i
= 0; i
< ME4000_BOARD_VERSIONS
; i
++) {
407 if (me4000_boards
[i
].device_id
==
408 pci_device
->device
) {
411 * bus/slot requested?
413 if ((it
->options
[0] != 0)
414 || (it
->options
[1] != 0)) {
416 * Are we on the wrong
419 if (pci_device
->bus
->number
!=
422 PCI_SLOT(pci_device
->devfn
)
427 dev
->board_ptr
= me4000_boards
+ i
;
429 (struct me4000_board
*)
431 info
->pci_dev_p
= pci_device
;
439 "comedi%d: me4000: me4000_probe(): "
440 "No supported board found (req. bus/slot : %d/%d)\n",
441 dev
->minor
, it
->options
[0], it
->options
[1]);
447 "comedi%d: me4000: me4000_probe(): "
448 "Found %s at PCI bus %d, slot %d\n",
449 dev
->minor
, me4000_boards
[i
].name
, pci_device
->bus
->number
,
450 PCI_SLOT(pci_device
->devfn
));
452 /* Set data in device structure */
453 dev
->board_name
= board
->name
;
455 /* Enable PCI device and request regions */
456 result
= comedi_pci_enable(pci_device
, dev
->board_name
);
459 "comedi%d: me4000: me4000_probe(): Cannot enable PCI "
460 "device and request I/O regions\n", dev
->minor
);
464 /* Get the PCI base registers */
465 result
= get_registers(dev
, pci_device
);
468 "comedi%d: me4000: me4000_probe(): "
469 "Cannot get registers\n", dev
->minor
);
472 /* Initialize board info */
473 result
= init_board_info(dev
, pci_device
);
476 "comedi%d: me4000: me4000_probe(): "
477 "Cannot init baord info\n", dev
->minor
);
481 /* Init analog output context */
482 result
= init_ao_context(dev
);
485 "comedi%d: me4000: me4000_probe(): "
486 "Cannot init ao context\n", dev
->minor
);
490 /* Init analog input context */
491 result
= init_ai_context(dev
);
494 "comedi%d: me4000: me4000_probe(): "
495 "Cannot init ai context\n", dev
->minor
);
499 /* Init digital I/O context */
500 result
= init_dio_context(dev
);
503 "comedi%d: me4000: me4000_probe(): "
504 "Cannot init dio context\n", dev
->minor
);
508 /* Init counter context */
509 result
= init_cnt_context(dev
);
512 "comedi%d: me4000: me4000_probe(): "
513 "Cannot init cnt context\n", dev
->minor
);
517 /* Download the xilinx firmware */
518 result
= xilinx_download(dev
);
521 "comedi%d: me4000: me4000_probe(): "
522 "Can't download firmware\n", dev
->minor
);
526 /* Make a hardware reset */
527 result
= reset_board(dev
);
530 "comedi%d: me4000: me4000_probe(): Can't reset board\n",
538 static int get_registers(struct comedi_device
*dev
, struct pci_dev
*pci_dev_p
)
541 CALL_PDEBUG("In get_registers()\n");
543 /*--------------------------- plx regbase -------------------------------*/
545 info
->plx_regbase
= pci_resource_start(pci_dev_p
, 1);
546 if (info
->plx_regbase
== 0) {
548 "comedi%d: me4000: get_registers(): "
549 "PCI base address 1 is not available\n", dev
->minor
);
552 info
->plx_regbase_size
= pci_resource_len(pci_dev_p
, 1);
554 /*--------------------------- me4000 regbase ----------------------------*/
556 info
->me4000_regbase
= pci_resource_start(pci_dev_p
, 2);
557 if (info
->me4000_regbase
== 0) {
559 "comedi%d: me4000: get_registers(): "
560 "PCI base address 2 is not available\n", dev
->minor
);
563 info
->me4000_regbase_size
= pci_resource_len(pci_dev_p
, 2);
565 /*--------------------------- timer regbase ------------------------------*/
567 info
->timer_regbase
= pci_resource_start(pci_dev_p
, 3);
568 if (info
->timer_regbase
== 0) {
570 "comedi%d: me4000: get_registers(): "
571 "PCI base address 3 is not available\n", dev
->minor
);
574 info
->timer_regbase_size
= pci_resource_len(pci_dev_p
, 3);
576 /*--------------------------- program regbase ----------------------------*/
578 info
->program_regbase
= pci_resource_start(pci_dev_p
, 5);
579 if (info
->program_regbase
== 0) {
581 "comedi%d: me4000: get_registers(): "
582 "PCI base address 5 is not available\n", dev
->minor
);
585 info
->program_regbase_size
= pci_resource_len(pci_dev_p
, 5);
590 static int init_board_info(struct comedi_device
*dev
, struct pci_dev
*pci_dev_p
)
594 CALL_PDEBUG("In init_board_info()\n");
596 /* Init spin locks */
597 /* spin_lock_init(&info->preload_lock); */
598 /* spin_lock_init(&info->ai_ctrl_lock); */
600 /* Get the serial number */
601 result
= pci_read_config_dword(pci_dev_p
, 0x2C, &info
->serial_no
);
602 if (result
!= PCIBIOS_SUCCESSFUL
)
605 /* Get the hardware revision */
606 result
= pci_read_config_byte(pci_dev_p
, 0x08, &info
->hw_revision
);
607 if (result
!= PCIBIOS_SUCCESSFUL
)
610 /* Get the vendor id */
611 info
->vendor_id
= pci_dev_p
->vendor
;
613 /* Get the device id */
614 info
->device_id
= pci_dev_p
->device
;
616 /* Get the irq assigned to the board */
617 info
->irq
= pci_dev_p
->irq
;
622 static int init_ao_context(struct comedi_device
*dev
)
626 CALL_PDEBUG("In init_ao_context()\n");
628 for (i
= 0; i
< thisboard
->ao
.count
; i
++) {
629 /* spin_lock_init(&info->ao_context[i].use_lock); */
630 info
->ao_context
[i
].irq
= info
->irq
;
634 info
->ao_context
[i
].ctrl_reg
=
635 info
->me4000_regbase
+ ME4000_AO_00_CTRL_REG
;
636 info
->ao_context
[i
].status_reg
=
637 info
->me4000_regbase
+ ME4000_AO_00_STATUS_REG
;
638 info
->ao_context
[i
].fifo_reg
=
639 info
->me4000_regbase
+ ME4000_AO_00_FIFO_REG
;
640 info
->ao_context
[i
].single_reg
=
641 info
->me4000_regbase
+ ME4000_AO_00_SINGLE_REG
;
642 info
->ao_context
[i
].timer_reg
=
643 info
->me4000_regbase
+ ME4000_AO_00_TIMER_REG
;
644 info
->ao_context
[i
].irq_status_reg
=
645 info
->me4000_regbase
+ ME4000_IRQ_STATUS_REG
;
646 info
->ao_context
[i
].preload_reg
=
647 info
->me4000_regbase
+ ME4000_AO_LOADSETREG_XX
;
650 info
->ao_context
[i
].ctrl_reg
=
651 info
->me4000_regbase
+ ME4000_AO_01_CTRL_REG
;
652 info
->ao_context
[i
].status_reg
=
653 info
->me4000_regbase
+ ME4000_AO_01_STATUS_REG
;
654 info
->ao_context
[i
].fifo_reg
=
655 info
->me4000_regbase
+ ME4000_AO_01_FIFO_REG
;
656 info
->ao_context
[i
].single_reg
=
657 info
->me4000_regbase
+ ME4000_AO_01_SINGLE_REG
;
658 info
->ao_context
[i
].timer_reg
=
659 info
->me4000_regbase
+ ME4000_AO_01_TIMER_REG
;
660 info
->ao_context
[i
].irq_status_reg
=
661 info
->me4000_regbase
+ ME4000_IRQ_STATUS_REG
;
662 info
->ao_context
[i
].preload_reg
=
663 info
->me4000_regbase
+ ME4000_AO_LOADSETREG_XX
;
666 info
->ao_context
[i
].ctrl_reg
=
667 info
->me4000_regbase
+ ME4000_AO_02_CTRL_REG
;
668 info
->ao_context
[i
].status_reg
=
669 info
->me4000_regbase
+ ME4000_AO_02_STATUS_REG
;
670 info
->ao_context
[i
].fifo_reg
=
671 info
->me4000_regbase
+ ME4000_AO_02_FIFO_REG
;
672 info
->ao_context
[i
].single_reg
=
673 info
->me4000_regbase
+ ME4000_AO_02_SINGLE_REG
;
674 info
->ao_context
[i
].timer_reg
=
675 info
->me4000_regbase
+ ME4000_AO_02_TIMER_REG
;
676 info
->ao_context
[i
].irq_status_reg
=
677 info
->me4000_regbase
+ ME4000_IRQ_STATUS_REG
;
678 info
->ao_context
[i
].preload_reg
=
679 info
->me4000_regbase
+ ME4000_AO_LOADSETREG_XX
;
682 info
->ao_context
[i
].ctrl_reg
=
683 info
->me4000_regbase
+ ME4000_AO_03_CTRL_REG
;
684 info
->ao_context
[i
].status_reg
=
685 info
->me4000_regbase
+ ME4000_AO_03_STATUS_REG
;
686 info
->ao_context
[i
].fifo_reg
=
687 info
->me4000_regbase
+ ME4000_AO_03_FIFO_REG
;
688 info
->ao_context
[i
].single_reg
=
689 info
->me4000_regbase
+ ME4000_AO_03_SINGLE_REG
;
690 info
->ao_context
[i
].timer_reg
=
691 info
->me4000_regbase
+ ME4000_AO_03_TIMER_REG
;
692 info
->ao_context
[i
].irq_status_reg
=
693 info
->me4000_regbase
+ ME4000_IRQ_STATUS_REG
;
694 info
->ao_context
[i
].preload_reg
=
695 info
->me4000_regbase
+ ME4000_AO_LOADSETREG_XX
;
705 static int init_ai_context(struct comedi_device
*dev
)
708 CALL_PDEBUG("In init_ai_context()\n");
710 info
->ai_context
.irq
= info
->irq
;
712 info
->ai_context
.ctrl_reg
= info
->me4000_regbase
+ ME4000_AI_CTRL_REG
;
713 info
->ai_context
.status_reg
=
714 info
->me4000_regbase
+ ME4000_AI_STATUS_REG
;
715 info
->ai_context
.channel_list_reg
=
716 info
->me4000_regbase
+ ME4000_AI_CHANNEL_LIST_REG
;
717 info
->ai_context
.data_reg
= info
->me4000_regbase
+ ME4000_AI_DATA_REG
;
718 info
->ai_context
.chan_timer_reg
=
719 info
->me4000_regbase
+ ME4000_AI_CHAN_TIMER_REG
;
720 info
->ai_context
.chan_pre_timer_reg
=
721 info
->me4000_regbase
+ ME4000_AI_CHAN_PRE_TIMER_REG
;
722 info
->ai_context
.scan_timer_low_reg
=
723 info
->me4000_regbase
+ ME4000_AI_SCAN_TIMER_LOW_REG
;
724 info
->ai_context
.scan_timer_high_reg
=
725 info
->me4000_regbase
+ ME4000_AI_SCAN_TIMER_HIGH_REG
;
726 info
->ai_context
.scan_pre_timer_low_reg
=
727 info
->me4000_regbase
+ ME4000_AI_SCAN_PRE_TIMER_LOW_REG
;
728 info
->ai_context
.scan_pre_timer_high_reg
=
729 info
->me4000_regbase
+ ME4000_AI_SCAN_PRE_TIMER_HIGH_REG
;
730 info
->ai_context
.start_reg
= info
->me4000_regbase
+ ME4000_AI_START_REG
;
731 info
->ai_context
.irq_status_reg
=
732 info
->me4000_regbase
+ ME4000_IRQ_STATUS_REG
;
733 info
->ai_context
.sample_counter_reg
=
734 info
->me4000_regbase
+ ME4000_AI_SAMPLE_COUNTER_REG
;
739 static int init_dio_context(struct comedi_device
*dev
)
742 CALL_PDEBUG("In init_dio_context()\n");
744 info
->dio_context
.dir_reg
= info
->me4000_regbase
+ ME4000_DIO_DIR_REG
;
745 info
->dio_context
.ctrl_reg
= info
->me4000_regbase
+ ME4000_DIO_CTRL_REG
;
746 info
->dio_context
.port_0_reg
=
747 info
->me4000_regbase
+ ME4000_DIO_PORT_0_REG
;
748 info
->dio_context
.port_1_reg
=
749 info
->me4000_regbase
+ ME4000_DIO_PORT_1_REG
;
750 info
->dio_context
.port_2_reg
=
751 info
->me4000_regbase
+ ME4000_DIO_PORT_2_REG
;
752 info
->dio_context
.port_3_reg
=
753 info
->me4000_regbase
+ ME4000_DIO_PORT_3_REG
;
758 static int init_cnt_context(struct comedi_device
*dev
)
761 CALL_PDEBUG("In init_cnt_context()\n");
763 info
->cnt_context
.ctrl_reg
= info
->timer_regbase
+ ME4000_CNT_CTRL_REG
;
764 info
->cnt_context
.counter_0_reg
=
765 info
->timer_regbase
+ ME4000_CNT_COUNTER_0_REG
;
766 info
->cnt_context
.counter_1_reg
=
767 info
->timer_regbase
+ ME4000_CNT_COUNTER_1_REG
;
768 info
->cnt_context
.counter_2_reg
=
769 info
->timer_regbase
+ ME4000_CNT_COUNTER_2_REG
;
774 #define FIRMWARE_NOT_AVAILABLE 1
775 #if FIRMWARE_NOT_AVAILABLE
776 extern unsigned char *xilinx_firm
;
779 static int xilinx_download(struct comedi_device
*dev
)
782 wait_queue_head_t queue
;
786 CALL_PDEBUG("In xilinx_download()\n");
788 init_waitqueue_head(&queue
);
791 * Set PLX local interrupt 2 polarity to high.
792 * Interrupt is thrown by init pin of xilinx.
794 outl(0x10, info
->plx_regbase
+ PLX_INTCSR
);
796 /* Set /CS and /WRITE of the Xilinx */
797 value
= inl(info
->plx_regbase
+ PLX_ICR
);
799 outl(value
, info
->plx_regbase
+ PLX_ICR
);
801 /* Init Xilinx with CS1 */
802 inb(info
->program_regbase
+ 0xC8);
804 /* Wait until /INIT pin is set */
806 if (!(inl(info
->plx_regbase
+ PLX_INTCSR
) & 0x20)) {
808 "comedi%d: me4000: xilinx_download(): "
809 "Can't init Xilinx\n", dev
->minor
);
813 /* Reset /CS and /WRITE of the Xilinx */
814 value
= inl(info
->plx_regbase
+ PLX_ICR
);
816 outl(value
, info
->plx_regbase
+ PLX_ICR
);
817 if (FIRMWARE_NOT_AVAILABLE
) {
818 comedi_error(dev
, "xilinx firmware unavailable "
819 "due to licensing, aborting");
822 /* Download Xilinx firmware */
823 size
= (xilinx_firm
[0] << 24) + (xilinx_firm
[1] << 16) +
824 (xilinx_firm
[2] << 8) + xilinx_firm
[3];
827 for (idx
= 0; idx
< size
; idx
++) {
828 outb(xilinx_firm
[16 + idx
], info
->program_regbase
);
831 /* Check if BUSY flag is low */
832 if (inl(info
->plx_regbase
+ PLX_ICR
) & 0x20) {
834 "comedi%d: me4000: xilinx_download(): "
835 "Xilinx is still busy (idx = %d)\n",
842 /* If done flag is high download was successful */
843 if (inl(info
->plx_regbase
+ PLX_ICR
) & 0x4) {
846 "comedi%d: me4000: xilinx_download(): "
847 "DONE flag is not set\n", dev
->minor
);
849 "comedi%d: me4000: xilinx_download(): "
850 "Download not successful\n", dev
->minor
);
854 /* Set /CS and /WRITE */
855 value
= inl(info
->plx_regbase
+ PLX_ICR
);
857 outl(value
, info
->plx_regbase
+ PLX_ICR
);
862 static int reset_board(struct comedi_device
*dev
)
866 CALL_PDEBUG("In reset_board()\n");
868 /* Make a hardware reset */
869 icr
= me4000_inl(dev
, info
->plx_regbase
+ PLX_ICR
);
871 me4000_outl(dev
, icr
, info
->plx_regbase
+ PLX_ICR
);
873 me4000_outl(dev
, icr
, info
->plx_regbase
+ PLX_ICR
);
875 /* 0x8000 to the DACs means an output voltage of 0V */
876 me4000_outl(dev
, 0x8000,
877 info
->me4000_regbase
+ ME4000_AO_00_SINGLE_REG
);
878 me4000_outl(dev
, 0x8000,
879 info
->me4000_regbase
+ ME4000_AO_01_SINGLE_REG
);
880 me4000_outl(dev
, 0x8000,
881 info
->me4000_regbase
+ ME4000_AO_02_SINGLE_REG
);
882 me4000_outl(dev
, 0x8000,
883 info
->me4000_regbase
+ ME4000_AO_03_SINGLE_REG
);
885 /* Set both stop bits in the analog input control register */
887 ME4000_AI_CTRL_BIT_IMMEDIATE_STOP
| ME4000_AI_CTRL_BIT_STOP
,
888 info
->me4000_regbase
+ ME4000_AI_CTRL_REG
);
890 /* Set both stop bits in the analog output control register */
892 ME4000_AO_CTRL_BIT_IMMEDIATE_STOP
| ME4000_AO_CTRL_BIT_STOP
,
893 info
->me4000_regbase
+ ME4000_AO_00_CTRL_REG
);
895 ME4000_AO_CTRL_BIT_IMMEDIATE_STOP
| ME4000_AO_CTRL_BIT_STOP
,
896 info
->me4000_regbase
+ ME4000_AO_01_CTRL_REG
);
898 ME4000_AO_CTRL_BIT_IMMEDIATE_STOP
| ME4000_AO_CTRL_BIT_STOP
,
899 info
->me4000_regbase
+ ME4000_AO_02_CTRL_REG
);
901 ME4000_AO_CTRL_BIT_IMMEDIATE_STOP
| ME4000_AO_CTRL_BIT_STOP
,
902 info
->me4000_regbase
+ ME4000_AO_03_CTRL_REG
);
904 /* Enable interrupts on the PLX */
905 me4000_outl(dev
, 0x43, info
->plx_regbase
+ PLX_INTCSR
);
907 /* Set the adustment register for AO demux */
908 me4000_outl(dev
, ME4000_AO_DEMUX_ADJUST_VALUE
,
909 info
->me4000_regbase
+ ME4000_AO_DEMUX_ADJUST_REG
);
912 * Set digital I/O direction for port 0
913 * to output on isolated versions
915 if (!(me4000_inl(dev
, info
->me4000_regbase
+ ME4000_DIO_DIR_REG
) & 0x1)) {
916 me4000_outl(dev
, 0x1,
917 info
->me4000_regbase
+ ME4000_DIO_CTRL_REG
);
923 static int me4000_detach(struct comedi_device
*dev
)
925 CALL_PDEBUG("In me4000_detach()\n");
928 if (info
->pci_dev_p
) {
930 if (info
->plx_regbase
)
931 comedi_pci_disable(info
->pci_dev_p
);
932 pci_dev_put(info
->pci_dev_p
);
939 /*=============================================================================
941 ===========================================================================*/
943 static int me4000_ai_insn_read(struct comedi_device
*dev
,
944 struct comedi_subdevice
*subdevice
,
945 struct comedi_insn
*insn
, unsigned int *data
)
948 int chan
= CR_CHAN(insn
->chanspec
);
949 int rang
= CR_RANGE(insn
->chanspec
);
950 int aref
= CR_AREF(insn
->chanspec
);
952 unsigned long entry
= 0;
956 CALL_PDEBUG("In me4000_ai_insn_read()\n");
960 } else if (insn
->n
> 1) {
962 "comedi%d: me4000: me4000_ai_insn_read(): "
963 "Invalid instruction length %d\n", dev
->minor
, insn
->n
);
969 entry
|= ME4000_AI_LIST_RANGE_UNIPOLAR_2_5
;
972 entry
|= ME4000_AI_LIST_RANGE_UNIPOLAR_10
;
975 entry
|= ME4000_AI_LIST_RANGE_BIPOLAR_2_5
;
978 entry
|= ME4000_AI_LIST_RANGE_BIPOLAR_10
;
982 "comedi%d: me4000: me4000_ai_insn_read(): "
983 "Invalid range specified\n", dev
->minor
);
990 if (chan
>= thisboard
->ai
.count
) {
992 "comedi%d: me4000: me4000_ai_insn_read(): "
993 "Analog input is not available\n", dev
->minor
);
996 entry
|= ME4000_AI_LIST_INPUT_SINGLE_ENDED
| chan
;
1000 if (rang
== 0 || rang
== 1) {
1002 "comedi%d: me4000: me4000_ai_insn_read(): "
1003 "Range must be bipolar when aref = diff\n",
1008 if (chan
>= thisboard
->ai
.diff_count
) {
1010 "comedi%d: me4000: me4000_ai_insn_read(): "
1011 "Analog input is not available\n", dev
->minor
);
1014 entry
|= ME4000_AI_LIST_INPUT_DIFFERENTIAL
| chan
;
1018 "comedi%d: me4000: me4000_ai_insn_read(): "
1019 "Invalid aref specified\n", dev
->minor
);
1023 entry
|= ME4000_AI_LIST_LAST_ENTRY
;
1025 /* Clear channel list, data fifo and both stop bits */
1026 tmp
= me4000_inl(dev
, info
->ai_context
.ctrl_reg
);
1027 tmp
&= ~(ME4000_AI_CTRL_BIT_CHANNEL_FIFO
|
1028 ME4000_AI_CTRL_BIT_DATA_FIFO
|
1029 ME4000_AI_CTRL_BIT_STOP
| ME4000_AI_CTRL_BIT_IMMEDIATE_STOP
);
1030 me4000_outl(dev
, tmp
, info
->ai_context
.ctrl_reg
);
1032 /* Set the acquisition mode to single */
1033 tmp
&= ~(ME4000_AI_CTRL_BIT_MODE_0
| ME4000_AI_CTRL_BIT_MODE_1
|
1034 ME4000_AI_CTRL_BIT_MODE_2
);
1035 me4000_outl(dev
, tmp
, info
->ai_context
.ctrl_reg
);
1037 /* Enable channel list and data fifo */
1038 tmp
|= ME4000_AI_CTRL_BIT_CHANNEL_FIFO
| ME4000_AI_CTRL_BIT_DATA_FIFO
;
1039 me4000_outl(dev
, tmp
, info
->ai_context
.ctrl_reg
);
1041 /* Generate channel list entry */
1042 me4000_outl(dev
, entry
, info
->ai_context
.channel_list_reg
);
1044 /* Set the timer to maximum sample rate */
1045 me4000_outl(dev
, ME4000_AI_MIN_TICKS
, info
->ai_context
.chan_timer_reg
);
1046 me4000_outl(dev
, ME4000_AI_MIN_TICKS
,
1047 info
->ai_context
.chan_pre_timer_reg
);
1049 /* Start conversion by dummy read */
1050 me4000_inl(dev
, info
->ai_context
.start_reg
);
1052 /* Wait until ready */
1055 (me4000_inl(dev
, info
->ai_context
.status_reg
) &
1056 ME4000_AI_STATUS_BIT_EF_DATA
)) {
1058 "comedi%d: me4000: me4000_ai_insn_read(): "
1059 "Value not available after wait\n", dev
->minor
);
1063 /* Read value from data fifo */
1064 lval
= me4000_inl(dev
, info
->ai_context
.data_reg
) & 0xFFFF;
1065 data
[0] = lval
^ 0x8000;
1070 static int me4000_ai_cancel(struct comedi_device
*dev
,
1071 struct comedi_subdevice
*s
)
1075 CALL_PDEBUG("In me4000_ai_cancel()\n");
1077 /* Stop any running conversion */
1078 tmp
= me4000_inl(dev
, info
->ai_context
.ctrl_reg
);
1079 tmp
&= ~(ME4000_AI_CTRL_BIT_STOP
| ME4000_AI_CTRL_BIT_IMMEDIATE_STOP
);
1080 me4000_outl(dev
, tmp
, info
->ai_context
.ctrl_reg
);
1082 /* Clear the control register */
1083 me4000_outl(dev
, 0x0, info
->ai_context
.ctrl_reg
);
1088 static int ai_check_chanlist(struct comedi_device
*dev
,
1089 struct comedi_subdevice
*s
, struct comedi_cmd
*cmd
)
1094 CALL_PDEBUG("In ai_check_chanlist()\n");
1096 /* Check whether a channel list is available */
1097 if (!cmd
->chanlist_len
) {
1099 "comedi%d: me4000: ai_check_chanlist(): "
1100 "No channel list available\n", dev
->minor
);
1104 /* Check the channel list size */
1105 if (cmd
->chanlist_len
> ME4000_AI_CHANNEL_LIST_COUNT
) {
1107 "comedi%d: me4000: ai_check_chanlist(): "
1108 "Channel list is to large\n", dev
->minor
);
1112 /* Check the pointer */
1113 if (!cmd
->chanlist
) {
1115 "comedi%d: me4000: ai_check_chanlist(): "
1116 "NULL pointer to channel list\n", dev
->minor
);
1120 /* Check whether aref is equal for all entries */
1121 aref
= CR_AREF(cmd
->chanlist
[0]);
1122 for (i
= 0; i
< cmd
->chanlist_len
; i
++) {
1123 if (CR_AREF(cmd
->chanlist
[i
]) != aref
) {
1125 "comedi%d: me4000: ai_check_chanlist(): "
1126 "Mode is not equal for all entries\n",
1132 /* Check whether channels are available for this ending */
1133 if (aref
== SDF_DIFF
) {
1134 for (i
= 0; i
< cmd
->chanlist_len
; i
++) {
1135 if (CR_CHAN(cmd
->chanlist
[i
]) >=
1136 thisboard
->ai
.diff_count
) {
1138 "comedi%d: me4000: ai_check_chanlist():"
1139 " Channel number to high\n", dev
->minor
);
1144 for (i
= 0; i
< cmd
->chanlist_len
; i
++) {
1145 if (CR_CHAN(cmd
->chanlist
[i
]) >= thisboard
->ai
.count
) {
1147 "comedi%d: me4000: ai_check_chanlist(): "
1148 "Channel number to high\n", dev
->minor
);
1154 /* Check if bipolar is set for all entries when in differential mode */
1155 if (aref
== SDF_DIFF
) {
1156 for (i
= 0; i
< cmd
->chanlist_len
; i
++) {
1157 if (CR_RANGE(cmd
->chanlist
[i
]) != 1 &&
1158 CR_RANGE(cmd
->chanlist
[i
]) != 2) {
1160 "comedi%d: me4000: ai_check_chanlist(): "
1161 "Bipolar is not selected in "
1162 "differential mode\n",
1172 static int ai_round_cmd_args(struct comedi_device
*dev
,
1173 struct comedi_subdevice
*s
,
1174 struct comedi_cmd
*cmd
,
1175 unsigned int *init_ticks
,
1176 unsigned int *scan_ticks
, unsigned int *chan_ticks
)
1181 CALL_PDEBUG("In ai_round_cmd_args()\n");
1187 PDEBUG("ai_round_cmd_arg(): start_arg = %d\n", cmd
->start_arg
);
1188 PDEBUG("ai_round_cmd_arg(): scan_begin_arg = %d\n",
1189 cmd
->scan_begin_arg
);
1190 PDEBUG("ai_round_cmd_arg(): convert_arg = %d\n", cmd
->convert_arg
);
1192 if (cmd
->start_arg
) {
1193 *init_ticks
= (cmd
->start_arg
* 33) / 1000;
1194 rest
= (cmd
->start_arg
* 33) % 1000;
1196 if (cmd
->flags
& TRIG_ROUND_NEAREST
) {
1199 } else if (cmd
->flags
& TRIG_ROUND_UP
) {
1205 if (cmd
->scan_begin_arg
) {
1206 *scan_ticks
= (cmd
->scan_begin_arg
* 33) / 1000;
1207 rest
= (cmd
->scan_begin_arg
* 33) % 1000;
1209 if (cmd
->flags
& TRIG_ROUND_NEAREST
) {
1212 } else if (cmd
->flags
& TRIG_ROUND_UP
) {
1218 if (cmd
->convert_arg
) {
1219 *chan_ticks
= (cmd
->convert_arg
* 33) / 1000;
1220 rest
= (cmd
->convert_arg
* 33) % 1000;
1222 if (cmd
->flags
& TRIG_ROUND_NEAREST
) {
1225 } else if (cmd
->flags
& TRIG_ROUND_UP
) {
1231 PDEBUG("ai_round_cmd_args(): init_ticks = %d\n", *init_ticks
);
1232 PDEBUG("ai_round_cmd_args(): scan_ticks = %d\n", *scan_ticks
);
1233 PDEBUG("ai_round_cmd_args(): chan_ticks = %d\n", *chan_ticks
);
1238 static void ai_write_timer(struct comedi_device
*dev
,
1239 unsigned int init_ticks
,
1240 unsigned int scan_ticks
, unsigned int chan_ticks
)
1243 CALL_PDEBUG("In ai_write_timer()\n");
1245 me4000_outl(dev
, init_ticks
- 1,
1246 info
->ai_context
.scan_pre_timer_low_reg
);
1247 me4000_outl(dev
, 0x0, info
->ai_context
.scan_pre_timer_high_reg
);
1250 me4000_outl(dev
, scan_ticks
- 1,
1251 info
->ai_context
.scan_timer_low_reg
);
1252 me4000_outl(dev
, 0x0, info
->ai_context
.scan_timer_high_reg
);
1255 me4000_outl(dev
, chan_ticks
- 1, info
->ai_context
.chan_pre_timer_reg
);
1256 me4000_outl(dev
, chan_ticks
- 1, info
->ai_context
.chan_timer_reg
);
1259 static int ai_prepare(struct comedi_device
*dev
,
1260 struct comedi_subdevice
*s
,
1261 struct comedi_cmd
*cmd
,
1262 unsigned int init_ticks
,
1263 unsigned int scan_ticks
, unsigned int chan_ticks
)
1266 unsigned long tmp
= 0;
1268 CALL_PDEBUG("In ai_prepare()\n");
1270 /* Write timer arguments */
1271 ai_write_timer(dev
, init_ticks
, scan_ticks
, chan_ticks
);
1273 /* Reset control register */
1274 me4000_outl(dev
, tmp
, info
->ai_context
.ctrl_reg
);
1277 if ((cmd
->start_src
== TRIG_EXT
&&
1278 cmd
->scan_begin_src
== TRIG_TIMER
&&
1279 cmd
->convert_src
== TRIG_TIMER
) ||
1280 (cmd
->start_src
== TRIG_EXT
&&
1281 cmd
->scan_begin_src
== TRIG_FOLLOW
&&
1282 cmd
->convert_src
== TRIG_TIMER
)) {
1283 tmp
= ME4000_AI_CTRL_BIT_MODE_1
|
1284 ME4000_AI_CTRL_BIT_CHANNEL_FIFO
|
1285 ME4000_AI_CTRL_BIT_DATA_FIFO
;
1286 } else if (cmd
->start_src
== TRIG_EXT
&&
1287 cmd
->scan_begin_src
== TRIG_EXT
&&
1288 cmd
->convert_src
== TRIG_TIMER
) {
1289 tmp
= ME4000_AI_CTRL_BIT_MODE_2
|
1290 ME4000_AI_CTRL_BIT_CHANNEL_FIFO
|
1291 ME4000_AI_CTRL_BIT_DATA_FIFO
;
1292 } else if (cmd
->start_src
== TRIG_EXT
&&
1293 cmd
->scan_begin_src
== TRIG_EXT
&&
1294 cmd
->convert_src
== TRIG_EXT
) {
1295 tmp
= ME4000_AI_CTRL_BIT_MODE_0
|
1296 ME4000_AI_CTRL_BIT_MODE_1
|
1297 ME4000_AI_CTRL_BIT_CHANNEL_FIFO
|
1298 ME4000_AI_CTRL_BIT_DATA_FIFO
;
1300 tmp
= ME4000_AI_CTRL_BIT_MODE_0
|
1301 ME4000_AI_CTRL_BIT_CHANNEL_FIFO
|
1302 ME4000_AI_CTRL_BIT_DATA_FIFO
;
1306 if (cmd
->stop_src
== TRIG_COUNT
) {
1307 me4000_outl(dev
, cmd
->chanlist_len
* cmd
->stop_arg
,
1308 info
->ai_context
.sample_counter_reg
);
1309 tmp
|= ME4000_AI_CTRL_BIT_HF_IRQ
| ME4000_AI_CTRL_BIT_SC_IRQ
;
1310 } else if (cmd
->stop_src
== TRIG_NONE
&&
1311 cmd
->scan_end_src
== TRIG_COUNT
) {
1312 me4000_outl(dev
, cmd
->scan_end_arg
,
1313 info
->ai_context
.sample_counter_reg
);
1314 tmp
|= ME4000_AI_CTRL_BIT_HF_IRQ
| ME4000_AI_CTRL_BIT_SC_IRQ
;
1316 tmp
|= ME4000_AI_CTRL_BIT_HF_IRQ
;
1319 /* Write the setup to the control register */
1320 me4000_outl(dev
, tmp
, info
->ai_context
.ctrl_reg
);
1322 /* Write the channel list */
1323 ai_write_chanlist(dev
, s
, cmd
);
1328 static int ai_write_chanlist(struct comedi_device
*dev
,
1329 struct comedi_subdevice
*s
, struct comedi_cmd
*cmd
)
1337 CALL_PDEBUG("In ai_write_chanlist()\n");
1339 for (i
= 0; i
< cmd
->chanlist_len
; i
++) {
1340 chan
= CR_CHAN(cmd
->chanlist
[i
]);
1341 rang
= CR_RANGE(cmd
->chanlist
[i
]);
1342 aref
= CR_AREF(cmd
->chanlist
[i
]);
1347 entry
|= ME4000_AI_LIST_RANGE_UNIPOLAR_2_5
;
1349 entry
|= ME4000_AI_LIST_RANGE_UNIPOLAR_10
;
1351 entry
|= ME4000_AI_LIST_RANGE_BIPOLAR_2_5
;
1353 entry
|= ME4000_AI_LIST_RANGE_BIPOLAR_10
;
1355 if (aref
== SDF_DIFF
)
1356 entry
|= ME4000_AI_LIST_INPUT_DIFFERENTIAL
;
1358 entry
|= ME4000_AI_LIST_INPUT_SINGLE_ENDED
;
1360 me4000_outl(dev
, entry
, info
->ai_context
.channel_list_reg
);
1366 static int me4000_ai_do_cmd(struct comedi_device
*dev
,
1367 struct comedi_subdevice
*s
)
1370 unsigned int init_ticks
= 0;
1371 unsigned int scan_ticks
= 0;
1372 unsigned int chan_ticks
= 0;
1373 struct comedi_cmd
*cmd
= &s
->async
->cmd
;
1375 CALL_PDEBUG("In me4000_ai_do_cmd()\n");
1377 /* Reset the analog input */
1378 err
= me4000_ai_cancel(dev
, s
);
1382 /* Round the timer arguments */
1383 err
= ai_round_cmd_args(dev
,
1384 s
, cmd
, &init_ticks
, &scan_ticks
, &chan_ticks
);
1388 /* Prepare the AI for acquisition */
1389 err
= ai_prepare(dev
, s
, cmd
, init_ticks
, scan_ticks
, chan_ticks
);
1393 /* Start acquistion by dummy read */
1394 me4000_inl(dev
, info
->ai_context
.start_reg
);
1400 * me4000_ai_do_cmd_test():
1402 * The demo cmd.c in ./comedilib/demo specifies 6 return values:
1406 * - invalid argument
1407 * - argument conflict
1408 * - invalid chanlist
1409 * So I tried to adopt this scheme.
1411 static int me4000_ai_do_cmd_test(struct comedi_device
*dev
,
1412 struct comedi_subdevice
*s
,
1413 struct comedi_cmd
*cmd
)
1416 unsigned int init_ticks
;
1417 unsigned int chan_ticks
;
1418 unsigned int scan_ticks
;
1421 CALL_PDEBUG("In me4000_ai_do_cmd_test()\n");
1423 PDEBUG("me4000_ai_do_cmd_test(): subdev = %d\n", cmd
->subdev
);
1424 PDEBUG("me4000_ai_do_cmd_test(): flags = %08X\n", cmd
->flags
);
1425 PDEBUG("me4000_ai_do_cmd_test(): start_src = %08X\n",
1427 PDEBUG("me4000_ai_do_cmd_test(): start_arg = %d\n",
1429 PDEBUG("me4000_ai_do_cmd_test(): scan_begin_src = %08X\n",
1430 cmd
->scan_begin_src
);
1431 PDEBUG("me4000_ai_do_cmd_test(): scan_begin_arg = %d\n",
1432 cmd
->scan_begin_arg
);
1433 PDEBUG("me4000_ai_do_cmd_test(): convert_src = %08X\n",
1435 PDEBUG("me4000_ai_do_cmd_test(): convert_arg = %d\n",
1437 PDEBUG("me4000_ai_do_cmd_test(): scan_end_src = %08X\n",
1439 PDEBUG("me4000_ai_do_cmd_test(): scan_end_arg = %d\n",
1441 PDEBUG("me4000_ai_do_cmd_test(): stop_src = %08X\n",
1443 PDEBUG("me4000_ai_do_cmd_test(): stop_arg = %d\n", cmd
->stop_arg
);
1444 PDEBUG("me4000_ai_do_cmd_test(): chanlist = %d\n",
1445 (unsigned int)cmd
->chanlist
);
1446 PDEBUG("me4000_ai_do_cmd_test(): chanlist_len = %d\n",
1449 /* Only rounding flags are implemented */
1450 cmd
->flags
&= TRIG_ROUND_NEAREST
| TRIG_ROUND_UP
| TRIG_ROUND_DOWN
;
1452 /* Round the timer arguments */
1453 ai_round_cmd_args(dev
, s
, cmd
, &init_ticks
, &scan_ticks
, &chan_ticks
);
1456 * Stage 1. Check if the trigger sources are generally valid.
1458 switch (cmd
->start_src
) {
1463 cmd
->start_src
&= TRIG_NOW
| TRIG_EXT
;
1468 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1469 "Invalid start source\n", dev
->minor
);
1470 cmd
->start_src
= TRIG_NOW
;
1473 switch (cmd
->scan_begin_src
) {
1479 cmd
->scan_begin_src
&= TRIG_FOLLOW
| TRIG_TIMER
| TRIG_EXT
;
1484 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1485 "Invalid scan begin source\n", dev
->minor
);
1486 cmd
->scan_begin_src
= TRIG_FOLLOW
;
1489 switch (cmd
->convert_src
) {
1494 cmd
->convert_src
&= TRIG_TIMER
| TRIG_EXT
;
1499 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1500 "Invalid convert source\n", dev
->minor
);
1501 cmd
->convert_src
= TRIG_TIMER
;
1504 switch (cmd
->scan_end_src
) {
1509 cmd
->scan_end_src
&= TRIG_NONE
| TRIG_COUNT
;
1514 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1515 "Invalid scan end source\n", dev
->minor
);
1516 cmd
->scan_end_src
= TRIG_NONE
;
1519 switch (cmd
->stop_src
) {
1524 cmd
->stop_src
&= TRIG_NONE
| TRIG_COUNT
;
1529 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1530 "Invalid stop source\n", dev
->minor
);
1531 cmd
->stop_src
= TRIG_NONE
;
1538 * Stage 2. Check for trigger source conflicts.
1540 if (cmd
->start_src
== TRIG_NOW
&&
1541 cmd
->scan_begin_src
== TRIG_TIMER
&&
1542 cmd
->convert_src
== TRIG_TIMER
) {
1543 } else if (cmd
->start_src
== TRIG_NOW
&&
1544 cmd
->scan_begin_src
== TRIG_FOLLOW
&&
1545 cmd
->convert_src
== TRIG_TIMER
) {
1546 } else if (cmd
->start_src
== TRIG_EXT
&&
1547 cmd
->scan_begin_src
== TRIG_TIMER
&&
1548 cmd
->convert_src
== TRIG_TIMER
) {
1549 } else if (cmd
->start_src
== TRIG_EXT
&&
1550 cmd
->scan_begin_src
== TRIG_FOLLOW
&&
1551 cmd
->convert_src
== TRIG_TIMER
) {
1552 } else if (cmd
->start_src
== TRIG_EXT
&&
1553 cmd
->scan_begin_src
== TRIG_EXT
&&
1554 cmd
->convert_src
== TRIG_TIMER
) {
1555 } else if (cmd
->start_src
== TRIG_EXT
&&
1556 cmd
->scan_begin_src
== TRIG_EXT
&&
1557 cmd
->convert_src
== TRIG_EXT
) {
1560 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1561 "Invalid start trigger combination\n", dev
->minor
);
1562 cmd
->start_src
= TRIG_NOW
;
1563 cmd
->scan_begin_src
= TRIG_FOLLOW
;
1564 cmd
->convert_src
= TRIG_TIMER
;
1568 if (cmd
->stop_src
== TRIG_NONE
&& cmd
->scan_end_src
== TRIG_NONE
) {
1569 } else if (cmd
->stop_src
== TRIG_COUNT
&&
1570 cmd
->scan_end_src
== TRIG_NONE
) {
1571 } else if (cmd
->stop_src
== TRIG_NONE
&&
1572 cmd
->scan_end_src
== TRIG_COUNT
) {
1573 } else if (cmd
->stop_src
== TRIG_COUNT
&&
1574 cmd
->scan_end_src
== TRIG_COUNT
) {
1577 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1578 "Invalid stop trigger combination\n", dev
->minor
);
1579 cmd
->stop_src
= TRIG_NONE
;
1580 cmd
->scan_end_src
= TRIG_NONE
;
1587 * Stage 3. Check if arguments are generally valid.
1589 if (cmd
->chanlist_len
< 1) {
1591 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1592 "No channel list\n", dev
->minor
);
1593 cmd
->chanlist_len
= 1;
1596 if (init_ticks
< 66) {
1598 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1599 "Start arg to low\n", dev
->minor
);
1600 cmd
->start_arg
= 2000;
1603 if (scan_ticks
&& scan_ticks
< 67) {
1605 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1606 "Scan begin arg to low\n", dev
->minor
);
1607 cmd
->scan_begin_arg
= 2031;
1610 if (chan_ticks
< 66) {
1612 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1613 "Convert arg to low\n", dev
->minor
);
1614 cmd
->convert_arg
= 2000;
1622 * Stage 4. Check for argument conflicts.
1624 if (cmd
->start_src
== TRIG_NOW
&&
1625 cmd
->scan_begin_src
== TRIG_TIMER
&&
1626 cmd
->convert_src
== TRIG_TIMER
) {
1628 /* Check timer arguments */
1629 if (init_ticks
< ME4000_AI_MIN_TICKS
) {
1631 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1632 "Invalid start arg\n", dev
->minor
);
1633 cmd
->start_arg
= 2000; /* 66 ticks at least */
1636 if (chan_ticks
< ME4000_AI_MIN_TICKS
) {
1638 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1639 "Invalid convert arg\n", dev
->minor
);
1640 cmd
->convert_arg
= 2000; /* 66 ticks at least */
1643 if (scan_ticks
<= cmd
->chanlist_len
* chan_ticks
) {
1645 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1646 "Invalid scan end arg\n", dev
->minor
);
1648 /* At least one tick more */
1649 cmd
->scan_end_arg
= 2000 * cmd
->chanlist_len
+ 31;
1652 } else if (cmd
->start_src
== TRIG_NOW
&&
1653 cmd
->scan_begin_src
== TRIG_FOLLOW
&&
1654 cmd
->convert_src
== TRIG_TIMER
) {
1656 /* Check timer arguments */
1657 if (init_ticks
< ME4000_AI_MIN_TICKS
) {
1659 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1660 "Invalid start arg\n", dev
->minor
);
1661 cmd
->start_arg
= 2000; /* 66 ticks at least */
1664 if (chan_ticks
< ME4000_AI_MIN_TICKS
) {
1666 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1667 "Invalid convert arg\n", dev
->minor
);
1668 cmd
->convert_arg
= 2000; /* 66 ticks at least */
1671 } else if (cmd
->start_src
== TRIG_EXT
&&
1672 cmd
->scan_begin_src
== TRIG_TIMER
&&
1673 cmd
->convert_src
== TRIG_TIMER
) {
1675 /* Check timer arguments */
1676 if (init_ticks
< ME4000_AI_MIN_TICKS
) {
1678 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1679 "Invalid start arg\n", dev
->minor
);
1680 cmd
->start_arg
= 2000; /* 66 ticks at least */
1683 if (chan_ticks
< ME4000_AI_MIN_TICKS
) {
1685 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1686 "Invalid convert arg\n", dev
->minor
);
1687 cmd
->convert_arg
= 2000; /* 66 ticks at least */
1690 if (scan_ticks
<= cmd
->chanlist_len
* chan_ticks
) {
1692 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1693 "Invalid scan end arg\n", dev
->minor
);
1695 /* At least one tick more */
1696 cmd
->scan_end_arg
= 2000 * cmd
->chanlist_len
+ 31;
1699 } else if (cmd
->start_src
== TRIG_EXT
&&
1700 cmd
->scan_begin_src
== TRIG_FOLLOW
&&
1701 cmd
->convert_src
== TRIG_TIMER
) {
1703 /* Check timer arguments */
1704 if (init_ticks
< ME4000_AI_MIN_TICKS
) {
1706 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1707 "Invalid start arg\n", dev
->minor
);
1708 cmd
->start_arg
= 2000; /* 66 ticks at least */
1711 if (chan_ticks
< ME4000_AI_MIN_TICKS
) {
1713 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1714 "Invalid convert arg\n", dev
->minor
);
1715 cmd
->convert_arg
= 2000; /* 66 ticks at least */
1718 } else if (cmd
->start_src
== TRIG_EXT
&&
1719 cmd
->scan_begin_src
== TRIG_EXT
&&
1720 cmd
->convert_src
== TRIG_TIMER
) {
1722 /* Check timer arguments */
1723 if (init_ticks
< ME4000_AI_MIN_TICKS
) {
1725 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1726 "Invalid start arg\n", dev
->minor
);
1727 cmd
->start_arg
= 2000; /* 66 ticks at least */
1730 if (chan_ticks
< ME4000_AI_MIN_TICKS
) {
1732 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1733 "Invalid convert arg\n", dev
->minor
);
1734 cmd
->convert_arg
= 2000; /* 66 ticks at least */
1737 } else if (cmd
->start_src
== TRIG_EXT
&&
1738 cmd
->scan_begin_src
== TRIG_EXT
&&
1739 cmd
->convert_src
== TRIG_EXT
) {
1741 /* Check timer arguments */
1742 if (init_ticks
< ME4000_AI_MIN_TICKS
) {
1744 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1745 "Invalid start arg\n", dev
->minor
);
1746 cmd
->start_arg
= 2000; /* 66 ticks at least */
1750 if (cmd
->stop_src
== TRIG_COUNT
) {
1751 if (cmd
->stop_arg
== 0) {
1753 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1754 "Invalid stop arg\n", dev
->minor
);
1759 if (cmd
->scan_end_src
== TRIG_COUNT
) {
1760 if (cmd
->scan_end_arg
== 0) {
1762 "comedi%d: me4000: me4000_ai_do_cmd_test(): "
1763 "Invalid scan end arg\n", dev
->minor
);
1764 cmd
->scan_end_arg
= 1;
1773 * Stage 5. Check the channel list.
1775 if (ai_check_chanlist(dev
, s
, cmd
))
1781 static irqreturn_t
me4000_ai_isr(int irq
, void *dev_id
)
1784 struct comedi_device
*dev
= dev_id
;
1785 struct comedi_subdevice
*s
= dev
->subdevices
;
1786 struct me4000_ai_context
*ai_context
= &info
->ai_context
;
1791 ISR_PDEBUG("me4000_ai_isr() is executed\n");
1793 if (!dev
->attached
) {
1794 ISR_PDEBUG("me4000_ai_isr() premature interrupt\n");
1798 /* Reset all events */
1799 s
->async
->events
= 0;
1801 /* Check if irq number is right */
1802 if (irq
!= ai_context
->irq
) {
1804 "comedi%d: me4000: me4000_ai_isr(): "
1805 "Incorrect interrupt num: %d\n", dev
->minor
, irq
);
1810 ai_context
->irq_status_reg
) &
1811 ME4000_IRQ_STATUS_BIT_AI_HF
) {
1813 ("me4000_ai_isr(): Fifo half full interrupt occurred\n");
1815 /* Read status register to find out what happened */
1816 tmp
= me4000_inl(dev
, ai_context
->ctrl_reg
);
1818 if (!(tmp
& ME4000_AI_STATUS_BIT_FF_DATA
) &&
1819 !(tmp
& ME4000_AI_STATUS_BIT_HF_DATA
) &&
1820 (tmp
& ME4000_AI_STATUS_BIT_EF_DATA
)) {
1821 ISR_PDEBUG("me4000_ai_isr(): Fifo full\n");
1822 c
= ME4000_AI_FIFO_COUNT
;
1825 * FIFO overflow, so stop conversion
1826 * and disable all interrupts
1828 tmp
|= ME4000_AI_CTRL_BIT_IMMEDIATE_STOP
;
1829 tmp
&= ~(ME4000_AI_CTRL_BIT_HF_IRQ
|
1830 ME4000_AI_CTRL_BIT_SC_IRQ
);
1831 me4000_outl(dev
, tmp
, ai_context
->ctrl_reg
);
1833 s
->async
->events
|= COMEDI_CB_ERROR
| COMEDI_CB_EOA
;
1836 "comedi%d: me4000: me4000_ai_isr(): "
1837 "FIFO overflow\n", dev
->minor
);
1838 } else if ((tmp
& ME4000_AI_STATUS_BIT_FF_DATA
)
1839 && !(tmp
& ME4000_AI_STATUS_BIT_HF_DATA
)
1840 && (tmp
& ME4000_AI_STATUS_BIT_EF_DATA
)) {
1841 ISR_PDEBUG("me4000_ai_isr(): Fifo half full\n");
1843 s
->async
->events
|= COMEDI_CB_BLOCK
;
1845 c
= ME4000_AI_FIFO_COUNT
/ 2;
1848 "comedi%d: me4000: me4000_ai_isr(): "
1849 "Can't determine state of fifo\n", dev
->minor
);
1853 * Undefined state, so stop conversion
1854 * and disable all interrupts
1856 tmp
|= ME4000_AI_CTRL_BIT_IMMEDIATE_STOP
;
1857 tmp
&= ~(ME4000_AI_CTRL_BIT_HF_IRQ
|
1858 ME4000_AI_CTRL_BIT_SC_IRQ
);
1859 me4000_outl(dev
, tmp
, ai_context
->ctrl_reg
);
1861 s
->async
->events
|= COMEDI_CB_ERROR
| COMEDI_CB_EOA
;
1864 "comedi%d: me4000: me4000_ai_isr(): "
1865 "Undefined FIFO state\n", dev
->minor
);
1868 ISR_PDEBUG("me4000_ai_isr(): Try to read %d values\n", c
);
1870 for (i
= 0; i
< c
; i
++) {
1871 /* Read value from data fifo */
1872 lval
= inl(ai_context
->data_reg
) & 0xFFFF;
1875 if (!comedi_buf_put(s
->async
, lval
)) {
1877 * Buffer overflow, so stop conversion
1878 * and disable all interrupts
1880 tmp
|= ME4000_AI_CTRL_BIT_IMMEDIATE_STOP
;
1881 tmp
&= ~(ME4000_AI_CTRL_BIT_HF_IRQ
|
1882 ME4000_AI_CTRL_BIT_SC_IRQ
);
1883 me4000_outl(dev
, tmp
, ai_context
->ctrl_reg
);
1885 s
->async
->events
|= COMEDI_CB_OVERFLOW
;
1888 "comedi%d: me4000: me4000_ai_isr(): "
1889 "Buffer overflow\n", dev
->minor
);
1895 /* Work is done, so reset the interrupt */
1896 ISR_PDEBUG("me4000_ai_isr(): Reset fifo half full interrupt\n");
1897 tmp
|= ME4000_AI_CTRL_BIT_HF_IRQ_RESET
;
1898 me4000_outl(dev
, tmp
, ai_context
->ctrl_reg
);
1899 tmp
&= ~ME4000_AI_CTRL_BIT_HF_IRQ_RESET
;
1900 me4000_outl(dev
, tmp
, ai_context
->ctrl_reg
);
1904 ai_context
->irq_status_reg
) & ME4000_IRQ_STATUS_BIT_SC
) {
1906 ("me4000_ai_isr(): Sample counter interrupt occurred\n");
1908 s
->async
->events
|= COMEDI_CB_BLOCK
| COMEDI_CB_EOA
;
1911 * Acquisition is complete, so stop
1912 * conversion and disable all interrupts
1914 tmp
= me4000_inl(dev
, ai_context
->ctrl_reg
);
1915 tmp
|= ME4000_AI_CTRL_BIT_IMMEDIATE_STOP
;
1916 tmp
&= ~(ME4000_AI_CTRL_BIT_HF_IRQ
| ME4000_AI_CTRL_BIT_SC_IRQ
);
1917 me4000_outl(dev
, tmp
, ai_context
->ctrl_reg
);
1919 /* Poll data until fifo empty */
1920 while (inl(ai_context
->ctrl_reg
) & ME4000_AI_STATUS_BIT_EF_DATA
) {
1921 /* Read value from data fifo */
1922 lval
= inl(ai_context
->data_reg
) & 0xFFFF;
1925 if (!comedi_buf_put(s
->async
, lval
)) {
1927 "comedi%d: me4000: me4000_ai_isr(): "
1928 "Buffer overflow\n", dev
->minor
);
1929 s
->async
->events
|= COMEDI_CB_OVERFLOW
;
1934 /* Work is done, so reset the interrupt */
1936 ("me4000_ai_isr(): Reset interrupt from sample counter\n");
1937 tmp
|= ME4000_AI_CTRL_BIT_SC_IRQ_RESET
;
1938 me4000_outl(dev
, tmp
, ai_context
->ctrl_reg
);
1939 tmp
&= ~ME4000_AI_CTRL_BIT_SC_IRQ_RESET
;
1940 me4000_outl(dev
, tmp
, ai_context
->ctrl_reg
);
1943 ISR_PDEBUG("me4000_ai_isr(): Events = 0x%X\n", s
->async
->events
);
1945 if (s
->async
->events
)
1946 comedi_event(dev
, s
);
1951 /*=============================================================================
1952 Analog output section
1953 ===========================================================================*/
1955 static int me4000_ao_insn_write(struct comedi_device
*dev
,
1956 struct comedi_subdevice
*s
,
1957 struct comedi_insn
*insn
, unsigned int *data
)
1960 int chan
= CR_CHAN(insn
->chanspec
);
1961 int rang
= CR_RANGE(insn
->chanspec
);
1962 int aref
= CR_AREF(insn
->chanspec
);
1965 CALL_PDEBUG("In me4000_ao_insn_write()\n");
1969 } else if (insn
->n
> 1) {
1971 "comedi%d: me4000: me4000_ao_insn_write(): "
1972 "Invalid instruction length %d\n", dev
->minor
, insn
->n
);
1976 if (chan
>= thisboard
->ao
.count
) {
1978 "comedi%d: me4000: me4000_ao_insn_write(): "
1979 "Invalid channel %d\n", dev
->minor
, insn
->n
);
1985 "comedi%d: me4000: me4000_ao_insn_write(): "
1986 "Invalid range %d\n", dev
->minor
, insn
->n
);
1990 if (aref
!= AREF_GROUND
&& aref
!= AREF_COMMON
) {
1992 "comedi%d: me4000: me4000_ao_insn_write(): "
1993 "Invalid aref %d\n", dev
->minor
, insn
->n
);
1997 /* Stop any running conversion */
1998 tmp
= me4000_inl(dev
, info
->ao_context
[chan
].ctrl_reg
);
1999 tmp
|= ME4000_AO_CTRL_BIT_IMMEDIATE_STOP
;
2000 me4000_outl(dev
, tmp
, info
->ao_context
[chan
].ctrl_reg
);
2002 /* Clear control register and set to single mode */
2003 me4000_outl(dev
, 0x0, info
->ao_context
[chan
].ctrl_reg
);
2005 /* Write data value */
2006 me4000_outl(dev
, data
[0], info
->ao_context
[chan
].single_reg
);
2008 /* Store in the mirror */
2009 info
->ao_context
[chan
].mirror
= data
[0];
2014 static int me4000_ao_insn_read(struct comedi_device
*dev
,
2015 struct comedi_subdevice
*s
,
2016 struct comedi_insn
*insn
, unsigned int *data
)
2018 int chan
= CR_CHAN(insn
->chanspec
);
2022 } else if (insn
->n
> 1) {
2024 ("comedi%d: me4000: me4000_ao_insn_read(): "
2025 "Invalid instruction length\n", dev
->minor
);
2029 data
[0] = info
->ao_context
[chan
].mirror
;
2034 /*=============================================================================
2036 ===========================================================================*/
2038 static int me4000_dio_insn_bits(struct comedi_device
*dev
,
2039 struct comedi_subdevice
*s
,
2040 struct comedi_insn
*insn
, unsigned int *data
)
2043 CALL_PDEBUG("In me4000_dio_insn_bits()\n");
2045 /* Length of data must be 2 (mask and new data, see below) */
2051 ("comedi%d: me4000: me4000_dio_insn_bits(): "
2052 "Invalid instruction length\n", dev
->minor
);
2057 * The insn data consists of a mask in data[0] and the new data
2058 * in data[1]. The mask defines which bits we are concerning about.
2059 * The new data must be anded with the mask.
2060 * Each channel corresponds to a bit.
2063 /* Check if requested ports are configured for output */
2064 if ((s
->io_bits
& data
[0]) != data
[0])
2067 s
->state
&= ~data
[0];
2068 s
->state
|= data
[0] & data
[1];
2070 /* Write out the new digital output lines */
2071 me4000_outl(dev
, (s
->state
>> 0) & 0xFF,
2072 info
->dio_context
.port_0_reg
);
2073 me4000_outl(dev
, (s
->state
>> 8) & 0xFF,
2074 info
->dio_context
.port_1_reg
);
2075 me4000_outl(dev
, (s
->state
>> 16) & 0xFF,
2076 info
->dio_context
.port_2_reg
);
2077 me4000_outl(dev
, (s
->state
>> 24) & 0xFF,
2078 info
->dio_context
.port_3_reg
);
2081 /* On return, data[1] contains the value of
2082 the digital input and output lines. */
2084 ((me4000_inl(dev
, info
->dio_context
.port_0_reg
) & 0xFF) << 0) |
2085 ((me4000_inl(dev
, info
->dio_context
.port_1_reg
) & 0xFF) << 8) |
2086 ((me4000_inl(dev
, info
->dio_context
.port_2_reg
) & 0xFF) << 16) |
2087 ((me4000_inl(dev
, info
->dio_context
.port_3_reg
) & 0xFF) << 24);
2092 static int me4000_dio_insn_config(struct comedi_device
*dev
,
2093 struct comedi_subdevice
*s
,
2094 struct comedi_insn
*insn
, unsigned int *data
)
2097 int chan
= CR_CHAN(insn
->chanspec
);
2099 CALL_PDEBUG("In me4000_dio_insn_config()\n");
2101 if (data
[0] == INSN_CONFIG_DIO_QUERY
) {
2103 (s
->io_bits
& (1 << chan
)) ? COMEDI_OUTPUT
: COMEDI_INPUT
;
2108 * The input or output configuration of each digital line is
2109 * configured by a special insn_config instruction. chanspec
2110 * contains the channel to be changed, and data[0] contains the
2111 * value COMEDI_INPUT or COMEDI_OUTPUT.
2112 * On the ME-4000 it is only possible to switch port wise (8 bit)
2115 tmp
= me4000_inl(dev
, info
->dio_context
.ctrl_reg
);
2117 if (data
[0] == COMEDI_OUTPUT
) {
2120 tmp
&= ~(ME4000_DIO_CTRL_BIT_MODE_0
|
2121 ME4000_DIO_CTRL_BIT_MODE_1
);
2122 tmp
|= ME4000_DIO_CTRL_BIT_MODE_0
;
2123 } else if (chan
< 16) {
2125 * Chech for optoisolated ME-4000 version.
2126 * If one the first port is a fixed output
2127 * port and the second is a fixed input port.
2129 if (!me4000_inl(dev
, info
->dio_context
.dir_reg
))
2132 s
->io_bits
|= 0xFF00;
2133 tmp
&= ~(ME4000_DIO_CTRL_BIT_MODE_2
|
2134 ME4000_DIO_CTRL_BIT_MODE_3
);
2135 tmp
|= ME4000_DIO_CTRL_BIT_MODE_2
;
2136 } else if (chan
< 24) {
2137 s
->io_bits
|= 0xFF0000;
2138 tmp
&= ~(ME4000_DIO_CTRL_BIT_MODE_4
|
2139 ME4000_DIO_CTRL_BIT_MODE_5
);
2140 tmp
|= ME4000_DIO_CTRL_BIT_MODE_4
;
2141 } else if (chan
< 32) {
2142 s
->io_bits
|= 0xFF000000;
2143 tmp
&= ~(ME4000_DIO_CTRL_BIT_MODE_6
|
2144 ME4000_DIO_CTRL_BIT_MODE_7
);
2145 tmp
|= ME4000_DIO_CTRL_BIT_MODE_6
;
2152 * Chech for optoisolated ME-4000 version.
2153 * If one the first port is a fixed output
2154 * port and the second is a fixed input port.
2156 if (!me4000_inl(dev
, info
->dio_context
.dir_reg
))
2159 s
->io_bits
&= ~0xFF;
2160 tmp
&= ~(ME4000_DIO_CTRL_BIT_MODE_0
|
2161 ME4000_DIO_CTRL_BIT_MODE_1
);
2162 } else if (chan
< 16) {
2163 s
->io_bits
&= ~0xFF00;
2164 tmp
&= ~(ME4000_DIO_CTRL_BIT_MODE_2
|
2165 ME4000_DIO_CTRL_BIT_MODE_3
);
2166 } else if (chan
< 24) {
2167 s
->io_bits
&= ~0xFF0000;
2168 tmp
&= ~(ME4000_DIO_CTRL_BIT_MODE_4
|
2169 ME4000_DIO_CTRL_BIT_MODE_5
);
2170 } else if (chan
< 32) {
2171 s
->io_bits
&= ~0xFF000000;
2172 tmp
&= ~(ME4000_DIO_CTRL_BIT_MODE_6
|
2173 ME4000_DIO_CTRL_BIT_MODE_7
);
2179 me4000_outl(dev
, tmp
, info
->dio_context
.ctrl_reg
);
2184 /*=============================================================================
2186 ===========================================================================*/
2188 static int cnt_reset(struct comedi_device
*dev
, unsigned int channel
)
2191 CALL_PDEBUG("In cnt_reset()\n");
2195 me4000_outb(dev
, 0x30, info
->cnt_context
.ctrl_reg
);
2196 me4000_outb(dev
, 0x00, info
->cnt_context
.counter_0_reg
);
2197 me4000_outb(dev
, 0x00, info
->cnt_context
.counter_0_reg
);
2200 me4000_outb(dev
, 0x70, info
->cnt_context
.ctrl_reg
);
2201 me4000_outb(dev
, 0x00, info
->cnt_context
.counter_1_reg
);
2202 me4000_outb(dev
, 0x00, info
->cnt_context
.counter_1_reg
);
2205 me4000_outb(dev
, 0xB0, info
->cnt_context
.ctrl_reg
);
2206 me4000_outb(dev
, 0x00, info
->cnt_context
.counter_2_reg
);
2207 me4000_outb(dev
, 0x00, info
->cnt_context
.counter_2_reg
);
2211 "comedi%d: me4000: cnt_reset(): Invalid channel\n",
2219 static int cnt_config(struct comedi_device
*dev
, unsigned int channel
,
2224 CALL_PDEBUG("In cnt_config()\n");
2228 tmp
|= ME4000_CNT_COUNTER_0
;
2231 tmp
|= ME4000_CNT_COUNTER_1
;
2234 tmp
|= ME4000_CNT_COUNTER_2
;
2238 "comedi%d: me4000: cnt_config(): Invalid channel\n",
2245 tmp
|= ME4000_CNT_MODE_0
;
2248 tmp
|= ME4000_CNT_MODE_1
;
2251 tmp
|= ME4000_CNT_MODE_2
;
2254 tmp
|= ME4000_CNT_MODE_3
;
2257 tmp
|= ME4000_CNT_MODE_4
;
2260 tmp
|= ME4000_CNT_MODE_5
;
2264 "comedi%d: me4000: cnt_config(): Invalid counter mode\n",
2269 /* Write the control word */
2271 me4000_outb(dev
, tmp
, info
->cnt_context
.ctrl_reg
);
2276 static int me4000_cnt_insn_config(struct comedi_device
*dev
,
2277 struct comedi_subdevice
*s
,
2278 struct comedi_insn
*insn
, unsigned int *data
)
2283 CALL_PDEBUG("In me4000_cnt_insn_config()\n");
2289 "comedi%d: me4000: me4000_cnt_insn_config(): "
2290 "Invalid instruction length%d\n",
2291 dev
->minor
, insn
->n
);
2295 err
= cnt_reset(dev
, insn
->chanspec
);
2299 case GPCT_SET_OPERATION
:
2302 "comedi%d: me4000: me4000_cnt_insn_config(): "
2303 "Invalid instruction length%d\n",
2304 dev
->minor
, insn
->n
);
2308 err
= cnt_config(dev
, insn
->chanspec
, data
[1]);
2314 "comedi%d: me4000: me4000_cnt_insn_config(): "
2315 "Invalid instruction\n", dev
->minor
);
2322 static int me4000_cnt_insn_read(struct comedi_device
*dev
,
2323 struct comedi_subdevice
*s
,
2324 struct comedi_insn
*insn
, unsigned int *data
)
2329 CALL_PDEBUG("In me4000_cnt_insn_read()\n");
2336 "comedi%d: me4000: me4000_cnt_insn_read(): "
2337 "Invalid instruction length %d\n",
2338 dev
->minor
, insn
->n
);
2342 switch (insn
->chanspec
) {
2344 tmp
= me4000_inb(dev
, info
->cnt_context
.counter_0_reg
);
2346 tmp
= me4000_inb(dev
, info
->cnt_context
.counter_0_reg
);
2347 data
[0] |= tmp
<< 8;
2350 tmp
= me4000_inb(dev
, info
->cnt_context
.counter_1_reg
);
2352 tmp
= me4000_inb(dev
, info
->cnt_context
.counter_1_reg
);
2353 data
[0] |= tmp
<< 8;
2356 tmp
= me4000_inb(dev
, info
->cnt_context
.counter_2_reg
);
2358 tmp
= me4000_inb(dev
, info
->cnt_context
.counter_2_reg
);
2359 data
[0] |= tmp
<< 8;
2363 "comedi%d: me4000: me4000_cnt_insn_read(): "
2364 "Invalid channel %d\n",
2365 dev
->minor
, insn
->chanspec
);
2372 static int me4000_cnt_insn_write(struct comedi_device
*dev
,
2373 struct comedi_subdevice
*s
,
2374 struct comedi_insn
*insn
, unsigned int *data
)
2379 CALL_PDEBUG("In me4000_cnt_insn_write()\n");
2383 } else if (insn
->n
> 1) {
2385 "comedi%d: me4000: me4000_cnt_insn_write(): "
2386 "Invalid instruction length %d\n",
2387 dev
->minor
, insn
->n
);
2391 switch (insn
->chanspec
) {
2393 tmp
= data
[0] & 0xFF;
2394 me4000_outb(dev
, tmp
, info
->cnt_context
.counter_0_reg
);
2395 tmp
= (data
[0] >> 8) & 0xFF;
2396 me4000_outb(dev
, tmp
, info
->cnt_context
.counter_0_reg
);
2399 tmp
= data
[0] & 0xFF;
2400 me4000_outb(dev
, tmp
, info
->cnt_context
.counter_1_reg
);
2401 tmp
= (data
[0] >> 8) & 0xFF;
2402 me4000_outb(dev
, tmp
, info
->cnt_context
.counter_1_reg
);
2405 tmp
= data
[0] & 0xFF;
2406 me4000_outb(dev
, tmp
, info
->cnt_context
.counter_2_reg
);
2407 tmp
= (data
[0] >> 8) & 0xFF;
2408 me4000_outb(dev
, tmp
, info
->cnt_context
.counter_2_reg
);
2412 "comedi%d: me4000: me4000_cnt_insn_write(): "
2413 "Invalid channel %d\n",
2414 dev
->minor
, insn
->chanspec
);
2421 static int __devinit
driver_me4000_pci_probe(struct pci_dev
*dev
,
2422 const struct pci_device_id
*ent
)
2424 return comedi_pci_auto_config(dev
, driver_me4000
.driver_name
);
2427 static void __devexit
driver_me4000_pci_remove(struct pci_dev
*dev
)
2429 comedi_pci_auto_unconfig(dev
);
2432 static struct pci_driver driver_me4000_pci_driver
= {
2433 .id_table
= me4000_pci_table
,
2434 .probe
= &driver_me4000_pci_probe
,
2435 .remove
= __devexit_p(&driver_me4000_pci_remove
)
2438 static int __init
driver_me4000_init_module(void)
2442 retval
= comedi_driver_register(&driver_me4000
);
2446 driver_me4000_pci_driver
.name
= (char *)driver_me4000
.driver_name
;
2447 return pci_register_driver(&driver_me4000_pci_driver
);
2450 static void __exit
driver_me4000_cleanup_module(void)
2452 pci_unregister_driver(&driver_me4000_pci_driver
);
2453 comedi_driver_unregister(&driver_me4000
);
2456 module_init(driver_me4000_init_module
);
2457 module_exit(driver_me4000_cleanup_module
);
2459 MODULE_AUTHOR("Comedi http://www.comedi.org");
2460 MODULE_DESCRIPTION("Comedi low-level driver");
2461 MODULE_LICENSE("GPL");