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 "../comedidev.h"
56 #include <linux/delay.h>
57 #include <linux/list.h>
58 #include <linux/spinlock.h>
60 #include "comedi_pci.h"
63 /* file removed due to GPL incompatibility */
64 #include "me4000_fw.h"
67 /*=============================================================================
69 This is used by modprobe to translate PCI IDs to drivers.
70 ===========================================================================*/
72 static DEFINE_PCI_DEVICE_TABLE(me4000_pci_table
) = {
73 {PCI_VENDOR_ID_MEILHAUS
, 0x4650, PCI_ANY_ID
, PCI_ANY_ID
, 0, 0, 0},
75 {PCI_VENDOR_ID_MEILHAUS
, 0x4660, PCI_ANY_ID
, PCI_ANY_ID
, 0, 0, 0},
76 {PCI_VENDOR_ID_MEILHAUS
, 0x4661, PCI_ANY_ID
, PCI_ANY_ID
, 0, 0, 0},
77 {PCI_VENDOR_ID_MEILHAUS
, 0x4662, PCI_ANY_ID
, PCI_ANY_ID
, 0, 0, 0},
78 {PCI_VENDOR_ID_MEILHAUS
, 0x4663, PCI_ANY_ID
, PCI_ANY_ID
, 0, 0, 0},
80 {PCI_VENDOR_ID_MEILHAUS
, 0x4670, PCI_ANY_ID
, PCI_ANY_ID
, 0, 0, 0},
81 {PCI_VENDOR_ID_MEILHAUS
, 0x4671, PCI_ANY_ID
, PCI_ANY_ID
, 0, 0, 0},
82 {PCI_VENDOR_ID_MEILHAUS
, 0x4672, PCI_ANY_ID
, PCI_ANY_ID
, 0, 0, 0},
83 {PCI_VENDOR_ID_MEILHAUS
, 0x4673, PCI_ANY_ID
, PCI_ANY_ID
, 0, 0, 0},
85 {PCI_VENDOR_ID_MEILHAUS
, 0x4680, PCI_ANY_ID
, PCI_ANY_ID
, 0, 0, 0},
86 {PCI_VENDOR_ID_MEILHAUS
, 0x4681, PCI_ANY_ID
, PCI_ANY_ID
, 0, 0, 0},
87 {PCI_VENDOR_ID_MEILHAUS
, 0x4682, PCI_ANY_ID
, PCI_ANY_ID
, 0, 0, 0},
88 {PCI_VENDOR_ID_MEILHAUS
, 0x4683, PCI_ANY_ID
, PCI_ANY_ID
, 0, 0, 0},
93 MODULE_DEVICE_TABLE(pci
, me4000_pci_table
);
95 static const me4000_board_t me4000_boards
[] = {
96 {"ME-4650", 0x4650, {0, 0}, {16, 0, 0, 0}, {4}, {0}},
98 {"ME-4660", 0x4660, {0, 0}, {32, 0, 16, 0}, {4}, {3}},
99 {"ME-4660i", 0x4661, {0, 0}, {32, 0, 16, 0}, {4}, {3}},
100 {"ME-4660s", 0x4662, {0, 0}, {32, 8, 16, 0}, {4}, {3}},
101 {"ME-4660is", 0x4663, {0, 0}, {32, 8, 16, 0}, {4}, {3}},
103 {"ME-4670", 0x4670, {4, 0}, {32, 0, 16, 1}, {4}, {3}},
104 {"ME-4670i", 0x4671, {4, 0}, {32, 0, 16, 1}, {4}, {3}},
105 {"ME-4670s", 0x4672, {4, 0}, {32, 8, 16, 1}, {4}, {3}},
106 {"ME-4670is", 0x4673, {4, 0}, {32, 8, 16, 1}, {4}, {3}},
108 {"ME-4680", 0x4680, {4, 4}, {32, 0, 16, 1}, {4}, {3}},
109 {"ME-4680i", 0x4681, {4, 4}, {32, 0, 16, 1}, {4}, {3}},
110 {"ME-4680s", 0x4682, {4, 4}, {32, 8, 16, 1}, {4}, {3}},
111 {"ME-4680is", 0x4683, {4, 4}, {32, 8, 16, 1}, {4}, {3}},
116 #define ME4000_BOARD_VERSIONS (sizeof(me4000_boards) / sizeof(me4000_board_t) - 1)
118 /*-----------------------------------------------------------------------------
119 Comedi function prototypes
120 ---------------------------------------------------------------------------*/
121 static int me4000_attach(struct comedi_device
*dev
, comedi_devconfig
*it
);
122 static int me4000_detach(struct comedi_device
*dev
);
123 static struct comedi_driver driver_me4000
= {
124 driver_name
:"me4000",
125 module
: THIS_MODULE
,
126 attach
: me4000_attach
,
127 detach
: me4000_detach
,
130 /*-----------------------------------------------------------------------------
131 Meilhaus function prototypes
132 ---------------------------------------------------------------------------*/
133 static int me4000_probe(struct comedi_device
*dev
, comedi_devconfig
*it
);
134 static int get_registers(struct comedi_device
*dev
, struct pci_dev
*pci_dev_p
);
135 static int init_board_info(struct comedi_device
*dev
, struct pci_dev
*pci_dev_p
);
136 static int init_ao_context(struct comedi_device
*dev
);
137 static int init_ai_context(struct comedi_device
*dev
);
138 static int init_dio_context(struct comedi_device
*dev
);
139 static int init_cnt_context(struct comedi_device
*dev
);
140 static int xilinx_download(struct comedi_device
*dev
);
141 static int reset_board(struct comedi_device
*dev
);
143 static int me4000_dio_insn_bits(struct comedi_device
*dev
,
144 struct comedi_subdevice
*s
, comedi_insn
*insn
, unsigned int *data
);
146 static int me4000_dio_insn_config(struct comedi_device
*dev
,
147 struct comedi_subdevice
*s
, comedi_insn
*insn
, unsigned int *data
);
149 static int cnt_reset(struct comedi_device
*dev
, unsigned int channel
);
151 static int cnt_config(struct comedi_device
*dev
,
152 unsigned int channel
, unsigned int mode
);
154 static int me4000_cnt_insn_config(struct comedi_device
*dev
,
155 struct comedi_subdevice
*s
, comedi_insn
*insn
, unsigned int *data
);
157 static int me4000_cnt_insn_write(struct comedi_device
*dev
,
158 struct comedi_subdevice
*s
, comedi_insn
*insn
, unsigned int *data
);
160 static int me4000_cnt_insn_read(struct comedi_device
*dev
,
161 struct comedi_subdevice
*s
, comedi_insn
*insn
, unsigned int *data
);
163 static int me4000_ai_insn_read(struct comedi_device
*dev
,
164 struct comedi_subdevice
*subdevice
, comedi_insn
*insn
, unsigned int *data
);
166 static int me4000_ai_cancel(struct comedi_device
*dev
, struct comedi_subdevice
*s
);
168 static int ai_check_chanlist(struct comedi_device
*dev
,
169 struct comedi_subdevice
*s
, comedi_cmd
*cmd
);
171 static int ai_round_cmd_args(struct comedi_device
*dev
,
172 struct comedi_subdevice
*s
,
174 unsigned int *init_ticks
,
175 unsigned int *scan_ticks
, unsigned int *chan_ticks
);
177 static int ai_prepare(struct comedi_device
*dev
,
178 struct comedi_subdevice
*s
,
180 unsigned int init_ticks
,
181 unsigned int scan_ticks
, unsigned int chan_ticks
);
183 static int ai_write_chanlist(struct comedi_device
*dev
,
184 struct comedi_subdevice
*s
, comedi_cmd
*cmd
);
186 static irqreturn_t
me4000_ai_isr(int irq
, void *dev_id PT_REGS_ARG
);
188 static int me4000_ai_do_cmd_test(struct comedi_device
*dev
,
189 struct comedi_subdevice
*s
, comedi_cmd
*cmd
);
191 static int me4000_ai_do_cmd(struct comedi_device
*dev
, struct comedi_subdevice
*s
);
193 static int me4000_ao_insn_write(struct comedi_device
*dev
,
194 struct comedi_subdevice
*s
, comedi_insn
*insn
, unsigned int *data
);
196 static int me4000_ao_insn_read(struct comedi_device
*dev
,
197 struct comedi_subdevice
*s
, comedi_insn
*insn
, unsigned int *data
);
199 /*-----------------------------------------------------------------------------
200 Meilhaus inline functions
201 ---------------------------------------------------------------------------*/
203 static inline void me4000_outb(struct comedi_device
*dev
, unsigned char value
,
206 PORT_PDEBUG("--> 0x%02X port 0x%04lX\n", value
, port
);
210 static inline void me4000_outl(struct comedi_device
*dev
, unsigned long value
,
213 PORT_PDEBUG("--> 0x%08lX port 0x%04lX\n", value
, port
);
217 static inline unsigned long me4000_inl(struct comedi_device
*dev
, unsigned long port
)
221 PORT_PDEBUG("<-- 0x%08lX port 0x%04lX\n", value
, port
);
225 static inline unsigned char me4000_inb(struct comedi_device
*dev
, unsigned long port
)
229 PORT_PDEBUG("<-- 0x%08X port 0x%04lX\n", value
, port
);
233 static const struct comedi_lrange me4000_ai_range
= {
243 static const struct comedi_lrange me4000_ao_range
= {
250 static int me4000_attach(struct comedi_device
*dev
, comedi_devconfig
*it
)
252 struct comedi_subdevice
*s
;
255 CALL_PDEBUG("In me4000_attach()\n");
257 result
= me4000_probe(dev
, it
);
262 * Allocate the subdevice structures. alloc_subdevice() is a
263 * convenient macro defined in comedidev.h. It relies on
264 * n_subdevices being set correctly.
266 if (alloc_subdevices(dev
, 4) < 0)
269 /*=========================================================================
270 Analog input subdevice
271 ========================================================================*/
273 s
= dev
->subdevices
+ 0;
275 if (thisboard
->ai
.count
) {
276 s
->type
= COMEDI_SUBD_AI
;
278 SDF_READABLE
| SDF_COMMON
| SDF_GROUND
| SDF_DIFF
;
279 s
->n_chan
= thisboard
->ai
.count
;
280 s
->maxdata
= 0xFFFF; /* 16 bit ADC */
281 s
->len_chanlist
= ME4000_AI_CHANNEL_LIST_COUNT
;
282 s
->range_table
= &me4000_ai_range
;
283 s
->insn_read
= me4000_ai_insn_read
;
286 if (comedi_request_irq(info
->irq
, me4000_ai_isr
,
287 IRQF_SHARED
, "ME-4000", dev
)) {
288 printk("comedi%d: me4000: me4000_attach(): Unable to allocate irq\n", dev
->minor
);
290 dev
->read_subdev
= s
;
291 s
->subdev_flags
|= SDF_CMD_READ
;
292 s
->cancel
= me4000_ai_cancel
;
293 s
->do_cmdtest
= me4000_ai_do_cmd_test
;
294 s
->do_cmd
= me4000_ai_do_cmd
;
298 "comedi%d: me4000: me4000_attach(): No interrupt available\n",
302 s
->type
= COMEDI_SUBD_UNUSED
;
305 /*=========================================================================
306 Analog output subdevice
307 ========================================================================*/
309 s
= dev
->subdevices
+ 1;
311 if (thisboard
->ao
.count
) {
312 s
->type
= COMEDI_SUBD_AO
;
313 s
->subdev_flags
= SDF_WRITEABLE
| SDF_COMMON
| SDF_GROUND
;
314 s
->n_chan
= thisboard
->ao
.count
;
315 s
->maxdata
= 0xFFFF; /* 16 bit DAC */
316 s
->range_table
= &me4000_ao_range
;
317 s
->insn_write
= me4000_ao_insn_write
;
318 s
->insn_read
= me4000_ao_insn_read
;
320 s
->type
= COMEDI_SUBD_UNUSED
;
323 /*=========================================================================
324 Digital I/O subdevice
325 ========================================================================*/
327 s
= dev
->subdevices
+ 2;
329 if (thisboard
->dio
.count
) {
330 s
->type
= COMEDI_SUBD_DIO
;
331 s
->subdev_flags
= SDF_READABLE
| SDF_WRITABLE
;
332 s
->n_chan
= thisboard
->dio
.count
* 8;
334 s
->range_table
= &range_digital
;
335 s
->insn_bits
= me4000_dio_insn_bits
;
336 s
->insn_config
= me4000_dio_insn_config
;
338 s
->type
= COMEDI_SUBD_UNUSED
;
342 * Check for optoisolated ME-4000 version. If one the first
343 * port is a fixed output port and the second is a fixed input port.
345 if (!me4000_inl(dev
, info
->dio_context
.dir_reg
)) {
347 me4000_outl(dev
, ME4000_DIO_CTRL_BIT_MODE_0
,
348 info
->dio_context
.dir_reg
);
351 /*=========================================================================
353 ========================================================================*/
355 s
= dev
->subdevices
+ 3;
357 if (thisboard
->cnt
.count
) {
358 s
->type
= COMEDI_SUBD_COUNTER
;
359 s
->subdev_flags
= SDF_READABLE
| SDF_WRITABLE
;
360 s
->n_chan
= thisboard
->cnt
.count
;
361 s
->maxdata
= 0xFFFF; /* 16 bit counters */
362 s
->insn_read
= me4000_cnt_insn_read
;
363 s
->insn_write
= me4000_cnt_insn_write
;
364 s
->insn_config
= me4000_cnt_insn_config
;
366 s
->type
= COMEDI_SUBD_UNUSED
;
372 static int me4000_probe(struct comedi_device
*dev
, comedi_devconfig
*it
)
374 struct pci_dev
*pci_device
;
376 me4000_board_t
*board
;
378 CALL_PDEBUG("In me4000_probe()\n");
380 /* Allocate private memory */
381 if (alloc_private(dev
, sizeof(me4000_info_t
)) < 0)
385 * Probe the device to determine what device in the series it is.
387 for (pci_device
= pci_get_device(PCI_ANY_ID
, PCI_ANY_ID
, NULL
);
390 pci_get_device(PCI_ANY_ID
, PCI_ANY_ID
, pci_device
)) {
391 if (pci_device
->vendor
== PCI_VENDOR_ID_MEILHAUS
) {
392 for (i
= 0; i
< ME4000_BOARD_VERSIONS
; i
++) {
393 if (me4000_boards
[i
].device_id
==
394 pci_device
->device
) {
395 /* Was a particular bus/slot requested? */
396 if ((it
->options
[0] != 0)
397 || (it
->options
[1] != 0)) {
398 /* Are we on the wrong bus/slot? */
399 if (pci_device
->bus
->number
!=
401 || PCI_SLOT(pci_device
->
407 dev
->board_ptr
= me4000_boards
+ i
;
408 board
= (me4000_board_t
*) dev
->
410 info
->pci_dev_p
= pci_device
;
418 "comedi%d: me4000: me4000_probe(): No supported board found (req. bus/slot : %d/%d)\n",
419 dev
->minor
, it
->options
[0], it
->options
[1]);
425 "comedi%d: me4000: me4000_probe(): Found %s at PCI bus %d, slot %d\n",
426 dev
->minor
, me4000_boards
[i
].name
, pci_device
->bus
->number
,
427 PCI_SLOT(pci_device
->devfn
));
429 /* Set data in device structure */
430 dev
->board_name
= board
->name
;
432 /* Enable PCI device and request regions */
433 result
= comedi_pci_enable(pci_device
, dev
->board_name
);
436 "comedi%d: me4000: me4000_probe(): Cannot enable PCI device and request I/O regions\n",
441 /* Get the PCI base registers */
442 result
= get_registers(dev
, pci_device
);
445 "comedi%d: me4000: me4000_probe(): Cannot get registers\n",
449 /* Initialize board info */
450 result
= init_board_info(dev
, pci_device
);
453 "comedi%d: me4000: me4000_probe(): Cannot init baord info\n",
458 /* Init analog output context */
459 result
= init_ao_context(dev
);
462 "comedi%d: me4000: me4000_probe(): Cannot init ao context\n",
467 /* Init analog input context */
468 result
= init_ai_context(dev
);
471 "comedi%d: me4000: me4000_probe(): Cannot init ai context\n",
476 /* Init digital I/O context */
477 result
= init_dio_context(dev
);
480 "comedi%d: me4000: me4000_probe(): Cannot init dio context\n",
485 /* Init counter context */
486 result
= init_cnt_context(dev
);
489 "comedi%d: me4000: me4000_probe(): Cannot init cnt context\n",
494 /* Download the xilinx firmware */
495 result
= xilinx_download(dev
);
498 "comedi%d: me4000: me4000_probe(): Can't download firmware\n",
503 /* Make a hardware reset */
504 result
= reset_board(dev
);
507 "comedi%d: me4000: me4000_probe(): Can't reset board\n",
515 static int get_registers(struct comedi_device
*dev
, struct pci_dev
*pci_dev_p
)
518 CALL_PDEBUG("In get_registers()\n");
520 /*--------------------------- plx regbase ---------------------------------*/
522 info
->plx_regbase
= pci_resource_start(pci_dev_p
, 1);
523 if (info
->plx_regbase
== 0) {
525 "comedi%d: me4000: get_registers(): PCI base address 1 is not available\n",
529 info
->plx_regbase_size
= pci_resource_len(pci_dev_p
, 1);
531 /*--------------------------- me4000 regbase ------------------------------*/
533 info
->me4000_regbase
= pci_resource_start(pci_dev_p
, 2);
534 if (info
->me4000_regbase
== 0) {
536 "comedi%d: me4000: get_registers(): PCI base address 2 is not available\n",
540 info
->me4000_regbase_size
= pci_resource_len(pci_dev_p
, 2);
542 /*--------------------------- timer regbase ------------------------------*/
544 info
->timer_regbase
= pci_resource_start(pci_dev_p
, 3);
545 if (info
->timer_regbase
== 0) {
547 "comedi%d: me4000: get_registers(): PCI base address 3 is not available\n",
551 info
->timer_regbase_size
= pci_resource_len(pci_dev_p
, 3);
553 /*--------------------------- program regbase ------------------------------*/
555 info
->program_regbase
= pci_resource_start(pci_dev_p
, 5);
556 if (info
->program_regbase
== 0) {
558 "comedi%d: me4000: get_registers(): PCI base address 5 is not available\n",
562 info
->program_regbase_size
= pci_resource_len(pci_dev_p
, 5);
567 static int init_board_info(struct comedi_device
*dev
, struct pci_dev
*pci_dev_p
)
571 CALL_PDEBUG("In init_board_info()\n");
573 /* Init spin locks */
574 /* spin_lock_init(&info->preload_lock); */
575 /* spin_lock_init(&info->ai_ctrl_lock); */
577 /* Get the serial number */
578 result
= pci_read_config_dword(pci_dev_p
, 0x2C, &info
->serial_no
);
579 if (result
!= PCIBIOS_SUCCESSFUL
)
582 /* Get the hardware revision */
583 result
= pci_read_config_byte(pci_dev_p
, 0x08, &info
->hw_revision
);
584 if (result
!= PCIBIOS_SUCCESSFUL
)
587 /* Get the vendor id */
588 info
->vendor_id
= pci_dev_p
->vendor
;
590 /* Get the device id */
591 info
->device_id
= pci_dev_p
->device
;
593 /* Get the irq assigned to the board */
594 info
->irq
= pci_dev_p
->irq
;
599 static int init_ao_context(struct comedi_device
*dev
)
603 CALL_PDEBUG("In init_ao_context()\n");
605 for (i
= 0; i
< thisboard
->ao
.count
; i
++) {
606 /* spin_lock_init(&info->ao_context[i].use_lock); */
607 info
->ao_context
[i
].irq
= info
->irq
;
611 info
->ao_context
[i
].ctrl_reg
=
612 info
->me4000_regbase
+ ME4000_AO_00_CTRL_REG
;
613 info
->ao_context
[i
].status_reg
=
614 info
->me4000_regbase
+ ME4000_AO_00_STATUS_REG
;
615 info
->ao_context
[i
].fifo_reg
=
616 info
->me4000_regbase
+ ME4000_AO_00_FIFO_REG
;
617 info
->ao_context
[i
].single_reg
=
618 info
->me4000_regbase
+ ME4000_AO_00_SINGLE_REG
;
619 info
->ao_context
[i
].timer_reg
=
620 info
->me4000_regbase
+ ME4000_AO_00_TIMER_REG
;
621 info
->ao_context
[i
].irq_status_reg
=
622 info
->me4000_regbase
+ ME4000_IRQ_STATUS_REG
;
623 info
->ao_context
[i
].preload_reg
=
624 info
->me4000_regbase
+ ME4000_AO_LOADSETREG_XX
;
627 info
->ao_context
[i
].ctrl_reg
=
628 info
->me4000_regbase
+ ME4000_AO_01_CTRL_REG
;
629 info
->ao_context
[i
].status_reg
=
630 info
->me4000_regbase
+ ME4000_AO_01_STATUS_REG
;
631 info
->ao_context
[i
].fifo_reg
=
632 info
->me4000_regbase
+ ME4000_AO_01_FIFO_REG
;
633 info
->ao_context
[i
].single_reg
=
634 info
->me4000_regbase
+ ME4000_AO_01_SINGLE_REG
;
635 info
->ao_context
[i
].timer_reg
=
636 info
->me4000_regbase
+ ME4000_AO_01_TIMER_REG
;
637 info
->ao_context
[i
].irq_status_reg
=
638 info
->me4000_regbase
+ ME4000_IRQ_STATUS_REG
;
639 info
->ao_context
[i
].preload_reg
=
640 info
->me4000_regbase
+ ME4000_AO_LOADSETREG_XX
;
643 info
->ao_context
[i
].ctrl_reg
=
644 info
->me4000_regbase
+ ME4000_AO_02_CTRL_REG
;
645 info
->ao_context
[i
].status_reg
=
646 info
->me4000_regbase
+ ME4000_AO_02_STATUS_REG
;
647 info
->ao_context
[i
].fifo_reg
=
648 info
->me4000_regbase
+ ME4000_AO_02_FIFO_REG
;
649 info
->ao_context
[i
].single_reg
=
650 info
->me4000_regbase
+ ME4000_AO_02_SINGLE_REG
;
651 info
->ao_context
[i
].timer_reg
=
652 info
->me4000_regbase
+ ME4000_AO_02_TIMER_REG
;
653 info
->ao_context
[i
].irq_status_reg
=
654 info
->me4000_regbase
+ ME4000_IRQ_STATUS_REG
;
655 info
->ao_context
[i
].preload_reg
=
656 info
->me4000_regbase
+ ME4000_AO_LOADSETREG_XX
;
659 info
->ao_context
[i
].ctrl_reg
=
660 info
->me4000_regbase
+ ME4000_AO_03_CTRL_REG
;
661 info
->ao_context
[i
].status_reg
=
662 info
->me4000_regbase
+ ME4000_AO_03_STATUS_REG
;
663 info
->ao_context
[i
].fifo_reg
=
664 info
->me4000_regbase
+ ME4000_AO_03_FIFO_REG
;
665 info
->ao_context
[i
].single_reg
=
666 info
->me4000_regbase
+ ME4000_AO_03_SINGLE_REG
;
667 info
->ao_context
[i
].timer_reg
=
668 info
->me4000_regbase
+ ME4000_AO_03_TIMER_REG
;
669 info
->ao_context
[i
].irq_status_reg
=
670 info
->me4000_regbase
+ ME4000_IRQ_STATUS_REG
;
671 info
->ao_context
[i
].preload_reg
=
672 info
->me4000_regbase
+ ME4000_AO_LOADSETREG_XX
;
682 static int init_ai_context(struct comedi_device
*dev
)
685 CALL_PDEBUG("In init_ai_context()\n");
687 info
->ai_context
.irq
= info
->irq
;
689 info
->ai_context
.ctrl_reg
= info
->me4000_regbase
+ ME4000_AI_CTRL_REG
;
690 info
->ai_context
.status_reg
=
691 info
->me4000_regbase
+ ME4000_AI_STATUS_REG
;
692 info
->ai_context
.channel_list_reg
=
693 info
->me4000_regbase
+ ME4000_AI_CHANNEL_LIST_REG
;
694 info
->ai_context
.data_reg
= info
->me4000_regbase
+ ME4000_AI_DATA_REG
;
695 info
->ai_context
.chan_timer_reg
=
696 info
->me4000_regbase
+ ME4000_AI_CHAN_TIMER_REG
;
697 info
->ai_context
.chan_pre_timer_reg
=
698 info
->me4000_regbase
+ ME4000_AI_CHAN_PRE_TIMER_REG
;
699 info
->ai_context
.scan_timer_low_reg
=
700 info
->me4000_regbase
+ ME4000_AI_SCAN_TIMER_LOW_REG
;
701 info
->ai_context
.scan_timer_high_reg
=
702 info
->me4000_regbase
+ ME4000_AI_SCAN_TIMER_HIGH_REG
;
703 info
->ai_context
.scan_pre_timer_low_reg
=
704 info
->me4000_regbase
+ ME4000_AI_SCAN_PRE_TIMER_LOW_REG
;
705 info
->ai_context
.scan_pre_timer_high_reg
=
706 info
->me4000_regbase
+ ME4000_AI_SCAN_PRE_TIMER_HIGH_REG
;
707 info
->ai_context
.start_reg
= info
->me4000_regbase
+ ME4000_AI_START_REG
;
708 info
->ai_context
.irq_status_reg
=
709 info
->me4000_regbase
+ ME4000_IRQ_STATUS_REG
;
710 info
->ai_context
.sample_counter_reg
=
711 info
->me4000_regbase
+ ME4000_AI_SAMPLE_COUNTER_REG
;
716 static int init_dio_context(struct comedi_device
*dev
)
719 CALL_PDEBUG("In init_dio_context()\n");
721 info
->dio_context
.dir_reg
= info
->me4000_regbase
+ ME4000_DIO_DIR_REG
;
722 info
->dio_context
.ctrl_reg
= info
->me4000_regbase
+ ME4000_DIO_CTRL_REG
;
723 info
->dio_context
.port_0_reg
=
724 info
->me4000_regbase
+ ME4000_DIO_PORT_0_REG
;
725 info
->dio_context
.port_1_reg
=
726 info
->me4000_regbase
+ ME4000_DIO_PORT_1_REG
;
727 info
->dio_context
.port_2_reg
=
728 info
->me4000_regbase
+ ME4000_DIO_PORT_2_REG
;
729 info
->dio_context
.port_3_reg
=
730 info
->me4000_regbase
+ ME4000_DIO_PORT_3_REG
;
735 static int init_cnt_context(struct comedi_device
*dev
)
738 CALL_PDEBUG("In init_cnt_context()\n");
740 info
->cnt_context
.ctrl_reg
= info
->timer_regbase
+ ME4000_CNT_CTRL_REG
;
741 info
->cnt_context
.counter_0_reg
=
742 info
->timer_regbase
+ ME4000_CNT_COUNTER_0_REG
;
743 info
->cnt_context
.counter_1_reg
=
744 info
->timer_regbase
+ ME4000_CNT_COUNTER_1_REG
;
745 info
->cnt_context
.counter_2_reg
=
746 info
->timer_regbase
+ ME4000_CNT_COUNTER_2_REG
;
751 #define FIRMWARE_NOT_AVAILABLE 1
752 #if FIRMWARE_NOT_AVAILABLE
753 extern unsigned char *xilinx_firm
;
756 static int xilinx_download(struct comedi_device
*dev
)
759 wait_queue_head_t queue
;
763 CALL_PDEBUG("In xilinx_download()\n");
765 init_waitqueue_head(&queue
);
768 * Set PLX local interrupt 2 polarity to high.
769 * Interrupt is thrown by init pin of xilinx.
771 outl(0x10, info
->plx_regbase
+ PLX_INTCSR
);
773 /* Set /CS and /WRITE of the Xilinx */
774 value
= inl(info
->plx_regbase
+ PLX_ICR
);
776 outl(value
, info
->plx_regbase
+ PLX_ICR
);
778 /* Init Xilinx with CS1 */
779 inb(info
->program_regbase
+ 0xC8);
781 /* Wait until /INIT pin is set */
783 if (!(inl(info
->plx_regbase
+ PLX_INTCSR
) & 0x20)) {
785 "comedi%d: me4000: xilinx_download(): Can't init Xilinx\n",
790 /* Reset /CS and /WRITE of the Xilinx */
791 value
= inl(info
->plx_regbase
+ PLX_ICR
);
793 outl(value
, info
->plx_regbase
+ PLX_ICR
);
794 if (FIRMWARE_NOT_AVAILABLE
) {
796 "xilinx firmware unavailable due to licensing, aborting");
799 /* Download Xilinx firmware */
800 size
= (xilinx_firm
[0] << 24) + (xilinx_firm
[1] << 16) +
801 (xilinx_firm
[2] << 8) + xilinx_firm
[3];
804 for (idx
= 0; idx
< size
; idx
++) {
805 outb(xilinx_firm
[16 + idx
], info
->program_regbase
);
808 /* Check if BUSY flag is low */
809 if (inl(info
->plx_regbase
+ PLX_ICR
) & 0x20) {
811 "comedi%d: me4000: xilinx_download(): Xilinx is still busy (idx = %d)\n",
818 /* If done flag is high download was successful */
819 if (inl(info
->plx_regbase
+ PLX_ICR
) & 0x4) {
822 "comedi%d: me4000: xilinx_download(): DONE flag is not set\n",
825 "comedi%d: me4000: xilinx_download(): Download not succesful\n",
830 /* Set /CS and /WRITE */
831 value
= inl(info
->plx_regbase
+ PLX_ICR
);
833 outl(value
, info
->plx_regbase
+ PLX_ICR
);
838 static int reset_board(struct comedi_device
*dev
)
842 CALL_PDEBUG("In reset_board()\n");
844 /* Make a hardware reset */
845 icr
= me4000_inl(dev
, info
->plx_regbase
+ PLX_ICR
);
847 me4000_outl(dev
, icr
, info
->plx_regbase
+ PLX_ICR
);
849 me4000_outl(dev
, icr
, info
->plx_regbase
+ PLX_ICR
);
851 /* 0x8000 to the DACs means an output voltage of 0V */
852 me4000_outl(dev
, 0x8000,
853 info
->me4000_regbase
+ ME4000_AO_00_SINGLE_REG
);
854 me4000_outl(dev
, 0x8000,
855 info
->me4000_regbase
+ ME4000_AO_01_SINGLE_REG
);
856 me4000_outl(dev
, 0x8000,
857 info
->me4000_regbase
+ ME4000_AO_02_SINGLE_REG
);
858 me4000_outl(dev
, 0x8000,
859 info
->me4000_regbase
+ ME4000_AO_03_SINGLE_REG
);
861 /* Set both stop bits in the analog input control register */
863 ME4000_AI_CTRL_BIT_IMMEDIATE_STOP
| ME4000_AI_CTRL_BIT_STOP
,
864 info
->me4000_regbase
+ ME4000_AI_CTRL_REG
);
866 /* Set both stop bits in the analog output control register */
868 ME4000_AO_CTRL_BIT_IMMEDIATE_STOP
| ME4000_AO_CTRL_BIT_STOP
,
869 info
->me4000_regbase
+ ME4000_AO_00_CTRL_REG
);
871 ME4000_AO_CTRL_BIT_IMMEDIATE_STOP
| ME4000_AO_CTRL_BIT_STOP
,
872 info
->me4000_regbase
+ ME4000_AO_01_CTRL_REG
);
874 ME4000_AO_CTRL_BIT_IMMEDIATE_STOP
| ME4000_AO_CTRL_BIT_STOP
,
875 info
->me4000_regbase
+ ME4000_AO_02_CTRL_REG
);
877 ME4000_AO_CTRL_BIT_IMMEDIATE_STOP
| ME4000_AO_CTRL_BIT_STOP
,
878 info
->me4000_regbase
+ ME4000_AO_03_CTRL_REG
);
880 /* Enable interrupts on the PLX */
881 me4000_outl(dev
, 0x43, info
->plx_regbase
+ PLX_INTCSR
);
883 /* Set the adustment register for AO demux */
884 me4000_outl(dev
, ME4000_AO_DEMUX_ADJUST_VALUE
,
885 info
->me4000_regbase
+ ME4000_AO_DEMUX_ADJUST_REG
);
887 /* Set digital I/O direction for port 0 to output on isolated versions */
888 if (!(me4000_inl(dev
, info
->me4000_regbase
+ ME4000_DIO_DIR_REG
) & 0x1)) {
889 me4000_outl(dev
, 0x1,
890 info
->me4000_regbase
+ ME4000_DIO_CTRL_REG
);
896 static int me4000_detach(struct comedi_device
*dev
)
898 CALL_PDEBUG("In me4000_detach()\n");
901 if (info
->pci_dev_p
) {
903 if (info
->plx_regbase
)
904 comedi_pci_disable(info
->pci_dev_p
);
905 pci_dev_put(info
->pci_dev_p
);
912 /*=============================================================================
914 ===========================================================================*/
916 static int me4000_ai_insn_read(struct comedi_device
*dev
,
917 struct comedi_subdevice
*subdevice
, comedi_insn
*insn
, unsigned int *data
)
920 int chan
= CR_CHAN(insn
->chanspec
);
921 int rang
= CR_RANGE(insn
->chanspec
);
922 int aref
= CR_AREF(insn
->chanspec
);
924 unsigned long entry
= 0;
928 CALL_PDEBUG("In me4000_ai_insn_read()\n");
932 } else if (insn
->n
> 1) {
934 "comedi%d: me4000: me4000_ai_insn_read(): Invalid instruction length %d\n",
935 dev
->minor
, insn
->n
);
941 entry
|= ME4000_AI_LIST_RANGE_UNIPOLAR_2_5
;
944 entry
|= ME4000_AI_LIST_RANGE_UNIPOLAR_10
;
947 entry
|= ME4000_AI_LIST_RANGE_BIPOLAR_2_5
;
950 entry
|= ME4000_AI_LIST_RANGE_BIPOLAR_10
;
954 "comedi%d: me4000: me4000_ai_insn_read(): Invalid range specified\n",
962 if (chan
>= thisboard
->ai
.count
) {
964 "comedi%d: me4000: me4000_ai_insn_read(): Analog input is not available\n",
968 entry
|= ME4000_AI_LIST_INPUT_SINGLE_ENDED
| chan
;
972 if (rang
== 0 || rang
== 1) {
974 "comedi%d: me4000: me4000_ai_insn_read(): Range must be bipolar when aref = diff\n",
979 if (chan
>= thisboard
->ai
.diff_count
) {
981 "comedi%d: me4000: me4000_ai_insn_read(): Analog input is not available\n",
985 entry
|= ME4000_AI_LIST_INPUT_DIFFERENTIAL
| chan
;
989 "comedi%d: me4000: me4000_ai_insn_read(): Invalid aref specified\n",
994 entry
|= ME4000_AI_LIST_LAST_ENTRY
;
996 /* Clear channel list, data fifo and both stop bits */
997 tmp
= me4000_inl(dev
, info
->ai_context
.ctrl_reg
);
998 tmp
&= ~(ME4000_AI_CTRL_BIT_CHANNEL_FIFO
|
999 ME4000_AI_CTRL_BIT_DATA_FIFO
|
1000 ME4000_AI_CTRL_BIT_STOP
| ME4000_AI_CTRL_BIT_IMMEDIATE_STOP
);
1001 me4000_outl(dev
, tmp
, info
->ai_context
.ctrl_reg
);
1003 /* Set the acquisition mode to single */
1004 tmp
&= ~(ME4000_AI_CTRL_BIT_MODE_0
| ME4000_AI_CTRL_BIT_MODE_1
|
1005 ME4000_AI_CTRL_BIT_MODE_2
);
1006 me4000_outl(dev
, tmp
, info
->ai_context
.ctrl_reg
);
1008 /* Enable channel list and data fifo */
1009 tmp
|= ME4000_AI_CTRL_BIT_CHANNEL_FIFO
| ME4000_AI_CTRL_BIT_DATA_FIFO
;
1010 me4000_outl(dev
, tmp
, info
->ai_context
.ctrl_reg
);
1012 /* Generate channel list entry */
1013 me4000_outl(dev
, entry
, info
->ai_context
.channel_list_reg
);
1015 /* Set the timer to maximum sample rate */
1016 me4000_outl(dev
, ME4000_AI_MIN_TICKS
, info
->ai_context
.chan_timer_reg
);
1017 me4000_outl(dev
, ME4000_AI_MIN_TICKS
,
1018 info
->ai_context
.chan_pre_timer_reg
);
1020 /* Start conversion by dummy read */
1021 me4000_inl(dev
, info
->ai_context
.start_reg
);
1023 /* Wait until ready */
1025 if (!(me4000_inl(dev
, info
->ai_context
.
1026 status_reg
) & ME4000_AI_STATUS_BIT_EF_DATA
)) {
1028 "comedi%d: me4000: me4000_ai_insn_read(): Value not available after wait\n",
1033 /* Read value from data fifo */
1034 lval
= me4000_inl(dev
, info
->ai_context
.data_reg
) & 0xFFFF;
1035 data
[0] = lval
^ 0x8000;
1040 static int me4000_ai_cancel(struct comedi_device
*dev
, struct comedi_subdevice
*s
)
1044 CALL_PDEBUG("In me4000_ai_cancel()\n");
1046 /* Stop any running conversion */
1047 tmp
= me4000_inl(dev
, info
->ai_context
.ctrl_reg
);
1048 tmp
&= ~(ME4000_AI_CTRL_BIT_STOP
| ME4000_AI_CTRL_BIT_IMMEDIATE_STOP
);
1049 me4000_outl(dev
, tmp
, info
->ai_context
.ctrl_reg
);
1051 /* Clear the control register */
1052 me4000_outl(dev
, 0x0, info
->ai_context
.ctrl_reg
);
1057 static int ai_check_chanlist(struct comedi_device
*dev
,
1058 struct comedi_subdevice
*s
, comedi_cmd
*cmd
)
1063 CALL_PDEBUG("In ai_check_chanlist()\n");
1065 /* Check whether a channel list is available */
1066 if (!cmd
->chanlist_len
) {
1068 "comedi%d: me4000: ai_check_chanlist(): No channel list available\n",
1073 /* Check the channel list size */
1074 if (cmd
->chanlist_len
> ME4000_AI_CHANNEL_LIST_COUNT
) {
1076 "comedi%d: me4000: ai_check_chanlist(): Channel list is to large\n",
1081 /* Check the pointer */
1082 if (!cmd
->chanlist
) {
1084 "comedi%d: me4000: ai_check_chanlist(): NULL pointer to channel list\n",
1089 /* Check whether aref is equal for all entries */
1090 aref
= CR_AREF(cmd
->chanlist
[0]);
1091 for (i
= 0; i
< cmd
->chanlist_len
; i
++) {
1092 if (CR_AREF(cmd
->chanlist
[i
]) != aref
) {
1094 "comedi%d: me4000: ai_check_chanlist(): Mode is not equal for all entries\n",
1100 /* Check whether channels are available for this ending */
1101 if (aref
== SDF_DIFF
) {
1102 for (i
= 0; i
< cmd
->chanlist_len
; i
++) {
1103 if (CR_CHAN(cmd
->chanlist
[i
]) >=
1104 thisboard
->ai
.diff_count
) {
1106 "comedi%d: me4000: ai_check_chanlist(): Channel number to high\n",
1112 for (i
= 0; i
< cmd
->chanlist_len
; i
++) {
1113 if (CR_CHAN(cmd
->chanlist
[i
]) >= thisboard
->ai
.count
) {
1115 "comedi%d: me4000: ai_check_chanlist(): Channel number to high\n",
1122 /* Check if bipolar is set for all entries when in differential mode */
1123 if (aref
== SDF_DIFF
) {
1124 for (i
= 0; i
< cmd
->chanlist_len
; i
++) {
1125 if (CR_RANGE(cmd
->chanlist
[i
]) != 1 &&
1126 CR_RANGE(cmd
->chanlist
[i
]) != 2) {
1128 "comedi%d: me4000: ai_check_chanlist(): Bipolar is not selected in differential mode\n",
1138 static int ai_round_cmd_args(struct comedi_device
*dev
,
1139 struct comedi_subdevice
*s
,
1141 unsigned int *init_ticks
,
1142 unsigned int *scan_ticks
, unsigned int *chan_ticks
)
1147 CALL_PDEBUG("In ai_round_cmd_args()\n");
1153 PDEBUG("ai_round_cmd_arg(): start_arg = %d\n", cmd
->start_arg
);
1154 PDEBUG("ai_round_cmd_arg(): scan_begin_arg = %d\n",
1155 cmd
->scan_begin_arg
);
1156 PDEBUG("ai_round_cmd_arg(): convert_arg = %d\n", cmd
->convert_arg
);
1158 if (cmd
->start_arg
) {
1159 *init_ticks
= (cmd
->start_arg
* 33) / 1000;
1160 rest
= (cmd
->start_arg
* 33) % 1000;
1162 if (cmd
->flags
& TRIG_ROUND_NEAREST
) {
1165 } else if (cmd
->flags
& TRIG_ROUND_UP
) {
1171 if (cmd
->scan_begin_arg
) {
1172 *scan_ticks
= (cmd
->scan_begin_arg
* 33) / 1000;
1173 rest
= (cmd
->scan_begin_arg
* 33) % 1000;
1175 if (cmd
->flags
& TRIG_ROUND_NEAREST
) {
1178 } else if (cmd
->flags
& TRIG_ROUND_UP
) {
1184 if (cmd
->convert_arg
) {
1185 *chan_ticks
= (cmd
->convert_arg
* 33) / 1000;
1186 rest
= (cmd
->convert_arg
* 33) % 1000;
1188 if (cmd
->flags
& TRIG_ROUND_NEAREST
) {
1191 } else if (cmd
->flags
& TRIG_ROUND_UP
) {
1197 PDEBUG("ai_round_cmd_args(): init_ticks = %d\n", *init_ticks
);
1198 PDEBUG("ai_round_cmd_args(): scan_ticks = %d\n", *scan_ticks
);
1199 PDEBUG("ai_round_cmd_args(): chan_ticks = %d\n", *chan_ticks
);
1204 static void ai_write_timer(struct comedi_device
*dev
,
1205 unsigned int init_ticks
,
1206 unsigned int scan_ticks
, unsigned int chan_ticks
)
1209 CALL_PDEBUG("In ai_write_timer()\n");
1211 me4000_outl(dev
, init_ticks
- 1,
1212 info
->ai_context
.scan_pre_timer_low_reg
);
1213 me4000_outl(dev
, 0x0, info
->ai_context
.scan_pre_timer_high_reg
);
1216 me4000_outl(dev
, scan_ticks
- 1,
1217 info
->ai_context
.scan_timer_low_reg
);
1218 me4000_outl(dev
, 0x0, info
->ai_context
.scan_timer_high_reg
);
1221 me4000_outl(dev
, chan_ticks
- 1, info
->ai_context
.chan_pre_timer_reg
);
1222 me4000_outl(dev
, chan_ticks
- 1, info
->ai_context
.chan_timer_reg
);
1225 static int ai_prepare(struct comedi_device
*dev
,
1226 struct comedi_subdevice
*s
,
1228 unsigned int init_ticks
,
1229 unsigned int scan_ticks
, unsigned int chan_ticks
)
1232 unsigned long tmp
= 0;
1234 CALL_PDEBUG("In ai_prepare()\n");
1236 /* Write timer arguments */
1237 ai_write_timer(dev
, init_ticks
, scan_ticks
, chan_ticks
);
1239 /* Reset control register */
1240 me4000_outl(dev
, tmp
, info
->ai_context
.ctrl_reg
);
1243 if ((cmd
->start_src
== TRIG_EXT
&&
1244 cmd
->scan_begin_src
== TRIG_TIMER
&&
1245 cmd
->convert_src
== TRIG_TIMER
) ||
1246 (cmd
->start_src
== TRIG_EXT
&&
1247 cmd
->scan_begin_src
== TRIG_FOLLOW
&&
1248 cmd
->convert_src
== TRIG_TIMER
)) {
1249 tmp
= ME4000_AI_CTRL_BIT_MODE_1
|
1250 ME4000_AI_CTRL_BIT_CHANNEL_FIFO
|
1251 ME4000_AI_CTRL_BIT_DATA_FIFO
;
1252 } else if (cmd
->start_src
== TRIG_EXT
&&
1253 cmd
->scan_begin_src
== TRIG_EXT
&&
1254 cmd
->convert_src
== TRIG_TIMER
) {
1255 tmp
= ME4000_AI_CTRL_BIT_MODE_2
|
1256 ME4000_AI_CTRL_BIT_CHANNEL_FIFO
|
1257 ME4000_AI_CTRL_BIT_DATA_FIFO
;
1258 } else if (cmd
->start_src
== TRIG_EXT
&&
1259 cmd
->scan_begin_src
== TRIG_EXT
&&
1260 cmd
->convert_src
== TRIG_EXT
) {
1261 tmp
= ME4000_AI_CTRL_BIT_MODE_0
|
1262 ME4000_AI_CTRL_BIT_MODE_1
|
1263 ME4000_AI_CTRL_BIT_CHANNEL_FIFO
|
1264 ME4000_AI_CTRL_BIT_DATA_FIFO
;
1266 tmp
= ME4000_AI_CTRL_BIT_MODE_0
|
1267 ME4000_AI_CTRL_BIT_CHANNEL_FIFO
|
1268 ME4000_AI_CTRL_BIT_DATA_FIFO
;
1272 if (cmd
->stop_src
== TRIG_COUNT
) {
1273 me4000_outl(dev
, cmd
->chanlist_len
* cmd
->stop_arg
,
1274 info
->ai_context
.sample_counter_reg
);
1275 tmp
|= ME4000_AI_CTRL_BIT_HF_IRQ
| ME4000_AI_CTRL_BIT_SC_IRQ
;
1276 } else if (cmd
->stop_src
== TRIG_NONE
&&
1277 cmd
->scan_end_src
== TRIG_COUNT
) {
1278 me4000_outl(dev
, cmd
->scan_end_arg
,
1279 info
->ai_context
.sample_counter_reg
);
1280 tmp
|= ME4000_AI_CTRL_BIT_HF_IRQ
| ME4000_AI_CTRL_BIT_SC_IRQ
;
1282 tmp
|= ME4000_AI_CTRL_BIT_HF_IRQ
;
1285 /* Write the setup to the control register */
1286 me4000_outl(dev
, tmp
, info
->ai_context
.ctrl_reg
);
1288 /* Write the channel list */
1289 ai_write_chanlist(dev
, s
, cmd
);
1294 static int ai_write_chanlist(struct comedi_device
*dev
,
1295 struct comedi_subdevice
*s
, comedi_cmd
*cmd
)
1303 CALL_PDEBUG("In ai_write_chanlist()\n");
1305 for (i
= 0; i
< cmd
->chanlist_len
; i
++) {
1306 chan
= CR_CHAN(cmd
->chanlist
[i
]);
1307 rang
= CR_RANGE(cmd
->chanlist
[i
]);
1308 aref
= CR_AREF(cmd
->chanlist
[i
]);
1313 entry
|= ME4000_AI_LIST_RANGE_UNIPOLAR_2_5
;
1314 } else if (rang
== 1) {
1315 entry
|= ME4000_AI_LIST_RANGE_UNIPOLAR_10
;
1316 } else if (rang
== 2) {
1317 entry
|= ME4000_AI_LIST_RANGE_BIPOLAR_2_5
;
1319 entry
|= ME4000_AI_LIST_RANGE_BIPOLAR_10
;
1322 if (aref
== SDF_DIFF
) {
1323 entry
|= ME4000_AI_LIST_INPUT_DIFFERENTIAL
;
1325 entry
|= ME4000_AI_LIST_INPUT_SINGLE_ENDED
;
1328 me4000_outl(dev
, entry
, info
->ai_context
.channel_list_reg
);
1334 static int me4000_ai_do_cmd(struct comedi_device
*dev
, struct comedi_subdevice
*s
)
1337 unsigned int init_ticks
= 0;
1338 unsigned int scan_ticks
= 0;
1339 unsigned int chan_ticks
= 0;
1340 comedi_cmd
*cmd
= &s
->async
->cmd
;
1342 CALL_PDEBUG("In me4000_ai_do_cmd()\n");
1344 /* Reset the analog input */
1345 err
= me4000_ai_cancel(dev
, s
);
1349 /* Round the timer arguments */
1350 err
= ai_round_cmd_args(dev
,
1351 s
, cmd
, &init_ticks
, &scan_ticks
, &chan_ticks
);
1355 /* Prepare the AI for acquisition */
1356 err
= ai_prepare(dev
, s
, cmd
, init_ticks
, scan_ticks
, chan_ticks
);
1360 /* Start acquistion by dummy read */
1361 me4000_inl(dev
, info
->ai_context
.start_reg
);
1367 * me4000_ai_do_cmd_test():
1369 * The demo cmd.c in ./comedilib/demo specifies 6 return values:
1373 * - invalid argument
1374 * - argument conflict
1375 * - invalid chanlist
1376 * So I tried to adopt this scheme.
1378 static int me4000_ai_do_cmd_test(struct comedi_device
*dev
,
1379 struct comedi_subdevice
*s
, comedi_cmd
*cmd
)
1382 unsigned int init_ticks
;
1383 unsigned int chan_ticks
;
1384 unsigned int scan_ticks
;
1387 CALL_PDEBUG("In me4000_ai_do_cmd_test()\n");
1389 PDEBUG("me4000_ai_do_cmd_test(): subdev = %d\n", cmd
->subdev
);
1390 PDEBUG("me4000_ai_do_cmd_test(): flags = %08X\n", cmd
->flags
);
1391 PDEBUG("me4000_ai_do_cmd_test(): start_src = %08X\n",
1393 PDEBUG("me4000_ai_do_cmd_test(): start_arg = %d\n",
1395 PDEBUG("me4000_ai_do_cmd_test(): scan_begin_src = %08X\n",
1396 cmd
->scan_begin_src
);
1397 PDEBUG("me4000_ai_do_cmd_test(): scan_begin_arg = %d\n",
1398 cmd
->scan_begin_arg
);
1399 PDEBUG("me4000_ai_do_cmd_test(): convert_src = %08X\n",
1401 PDEBUG("me4000_ai_do_cmd_test(): convert_arg = %d\n",
1403 PDEBUG("me4000_ai_do_cmd_test(): scan_end_src = %08X\n",
1405 PDEBUG("me4000_ai_do_cmd_test(): scan_end_arg = %d\n",
1407 PDEBUG("me4000_ai_do_cmd_test(): stop_src = %08X\n",
1409 PDEBUG("me4000_ai_do_cmd_test(): stop_arg = %d\n", cmd
->stop_arg
);
1410 PDEBUG("me4000_ai_do_cmd_test(): chanlist = %d\n",
1411 (unsigned int)cmd
->chanlist
);
1412 PDEBUG("me4000_ai_do_cmd_test(): chanlist_len = %d\n",
1415 /* Only rounding flags are implemented */
1416 cmd
->flags
&= TRIG_ROUND_NEAREST
| TRIG_ROUND_UP
| TRIG_ROUND_DOWN
;
1418 /* Round the timer arguments */
1419 ai_round_cmd_args(dev
, s
, cmd
, &init_ticks
, &scan_ticks
, &chan_ticks
);
1422 * Stage 1. Check if the trigger sources are generally valid.
1424 switch (cmd
->start_src
) {
1429 cmd
->start_src
&= TRIG_NOW
| TRIG_EXT
;
1434 "comedi%d: me4000: me4000_ai_do_cmd_test(): Invalid start source\n",
1436 cmd
->start_src
= TRIG_NOW
;
1439 switch (cmd
->scan_begin_src
) {
1445 cmd
->scan_begin_src
&= TRIG_FOLLOW
| TRIG_TIMER
| TRIG_EXT
;
1450 "comedi%d: me4000: me4000_ai_do_cmd_test(): Invalid scan begin source\n",
1452 cmd
->scan_begin_src
= TRIG_FOLLOW
;
1455 switch (cmd
->convert_src
) {
1460 cmd
->convert_src
&= TRIG_TIMER
| TRIG_EXT
;
1465 "comedi%d: me4000: me4000_ai_do_cmd_test(): Invalid convert source\n",
1467 cmd
->convert_src
= TRIG_TIMER
;
1470 switch (cmd
->scan_end_src
) {
1475 cmd
->scan_end_src
&= TRIG_NONE
| TRIG_COUNT
;
1480 "comedi%d: me4000: me4000_ai_do_cmd_test(): Invalid scan end source\n",
1482 cmd
->scan_end_src
= TRIG_NONE
;
1485 switch (cmd
->stop_src
) {
1490 cmd
->stop_src
&= TRIG_NONE
| TRIG_COUNT
;
1495 "comedi%d: me4000: me4000_ai_do_cmd_test(): Invalid stop source\n",
1497 cmd
->stop_src
= TRIG_NONE
;
1504 * Stage 2. Check for trigger source conflicts.
1506 if (cmd
->start_src
== TRIG_NOW
&&
1507 cmd
->scan_begin_src
== TRIG_TIMER
&&
1508 cmd
->convert_src
== TRIG_TIMER
) {
1509 } else if (cmd
->start_src
== TRIG_NOW
&&
1510 cmd
->scan_begin_src
== TRIG_FOLLOW
&&
1511 cmd
->convert_src
== TRIG_TIMER
) {
1512 } else if (cmd
->start_src
== TRIG_EXT
&&
1513 cmd
->scan_begin_src
== TRIG_TIMER
&&
1514 cmd
->convert_src
== TRIG_TIMER
) {
1515 } else if (cmd
->start_src
== TRIG_EXT
&&
1516 cmd
->scan_begin_src
== TRIG_FOLLOW
&&
1517 cmd
->convert_src
== TRIG_TIMER
) {
1518 } else if (cmd
->start_src
== TRIG_EXT
&&
1519 cmd
->scan_begin_src
== TRIG_EXT
&&
1520 cmd
->convert_src
== TRIG_TIMER
) {
1521 } else if (cmd
->start_src
== TRIG_EXT
&&
1522 cmd
->scan_begin_src
== TRIG_EXT
&&
1523 cmd
->convert_src
== TRIG_EXT
) {
1526 "comedi%d: me4000: me4000_ai_do_cmd_test(): Invalid start trigger combination\n",
1528 cmd
->start_src
= TRIG_NOW
;
1529 cmd
->scan_begin_src
= TRIG_FOLLOW
;
1530 cmd
->convert_src
= TRIG_TIMER
;
1534 if (cmd
->stop_src
== TRIG_NONE
&& cmd
->scan_end_src
== TRIG_NONE
) {
1535 } else if (cmd
->stop_src
== TRIG_COUNT
&&
1536 cmd
->scan_end_src
== TRIG_NONE
) {
1537 } else if (cmd
->stop_src
== TRIG_NONE
&&
1538 cmd
->scan_end_src
== TRIG_COUNT
) {
1539 } else if (cmd
->stop_src
== TRIG_COUNT
&&
1540 cmd
->scan_end_src
== TRIG_COUNT
) {
1543 "comedi%d: me4000: me4000_ai_do_cmd_test(): Invalid stop trigger combination\n",
1545 cmd
->stop_src
= TRIG_NONE
;
1546 cmd
->scan_end_src
= TRIG_NONE
;
1553 * Stage 3. Check if arguments are generally valid.
1555 if (cmd
->chanlist_len
< 1) {
1557 "comedi%d: me4000: me4000_ai_do_cmd_test(): No channel list\n",
1559 cmd
->chanlist_len
= 1;
1562 if (init_ticks
< 66) {
1564 "comedi%d: me4000: me4000_ai_do_cmd_test(): Start arg to low\n",
1566 cmd
->start_arg
= 2000;
1569 if (scan_ticks
&& scan_ticks
< 67) {
1571 "comedi%d: me4000: me4000_ai_do_cmd_test(): Scan begin arg to low\n",
1573 cmd
->scan_begin_arg
= 2031;
1576 if (chan_ticks
< 66) {
1578 "comedi%d: me4000: me4000_ai_do_cmd_test(): Convert arg to low\n",
1580 cmd
->convert_arg
= 2000;
1588 * Stage 4. Check for argument conflicts.
1590 if (cmd
->start_src
== TRIG_NOW
&&
1591 cmd
->scan_begin_src
== TRIG_TIMER
&&
1592 cmd
->convert_src
== TRIG_TIMER
) {
1594 /* Check timer arguments */
1595 if (init_ticks
< ME4000_AI_MIN_TICKS
) {
1597 "comedi%d: me4000: me4000_ai_do_cmd_test(): Invalid start arg\n",
1599 cmd
->start_arg
= 2000; /* 66 ticks at least */
1602 if (chan_ticks
< ME4000_AI_MIN_TICKS
) {
1604 "comedi%d: me4000: me4000_ai_do_cmd_test(): Invalid convert arg\n",
1606 cmd
->convert_arg
= 2000; /* 66 ticks at least */
1609 if (scan_ticks
<= cmd
->chanlist_len
* chan_ticks
) {
1611 "comedi%d: me4000: me4000_ai_do_cmd_test(): Invalid scan end arg\n",
1613 cmd
->scan_end_arg
= 2000 * cmd
->chanlist_len
+ 31; /* At least one tick more */
1616 } else if (cmd
->start_src
== TRIG_NOW
&&
1617 cmd
->scan_begin_src
== TRIG_FOLLOW
&&
1618 cmd
->convert_src
== TRIG_TIMER
) {
1620 /* Check timer arguments */
1621 if (init_ticks
< ME4000_AI_MIN_TICKS
) {
1623 "comedi%d: me4000: me4000_ai_do_cmd_test(): Invalid start arg\n",
1625 cmd
->start_arg
= 2000; /* 66 ticks at least */
1628 if (chan_ticks
< ME4000_AI_MIN_TICKS
) {
1630 "comedi%d: me4000: me4000_ai_do_cmd_test(): Invalid convert arg\n",
1632 cmd
->convert_arg
= 2000; /* 66 ticks at least */
1635 } else if (cmd
->start_src
== TRIG_EXT
&&
1636 cmd
->scan_begin_src
== TRIG_TIMER
&&
1637 cmd
->convert_src
== TRIG_TIMER
) {
1639 /* Check timer arguments */
1640 if (init_ticks
< ME4000_AI_MIN_TICKS
) {
1642 "comedi%d: me4000: me4000_ai_do_cmd_test(): Invalid start arg\n",
1644 cmd
->start_arg
= 2000; /* 66 ticks at least */
1647 if (chan_ticks
< ME4000_AI_MIN_TICKS
) {
1649 "comedi%d: me4000: me4000_ai_do_cmd_test(): Invalid convert arg\n",
1651 cmd
->convert_arg
= 2000; /* 66 ticks at least */
1654 if (scan_ticks
<= cmd
->chanlist_len
* chan_ticks
) {
1656 "comedi%d: me4000: me4000_ai_do_cmd_test(): Invalid scan end arg\n",
1658 cmd
->scan_end_arg
= 2000 * cmd
->chanlist_len
+ 31; /* At least one tick more */
1661 } else if (cmd
->start_src
== TRIG_EXT
&&
1662 cmd
->scan_begin_src
== TRIG_FOLLOW
&&
1663 cmd
->convert_src
== TRIG_TIMER
) {
1665 /* Check timer arguments */
1666 if (init_ticks
< ME4000_AI_MIN_TICKS
) {
1668 "comedi%d: me4000: me4000_ai_do_cmd_test(): Invalid start arg\n",
1670 cmd
->start_arg
= 2000; /* 66 ticks at least */
1673 if (chan_ticks
< ME4000_AI_MIN_TICKS
) {
1675 "comedi%d: me4000: me4000_ai_do_cmd_test(): Invalid convert arg\n",
1677 cmd
->convert_arg
= 2000; /* 66 ticks at least */
1680 } else if (cmd
->start_src
== TRIG_EXT
&&
1681 cmd
->scan_begin_src
== TRIG_EXT
&&
1682 cmd
->convert_src
== TRIG_TIMER
) {
1684 /* Check timer arguments */
1685 if (init_ticks
< ME4000_AI_MIN_TICKS
) {
1687 "comedi%d: me4000: me4000_ai_do_cmd_test(): Invalid start arg\n",
1689 cmd
->start_arg
= 2000; /* 66 ticks at least */
1692 if (chan_ticks
< ME4000_AI_MIN_TICKS
) {
1694 "comedi%d: me4000: me4000_ai_do_cmd_test(): Invalid convert arg\n",
1696 cmd
->convert_arg
= 2000; /* 66 ticks at least */
1699 } else if (cmd
->start_src
== TRIG_EXT
&&
1700 cmd
->scan_begin_src
== TRIG_EXT
&&
1701 cmd
->convert_src
== TRIG_EXT
) {
1703 /* Check timer arguments */
1704 if (init_ticks
< ME4000_AI_MIN_TICKS
) {
1706 "comedi%d: me4000: me4000_ai_do_cmd_test(): Invalid start arg\n",
1708 cmd
->start_arg
= 2000; /* 66 ticks at least */
1712 if (cmd
->stop_src
== TRIG_COUNT
) {
1713 if (cmd
->stop_arg
== 0) {
1715 "comedi%d: me4000: me4000_ai_do_cmd_test(): Invalid stop arg\n",
1721 if (cmd
->scan_end_src
== TRIG_COUNT
) {
1722 if (cmd
->scan_end_arg
== 0) {
1724 "comedi%d: me4000: me4000_ai_do_cmd_test(): Invalid scan end arg\n",
1726 cmd
->scan_end_arg
= 1;
1735 * Stage 5. Check the channel list.
1737 if (ai_check_chanlist(dev
, s
, cmd
))
1743 static irqreturn_t
me4000_ai_isr(int irq
, void *dev_id PT_REGS_ARG
)
1746 struct comedi_device
*dev
= dev_id
;
1747 struct comedi_subdevice
*s
= dev
->subdevices
;
1748 me4000_ai_context_t
*ai_context
= &info
->ai_context
;
1753 ISR_PDEBUG("me4000_ai_isr() is executed\n");
1755 if (!dev
->attached
) {
1756 ISR_PDEBUG("me4000_ai_isr() premature interrupt\n");
1760 /* Reset all events */
1761 s
->async
->events
= 0;
1763 /* Check if irq number is right */
1764 if (irq
!= ai_context
->irq
) {
1766 "comedi%d: me4000: me4000_ai_isr(): Incorrect interrupt num: %d\n",
1773 irq_status_reg
) & ME4000_IRQ_STATUS_BIT_AI_HF
) {
1775 ("me4000_ai_isr(): Fifo half full interrupt occured\n");
1777 /* Read status register to find out what happened */
1778 tmp
= me4000_inl(dev
, ai_context
->ctrl_reg
);
1780 if (!(tmp
& ME4000_AI_STATUS_BIT_FF_DATA
) &&
1781 !(tmp
& ME4000_AI_STATUS_BIT_HF_DATA
) &&
1782 (tmp
& ME4000_AI_STATUS_BIT_EF_DATA
)) {
1783 ISR_PDEBUG("me4000_ai_isr(): Fifo full\n");
1784 c
= ME4000_AI_FIFO_COUNT
;
1786 /* FIFO overflow, so stop conversion and disable all interrupts */
1787 tmp
|= ME4000_AI_CTRL_BIT_IMMEDIATE_STOP
;
1788 tmp
&= ~(ME4000_AI_CTRL_BIT_HF_IRQ
|
1789 ME4000_AI_CTRL_BIT_SC_IRQ
);
1790 me4000_outl(dev
, tmp
, ai_context
->ctrl_reg
);
1792 s
->async
->events
|= COMEDI_CB_ERROR
| COMEDI_CB_EOA
;
1795 "comedi%d: me4000: me4000_ai_isr(): FIFO overflow\n",
1797 } else if ((tmp
& ME4000_AI_STATUS_BIT_FF_DATA
)
1798 && !(tmp
& ME4000_AI_STATUS_BIT_HF_DATA
)
1799 && (tmp
& ME4000_AI_STATUS_BIT_EF_DATA
)) {
1800 ISR_PDEBUG("me4000_ai_isr(): Fifo half full\n");
1802 s
->async
->events
|= COMEDI_CB_BLOCK
;
1804 c
= ME4000_AI_FIFO_COUNT
/ 2;
1807 "comedi%d: me4000: me4000_ai_isr(): Can't determine state of fifo\n",
1811 /* Undefined state, so stop conversion and disable all interrupts */
1812 tmp
|= ME4000_AI_CTRL_BIT_IMMEDIATE_STOP
;
1813 tmp
&= ~(ME4000_AI_CTRL_BIT_HF_IRQ
|
1814 ME4000_AI_CTRL_BIT_SC_IRQ
);
1815 me4000_outl(dev
, tmp
, ai_context
->ctrl_reg
);
1817 s
->async
->events
|= COMEDI_CB_ERROR
| COMEDI_CB_EOA
;
1820 "comedi%d: me4000: me4000_ai_isr(): Undefined FIFO state\n",
1824 ISR_PDEBUG("me4000_ai_isr(): Try to read %d values\n", c
);
1826 for (i
= 0; i
< c
; i
++) {
1827 /* Read value from data fifo */
1828 lval
= inl(ai_context
->data_reg
) & 0xFFFF;
1831 if (!comedi_buf_put(s
->async
, lval
)) {
1832 /* Buffer overflow, so stop conversion and disable all interrupts */
1833 tmp
|= ME4000_AI_CTRL_BIT_IMMEDIATE_STOP
;
1834 tmp
&= ~(ME4000_AI_CTRL_BIT_HF_IRQ
|
1835 ME4000_AI_CTRL_BIT_SC_IRQ
);
1836 me4000_outl(dev
, tmp
, ai_context
->ctrl_reg
);
1838 s
->async
->events
|= COMEDI_CB_OVERFLOW
;
1841 "comedi%d: me4000: me4000_ai_isr(): Buffer overflow\n",
1848 /* Work is done, so reset the interrupt */
1849 ISR_PDEBUG("me4000_ai_isr(): Reset fifo half full interrupt\n");
1850 tmp
|= ME4000_AI_CTRL_BIT_HF_IRQ_RESET
;
1851 me4000_outl(dev
, tmp
, ai_context
->ctrl_reg
);
1852 tmp
&= ~ME4000_AI_CTRL_BIT_HF_IRQ_RESET
;
1853 me4000_outl(dev
, tmp
, ai_context
->ctrl_reg
);
1858 irq_status_reg
) & ME4000_IRQ_STATUS_BIT_SC
) {
1860 ("me4000_ai_isr(): Sample counter interrupt occured\n");
1862 s
->async
->events
|= COMEDI_CB_BLOCK
| COMEDI_CB_EOA
;
1864 /* Acquisition is complete, so stop conversion and disable all interrupts */
1865 tmp
= me4000_inl(dev
, ai_context
->ctrl_reg
);
1866 tmp
|= ME4000_AI_CTRL_BIT_IMMEDIATE_STOP
;
1867 tmp
&= ~(ME4000_AI_CTRL_BIT_HF_IRQ
| ME4000_AI_CTRL_BIT_SC_IRQ
);
1868 me4000_outl(dev
, tmp
, ai_context
->ctrl_reg
);
1870 /* Poll data until fifo empty */
1871 while (inl(ai_context
->ctrl_reg
) & ME4000_AI_STATUS_BIT_EF_DATA
) {
1872 /* Read value from data fifo */
1873 lval
= inl(ai_context
->data_reg
) & 0xFFFF;
1876 if (!comedi_buf_put(s
->async
, lval
)) {
1878 "comedi%d: me4000: me4000_ai_isr(): Buffer overflow\n",
1880 s
->async
->events
|= COMEDI_CB_OVERFLOW
;
1885 /* Work is done, so reset the interrupt */
1887 ("me4000_ai_isr(): Reset interrupt from sample counter\n");
1888 tmp
|= ME4000_AI_CTRL_BIT_SC_IRQ_RESET
;
1889 me4000_outl(dev
, tmp
, ai_context
->ctrl_reg
);
1890 tmp
&= ~ME4000_AI_CTRL_BIT_SC_IRQ_RESET
;
1891 me4000_outl(dev
, tmp
, ai_context
->ctrl_reg
);
1894 ISR_PDEBUG("me4000_ai_isr(): Events = 0x%X\n", s
->async
->events
);
1896 if (s
->async
->events
)
1897 comedi_event(dev
, s
);
1902 /*=============================================================================
1903 Analog output section
1904 ===========================================================================*/
1906 static int me4000_ao_insn_write(struct comedi_device
*dev
,
1907 struct comedi_subdevice
*s
, comedi_insn
*insn
, unsigned int *data
)
1910 int chan
= CR_CHAN(insn
->chanspec
);
1911 int rang
= CR_RANGE(insn
->chanspec
);
1912 int aref
= CR_AREF(insn
->chanspec
);
1915 CALL_PDEBUG("In me4000_ao_insn_write()\n");
1919 } else if (insn
->n
> 1) {
1921 "comedi%d: me4000: me4000_ao_insn_write(): Invalid instruction length %d\n",
1922 dev
->minor
, insn
->n
);
1926 if (chan
>= thisboard
->ao
.count
) {
1928 "comedi%d: me4000: me4000_ao_insn_write(): Invalid channel %d\n",
1929 dev
->minor
, insn
->n
);
1935 "comedi%d: me4000: me4000_ao_insn_write(): Invalid range %d\n",
1936 dev
->minor
, insn
->n
);
1940 if (aref
!= AREF_GROUND
&& aref
!= AREF_COMMON
) {
1942 "comedi%d: me4000: me4000_ao_insn_write(): Invalid aref %d\n",
1943 dev
->minor
, insn
->n
);
1947 /* Stop any running conversion */
1948 tmp
= me4000_inl(dev
, info
->ao_context
[chan
].ctrl_reg
);
1949 tmp
|= ME4000_AO_CTRL_BIT_IMMEDIATE_STOP
;
1950 me4000_outl(dev
, tmp
, info
->ao_context
[chan
].ctrl_reg
);
1952 /* Clear control register and set to single mode */
1953 me4000_outl(dev
, 0x0, info
->ao_context
[chan
].ctrl_reg
);
1955 /* Write data value */
1956 me4000_outl(dev
, data
[0], info
->ao_context
[chan
].single_reg
);
1958 /* Store in the mirror */
1959 info
->ao_context
[chan
].mirror
= data
[0];
1964 static int me4000_ao_insn_read(struct comedi_device
*dev
,
1965 struct comedi_subdevice
*s
, comedi_insn
*insn
, unsigned int *data
)
1967 int chan
= CR_CHAN(insn
->chanspec
);
1971 } else if (insn
->n
> 1) {
1972 printk("comedi%d: me4000: me4000_ao_insn_read(): Invalid instruction length\n", dev
->minor
);
1976 data
[0] = info
->ao_context
[chan
].mirror
;
1981 /*=============================================================================
1983 ===========================================================================*/
1985 static int me4000_dio_insn_bits(struct comedi_device
*dev
,
1986 struct comedi_subdevice
*s
, comedi_insn
*insn
, unsigned int *data
)
1989 CALL_PDEBUG("In me4000_dio_insn_bits()\n");
1991 /* Length of data must be 2 (mask and new data, see below) */
1996 printk("comedi%d: me4000: me4000_dio_insn_bits(): Invalid instruction length\n", dev
->minor
);
2001 * The insn data consists of a mask in data[0] and the new data
2002 * in data[1]. The mask defines which bits we are concerning about.
2003 * The new data must be anded with the mask.
2004 * Each channel corresponds to a bit.
2007 /* Check if requested ports are configured for output */
2008 if ((s
->io_bits
& data
[0]) != data
[0])
2011 s
->state
&= ~data
[0];
2012 s
->state
|= data
[0] & data
[1];
2014 /* Write out the new digital output lines */
2015 me4000_outl(dev
, (s
->state
>> 0) & 0xFF,
2016 info
->dio_context
.port_0_reg
);
2017 me4000_outl(dev
, (s
->state
>> 8) & 0xFF,
2018 info
->dio_context
.port_1_reg
);
2019 me4000_outl(dev
, (s
->state
>> 16) & 0xFF,
2020 info
->dio_context
.port_2_reg
);
2021 me4000_outl(dev
, (s
->state
>> 24) & 0xFF,
2022 info
->dio_context
.port_3_reg
);
2025 /* On return, data[1] contains the value of
2026 the digital input and output lines. */
2028 ((me4000_inl(dev
, info
->dio_context
.port_0_reg
) & 0xFF) << 0) |
2029 ((me4000_inl(dev
, info
->dio_context
.port_1_reg
) & 0xFF) << 8) |
2030 ((me4000_inl(dev
, info
->dio_context
.port_2_reg
) & 0xFF) << 16) |
2031 ((me4000_inl(dev
, info
->dio_context
.port_3_reg
) & 0xFF) << 24);
2036 static int me4000_dio_insn_config(struct comedi_device
*dev
,
2037 struct comedi_subdevice
*s
, comedi_insn
*insn
, unsigned int *data
)
2040 int chan
= CR_CHAN(insn
->chanspec
);
2042 CALL_PDEBUG("In me4000_dio_insn_config()\n");
2044 if (data
[0] == INSN_CONFIG_DIO_QUERY
) {
2047 io_bits
& (1 << chan
)) ? COMEDI_OUTPUT
: COMEDI_INPUT
;
2052 * The input or output configuration of each digital line is
2053 * configured by a special insn_config instruction. chanspec
2054 * contains the channel to be changed, and data[0] contains the
2055 * value COMEDI_INPUT or COMEDI_OUTPUT.
2056 * On the ME-4000 it is only possible to switch port wise (8 bit)
2059 tmp
= me4000_inl(dev
, info
->dio_context
.ctrl_reg
);
2061 if (data
[0] == COMEDI_OUTPUT
) {
2064 tmp
&= ~(ME4000_DIO_CTRL_BIT_MODE_0
|
2065 ME4000_DIO_CTRL_BIT_MODE_1
);
2066 tmp
|= ME4000_DIO_CTRL_BIT_MODE_0
;
2067 } else if (chan
< 16) {
2069 * Chech for optoisolated ME-4000 version. If one the first
2070 * port is a fixed output port and the second is a fixed input port.
2072 if (!me4000_inl(dev
, info
->dio_context
.dir_reg
))
2075 s
->io_bits
|= 0xFF00;
2076 tmp
&= ~(ME4000_DIO_CTRL_BIT_MODE_2
|
2077 ME4000_DIO_CTRL_BIT_MODE_3
);
2078 tmp
|= ME4000_DIO_CTRL_BIT_MODE_2
;
2079 } else if (chan
< 24) {
2080 s
->io_bits
|= 0xFF0000;
2081 tmp
&= ~(ME4000_DIO_CTRL_BIT_MODE_4
|
2082 ME4000_DIO_CTRL_BIT_MODE_5
);
2083 tmp
|= ME4000_DIO_CTRL_BIT_MODE_4
;
2084 } else if (chan
< 32) {
2085 s
->io_bits
|= 0xFF000000;
2086 tmp
&= ~(ME4000_DIO_CTRL_BIT_MODE_6
|
2087 ME4000_DIO_CTRL_BIT_MODE_7
);
2088 tmp
|= ME4000_DIO_CTRL_BIT_MODE_6
;
2095 * Chech for optoisolated ME-4000 version. If one the first
2096 * port is a fixed output port and the second is a fixed input port.
2098 if (!me4000_inl(dev
, info
->dio_context
.dir_reg
))
2101 s
->io_bits
&= ~0xFF;
2102 tmp
&= ~(ME4000_DIO_CTRL_BIT_MODE_0
|
2103 ME4000_DIO_CTRL_BIT_MODE_1
);
2104 } else if (chan
< 16) {
2105 s
->io_bits
&= ~0xFF00;
2106 tmp
&= ~(ME4000_DIO_CTRL_BIT_MODE_2
|
2107 ME4000_DIO_CTRL_BIT_MODE_3
);
2108 } else if (chan
< 24) {
2109 s
->io_bits
&= ~0xFF0000;
2110 tmp
&= ~(ME4000_DIO_CTRL_BIT_MODE_4
|
2111 ME4000_DIO_CTRL_BIT_MODE_5
);
2112 } else if (chan
< 32) {
2113 s
->io_bits
&= ~0xFF000000;
2114 tmp
&= ~(ME4000_DIO_CTRL_BIT_MODE_6
|
2115 ME4000_DIO_CTRL_BIT_MODE_7
);
2121 me4000_outl(dev
, tmp
, info
->dio_context
.ctrl_reg
);
2126 /*=============================================================================
2128 ===========================================================================*/
2130 static int cnt_reset(struct comedi_device
*dev
, unsigned int channel
)
2133 CALL_PDEBUG("In cnt_reset()\n");
2137 me4000_outb(dev
, 0x30, info
->cnt_context
.ctrl_reg
);
2138 me4000_outb(dev
, 0x00, info
->cnt_context
.counter_0_reg
);
2139 me4000_outb(dev
, 0x00, info
->cnt_context
.counter_0_reg
);
2142 me4000_outb(dev
, 0x70, info
->cnt_context
.ctrl_reg
);
2143 me4000_outb(dev
, 0x00, info
->cnt_context
.counter_1_reg
);
2144 me4000_outb(dev
, 0x00, info
->cnt_context
.counter_1_reg
);
2147 me4000_outb(dev
, 0xB0, info
->cnt_context
.ctrl_reg
);
2148 me4000_outb(dev
, 0x00, info
->cnt_context
.counter_2_reg
);
2149 me4000_outb(dev
, 0x00, info
->cnt_context
.counter_2_reg
);
2153 "comedi%d: me4000: cnt_reset(): Invalid channel\n",
2161 static int cnt_config(struct comedi_device
*dev
, unsigned int channel
,
2166 CALL_PDEBUG("In cnt_config()\n");
2170 tmp
|= ME4000_CNT_COUNTER_0
;
2173 tmp
|= ME4000_CNT_COUNTER_1
;
2176 tmp
|= ME4000_CNT_COUNTER_2
;
2180 "comedi%d: me4000: cnt_config(): Invalid channel\n",
2187 tmp
|= ME4000_CNT_MODE_0
;
2190 tmp
|= ME4000_CNT_MODE_1
;
2193 tmp
|= ME4000_CNT_MODE_2
;
2196 tmp
|= ME4000_CNT_MODE_3
;
2199 tmp
|= ME4000_CNT_MODE_4
;
2202 tmp
|= ME4000_CNT_MODE_5
;
2206 "comedi%d: me4000: cnt_config(): Invalid counter mode\n",
2211 /* Write the control word */
2213 me4000_outb(dev
, tmp
, info
->cnt_context
.ctrl_reg
);
2218 static int me4000_cnt_insn_config(struct comedi_device
*dev
,
2219 struct comedi_subdevice
*s
, comedi_insn
*insn
, unsigned int *data
)
2224 CALL_PDEBUG("In me4000_cnt_insn_config()\n");
2230 "comedi%d: me4000: me4000_cnt_insn_config(): Invalid instruction length%d\n",
2231 dev
->minor
, insn
->n
);
2235 err
= cnt_reset(dev
, insn
->chanspec
);
2239 case GPCT_SET_OPERATION
:
2242 "comedi%d: me4000: me4000_cnt_insn_config(): Invalid instruction length%d\n",
2243 dev
->minor
, insn
->n
);
2247 err
= cnt_config(dev
, insn
->chanspec
, data
[1]);
2253 "comedi%d: me4000: me4000_cnt_insn_config(): Invalid instruction\n",
2261 static int me4000_cnt_insn_read(struct comedi_device
*dev
,
2262 struct comedi_subdevice
*s
, comedi_insn
*insn
, unsigned int *data
)
2267 CALL_PDEBUG("In me4000_cnt_insn_read()\n");
2274 "comedi%d: me4000: me4000_cnt_insn_read(): Invalid instruction length %d\n",
2275 dev
->minor
, insn
->n
);
2279 switch (insn
->chanspec
) {
2281 tmp
= me4000_inb(dev
, info
->cnt_context
.counter_0_reg
);
2283 tmp
= me4000_inb(dev
, info
->cnt_context
.counter_0_reg
);
2284 data
[0] |= tmp
<< 8;
2287 tmp
= me4000_inb(dev
, info
->cnt_context
.counter_1_reg
);
2289 tmp
= me4000_inb(dev
, info
->cnt_context
.counter_1_reg
);
2290 data
[0] |= tmp
<< 8;
2293 tmp
= me4000_inb(dev
, info
->cnt_context
.counter_2_reg
);
2295 tmp
= me4000_inb(dev
, info
->cnt_context
.counter_2_reg
);
2296 data
[0] |= tmp
<< 8;
2300 "comedi%d: me4000: me4000_cnt_insn_read(): Invalid channel %d\n",
2301 dev
->minor
, insn
->chanspec
);
2308 static int me4000_cnt_insn_write(struct comedi_device
*dev
,
2309 struct comedi_subdevice
*s
, comedi_insn
*insn
, unsigned int *data
)
2314 CALL_PDEBUG("In me4000_cnt_insn_write()\n");
2318 } else if (insn
->n
> 1) {
2320 "comedi%d: me4000: me4000_cnt_insn_write(): Invalid instruction length %d\n",
2321 dev
->minor
, insn
->n
);
2325 switch (insn
->chanspec
) {
2327 tmp
= data
[0] & 0xFF;
2328 me4000_outb(dev
, tmp
, info
->cnt_context
.counter_0_reg
);
2329 tmp
= (data
[0] >> 8) & 0xFF;
2330 me4000_outb(dev
, tmp
, info
->cnt_context
.counter_0_reg
);
2333 tmp
= data
[0] & 0xFF;
2334 me4000_outb(dev
, tmp
, info
->cnt_context
.counter_1_reg
);
2335 tmp
= (data
[0] >> 8) & 0xFF;
2336 me4000_outb(dev
, tmp
, info
->cnt_context
.counter_1_reg
);
2339 tmp
= data
[0] & 0xFF;
2340 me4000_outb(dev
, tmp
, info
->cnt_context
.counter_2_reg
);
2341 tmp
= (data
[0] >> 8) & 0xFF;
2342 me4000_outb(dev
, tmp
, info
->cnt_context
.counter_2_reg
);
2346 "comedi%d: me4000: me4000_cnt_insn_write(): Invalid channel %d\n",
2347 dev
->minor
, insn
->chanspec
);
2354 COMEDI_PCI_INITCLEANUP(driver_me4000
, me4000_pci_table
);