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_VENDOR_ID_MEILHAUS
, 0x4650, PCI_ANY_ID
, PCI_ANY_ID
, 0, 0, 0},
76 {PCI_VENDOR_ID_MEILHAUS
, 0x4660, PCI_ANY_ID
, PCI_ANY_ID
, 0, 0, 0},
77 {PCI_VENDOR_ID_MEILHAUS
, 0x4661, PCI_ANY_ID
, PCI_ANY_ID
, 0, 0, 0},
78 {PCI_VENDOR_ID_MEILHAUS
, 0x4662, PCI_ANY_ID
, PCI_ANY_ID
, 0, 0, 0},
79 {PCI_VENDOR_ID_MEILHAUS
, 0x4663, PCI_ANY_ID
, PCI_ANY_ID
, 0, 0, 0},
81 {PCI_VENDOR_ID_MEILHAUS
, 0x4670, PCI_ANY_ID
, PCI_ANY_ID
, 0, 0, 0},
82 {PCI_VENDOR_ID_MEILHAUS
, 0x4671, PCI_ANY_ID
, PCI_ANY_ID
, 0, 0, 0},
83 {PCI_VENDOR_ID_MEILHAUS
, 0x4672, PCI_ANY_ID
, PCI_ANY_ID
, 0, 0, 0},
84 {PCI_VENDOR_ID_MEILHAUS
, 0x4673, PCI_ANY_ID
, PCI_ANY_ID
, 0, 0, 0},
86 {PCI_VENDOR_ID_MEILHAUS
, 0x4680, PCI_ANY_ID
, PCI_ANY_ID
, 0, 0, 0},
87 {PCI_VENDOR_ID_MEILHAUS
, 0x4681, PCI_ANY_ID
, PCI_ANY_ID
, 0, 0, 0},
88 {PCI_VENDOR_ID_MEILHAUS
, 0x4682, PCI_ANY_ID
, PCI_ANY_ID
, 0, 0, 0},
89 {PCI_VENDOR_ID_MEILHAUS
, 0x4683, PCI_ANY_ID
, PCI_ANY_ID
, 0, 0, 0},
94 MODULE_DEVICE_TABLE(pci
, me4000_pci_table
);
96 static const struct me4000_board me4000_boards
[] = {
97 {"ME-4650", 0x4650, {0, 0}, {16, 0, 0, 0}, {4}, {0}},
99 {"ME-4660", 0x4660, {0, 0}, {32, 0, 16, 0}, {4}, {3}},
100 {"ME-4660i", 0x4661, {0, 0}, {32, 0, 16, 0}, {4}, {3}},
101 {"ME-4660s", 0x4662, {0, 0}, {32, 8, 16, 0}, {4}, {3}},
102 {"ME-4660is", 0x4663, {0, 0}, {32, 8, 16, 0}, {4}, {3}},
104 {"ME-4670", 0x4670, {4, 0}, {32, 0, 16, 1}, {4}, {3}},
105 {"ME-4670i", 0x4671, {4, 0}, {32, 0, 16, 1}, {4}, {3}},
106 {"ME-4670s", 0x4672, {4, 0}, {32, 8, 16, 1}, {4}, {3}},
107 {"ME-4670is", 0x4673, {4, 0}, {32, 8, 16, 1}, {4}, {3}},
109 {"ME-4680", 0x4680, {4, 4}, {32, 0, 16, 1}, {4}, {3}},
110 {"ME-4680i", 0x4681, {4, 4}, {32, 0, 16, 1}, {4}, {3}},
111 {"ME-4680s", 0x4682, {4, 4}, {32, 8, 16, 1}, {4}, {3}},
112 {"ME-4680is", 0x4683, {4, 4}, {32, 8, 16, 1}, {4}, {3}},
117 #define ME4000_BOARD_VERSIONS (ARRAY_SIZE(me4000_boards) - 1)
119 /*-----------------------------------------------------------------------------
120 Comedi function prototypes
121 ---------------------------------------------------------------------------*/
122 static int me4000_attach(struct comedi_device
*dev
, struct comedi_devconfig
*it
);
123 static int me4000_detach(struct comedi_device
*dev
);
124 static struct comedi_driver driver_me4000
= {
125 driver_name
:"me4000",
126 module
: THIS_MODULE
,
127 attach
: me4000_attach
,
128 detach
: me4000_detach
,
131 /*-----------------------------------------------------------------------------
132 Meilhaus function prototypes
133 ---------------------------------------------------------------------------*/
134 static int me4000_probe(struct comedi_device
*dev
, struct comedi_devconfig
*it
);
135 static int get_registers(struct comedi_device
*dev
, struct pci_dev
*pci_dev_p
);
136 static int init_board_info(struct comedi_device
*dev
, struct pci_dev
*pci_dev_p
);
137 static int init_ao_context(struct comedi_device
*dev
);
138 static int init_ai_context(struct comedi_device
*dev
);
139 static int init_dio_context(struct comedi_device
*dev
);
140 static int init_cnt_context(struct comedi_device
*dev
);
141 static int xilinx_download(struct comedi_device
*dev
);
142 static int reset_board(struct comedi_device
*dev
);
144 static int me4000_dio_insn_bits(struct comedi_device
*dev
,
145 struct comedi_subdevice
*s
, struct comedi_insn
*insn
, unsigned int *data
);
147 static int me4000_dio_insn_config(struct comedi_device
*dev
,
148 struct comedi_subdevice
*s
, 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
, struct comedi_insn
*insn
, unsigned int *data
);
158 static int me4000_cnt_insn_write(struct comedi_device
*dev
,
159 struct comedi_subdevice
*s
, struct comedi_insn
*insn
, unsigned int *data
);
161 static int me4000_cnt_insn_read(struct comedi_device
*dev
,
162 struct comedi_subdevice
*s
, struct comedi_insn
*insn
, unsigned int *data
);
164 static int me4000_ai_insn_read(struct comedi_device
*dev
,
165 struct comedi_subdevice
*subdevice
, struct comedi_insn
*insn
, unsigned int *data
);
167 static int me4000_ai_cancel(struct comedi_device
*dev
, struct comedi_subdevice
*s
);
169 static int ai_check_chanlist(struct comedi_device
*dev
,
170 struct comedi_subdevice
*s
, struct comedi_cmd
*cmd
);
172 static int ai_round_cmd_args(struct comedi_device
*dev
,
173 struct comedi_subdevice
*s
,
174 struct comedi_cmd
*cmd
,
175 unsigned int *init_ticks
,
176 unsigned int *scan_ticks
, unsigned int *chan_ticks
);
178 static int ai_prepare(struct comedi_device
*dev
,
179 struct comedi_subdevice
*s
,
180 struct comedi_cmd
*cmd
,
181 unsigned int init_ticks
,
182 unsigned int scan_ticks
, unsigned int chan_ticks
);
184 static int ai_write_chanlist(struct comedi_device
*dev
,
185 struct comedi_subdevice
*s
, struct comedi_cmd
*cmd
);
187 static irqreturn_t
me4000_ai_isr(int irq
, void *dev_id
);
189 static int me4000_ai_do_cmd_test(struct comedi_device
*dev
,
190 struct comedi_subdevice
*s
, struct comedi_cmd
*cmd
);
192 static int me4000_ai_do_cmd(struct comedi_device
*dev
, struct comedi_subdevice
*s
);
194 static int me4000_ao_insn_write(struct comedi_device
*dev
,
195 struct comedi_subdevice
*s
, struct comedi_insn
*insn
, unsigned int *data
);
197 static int me4000_ao_insn_read(struct comedi_device
*dev
,
198 struct comedi_subdevice
*s
, struct comedi_insn
*insn
, unsigned int *data
);
200 /*-----------------------------------------------------------------------------
201 Meilhaus inline functions
202 ---------------------------------------------------------------------------*/
204 static inline void me4000_outb(struct comedi_device
*dev
, unsigned char value
,
207 PORT_PDEBUG("--> 0x%02X port 0x%04lX\n", value
, port
);
211 static inline void me4000_outl(struct comedi_device
*dev
, unsigned long value
,
214 PORT_PDEBUG("--> 0x%08lX port 0x%04lX\n", value
, port
);
218 static inline unsigned long me4000_inl(struct comedi_device
*dev
, unsigned long port
)
222 PORT_PDEBUG("<-- 0x%08lX port 0x%04lX\n", value
, port
);
226 static inline unsigned char me4000_inb(struct comedi_device
*dev
, unsigned long port
)
230 PORT_PDEBUG("<-- 0x%08X port 0x%04lX\n", value
, port
);
234 static const struct comedi_lrange me4000_ai_range
= {
244 static const struct comedi_lrange me4000_ao_range
= {
251 static int me4000_attach(struct comedi_device
*dev
, struct comedi_devconfig
*it
)
253 struct comedi_subdevice
*s
;
256 CALL_PDEBUG("In me4000_attach()\n");
258 result
= me4000_probe(dev
, it
);
263 * Allocate the subdevice structures. alloc_subdevice() is a
264 * convenient macro defined in comedidev.h. It relies on
265 * n_subdevices being set correctly.
267 if (alloc_subdevices(dev
, 4) < 0)
270 /*=========================================================================
271 Analog input subdevice
272 ========================================================================*/
274 s
= dev
->subdevices
+ 0;
276 if (thisboard
->ai
.count
) {
277 s
->type
= COMEDI_SUBD_AI
;
279 SDF_READABLE
| SDF_COMMON
| SDF_GROUND
| SDF_DIFF
;
280 s
->n_chan
= thisboard
->ai
.count
;
281 s
->maxdata
= 0xFFFF; /* 16 bit ADC */
282 s
->len_chanlist
= ME4000_AI_CHANNEL_LIST_COUNT
;
283 s
->range_table
= &me4000_ai_range
;
284 s
->insn_read
= me4000_ai_insn_read
;
287 if (request_irq(info
->irq
, me4000_ai_isr
,
288 IRQF_SHARED
, "ME-4000", dev
)) {
289 printk("comedi%d: me4000: me4000_attach(): Unable to allocate irq\n", dev
->minor
);
291 dev
->read_subdev
= s
;
292 s
->subdev_flags
|= SDF_CMD_READ
;
293 s
->cancel
= me4000_ai_cancel
;
294 s
->do_cmdtest
= me4000_ai_do_cmd_test
;
295 s
->do_cmd
= me4000_ai_do_cmd
;
299 "comedi%d: me4000: me4000_attach(): No interrupt available\n",
303 s
->type
= COMEDI_SUBD_UNUSED
;
306 /*=========================================================================
307 Analog output subdevice
308 ========================================================================*/
310 s
= dev
->subdevices
+ 1;
312 if (thisboard
->ao
.count
) {
313 s
->type
= COMEDI_SUBD_AO
;
314 s
->subdev_flags
= SDF_WRITEABLE
| SDF_COMMON
| SDF_GROUND
;
315 s
->n_chan
= thisboard
->ao
.count
;
316 s
->maxdata
= 0xFFFF; /* 16 bit DAC */
317 s
->range_table
= &me4000_ao_range
;
318 s
->insn_write
= me4000_ao_insn_write
;
319 s
->insn_read
= me4000_ao_insn_read
;
321 s
->type
= COMEDI_SUBD_UNUSED
;
324 /*=========================================================================
325 Digital I/O subdevice
326 ========================================================================*/
328 s
= dev
->subdevices
+ 2;
330 if (thisboard
->dio
.count
) {
331 s
->type
= COMEDI_SUBD_DIO
;
332 s
->subdev_flags
= SDF_READABLE
| SDF_WRITABLE
;
333 s
->n_chan
= thisboard
->dio
.count
* 8;
335 s
->range_table
= &range_digital
;
336 s
->insn_bits
= me4000_dio_insn_bits
;
337 s
->insn_config
= me4000_dio_insn_config
;
339 s
->type
= COMEDI_SUBD_UNUSED
;
343 * Check for optoisolated ME-4000 version. If one the first
344 * port is a fixed output port and the second is a fixed input port.
346 if (!me4000_inl(dev
, info
->dio_context
.dir_reg
)) {
348 me4000_outl(dev
, ME4000_DIO_CTRL_BIT_MODE_0
,
349 info
->dio_context
.dir_reg
);
352 /*=========================================================================
354 ========================================================================*/
356 s
= dev
->subdevices
+ 3;
358 if (thisboard
->cnt
.count
) {
359 s
->type
= COMEDI_SUBD_COUNTER
;
360 s
->subdev_flags
= SDF_READABLE
| SDF_WRITABLE
;
361 s
->n_chan
= thisboard
->cnt
.count
;
362 s
->maxdata
= 0xFFFF; /* 16 bit counters */
363 s
->insn_read
= me4000_cnt_insn_read
;
364 s
->insn_write
= me4000_cnt_insn_write
;
365 s
->insn_config
= me4000_cnt_insn_config
;
367 s
->type
= COMEDI_SUBD_UNUSED
;
373 static int me4000_probe(struct comedi_device
*dev
, struct comedi_devconfig
*it
)
375 struct pci_dev
*pci_device
;
377 struct me4000_board
*board
;
379 CALL_PDEBUG("In me4000_probe()\n");
381 /* Allocate private memory */
382 if (alloc_private(dev
, sizeof(struct me4000_info
)) < 0)
386 * Probe the device to determine what device in the series it is.
388 for (pci_device
= pci_get_device(PCI_ANY_ID
, PCI_ANY_ID
, NULL
);
391 pci_get_device(PCI_ANY_ID
, PCI_ANY_ID
, pci_device
)) {
392 if (pci_device
->vendor
== PCI_VENDOR_ID_MEILHAUS
) {
393 for (i
= 0; i
< ME4000_BOARD_VERSIONS
; i
++) {
394 if (me4000_boards
[i
].device_id
==
395 pci_device
->device
) {
396 /* Was a particular bus/slot requested? */
397 if ((it
->options
[0] != 0)
398 || (it
->options
[1] != 0)) {
399 /* Are we on the wrong bus/slot? */
400 if (pci_device
->bus
->number
!=
402 || PCI_SLOT(pci_device
->
408 dev
->board_ptr
= me4000_boards
+ i
;
409 board
= (struct me4000_board
*) dev
->
411 info
->pci_dev_p
= pci_device
;
419 "comedi%d: me4000: me4000_probe(): No supported board found (req. bus/slot : %d/%d)\n",
420 dev
->minor
, it
->options
[0], it
->options
[1]);
426 "comedi%d: me4000: me4000_probe(): Found %s at PCI bus %d, slot %d\n",
427 dev
->minor
, me4000_boards
[i
].name
, pci_device
->bus
->number
,
428 PCI_SLOT(pci_device
->devfn
));
430 /* Set data in device structure */
431 dev
->board_name
= board
->name
;
433 /* Enable PCI device and request regions */
434 result
= comedi_pci_enable(pci_device
, dev
->board_name
);
437 "comedi%d: me4000: me4000_probe(): Cannot enable PCI device and request I/O regions\n",
442 /* Get the PCI base registers */
443 result
= get_registers(dev
, pci_device
);
446 "comedi%d: me4000: me4000_probe(): Cannot get registers\n",
450 /* Initialize board info */
451 result
= init_board_info(dev
, pci_device
);
454 "comedi%d: me4000: me4000_probe(): Cannot init baord info\n",
459 /* Init analog output context */
460 result
= init_ao_context(dev
);
463 "comedi%d: me4000: me4000_probe(): Cannot init ao context\n",
468 /* Init analog input context */
469 result
= init_ai_context(dev
);
472 "comedi%d: me4000: me4000_probe(): Cannot init ai context\n",
477 /* Init digital I/O context */
478 result
= init_dio_context(dev
);
481 "comedi%d: me4000: me4000_probe(): Cannot init dio context\n",
486 /* Init counter context */
487 result
= init_cnt_context(dev
);
490 "comedi%d: me4000: me4000_probe(): Cannot init cnt context\n",
495 /* Download the xilinx firmware */
496 result
= xilinx_download(dev
);
499 "comedi%d: me4000: me4000_probe(): Can't download firmware\n",
504 /* Make a hardware reset */
505 result
= reset_board(dev
);
508 "comedi%d: me4000: me4000_probe(): Can't reset board\n",
516 static int get_registers(struct comedi_device
*dev
, struct pci_dev
*pci_dev_p
)
519 CALL_PDEBUG("In get_registers()\n");
521 /*--------------------------- plx regbase ---------------------------------*/
523 info
->plx_regbase
= pci_resource_start(pci_dev_p
, 1);
524 if (info
->plx_regbase
== 0) {
526 "comedi%d: me4000: get_registers(): PCI base address 1 is not available\n",
530 info
->plx_regbase_size
= pci_resource_len(pci_dev_p
, 1);
532 /*--------------------------- me4000 regbase ------------------------------*/
534 info
->me4000_regbase
= pci_resource_start(pci_dev_p
, 2);
535 if (info
->me4000_regbase
== 0) {
537 "comedi%d: me4000: get_registers(): PCI base address 2 is not available\n",
541 info
->me4000_regbase_size
= pci_resource_len(pci_dev_p
, 2);
543 /*--------------------------- timer regbase ------------------------------*/
545 info
->timer_regbase
= pci_resource_start(pci_dev_p
, 3);
546 if (info
->timer_regbase
== 0) {
548 "comedi%d: me4000: get_registers(): PCI base address 3 is not available\n",
552 info
->timer_regbase_size
= pci_resource_len(pci_dev_p
, 3);
554 /*--------------------------- program regbase ------------------------------*/
556 info
->program_regbase
= pci_resource_start(pci_dev_p
, 5);
557 if (info
->program_regbase
== 0) {
559 "comedi%d: me4000: get_registers(): PCI base address 5 is not available\n",
563 info
->program_regbase_size
= pci_resource_len(pci_dev_p
, 5);
568 static int init_board_info(struct comedi_device
*dev
, struct pci_dev
*pci_dev_p
)
572 CALL_PDEBUG("In init_board_info()\n");
574 /* Init spin locks */
575 /* spin_lock_init(&info->preload_lock); */
576 /* spin_lock_init(&info->ai_ctrl_lock); */
578 /* Get the serial number */
579 result
= pci_read_config_dword(pci_dev_p
, 0x2C, &info
->serial_no
);
580 if (result
!= PCIBIOS_SUCCESSFUL
)
583 /* Get the hardware revision */
584 result
= pci_read_config_byte(pci_dev_p
, 0x08, &info
->hw_revision
);
585 if (result
!= PCIBIOS_SUCCESSFUL
)
588 /* Get the vendor id */
589 info
->vendor_id
= pci_dev_p
->vendor
;
591 /* Get the device id */
592 info
->device_id
= pci_dev_p
->device
;
594 /* Get the irq assigned to the board */
595 info
->irq
= pci_dev_p
->irq
;
600 static int init_ao_context(struct comedi_device
*dev
)
604 CALL_PDEBUG("In init_ao_context()\n");
606 for (i
= 0; i
< thisboard
->ao
.count
; i
++) {
607 /* spin_lock_init(&info->ao_context[i].use_lock); */
608 info
->ao_context
[i
].irq
= info
->irq
;
612 info
->ao_context
[i
].ctrl_reg
=
613 info
->me4000_regbase
+ ME4000_AO_00_CTRL_REG
;
614 info
->ao_context
[i
].status_reg
=
615 info
->me4000_regbase
+ ME4000_AO_00_STATUS_REG
;
616 info
->ao_context
[i
].fifo_reg
=
617 info
->me4000_regbase
+ ME4000_AO_00_FIFO_REG
;
618 info
->ao_context
[i
].single_reg
=
619 info
->me4000_regbase
+ ME4000_AO_00_SINGLE_REG
;
620 info
->ao_context
[i
].timer_reg
=
621 info
->me4000_regbase
+ ME4000_AO_00_TIMER_REG
;
622 info
->ao_context
[i
].irq_status_reg
=
623 info
->me4000_regbase
+ ME4000_IRQ_STATUS_REG
;
624 info
->ao_context
[i
].preload_reg
=
625 info
->me4000_regbase
+ ME4000_AO_LOADSETREG_XX
;
628 info
->ao_context
[i
].ctrl_reg
=
629 info
->me4000_regbase
+ ME4000_AO_01_CTRL_REG
;
630 info
->ao_context
[i
].status_reg
=
631 info
->me4000_regbase
+ ME4000_AO_01_STATUS_REG
;
632 info
->ao_context
[i
].fifo_reg
=
633 info
->me4000_regbase
+ ME4000_AO_01_FIFO_REG
;
634 info
->ao_context
[i
].single_reg
=
635 info
->me4000_regbase
+ ME4000_AO_01_SINGLE_REG
;
636 info
->ao_context
[i
].timer_reg
=
637 info
->me4000_regbase
+ ME4000_AO_01_TIMER_REG
;
638 info
->ao_context
[i
].irq_status_reg
=
639 info
->me4000_regbase
+ ME4000_IRQ_STATUS_REG
;
640 info
->ao_context
[i
].preload_reg
=
641 info
->me4000_regbase
+ ME4000_AO_LOADSETREG_XX
;
644 info
->ao_context
[i
].ctrl_reg
=
645 info
->me4000_regbase
+ ME4000_AO_02_CTRL_REG
;
646 info
->ao_context
[i
].status_reg
=
647 info
->me4000_regbase
+ ME4000_AO_02_STATUS_REG
;
648 info
->ao_context
[i
].fifo_reg
=
649 info
->me4000_regbase
+ ME4000_AO_02_FIFO_REG
;
650 info
->ao_context
[i
].single_reg
=
651 info
->me4000_regbase
+ ME4000_AO_02_SINGLE_REG
;
652 info
->ao_context
[i
].timer_reg
=
653 info
->me4000_regbase
+ ME4000_AO_02_TIMER_REG
;
654 info
->ao_context
[i
].irq_status_reg
=
655 info
->me4000_regbase
+ ME4000_IRQ_STATUS_REG
;
656 info
->ao_context
[i
].preload_reg
=
657 info
->me4000_regbase
+ ME4000_AO_LOADSETREG_XX
;
660 info
->ao_context
[i
].ctrl_reg
=
661 info
->me4000_regbase
+ ME4000_AO_03_CTRL_REG
;
662 info
->ao_context
[i
].status_reg
=
663 info
->me4000_regbase
+ ME4000_AO_03_STATUS_REG
;
664 info
->ao_context
[i
].fifo_reg
=
665 info
->me4000_regbase
+ ME4000_AO_03_FIFO_REG
;
666 info
->ao_context
[i
].single_reg
=
667 info
->me4000_regbase
+ ME4000_AO_03_SINGLE_REG
;
668 info
->ao_context
[i
].timer_reg
=
669 info
->me4000_regbase
+ ME4000_AO_03_TIMER_REG
;
670 info
->ao_context
[i
].irq_status_reg
=
671 info
->me4000_regbase
+ ME4000_IRQ_STATUS_REG
;
672 info
->ao_context
[i
].preload_reg
=
673 info
->me4000_regbase
+ ME4000_AO_LOADSETREG_XX
;
683 static int init_ai_context(struct comedi_device
*dev
)
686 CALL_PDEBUG("In init_ai_context()\n");
688 info
->ai_context
.irq
= info
->irq
;
690 info
->ai_context
.ctrl_reg
= info
->me4000_regbase
+ ME4000_AI_CTRL_REG
;
691 info
->ai_context
.status_reg
=
692 info
->me4000_regbase
+ ME4000_AI_STATUS_REG
;
693 info
->ai_context
.channel_list_reg
=
694 info
->me4000_regbase
+ ME4000_AI_CHANNEL_LIST_REG
;
695 info
->ai_context
.data_reg
= info
->me4000_regbase
+ ME4000_AI_DATA_REG
;
696 info
->ai_context
.chan_timer_reg
=
697 info
->me4000_regbase
+ ME4000_AI_CHAN_TIMER_REG
;
698 info
->ai_context
.chan_pre_timer_reg
=
699 info
->me4000_regbase
+ ME4000_AI_CHAN_PRE_TIMER_REG
;
700 info
->ai_context
.scan_timer_low_reg
=
701 info
->me4000_regbase
+ ME4000_AI_SCAN_TIMER_LOW_REG
;
702 info
->ai_context
.scan_timer_high_reg
=
703 info
->me4000_regbase
+ ME4000_AI_SCAN_TIMER_HIGH_REG
;
704 info
->ai_context
.scan_pre_timer_low_reg
=
705 info
->me4000_regbase
+ ME4000_AI_SCAN_PRE_TIMER_LOW_REG
;
706 info
->ai_context
.scan_pre_timer_high_reg
=
707 info
->me4000_regbase
+ ME4000_AI_SCAN_PRE_TIMER_HIGH_REG
;
708 info
->ai_context
.start_reg
= info
->me4000_regbase
+ ME4000_AI_START_REG
;
709 info
->ai_context
.irq_status_reg
=
710 info
->me4000_regbase
+ ME4000_IRQ_STATUS_REG
;
711 info
->ai_context
.sample_counter_reg
=
712 info
->me4000_regbase
+ ME4000_AI_SAMPLE_COUNTER_REG
;
717 static int init_dio_context(struct comedi_device
*dev
)
720 CALL_PDEBUG("In init_dio_context()\n");
722 info
->dio_context
.dir_reg
= info
->me4000_regbase
+ ME4000_DIO_DIR_REG
;
723 info
->dio_context
.ctrl_reg
= info
->me4000_regbase
+ ME4000_DIO_CTRL_REG
;
724 info
->dio_context
.port_0_reg
=
725 info
->me4000_regbase
+ ME4000_DIO_PORT_0_REG
;
726 info
->dio_context
.port_1_reg
=
727 info
->me4000_regbase
+ ME4000_DIO_PORT_1_REG
;
728 info
->dio_context
.port_2_reg
=
729 info
->me4000_regbase
+ ME4000_DIO_PORT_2_REG
;
730 info
->dio_context
.port_3_reg
=
731 info
->me4000_regbase
+ ME4000_DIO_PORT_3_REG
;
736 static int init_cnt_context(struct comedi_device
*dev
)
739 CALL_PDEBUG("In init_cnt_context()\n");
741 info
->cnt_context
.ctrl_reg
= info
->timer_regbase
+ ME4000_CNT_CTRL_REG
;
742 info
->cnt_context
.counter_0_reg
=
743 info
->timer_regbase
+ ME4000_CNT_COUNTER_0_REG
;
744 info
->cnt_context
.counter_1_reg
=
745 info
->timer_regbase
+ ME4000_CNT_COUNTER_1_REG
;
746 info
->cnt_context
.counter_2_reg
=
747 info
->timer_regbase
+ ME4000_CNT_COUNTER_2_REG
;
752 #define FIRMWARE_NOT_AVAILABLE 1
753 #if FIRMWARE_NOT_AVAILABLE
754 extern unsigned char *xilinx_firm
;
757 static int xilinx_download(struct comedi_device
*dev
)
760 wait_queue_head_t queue
;
764 CALL_PDEBUG("In xilinx_download()\n");
766 init_waitqueue_head(&queue
);
769 * Set PLX local interrupt 2 polarity to high.
770 * Interrupt is thrown by init pin of xilinx.
772 outl(0x10, info
->plx_regbase
+ PLX_INTCSR
);
774 /* Set /CS and /WRITE of the Xilinx */
775 value
= inl(info
->plx_regbase
+ PLX_ICR
);
777 outl(value
, info
->plx_regbase
+ PLX_ICR
);
779 /* Init Xilinx with CS1 */
780 inb(info
->program_regbase
+ 0xC8);
782 /* Wait until /INIT pin is set */
784 if (!(inl(info
->plx_regbase
+ PLX_INTCSR
) & 0x20)) {
786 "comedi%d: me4000: xilinx_download(): Can't init Xilinx\n",
791 /* Reset /CS and /WRITE of the Xilinx */
792 value
= inl(info
->plx_regbase
+ PLX_ICR
);
794 outl(value
, info
->plx_regbase
+ PLX_ICR
);
795 if (FIRMWARE_NOT_AVAILABLE
) {
797 "xilinx firmware unavailable due to licensing, aborting");
800 /* Download Xilinx firmware */
801 size
= (xilinx_firm
[0] << 24) + (xilinx_firm
[1] << 16) +
802 (xilinx_firm
[2] << 8) + xilinx_firm
[3];
805 for (idx
= 0; idx
< size
; idx
++) {
806 outb(xilinx_firm
[16 + idx
], info
->program_regbase
);
809 /* Check if BUSY flag is low */
810 if (inl(info
->plx_regbase
+ PLX_ICR
) & 0x20) {
812 "comedi%d: me4000: xilinx_download(): Xilinx is still busy (idx = %d)\n",
819 /* If done flag is high download was successful */
820 if (inl(info
->plx_regbase
+ PLX_ICR
) & 0x4) {
823 "comedi%d: me4000: xilinx_download(): DONE flag is not set\n",
826 "comedi%d: me4000: xilinx_download(): Download not succesful\n",
831 /* Set /CS and /WRITE */
832 value
= inl(info
->plx_regbase
+ PLX_ICR
);
834 outl(value
, info
->plx_regbase
+ PLX_ICR
);
839 static int reset_board(struct comedi_device
*dev
)
843 CALL_PDEBUG("In reset_board()\n");
845 /* Make a hardware reset */
846 icr
= me4000_inl(dev
, info
->plx_regbase
+ PLX_ICR
);
848 me4000_outl(dev
, icr
, info
->plx_regbase
+ PLX_ICR
);
850 me4000_outl(dev
, icr
, info
->plx_regbase
+ PLX_ICR
);
852 /* 0x8000 to the DACs means an output voltage of 0V */
853 me4000_outl(dev
, 0x8000,
854 info
->me4000_regbase
+ ME4000_AO_00_SINGLE_REG
);
855 me4000_outl(dev
, 0x8000,
856 info
->me4000_regbase
+ ME4000_AO_01_SINGLE_REG
);
857 me4000_outl(dev
, 0x8000,
858 info
->me4000_regbase
+ ME4000_AO_02_SINGLE_REG
);
859 me4000_outl(dev
, 0x8000,
860 info
->me4000_regbase
+ ME4000_AO_03_SINGLE_REG
);
862 /* Set both stop bits in the analog input control register */
864 ME4000_AI_CTRL_BIT_IMMEDIATE_STOP
| ME4000_AI_CTRL_BIT_STOP
,
865 info
->me4000_regbase
+ ME4000_AI_CTRL_REG
);
867 /* Set both stop bits in the analog output control register */
869 ME4000_AO_CTRL_BIT_IMMEDIATE_STOP
| ME4000_AO_CTRL_BIT_STOP
,
870 info
->me4000_regbase
+ ME4000_AO_00_CTRL_REG
);
872 ME4000_AO_CTRL_BIT_IMMEDIATE_STOP
| ME4000_AO_CTRL_BIT_STOP
,
873 info
->me4000_regbase
+ ME4000_AO_01_CTRL_REG
);
875 ME4000_AO_CTRL_BIT_IMMEDIATE_STOP
| ME4000_AO_CTRL_BIT_STOP
,
876 info
->me4000_regbase
+ ME4000_AO_02_CTRL_REG
);
878 ME4000_AO_CTRL_BIT_IMMEDIATE_STOP
| ME4000_AO_CTRL_BIT_STOP
,
879 info
->me4000_regbase
+ ME4000_AO_03_CTRL_REG
);
881 /* Enable interrupts on the PLX */
882 me4000_outl(dev
, 0x43, info
->plx_regbase
+ PLX_INTCSR
);
884 /* Set the adustment register for AO demux */
885 me4000_outl(dev
, ME4000_AO_DEMUX_ADJUST_VALUE
,
886 info
->me4000_regbase
+ ME4000_AO_DEMUX_ADJUST_REG
);
888 /* Set digital I/O direction for port 0 to output on isolated versions */
889 if (!(me4000_inl(dev
, info
->me4000_regbase
+ ME4000_DIO_DIR_REG
) & 0x1)) {
890 me4000_outl(dev
, 0x1,
891 info
->me4000_regbase
+ ME4000_DIO_CTRL_REG
);
897 static int me4000_detach(struct comedi_device
*dev
)
899 CALL_PDEBUG("In me4000_detach()\n");
902 if (info
->pci_dev_p
) {
904 if (info
->plx_regbase
)
905 comedi_pci_disable(info
->pci_dev_p
);
906 pci_dev_put(info
->pci_dev_p
);
913 /*=============================================================================
915 ===========================================================================*/
917 static int me4000_ai_insn_read(struct comedi_device
*dev
,
918 struct comedi_subdevice
*subdevice
, struct comedi_insn
*insn
, unsigned int *data
)
921 int chan
= CR_CHAN(insn
->chanspec
);
922 int rang
= CR_RANGE(insn
->chanspec
);
923 int aref
= CR_AREF(insn
->chanspec
);
925 unsigned long entry
= 0;
929 CALL_PDEBUG("In me4000_ai_insn_read()\n");
933 } else if (insn
->n
> 1) {
935 "comedi%d: me4000: me4000_ai_insn_read(): Invalid instruction length %d\n",
936 dev
->minor
, insn
->n
);
942 entry
|= ME4000_AI_LIST_RANGE_UNIPOLAR_2_5
;
945 entry
|= ME4000_AI_LIST_RANGE_UNIPOLAR_10
;
948 entry
|= ME4000_AI_LIST_RANGE_BIPOLAR_2_5
;
951 entry
|= ME4000_AI_LIST_RANGE_BIPOLAR_10
;
955 "comedi%d: me4000: me4000_ai_insn_read(): Invalid range specified\n",
963 if (chan
>= thisboard
->ai
.count
) {
965 "comedi%d: me4000: me4000_ai_insn_read(): Analog input is not available\n",
969 entry
|= ME4000_AI_LIST_INPUT_SINGLE_ENDED
| chan
;
973 if (rang
== 0 || rang
== 1) {
975 "comedi%d: me4000: me4000_ai_insn_read(): Range must be bipolar when aref = diff\n",
980 if (chan
>= thisboard
->ai
.diff_count
) {
982 "comedi%d: me4000: me4000_ai_insn_read(): Analog input is not available\n",
986 entry
|= ME4000_AI_LIST_INPUT_DIFFERENTIAL
| chan
;
990 "comedi%d: me4000: me4000_ai_insn_read(): Invalid aref specified\n",
995 entry
|= ME4000_AI_LIST_LAST_ENTRY
;
997 /* Clear channel list, data fifo and both stop bits */
998 tmp
= me4000_inl(dev
, info
->ai_context
.ctrl_reg
);
999 tmp
&= ~(ME4000_AI_CTRL_BIT_CHANNEL_FIFO
|
1000 ME4000_AI_CTRL_BIT_DATA_FIFO
|
1001 ME4000_AI_CTRL_BIT_STOP
| ME4000_AI_CTRL_BIT_IMMEDIATE_STOP
);
1002 me4000_outl(dev
, tmp
, info
->ai_context
.ctrl_reg
);
1004 /* Set the acquisition mode to single */
1005 tmp
&= ~(ME4000_AI_CTRL_BIT_MODE_0
| ME4000_AI_CTRL_BIT_MODE_1
|
1006 ME4000_AI_CTRL_BIT_MODE_2
);
1007 me4000_outl(dev
, tmp
, info
->ai_context
.ctrl_reg
);
1009 /* Enable channel list and data fifo */
1010 tmp
|= ME4000_AI_CTRL_BIT_CHANNEL_FIFO
| ME4000_AI_CTRL_BIT_DATA_FIFO
;
1011 me4000_outl(dev
, tmp
, info
->ai_context
.ctrl_reg
);
1013 /* Generate channel list entry */
1014 me4000_outl(dev
, entry
, info
->ai_context
.channel_list_reg
);
1016 /* Set the timer to maximum sample rate */
1017 me4000_outl(dev
, ME4000_AI_MIN_TICKS
, info
->ai_context
.chan_timer_reg
);
1018 me4000_outl(dev
, ME4000_AI_MIN_TICKS
,
1019 info
->ai_context
.chan_pre_timer_reg
);
1021 /* Start conversion by dummy read */
1022 me4000_inl(dev
, info
->ai_context
.start_reg
);
1024 /* Wait until ready */
1026 if (!(me4000_inl(dev
, info
->ai_context
.
1027 status_reg
) & ME4000_AI_STATUS_BIT_EF_DATA
)) {
1029 "comedi%d: me4000: me4000_ai_insn_read(): Value not available after wait\n",
1034 /* Read value from data fifo */
1035 lval
= me4000_inl(dev
, info
->ai_context
.data_reg
) & 0xFFFF;
1036 data
[0] = lval
^ 0x8000;
1041 static int me4000_ai_cancel(struct comedi_device
*dev
, struct comedi_subdevice
*s
)
1045 CALL_PDEBUG("In me4000_ai_cancel()\n");
1047 /* Stop any running conversion */
1048 tmp
= me4000_inl(dev
, info
->ai_context
.ctrl_reg
);
1049 tmp
&= ~(ME4000_AI_CTRL_BIT_STOP
| ME4000_AI_CTRL_BIT_IMMEDIATE_STOP
);
1050 me4000_outl(dev
, tmp
, info
->ai_context
.ctrl_reg
);
1052 /* Clear the control register */
1053 me4000_outl(dev
, 0x0, info
->ai_context
.ctrl_reg
);
1058 static int ai_check_chanlist(struct comedi_device
*dev
,
1059 struct comedi_subdevice
*s
, struct comedi_cmd
*cmd
)
1064 CALL_PDEBUG("In ai_check_chanlist()\n");
1066 /* Check whether a channel list is available */
1067 if (!cmd
->chanlist_len
) {
1069 "comedi%d: me4000: ai_check_chanlist(): No channel list available\n",
1074 /* Check the channel list size */
1075 if (cmd
->chanlist_len
> ME4000_AI_CHANNEL_LIST_COUNT
) {
1077 "comedi%d: me4000: ai_check_chanlist(): Channel list is to large\n",
1082 /* Check the pointer */
1083 if (!cmd
->chanlist
) {
1085 "comedi%d: me4000: ai_check_chanlist(): NULL pointer to channel list\n",
1090 /* Check whether aref is equal for all entries */
1091 aref
= CR_AREF(cmd
->chanlist
[0]);
1092 for (i
= 0; i
< cmd
->chanlist_len
; i
++) {
1093 if (CR_AREF(cmd
->chanlist
[i
]) != aref
) {
1095 "comedi%d: me4000: ai_check_chanlist(): Mode is not equal for all entries\n",
1101 /* Check whether channels are available for this ending */
1102 if (aref
== SDF_DIFF
) {
1103 for (i
= 0; i
< cmd
->chanlist_len
; i
++) {
1104 if (CR_CHAN(cmd
->chanlist
[i
]) >=
1105 thisboard
->ai
.diff_count
) {
1107 "comedi%d: me4000: ai_check_chanlist(): Channel number to high\n",
1113 for (i
= 0; i
< cmd
->chanlist_len
; i
++) {
1114 if (CR_CHAN(cmd
->chanlist
[i
]) >= thisboard
->ai
.count
) {
1116 "comedi%d: me4000: ai_check_chanlist(): Channel number to high\n",
1123 /* Check if bipolar is set for all entries when in differential mode */
1124 if (aref
== SDF_DIFF
) {
1125 for (i
= 0; i
< cmd
->chanlist_len
; i
++) {
1126 if (CR_RANGE(cmd
->chanlist
[i
]) != 1 &&
1127 CR_RANGE(cmd
->chanlist
[i
]) != 2) {
1129 "comedi%d: me4000: ai_check_chanlist(): Bipolar is not selected in differential mode\n",
1139 static int ai_round_cmd_args(struct comedi_device
*dev
,
1140 struct comedi_subdevice
*s
,
1141 struct comedi_cmd
*cmd
,
1142 unsigned int *init_ticks
,
1143 unsigned int *scan_ticks
, unsigned int *chan_ticks
)
1148 CALL_PDEBUG("In ai_round_cmd_args()\n");
1154 PDEBUG("ai_round_cmd_arg(): start_arg = %d\n", cmd
->start_arg
);
1155 PDEBUG("ai_round_cmd_arg(): scan_begin_arg = %d\n",
1156 cmd
->scan_begin_arg
);
1157 PDEBUG("ai_round_cmd_arg(): convert_arg = %d\n", cmd
->convert_arg
);
1159 if (cmd
->start_arg
) {
1160 *init_ticks
= (cmd
->start_arg
* 33) / 1000;
1161 rest
= (cmd
->start_arg
* 33) % 1000;
1163 if (cmd
->flags
& TRIG_ROUND_NEAREST
) {
1166 } else if (cmd
->flags
& TRIG_ROUND_UP
) {
1172 if (cmd
->scan_begin_arg
) {
1173 *scan_ticks
= (cmd
->scan_begin_arg
* 33) / 1000;
1174 rest
= (cmd
->scan_begin_arg
* 33) % 1000;
1176 if (cmd
->flags
& TRIG_ROUND_NEAREST
) {
1179 } else if (cmd
->flags
& TRIG_ROUND_UP
) {
1185 if (cmd
->convert_arg
) {
1186 *chan_ticks
= (cmd
->convert_arg
* 33) / 1000;
1187 rest
= (cmd
->convert_arg
* 33) % 1000;
1189 if (cmd
->flags
& TRIG_ROUND_NEAREST
) {
1192 } else if (cmd
->flags
& TRIG_ROUND_UP
) {
1198 PDEBUG("ai_round_cmd_args(): init_ticks = %d\n", *init_ticks
);
1199 PDEBUG("ai_round_cmd_args(): scan_ticks = %d\n", *scan_ticks
);
1200 PDEBUG("ai_round_cmd_args(): chan_ticks = %d\n", *chan_ticks
);
1205 static void ai_write_timer(struct comedi_device
*dev
,
1206 unsigned int init_ticks
,
1207 unsigned int scan_ticks
, unsigned int chan_ticks
)
1210 CALL_PDEBUG("In ai_write_timer()\n");
1212 me4000_outl(dev
, init_ticks
- 1,
1213 info
->ai_context
.scan_pre_timer_low_reg
);
1214 me4000_outl(dev
, 0x0, info
->ai_context
.scan_pre_timer_high_reg
);
1217 me4000_outl(dev
, scan_ticks
- 1,
1218 info
->ai_context
.scan_timer_low_reg
);
1219 me4000_outl(dev
, 0x0, info
->ai_context
.scan_timer_high_reg
);
1222 me4000_outl(dev
, chan_ticks
- 1, info
->ai_context
.chan_pre_timer_reg
);
1223 me4000_outl(dev
, chan_ticks
- 1, info
->ai_context
.chan_timer_reg
);
1226 static int ai_prepare(struct comedi_device
*dev
,
1227 struct comedi_subdevice
*s
,
1228 struct comedi_cmd
*cmd
,
1229 unsigned int init_ticks
,
1230 unsigned int scan_ticks
, unsigned int chan_ticks
)
1233 unsigned long tmp
= 0;
1235 CALL_PDEBUG("In ai_prepare()\n");
1237 /* Write timer arguments */
1238 ai_write_timer(dev
, init_ticks
, scan_ticks
, chan_ticks
);
1240 /* Reset control register */
1241 me4000_outl(dev
, tmp
, info
->ai_context
.ctrl_reg
);
1244 if ((cmd
->start_src
== TRIG_EXT
&&
1245 cmd
->scan_begin_src
== TRIG_TIMER
&&
1246 cmd
->convert_src
== TRIG_TIMER
) ||
1247 (cmd
->start_src
== TRIG_EXT
&&
1248 cmd
->scan_begin_src
== TRIG_FOLLOW
&&
1249 cmd
->convert_src
== TRIG_TIMER
)) {
1250 tmp
= ME4000_AI_CTRL_BIT_MODE_1
|
1251 ME4000_AI_CTRL_BIT_CHANNEL_FIFO
|
1252 ME4000_AI_CTRL_BIT_DATA_FIFO
;
1253 } else if (cmd
->start_src
== TRIG_EXT
&&
1254 cmd
->scan_begin_src
== TRIG_EXT
&&
1255 cmd
->convert_src
== TRIG_TIMER
) {
1256 tmp
= ME4000_AI_CTRL_BIT_MODE_2
|
1257 ME4000_AI_CTRL_BIT_CHANNEL_FIFO
|
1258 ME4000_AI_CTRL_BIT_DATA_FIFO
;
1259 } else if (cmd
->start_src
== TRIG_EXT
&&
1260 cmd
->scan_begin_src
== TRIG_EXT
&&
1261 cmd
->convert_src
== TRIG_EXT
) {
1262 tmp
= ME4000_AI_CTRL_BIT_MODE_0
|
1263 ME4000_AI_CTRL_BIT_MODE_1
|
1264 ME4000_AI_CTRL_BIT_CHANNEL_FIFO
|
1265 ME4000_AI_CTRL_BIT_DATA_FIFO
;
1267 tmp
= ME4000_AI_CTRL_BIT_MODE_0
|
1268 ME4000_AI_CTRL_BIT_CHANNEL_FIFO
|
1269 ME4000_AI_CTRL_BIT_DATA_FIFO
;
1273 if (cmd
->stop_src
== TRIG_COUNT
) {
1274 me4000_outl(dev
, cmd
->chanlist_len
* cmd
->stop_arg
,
1275 info
->ai_context
.sample_counter_reg
);
1276 tmp
|= ME4000_AI_CTRL_BIT_HF_IRQ
| ME4000_AI_CTRL_BIT_SC_IRQ
;
1277 } else if (cmd
->stop_src
== TRIG_NONE
&&
1278 cmd
->scan_end_src
== TRIG_COUNT
) {
1279 me4000_outl(dev
, cmd
->scan_end_arg
,
1280 info
->ai_context
.sample_counter_reg
);
1281 tmp
|= ME4000_AI_CTRL_BIT_HF_IRQ
| ME4000_AI_CTRL_BIT_SC_IRQ
;
1283 tmp
|= ME4000_AI_CTRL_BIT_HF_IRQ
;
1286 /* Write the setup to the control register */
1287 me4000_outl(dev
, tmp
, info
->ai_context
.ctrl_reg
);
1289 /* Write the channel list */
1290 ai_write_chanlist(dev
, s
, cmd
);
1295 static int ai_write_chanlist(struct comedi_device
*dev
,
1296 struct comedi_subdevice
*s
, struct comedi_cmd
*cmd
)
1304 CALL_PDEBUG("In ai_write_chanlist()\n");
1306 for (i
= 0; i
< cmd
->chanlist_len
; i
++) {
1307 chan
= CR_CHAN(cmd
->chanlist
[i
]);
1308 rang
= CR_RANGE(cmd
->chanlist
[i
]);
1309 aref
= CR_AREF(cmd
->chanlist
[i
]);
1314 entry
|= ME4000_AI_LIST_RANGE_UNIPOLAR_2_5
;
1315 } else if (rang
== 1) {
1316 entry
|= ME4000_AI_LIST_RANGE_UNIPOLAR_10
;
1317 } else if (rang
== 2) {
1318 entry
|= ME4000_AI_LIST_RANGE_BIPOLAR_2_5
;
1320 entry
|= ME4000_AI_LIST_RANGE_BIPOLAR_10
;
1323 if (aref
== SDF_DIFF
) {
1324 entry
|= ME4000_AI_LIST_INPUT_DIFFERENTIAL
;
1326 entry
|= ME4000_AI_LIST_INPUT_SINGLE_ENDED
;
1329 me4000_outl(dev
, entry
, info
->ai_context
.channel_list_reg
);
1335 static int me4000_ai_do_cmd(struct comedi_device
*dev
, struct comedi_subdevice
*s
)
1338 unsigned int init_ticks
= 0;
1339 unsigned int scan_ticks
= 0;
1340 unsigned int chan_ticks
= 0;
1341 struct comedi_cmd
*cmd
= &s
->async
->cmd
;
1343 CALL_PDEBUG("In me4000_ai_do_cmd()\n");
1345 /* Reset the analog input */
1346 err
= me4000_ai_cancel(dev
, s
);
1350 /* Round the timer arguments */
1351 err
= ai_round_cmd_args(dev
,
1352 s
, cmd
, &init_ticks
, &scan_ticks
, &chan_ticks
);
1356 /* Prepare the AI for acquisition */
1357 err
= ai_prepare(dev
, s
, cmd
, init_ticks
, scan_ticks
, chan_ticks
);
1361 /* Start acquistion by dummy read */
1362 me4000_inl(dev
, info
->ai_context
.start_reg
);
1368 * me4000_ai_do_cmd_test():
1370 * The demo cmd.c in ./comedilib/demo specifies 6 return values:
1374 * - invalid argument
1375 * - argument conflict
1376 * - invalid chanlist
1377 * So I tried to adopt this scheme.
1379 static int me4000_ai_do_cmd_test(struct comedi_device
*dev
,
1380 struct comedi_subdevice
*s
, struct comedi_cmd
*cmd
)
1383 unsigned int init_ticks
;
1384 unsigned int chan_ticks
;
1385 unsigned int scan_ticks
;
1388 CALL_PDEBUG("In me4000_ai_do_cmd_test()\n");
1390 PDEBUG("me4000_ai_do_cmd_test(): subdev = %d\n", cmd
->subdev
);
1391 PDEBUG("me4000_ai_do_cmd_test(): flags = %08X\n", cmd
->flags
);
1392 PDEBUG("me4000_ai_do_cmd_test(): start_src = %08X\n",
1394 PDEBUG("me4000_ai_do_cmd_test(): start_arg = %d\n",
1396 PDEBUG("me4000_ai_do_cmd_test(): scan_begin_src = %08X\n",
1397 cmd
->scan_begin_src
);
1398 PDEBUG("me4000_ai_do_cmd_test(): scan_begin_arg = %d\n",
1399 cmd
->scan_begin_arg
);
1400 PDEBUG("me4000_ai_do_cmd_test(): convert_src = %08X\n",
1402 PDEBUG("me4000_ai_do_cmd_test(): convert_arg = %d\n",
1404 PDEBUG("me4000_ai_do_cmd_test(): scan_end_src = %08X\n",
1406 PDEBUG("me4000_ai_do_cmd_test(): scan_end_arg = %d\n",
1408 PDEBUG("me4000_ai_do_cmd_test(): stop_src = %08X\n",
1410 PDEBUG("me4000_ai_do_cmd_test(): stop_arg = %d\n", cmd
->stop_arg
);
1411 PDEBUG("me4000_ai_do_cmd_test(): chanlist = %d\n",
1412 (unsigned int)cmd
->chanlist
);
1413 PDEBUG("me4000_ai_do_cmd_test(): chanlist_len = %d\n",
1416 /* Only rounding flags are implemented */
1417 cmd
->flags
&= TRIG_ROUND_NEAREST
| TRIG_ROUND_UP
| TRIG_ROUND_DOWN
;
1419 /* Round the timer arguments */
1420 ai_round_cmd_args(dev
, s
, cmd
, &init_ticks
, &scan_ticks
, &chan_ticks
);
1423 * Stage 1. Check if the trigger sources are generally valid.
1425 switch (cmd
->start_src
) {
1430 cmd
->start_src
&= TRIG_NOW
| TRIG_EXT
;
1435 "comedi%d: me4000: me4000_ai_do_cmd_test(): Invalid start source\n",
1437 cmd
->start_src
= TRIG_NOW
;
1440 switch (cmd
->scan_begin_src
) {
1446 cmd
->scan_begin_src
&= TRIG_FOLLOW
| TRIG_TIMER
| TRIG_EXT
;
1451 "comedi%d: me4000: me4000_ai_do_cmd_test(): Invalid scan begin source\n",
1453 cmd
->scan_begin_src
= TRIG_FOLLOW
;
1456 switch (cmd
->convert_src
) {
1461 cmd
->convert_src
&= TRIG_TIMER
| TRIG_EXT
;
1466 "comedi%d: me4000: me4000_ai_do_cmd_test(): Invalid convert source\n",
1468 cmd
->convert_src
= TRIG_TIMER
;
1471 switch (cmd
->scan_end_src
) {
1476 cmd
->scan_end_src
&= TRIG_NONE
| TRIG_COUNT
;
1481 "comedi%d: me4000: me4000_ai_do_cmd_test(): Invalid scan end source\n",
1483 cmd
->scan_end_src
= TRIG_NONE
;
1486 switch (cmd
->stop_src
) {
1491 cmd
->stop_src
&= TRIG_NONE
| TRIG_COUNT
;
1496 "comedi%d: me4000: me4000_ai_do_cmd_test(): Invalid stop source\n",
1498 cmd
->stop_src
= TRIG_NONE
;
1505 * Stage 2. Check for trigger source conflicts.
1507 if (cmd
->start_src
== TRIG_NOW
&&
1508 cmd
->scan_begin_src
== TRIG_TIMER
&&
1509 cmd
->convert_src
== TRIG_TIMER
) {
1510 } else if (cmd
->start_src
== TRIG_NOW
&&
1511 cmd
->scan_begin_src
== TRIG_FOLLOW
&&
1512 cmd
->convert_src
== TRIG_TIMER
) {
1513 } else if (cmd
->start_src
== TRIG_EXT
&&
1514 cmd
->scan_begin_src
== TRIG_TIMER
&&
1515 cmd
->convert_src
== TRIG_TIMER
) {
1516 } else if (cmd
->start_src
== TRIG_EXT
&&
1517 cmd
->scan_begin_src
== TRIG_FOLLOW
&&
1518 cmd
->convert_src
== TRIG_TIMER
) {
1519 } else if (cmd
->start_src
== TRIG_EXT
&&
1520 cmd
->scan_begin_src
== TRIG_EXT
&&
1521 cmd
->convert_src
== TRIG_TIMER
) {
1522 } else if (cmd
->start_src
== TRIG_EXT
&&
1523 cmd
->scan_begin_src
== TRIG_EXT
&&
1524 cmd
->convert_src
== TRIG_EXT
) {
1527 "comedi%d: me4000: me4000_ai_do_cmd_test(): Invalid start trigger combination\n",
1529 cmd
->start_src
= TRIG_NOW
;
1530 cmd
->scan_begin_src
= TRIG_FOLLOW
;
1531 cmd
->convert_src
= TRIG_TIMER
;
1535 if (cmd
->stop_src
== TRIG_NONE
&& cmd
->scan_end_src
== TRIG_NONE
) {
1536 } else if (cmd
->stop_src
== TRIG_COUNT
&&
1537 cmd
->scan_end_src
== TRIG_NONE
) {
1538 } else if (cmd
->stop_src
== TRIG_NONE
&&
1539 cmd
->scan_end_src
== TRIG_COUNT
) {
1540 } else if (cmd
->stop_src
== TRIG_COUNT
&&
1541 cmd
->scan_end_src
== TRIG_COUNT
) {
1544 "comedi%d: me4000: me4000_ai_do_cmd_test(): Invalid stop trigger combination\n",
1546 cmd
->stop_src
= TRIG_NONE
;
1547 cmd
->scan_end_src
= TRIG_NONE
;
1554 * Stage 3. Check if arguments are generally valid.
1556 if (cmd
->chanlist_len
< 1) {
1558 "comedi%d: me4000: me4000_ai_do_cmd_test(): No channel list\n",
1560 cmd
->chanlist_len
= 1;
1563 if (init_ticks
< 66) {
1565 "comedi%d: me4000: me4000_ai_do_cmd_test(): Start arg to low\n",
1567 cmd
->start_arg
= 2000;
1570 if (scan_ticks
&& scan_ticks
< 67) {
1572 "comedi%d: me4000: me4000_ai_do_cmd_test(): Scan begin arg to low\n",
1574 cmd
->scan_begin_arg
= 2031;
1577 if (chan_ticks
< 66) {
1579 "comedi%d: me4000: me4000_ai_do_cmd_test(): Convert arg to low\n",
1581 cmd
->convert_arg
= 2000;
1589 * Stage 4. Check for argument conflicts.
1591 if (cmd
->start_src
== TRIG_NOW
&&
1592 cmd
->scan_begin_src
== TRIG_TIMER
&&
1593 cmd
->convert_src
== TRIG_TIMER
) {
1595 /* Check timer arguments */
1596 if (init_ticks
< ME4000_AI_MIN_TICKS
) {
1598 "comedi%d: me4000: me4000_ai_do_cmd_test(): Invalid start arg\n",
1600 cmd
->start_arg
= 2000; /* 66 ticks at least */
1603 if (chan_ticks
< ME4000_AI_MIN_TICKS
) {
1605 "comedi%d: me4000: me4000_ai_do_cmd_test(): Invalid convert arg\n",
1607 cmd
->convert_arg
= 2000; /* 66 ticks at least */
1610 if (scan_ticks
<= cmd
->chanlist_len
* chan_ticks
) {
1612 "comedi%d: me4000: me4000_ai_do_cmd_test(): Invalid scan end arg\n",
1614 cmd
->scan_end_arg
= 2000 * cmd
->chanlist_len
+ 31; /* At least one tick more */
1617 } else if (cmd
->start_src
== TRIG_NOW
&&
1618 cmd
->scan_begin_src
== TRIG_FOLLOW
&&
1619 cmd
->convert_src
== TRIG_TIMER
) {
1621 /* Check timer arguments */
1622 if (init_ticks
< ME4000_AI_MIN_TICKS
) {
1624 "comedi%d: me4000: me4000_ai_do_cmd_test(): Invalid start arg\n",
1626 cmd
->start_arg
= 2000; /* 66 ticks at least */
1629 if (chan_ticks
< ME4000_AI_MIN_TICKS
) {
1631 "comedi%d: me4000: me4000_ai_do_cmd_test(): Invalid convert arg\n",
1633 cmd
->convert_arg
= 2000; /* 66 ticks at least */
1636 } else if (cmd
->start_src
== TRIG_EXT
&&
1637 cmd
->scan_begin_src
== TRIG_TIMER
&&
1638 cmd
->convert_src
== TRIG_TIMER
) {
1640 /* Check timer arguments */
1641 if (init_ticks
< ME4000_AI_MIN_TICKS
) {
1643 "comedi%d: me4000: me4000_ai_do_cmd_test(): Invalid start arg\n",
1645 cmd
->start_arg
= 2000; /* 66 ticks at least */
1648 if (chan_ticks
< ME4000_AI_MIN_TICKS
) {
1650 "comedi%d: me4000: me4000_ai_do_cmd_test(): Invalid convert arg\n",
1652 cmd
->convert_arg
= 2000; /* 66 ticks at least */
1655 if (scan_ticks
<= cmd
->chanlist_len
* chan_ticks
) {
1657 "comedi%d: me4000: me4000_ai_do_cmd_test(): Invalid scan end arg\n",
1659 cmd
->scan_end_arg
= 2000 * cmd
->chanlist_len
+ 31; /* At least one tick more */
1662 } else if (cmd
->start_src
== TRIG_EXT
&&
1663 cmd
->scan_begin_src
== TRIG_FOLLOW
&&
1664 cmd
->convert_src
== TRIG_TIMER
) {
1666 /* Check timer arguments */
1667 if (init_ticks
< ME4000_AI_MIN_TICKS
) {
1669 "comedi%d: me4000: me4000_ai_do_cmd_test(): Invalid start arg\n",
1671 cmd
->start_arg
= 2000; /* 66 ticks at least */
1674 if (chan_ticks
< ME4000_AI_MIN_TICKS
) {
1676 "comedi%d: me4000: me4000_ai_do_cmd_test(): Invalid convert arg\n",
1678 cmd
->convert_arg
= 2000; /* 66 ticks at least */
1681 } else if (cmd
->start_src
== TRIG_EXT
&&
1682 cmd
->scan_begin_src
== TRIG_EXT
&&
1683 cmd
->convert_src
== TRIG_TIMER
) {
1685 /* Check timer arguments */
1686 if (init_ticks
< ME4000_AI_MIN_TICKS
) {
1688 "comedi%d: me4000: me4000_ai_do_cmd_test(): Invalid start arg\n",
1690 cmd
->start_arg
= 2000; /* 66 ticks at least */
1693 if (chan_ticks
< ME4000_AI_MIN_TICKS
) {
1695 "comedi%d: me4000: me4000_ai_do_cmd_test(): Invalid convert arg\n",
1697 cmd
->convert_arg
= 2000; /* 66 ticks at least */
1700 } else if (cmd
->start_src
== TRIG_EXT
&&
1701 cmd
->scan_begin_src
== TRIG_EXT
&&
1702 cmd
->convert_src
== TRIG_EXT
) {
1704 /* Check timer arguments */
1705 if (init_ticks
< ME4000_AI_MIN_TICKS
) {
1707 "comedi%d: me4000: me4000_ai_do_cmd_test(): Invalid start arg\n",
1709 cmd
->start_arg
= 2000; /* 66 ticks at least */
1713 if (cmd
->stop_src
== TRIG_COUNT
) {
1714 if (cmd
->stop_arg
== 0) {
1716 "comedi%d: me4000: me4000_ai_do_cmd_test(): Invalid stop arg\n",
1722 if (cmd
->scan_end_src
== TRIG_COUNT
) {
1723 if (cmd
->scan_end_arg
== 0) {
1725 "comedi%d: me4000: me4000_ai_do_cmd_test(): Invalid scan end arg\n",
1727 cmd
->scan_end_arg
= 1;
1736 * Stage 5. Check the channel list.
1738 if (ai_check_chanlist(dev
, s
, cmd
))
1744 static irqreturn_t
me4000_ai_isr(int irq
, void *dev_id
)
1747 struct comedi_device
*dev
= dev_id
;
1748 struct comedi_subdevice
*s
= dev
->subdevices
;
1749 struct me4000_ai_context
*ai_context
= &info
->ai_context
;
1754 ISR_PDEBUG("me4000_ai_isr() is executed\n");
1756 if (!dev
->attached
) {
1757 ISR_PDEBUG("me4000_ai_isr() premature interrupt\n");
1761 /* Reset all events */
1762 s
->async
->events
= 0;
1764 /* Check if irq number is right */
1765 if (irq
!= ai_context
->irq
) {
1767 "comedi%d: me4000: me4000_ai_isr(): Incorrect interrupt num: %d\n",
1774 irq_status_reg
) & ME4000_IRQ_STATUS_BIT_AI_HF
) {
1776 ("me4000_ai_isr(): Fifo half full interrupt occured\n");
1778 /* Read status register to find out what happened */
1779 tmp
= me4000_inl(dev
, ai_context
->ctrl_reg
);
1781 if (!(tmp
& ME4000_AI_STATUS_BIT_FF_DATA
) &&
1782 !(tmp
& ME4000_AI_STATUS_BIT_HF_DATA
) &&
1783 (tmp
& ME4000_AI_STATUS_BIT_EF_DATA
)) {
1784 ISR_PDEBUG("me4000_ai_isr(): Fifo full\n");
1785 c
= ME4000_AI_FIFO_COUNT
;
1787 /* FIFO overflow, so stop conversion and disable all interrupts */
1788 tmp
|= ME4000_AI_CTRL_BIT_IMMEDIATE_STOP
;
1789 tmp
&= ~(ME4000_AI_CTRL_BIT_HF_IRQ
|
1790 ME4000_AI_CTRL_BIT_SC_IRQ
);
1791 me4000_outl(dev
, tmp
, ai_context
->ctrl_reg
);
1793 s
->async
->events
|= COMEDI_CB_ERROR
| COMEDI_CB_EOA
;
1796 "comedi%d: me4000: me4000_ai_isr(): FIFO overflow\n",
1798 } else if ((tmp
& ME4000_AI_STATUS_BIT_FF_DATA
)
1799 && !(tmp
& ME4000_AI_STATUS_BIT_HF_DATA
)
1800 && (tmp
& ME4000_AI_STATUS_BIT_EF_DATA
)) {
1801 ISR_PDEBUG("me4000_ai_isr(): Fifo half full\n");
1803 s
->async
->events
|= COMEDI_CB_BLOCK
;
1805 c
= ME4000_AI_FIFO_COUNT
/ 2;
1808 "comedi%d: me4000: me4000_ai_isr(): Can't determine state of fifo\n",
1812 /* Undefined state, so stop conversion and disable all interrupts */
1813 tmp
|= ME4000_AI_CTRL_BIT_IMMEDIATE_STOP
;
1814 tmp
&= ~(ME4000_AI_CTRL_BIT_HF_IRQ
|
1815 ME4000_AI_CTRL_BIT_SC_IRQ
);
1816 me4000_outl(dev
, tmp
, ai_context
->ctrl_reg
);
1818 s
->async
->events
|= COMEDI_CB_ERROR
| COMEDI_CB_EOA
;
1821 "comedi%d: me4000: me4000_ai_isr(): Undefined FIFO state\n",
1825 ISR_PDEBUG("me4000_ai_isr(): Try to read %d values\n", c
);
1827 for (i
= 0; i
< c
; i
++) {
1828 /* Read value from data fifo */
1829 lval
= inl(ai_context
->data_reg
) & 0xFFFF;
1832 if (!comedi_buf_put(s
->async
, lval
)) {
1833 /* Buffer overflow, so stop conversion and disable all interrupts */
1834 tmp
|= ME4000_AI_CTRL_BIT_IMMEDIATE_STOP
;
1835 tmp
&= ~(ME4000_AI_CTRL_BIT_HF_IRQ
|
1836 ME4000_AI_CTRL_BIT_SC_IRQ
);
1837 me4000_outl(dev
, tmp
, ai_context
->ctrl_reg
);
1839 s
->async
->events
|= COMEDI_CB_OVERFLOW
;
1842 "comedi%d: me4000: me4000_ai_isr(): Buffer overflow\n",
1849 /* Work is done, so reset the interrupt */
1850 ISR_PDEBUG("me4000_ai_isr(): Reset fifo half full interrupt\n");
1851 tmp
|= ME4000_AI_CTRL_BIT_HF_IRQ_RESET
;
1852 me4000_outl(dev
, tmp
, ai_context
->ctrl_reg
);
1853 tmp
&= ~ME4000_AI_CTRL_BIT_HF_IRQ_RESET
;
1854 me4000_outl(dev
, tmp
, ai_context
->ctrl_reg
);
1859 irq_status_reg
) & ME4000_IRQ_STATUS_BIT_SC
) {
1861 ("me4000_ai_isr(): Sample counter interrupt occured\n");
1863 s
->async
->events
|= COMEDI_CB_BLOCK
| COMEDI_CB_EOA
;
1865 /* Acquisition is complete, so stop conversion and disable all interrupts */
1866 tmp
= me4000_inl(dev
, ai_context
->ctrl_reg
);
1867 tmp
|= ME4000_AI_CTRL_BIT_IMMEDIATE_STOP
;
1868 tmp
&= ~(ME4000_AI_CTRL_BIT_HF_IRQ
| ME4000_AI_CTRL_BIT_SC_IRQ
);
1869 me4000_outl(dev
, tmp
, ai_context
->ctrl_reg
);
1871 /* Poll data until fifo empty */
1872 while (inl(ai_context
->ctrl_reg
) & ME4000_AI_STATUS_BIT_EF_DATA
) {
1873 /* Read value from data fifo */
1874 lval
= inl(ai_context
->data_reg
) & 0xFFFF;
1877 if (!comedi_buf_put(s
->async
, lval
)) {
1879 "comedi%d: me4000: me4000_ai_isr(): Buffer overflow\n",
1881 s
->async
->events
|= COMEDI_CB_OVERFLOW
;
1886 /* Work is done, so reset the interrupt */
1888 ("me4000_ai_isr(): Reset interrupt from sample counter\n");
1889 tmp
|= ME4000_AI_CTRL_BIT_SC_IRQ_RESET
;
1890 me4000_outl(dev
, tmp
, ai_context
->ctrl_reg
);
1891 tmp
&= ~ME4000_AI_CTRL_BIT_SC_IRQ_RESET
;
1892 me4000_outl(dev
, tmp
, ai_context
->ctrl_reg
);
1895 ISR_PDEBUG("me4000_ai_isr(): Events = 0x%X\n", s
->async
->events
);
1897 if (s
->async
->events
)
1898 comedi_event(dev
, s
);
1903 /*=============================================================================
1904 Analog output section
1905 ===========================================================================*/
1907 static int me4000_ao_insn_write(struct comedi_device
*dev
,
1908 struct comedi_subdevice
*s
, struct comedi_insn
*insn
, unsigned int *data
)
1911 int chan
= CR_CHAN(insn
->chanspec
);
1912 int rang
= CR_RANGE(insn
->chanspec
);
1913 int aref
= CR_AREF(insn
->chanspec
);
1916 CALL_PDEBUG("In me4000_ao_insn_write()\n");
1920 } else if (insn
->n
> 1) {
1922 "comedi%d: me4000: me4000_ao_insn_write(): Invalid instruction length %d\n",
1923 dev
->minor
, insn
->n
);
1927 if (chan
>= thisboard
->ao
.count
) {
1929 "comedi%d: me4000: me4000_ao_insn_write(): Invalid channel %d\n",
1930 dev
->minor
, insn
->n
);
1936 "comedi%d: me4000: me4000_ao_insn_write(): Invalid range %d\n",
1937 dev
->minor
, insn
->n
);
1941 if (aref
!= AREF_GROUND
&& aref
!= AREF_COMMON
) {
1943 "comedi%d: me4000: me4000_ao_insn_write(): Invalid aref %d\n",
1944 dev
->minor
, insn
->n
);
1948 /* Stop any running conversion */
1949 tmp
= me4000_inl(dev
, info
->ao_context
[chan
].ctrl_reg
);
1950 tmp
|= ME4000_AO_CTRL_BIT_IMMEDIATE_STOP
;
1951 me4000_outl(dev
, tmp
, info
->ao_context
[chan
].ctrl_reg
);
1953 /* Clear control register and set to single mode */
1954 me4000_outl(dev
, 0x0, info
->ao_context
[chan
].ctrl_reg
);
1956 /* Write data value */
1957 me4000_outl(dev
, data
[0], info
->ao_context
[chan
].single_reg
);
1959 /* Store in the mirror */
1960 info
->ao_context
[chan
].mirror
= data
[0];
1965 static int me4000_ao_insn_read(struct comedi_device
*dev
,
1966 struct comedi_subdevice
*s
, struct comedi_insn
*insn
, unsigned int *data
)
1968 int chan
= CR_CHAN(insn
->chanspec
);
1972 } else if (insn
->n
> 1) {
1973 printk("comedi%d: me4000: me4000_ao_insn_read(): Invalid instruction length\n", dev
->minor
);
1977 data
[0] = info
->ao_context
[chan
].mirror
;
1982 /*=============================================================================
1984 ===========================================================================*/
1986 static int me4000_dio_insn_bits(struct comedi_device
*dev
,
1987 struct comedi_subdevice
*s
, struct comedi_insn
*insn
, unsigned int *data
)
1990 CALL_PDEBUG("In me4000_dio_insn_bits()\n");
1992 /* Length of data must be 2 (mask and new data, see below) */
1997 printk("comedi%d: me4000: me4000_dio_insn_bits(): Invalid instruction length\n", dev
->minor
);
2002 * The insn data consists of a mask in data[0] and the new data
2003 * in data[1]. The mask defines which bits we are concerning about.
2004 * The new data must be anded with the mask.
2005 * Each channel corresponds to a bit.
2008 /* Check if requested ports are configured for output */
2009 if ((s
->io_bits
& data
[0]) != data
[0])
2012 s
->state
&= ~data
[0];
2013 s
->state
|= data
[0] & data
[1];
2015 /* Write out the new digital output lines */
2016 me4000_outl(dev
, (s
->state
>> 0) & 0xFF,
2017 info
->dio_context
.port_0_reg
);
2018 me4000_outl(dev
, (s
->state
>> 8) & 0xFF,
2019 info
->dio_context
.port_1_reg
);
2020 me4000_outl(dev
, (s
->state
>> 16) & 0xFF,
2021 info
->dio_context
.port_2_reg
);
2022 me4000_outl(dev
, (s
->state
>> 24) & 0xFF,
2023 info
->dio_context
.port_3_reg
);
2026 /* On return, data[1] contains the value of
2027 the digital input and output lines. */
2029 ((me4000_inl(dev
, info
->dio_context
.port_0_reg
) & 0xFF) << 0) |
2030 ((me4000_inl(dev
, info
->dio_context
.port_1_reg
) & 0xFF) << 8) |
2031 ((me4000_inl(dev
, info
->dio_context
.port_2_reg
) & 0xFF) << 16) |
2032 ((me4000_inl(dev
, info
->dio_context
.port_3_reg
) & 0xFF) << 24);
2037 static int me4000_dio_insn_config(struct comedi_device
*dev
,
2038 struct comedi_subdevice
*s
, struct comedi_insn
*insn
, unsigned int *data
)
2041 int chan
= CR_CHAN(insn
->chanspec
);
2043 CALL_PDEBUG("In me4000_dio_insn_config()\n");
2045 if (data
[0] == INSN_CONFIG_DIO_QUERY
) {
2048 io_bits
& (1 << chan
)) ? COMEDI_OUTPUT
: COMEDI_INPUT
;
2053 * The input or output configuration of each digital line is
2054 * configured by a special insn_config instruction. chanspec
2055 * contains the channel to be changed, and data[0] contains the
2056 * value COMEDI_INPUT or COMEDI_OUTPUT.
2057 * On the ME-4000 it is only possible to switch port wise (8 bit)
2060 tmp
= me4000_inl(dev
, info
->dio_context
.ctrl_reg
);
2062 if (data
[0] == COMEDI_OUTPUT
) {
2065 tmp
&= ~(ME4000_DIO_CTRL_BIT_MODE_0
|
2066 ME4000_DIO_CTRL_BIT_MODE_1
);
2067 tmp
|= ME4000_DIO_CTRL_BIT_MODE_0
;
2068 } else if (chan
< 16) {
2070 * Chech for optoisolated ME-4000 version. If one the first
2071 * port is a fixed output port and the second is a fixed input port.
2073 if (!me4000_inl(dev
, info
->dio_context
.dir_reg
))
2076 s
->io_bits
|= 0xFF00;
2077 tmp
&= ~(ME4000_DIO_CTRL_BIT_MODE_2
|
2078 ME4000_DIO_CTRL_BIT_MODE_3
);
2079 tmp
|= ME4000_DIO_CTRL_BIT_MODE_2
;
2080 } else if (chan
< 24) {
2081 s
->io_bits
|= 0xFF0000;
2082 tmp
&= ~(ME4000_DIO_CTRL_BIT_MODE_4
|
2083 ME4000_DIO_CTRL_BIT_MODE_5
);
2084 tmp
|= ME4000_DIO_CTRL_BIT_MODE_4
;
2085 } else if (chan
< 32) {
2086 s
->io_bits
|= 0xFF000000;
2087 tmp
&= ~(ME4000_DIO_CTRL_BIT_MODE_6
|
2088 ME4000_DIO_CTRL_BIT_MODE_7
);
2089 tmp
|= ME4000_DIO_CTRL_BIT_MODE_6
;
2096 * Chech for optoisolated ME-4000 version. If one the first
2097 * port is a fixed output port and the second is a fixed input port.
2099 if (!me4000_inl(dev
, info
->dio_context
.dir_reg
))
2102 s
->io_bits
&= ~0xFF;
2103 tmp
&= ~(ME4000_DIO_CTRL_BIT_MODE_0
|
2104 ME4000_DIO_CTRL_BIT_MODE_1
);
2105 } else if (chan
< 16) {
2106 s
->io_bits
&= ~0xFF00;
2107 tmp
&= ~(ME4000_DIO_CTRL_BIT_MODE_2
|
2108 ME4000_DIO_CTRL_BIT_MODE_3
);
2109 } else if (chan
< 24) {
2110 s
->io_bits
&= ~0xFF0000;
2111 tmp
&= ~(ME4000_DIO_CTRL_BIT_MODE_4
|
2112 ME4000_DIO_CTRL_BIT_MODE_5
);
2113 } else if (chan
< 32) {
2114 s
->io_bits
&= ~0xFF000000;
2115 tmp
&= ~(ME4000_DIO_CTRL_BIT_MODE_6
|
2116 ME4000_DIO_CTRL_BIT_MODE_7
);
2122 me4000_outl(dev
, tmp
, info
->dio_context
.ctrl_reg
);
2127 /*=============================================================================
2129 ===========================================================================*/
2131 static int cnt_reset(struct comedi_device
*dev
, unsigned int channel
)
2134 CALL_PDEBUG("In cnt_reset()\n");
2138 me4000_outb(dev
, 0x30, info
->cnt_context
.ctrl_reg
);
2139 me4000_outb(dev
, 0x00, info
->cnt_context
.counter_0_reg
);
2140 me4000_outb(dev
, 0x00, info
->cnt_context
.counter_0_reg
);
2143 me4000_outb(dev
, 0x70, info
->cnt_context
.ctrl_reg
);
2144 me4000_outb(dev
, 0x00, info
->cnt_context
.counter_1_reg
);
2145 me4000_outb(dev
, 0x00, info
->cnt_context
.counter_1_reg
);
2148 me4000_outb(dev
, 0xB0, info
->cnt_context
.ctrl_reg
);
2149 me4000_outb(dev
, 0x00, info
->cnt_context
.counter_2_reg
);
2150 me4000_outb(dev
, 0x00, info
->cnt_context
.counter_2_reg
);
2154 "comedi%d: me4000: cnt_reset(): Invalid channel\n",
2162 static int cnt_config(struct comedi_device
*dev
, unsigned int channel
,
2167 CALL_PDEBUG("In cnt_config()\n");
2171 tmp
|= ME4000_CNT_COUNTER_0
;
2174 tmp
|= ME4000_CNT_COUNTER_1
;
2177 tmp
|= ME4000_CNT_COUNTER_2
;
2181 "comedi%d: me4000: cnt_config(): Invalid channel\n",
2188 tmp
|= ME4000_CNT_MODE_0
;
2191 tmp
|= ME4000_CNT_MODE_1
;
2194 tmp
|= ME4000_CNT_MODE_2
;
2197 tmp
|= ME4000_CNT_MODE_3
;
2200 tmp
|= ME4000_CNT_MODE_4
;
2203 tmp
|= ME4000_CNT_MODE_5
;
2207 "comedi%d: me4000: cnt_config(): Invalid counter mode\n",
2212 /* Write the control word */
2214 me4000_outb(dev
, tmp
, info
->cnt_context
.ctrl_reg
);
2219 static int me4000_cnt_insn_config(struct comedi_device
*dev
,
2220 struct comedi_subdevice
*s
, struct comedi_insn
*insn
, unsigned int *data
)
2225 CALL_PDEBUG("In me4000_cnt_insn_config()\n");
2231 "comedi%d: me4000: me4000_cnt_insn_config(): Invalid instruction length%d\n",
2232 dev
->minor
, insn
->n
);
2236 err
= cnt_reset(dev
, insn
->chanspec
);
2240 case GPCT_SET_OPERATION
:
2243 "comedi%d: me4000: me4000_cnt_insn_config(): Invalid instruction length%d\n",
2244 dev
->minor
, insn
->n
);
2248 err
= cnt_config(dev
, insn
->chanspec
, data
[1]);
2254 "comedi%d: me4000: me4000_cnt_insn_config(): Invalid instruction\n",
2262 static int me4000_cnt_insn_read(struct comedi_device
*dev
,
2263 struct comedi_subdevice
*s
, struct comedi_insn
*insn
, unsigned int *data
)
2268 CALL_PDEBUG("In me4000_cnt_insn_read()\n");
2275 "comedi%d: me4000: me4000_cnt_insn_read(): Invalid instruction length %d\n",
2276 dev
->minor
, insn
->n
);
2280 switch (insn
->chanspec
) {
2282 tmp
= me4000_inb(dev
, info
->cnt_context
.counter_0_reg
);
2284 tmp
= me4000_inb(dev
, info
->cnt_context
.counter_0_reg
);
2285 data
[0] |= tmp
<< 8;
2288 tmp
= me4000_inb(dev
, info
->cnt_context
.counter_1_reg
);
2290 tmp
= me4000_inb(dev
, info
->cnt_context
.counter_1_reg
);
2291 data
[0] |= tmp
<< 8;
2294 tmp
= me4000_inb(dev
, info
->cnt_context
.counter_2_reg
);
2296 tmp
= me4000_inb(dev
, info
->cnt_context
.counter_2_reg
);
2297 data
[0] |= tmp
<< 8;
2301 "comedi%d: me4000: me4000_cnt_insn_read(): Invalid channel %d\n",
2302 dev
->minor
, insn
->chanspec
);
2309 static int me4000_cnt_insn_write(struct comedi_device
*dev
,
2310 struct comedi_subdevice
*s
, struct comedi_insn
*insn
, unsigned int *data
)
2315 CALL_PDEBUG("In me4000_cnt_insn_write()\n");
2319 } else if (insn
->n
> 1) {
2321 "comedi%d: me4000: me4000_cnt_insn_write(): Invalid instruction length %d\n",
2322 dev
->minor
, insn
->n
);
2326 switch (insn
->chanspec
) {
2328 tmp
= data
[0] & 0xFF;
2329 me4000_outb(dev
, tmp
, info
->cnt_context
.counter_0_reg
);
2330 tmp
= (data
[0] >> 8) & 0xFF;
2331 me4000_outb(dev
, tmp
, info
->cnt_context
.counter_0_reg
);
2334 tmp
= data
[0] & 0xFF;
2335 me4000_outb(dev
, tmp
, info
->cnt_context
.counter_1_reg
);
2336 tmp
= (data
[0] >> 8) & 0xFF;
2337 me4000_outb(dev
, tmp
, info
->cnt_context
.counter_1_reg
);
2340 tmp
= data
[0] & 0xFF;
2341 me4000_outb(dev
, tmp
, info
->cnt_context
.counter_2_reg
);
2342 tmp
= (data
[0] >> 8) & 0xFF;
2343 me4000_outb(dev
, tmp
, info
->cnt_context
.counter_2_reg
);
2347 "comedi%d: me4000: me4000_cnt_insn_write(): Invalid channel %d\n",
2348 dev
->minor
, insn
->chanspec
);
2355 COMEDI_PCI_INITCLEANUP(driver_me4000
, me4000_pci_table
);