]> git.proxmox.com Git - mirror_ubuntu-hirsute-kernel.git/blame - drivers/staging/comedi/drivers/me4000.c
Staging: comedi: fix printk() coding style issue in ni_labpc.c
[mirror_ubuntu-hirsute-kernel.git] / drivers / staging / comedi / drivers / me4000.c
CommitLineData
e55c95a3
GG
1/*
2 comedi/drivers/me4000.c
3 Source code for the Meilhaus ME-4000 board family.
4
5 COMEDI - Linux Control and Measurement Device Interface
6 Copyright (C) 2000 David A. Schleef <ds@schleef.org>
7
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.
12
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.
17
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.
21
22 */
23/*
24Driver: me4000
25Description: Meilhaus ME-4000 series boards
26Devices: [Meilhaus] ME-4650 (me4000), ME-4670i, ME-4680, ME-4680i, ME-4680is
27Author: gg (Guenter Gebhardt <g.gebhardt@meilhaus.com>)
28Updated: Mon, 18 Mar 2002 15:34:01 -0800
29Status: broken (no support for loading firmware)
30
31Supports:
32
33 - Analog Input
34 - Analog Output
35 - Digital I/O
36 - Counter
37
38Configuration Options:
39
40 [0] - PCI bus number (optional)
41 [1] - PCI slot number (optional)
42
43 If bus/slot is not specified, the first available PCI
44 device will be used.
45
46The firmware required by these boards is available in the
47comedi_nonfree_firmware tarball available from
48http://www.comedi.org. However, the driver's support for
49loading the firmware through comedi_config is currently
50broken.
51
52 */
53
25436dc9 54#include <linux/interrupt.h>
e55c95a3
GG
55#include "../comedidev.h"
56
57#include <linux/delay.h>
58#include <linux/list.h>
59#include <linux/spinlock.h>
60
61#include "comedi_pci.h"
62#include "me4000.h"
63#if 0
64/* file removed due to GPL incompatibility */
65#include "me4000_fw.h"
66#endif
67
68/*=============================================================================
69 PCI device table.
70 This is used by modprobe to translate PCI IDs to drivers.
71 ===========================================================================*/
72
73static DEFINE_PCI_DEVICE_TABLE(me4000_pci_table) = {
0a85b6f0
MT
74 {
75 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}, {
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}, {
84 PCI_VENDOR_ID_MEILHAUS, 0x4680, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {
85 PCI_VENDOR_ID_MEILHAUS, 0x4681, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {
86 PCI_VENDOR_ID_MEILHAUS, 0x4682, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {
87 PCI_VENDOR_ID_MEILHAUS, 0x4683, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {
88 0}
e55c95a3
GG
89};
90
91MODULE_DEVICE_TABLE(pci, me4000_pci_table);
92
27f4caaa 93static const struct me4000_board me4000_boards[] = {
e55c95a3
GG
94 {"ME-4650", 0x4650, {0, 0}, {16, 0, 0, 0}, {4}, {0}},
95
96 {"ME-4660", 0x4660, {0, 0}, {32, 0, 16, 0}, {4}, {3}},
97 {"ME-4660i", 0x4661, {0, 0}, {32, 0, 16, 0}, {4}, {3}},
98 {"ME-4660s", 0x4662, {0, 0}, {32, 8, 16, 0}, {4}, {3}},
99 {"ME-4660is", 0x4663, {0, 0}, {32, 8, 16, 0}, {4}, {3}},
100
101 {"ME-4670", 0x4670, {4, 0}, {32, 0, 16, 1}, {4}, {3}},
102 {"ME-4670i", 0x4671, {4, 0}, {32, 0, 16, 1}, {4}, {3}},
103 {"ME-4670s", 0x4672, {4, 0}, {32, 8, 16, 1}, {4}, {3}},
104 {"ME-4670is", 0x4673, {4, 0}, {32, 8, 16, 1}, {4}, {3}},
105
106 {"ME-4680", 0x4680, {4, 4}, {32, 0, 16, 1}, {4}, {3}},
107 {"ME-4680i", 0x4681, {4, 4}, {32, 0, 16, 1}, {4}, {3}},
108 {"ME-4680s", 0x4682, {4, 4}, {32, 8, 16, 1}, {4}, {3}},
109 {"ME-4680is", 0x4683, {4, 4}, {32, 8, 16, 1}, {4}, {3}},
110
111 {0},
112};
113
8629efa4 114#define ME4000_BOARD_VERSIONS (ARRAY_SIZE(me4000_boards) - 1)
e55c95a3
GG
115
116/*-----------------------------------------------------------------------------
117 Comedi function prototypes
118 ---------------------------------------------------------------------------*/
0a85b6f0
MT
119static int me4000_attach(struct comedi_device *dev,
120 struct comedi_devconfig *it);
71b5f4f1 121static int me4000_detach(struct comedi_device *dev);
139dfbdf 122static struct comedi_driver driver_me4000 = {
0a85b6f0
MT
123driver_name:"me4000",
124module:THIS_MODULE,
125attach:me4000_attach,
126detach:me4000_detach,
e55c95a3
GG
127};
128
129/*-----------------------------------------------------------------------------
130 Meilhaus function prototypes
131 ---------------------------------------------------------------------------*/
0707bb04 132static int me4000_probe(struct comedi_device *dev, struct comedi_devconfig *it);
71b5f4f1 133static int get_registers(struct comedi_device *dev, struct pci_dev *pci_dev_p);
0a85b6f0
MT
134static int init_board_info(struct comedi_device *dev,
135 struct pci_dev *pci_dev_p);
71b5f4f1
BP
136static int init_ao_context(struct comedi_device *dev);
137static int init_ai_context(struct comedi_device *dev);
138static int init_dio_context(struct comedi_device *dev);
139static int init_cnt_context(struct comedi_device *dev);
140static int xilinx_download(struct comedi_device *dev);
141static int reset_board(struct comedi_device *dev);
142
143static int me4000_dio_insn_bits(struct comedi_device *dev,
0a85b6f0
MT
144 struct comedi_subdevice *s,
145 struct comedi_insn *insn, unsigned int *data);
e55c95a3 146
71b5f4f1 147static int me4000_dio_insn_config(struct comedi_device *dev,
0a85b6f0
MT
148 struct comedi_subdevice *s,
149 struct comedi_insn *insn, unsigned int *data);
e55c95a3 150
71b5f4f1 151static int cnt_reset(struct comedi_device *dev, unsigned int channel);
e55c95a3 152
71b5f4f1 153static int cnt_config(struct comedi_device *dev,
0a85b6f0 154 unsigned int channel, unsigned int mode);
e55c95a3 155
71b5f4f1 156static int me4000_cnt_insn_config(struct comedi_device *dev,
0a85b6f0
MT
157 struct comedi_subdevice *s,
158 struct comedi_insn *insn, unsigned int *data);
e55c95a3 159
71b5f4f1 160static int me4000_cnt_insn_write(struct comedi_device *dev,
0a85b6f0
MT
161 struct comedi_subdevice *s,
162 struct comedi_insn *insn, unsigned int *data);
e55c95a3 163
71b5f4f1 164static int me4000_cnt_insn_read(struct comedi_device *dev,
0a85b6f0
MT
165 struct comedi_subdevice *s,
166 struct comedi_insn *insn, unsigned int *data);
e55c95a3 167
71b5f4f1 168static int me4000_ai_insn_read(struct comedi_device *dev,
0a85b6f0
MT
169 struct comedi_subdevice *subdevice,
170 struct comedi_insn *insn, unsigned int *data);
e55c95a3 171
0a85b6f0
MT
172static int me4000_ai_cancel(struct comedi_device *dev,
173 struct comedi_subdevice *s);
e55c95a3 174
71b5f4f1 175static int ai_check_chanlist(struct comedi_device *dev,
0a85b6f0
MT
176 struct comedi_subdevice *s,
177 struct comedi_cmd *cmd);
e55c95a3 178
71b5f4f1 179static int ai_round_cmd_args(struct comedi_device *dev,
0a85b6f0
MT
180 struct comedi_subdevice *s,
181 struct comedi_cmd *cmd,
182 unsigned int *init_ticks,
183 unsigned int *scan_ticks,
184 unsigned int *chan_ticks);
e55c95a3 185
71b5f4f1 186static int ai_prepare(struct comedi_device *dev,
0a85b6f0
MT
187 struct comedi_subdevice *s,
188 struct comedi_cmd *cmd,
189 unsigned int init_ticks,
190 unsigned int scan_ticks, unsigned int chan_ticks);
e55c95a3 191
71b5f4f1 192static int ai_write_chanlist(struct comedi_device *dev,
0a85b6f0
MT
193 struct comedi_subdevice *s,
194 struct comedi_cmd *cmd);
e55c95a3 195
70265d24 196static irqreturn_t me4000_ai_isr(int irq, void *dev_id);
e55c95a3 197
71b5f4f1 198static int me4000_ai_do_cmd_test(struct comedi_device *dev,
0a85b6f0
MT
199 struct comedi_subdevice *s,
200 struct comedi_cmd *cmd);
e55c95a3 201
0a85b6f0
MT
202static int me4000_ai_do_cmd(struct comedi_device *dev,
203 struct comedi_subdevice *s);
e55c95a3 204
71b5f4f1 205static int me4000_ao_insn_write(struct comedi_device *dev,
0a85b6f0
MT
206 struct comedi_subdevice *s,
207 struct comedi_insn *insn, unsigned int *data);
e55c95a3 208
71b5f4f1 209static int me4000_ao_insn_read(struct comedi_device *dev,
0a85b6f0
MT
210 struct comedi_subdevice *s,
211 struct comedi_insn *insn, unsigned int *data);
e55c95a3
GG
212
213/*-----------------------------------------------------------------------------
214 Meilhaus inline functions
215 ---------------------------------------------------------------------------*/
216
71b5f4f1 217static inline void me4000_outb(struct comedi_device *dev, unsigned char value,
0a85b6f0 218 unsigned long port)
e55c95a3
GG
219{
220 PORT_PDEBUG("--> 0x%02X port 0x%04lX\n", value, port);
221 outb(value, port);
222}
223
71b5f4f1 224static inline void me4000_outl(struct comedi_device *dev, unsigned long value,
0a85b6f0 225 unsigned long port)
e55c95a3
GG
226{
227 PORT_PDEBUG("--> 0x%08lX port 0x%04lX\n", value, port);
228 outl(value, port);
229}
230
0a85b6f0
MT
231static inline unsigned long me4000_inl(struct comedi_device *dev,
232 unsigned long port)
e55c95a3
GG
233{
234 unsigned long value;
235 value = inl(port);
236 PORT_PDEBUG("<-- 0x%08lX port 0x%04lX\n", value, port);
237 return value;
238}
239
0a85b6f0
MT
240static inline unsigned char me4000_inb(struct comedi_device *dev,
241 unsigned long port)
e55c95a3
GG
242{
243 unsigned char value;
244 value = inb(port);
245 PORT_PDEBUG("<-- 0x%08X port 0x%04lX\n", value, port);
246 return value;
247}
248
9ced1de6 249static const struct comedi_lrange me4000_ai_range = {
e55c95a3
GG
250 4,
251 {
0a85b6f0
MT
252 UNI_RANGE(2.5),
253 UNI_RANGE(10),
254 BIP_RANGE(2.5),
255 BIP_RANGE(10),
256 }
e55c95a3
GG
257};
258
9ced1de6 259static const struct comedi_lrange me4000_ao_range = {
e55c95a3
GG
260 1,
261 {
0a85b6f0
MT
262 BIP_RANGE(10),
263 }
e55c95a3
GG
264};
265
0707bb04 266static int me4000_attach(struct comedi_device *dev, struct comedi_devconfig *it)
e55c95a3 267{
34c43922 268 struct comedi_subdevice *s;
e55c95a3
GG
269 int result;
270
271 CALL_PDEBUG("In me4000_attach()\n");
272
273 result = me4000_probe(dev, it);
274 if (result)
275 return result;
276
277 /*
278 * Allocate the subdevice structures. alloc_subdevice() is a
279 * convenient macro defined in comedidev.h. It relies on
280 * n_subdevices being set correctly.
281 */
282 if (alloc_subdevices(dev, 4) < 0)
283 return -ENOMEM;
284
285 /*=========================================================================
286 Analog input subdevice
287 ========================================================================*/
288
289 s = dev->subdevices + 0;
290
291 if (thisboard->ai.count) {
292 s->type = COMEDI_SUBD_AI;
293 s->subdev_flags =
0a85b6f0 294 SDF_READABLE | SDF_COMMON | SDF_GROUND | SDF_DIFF;
e55c95a3 295 s->n_chan = thisboard->ai.count;
b6c77757 296 s->maxdata = 0xFFFF; /* 16 bit ADC */
e55c95a3
GG
297 s->len_chanlist = ME4000_AI_CHANNEL_LIST_COUNT;
298 s->range_table = &me4000_ai_range;
299 s->insn_read = me4000_ai_insn_read;
300
301 if (info->irq > 0) {
5f74ea14 302 if (request_irq(info->irq, me4000_ai_isr,
e55c95a3 303 IRQF_SHARED, "ME-4000", dev)) {
0a85b6f0
MT
304 printk
305 ("comedi%d: me4000: me4000_attach(): Unable to allocate irq\n",
306 dev->minor);
e55c95a3
GG
307 } else {
308 dev->read_subdev = s;
309 s->subdev_flags |= SDF_CMD_READ;
310 s->cancel = me4000_ai_cancel;
311 s->do_cmdtest = me4000_ai_do_cmd_test;
312 s->do_cmd = me4000_ai_do_cmd;
313 }
314 } else {
315 printk(KERN_WARNING
0a85b6f0
MT
316 "comedi%d: me4000: me4000_attach(): No interrupt available\n",
317 dev->minor);
e55c95a3
GG
318 }
319 } else {
320 s->type = COMEDI_SUBD_UNUSED;
321 }
322
323 /*=========================================================================
324 Analog output subdevice
325 ========================================================================*/
326
327 s = dev->subdevices + 1;
328
329 if (thisboard->ao.count) {
330 s->type = COMEDI_SUBD_AO;
331 s->subdev_flags = SDF_WRITEABLE | SDF_COMMON | SDF_GROUND;
332 s->n_chan = thisboard->ao.count;
b6c77757 333 s->maxdata = 0xFFFF; /* 16 bit DAC */
e55c95a3
GG
334 s->range_table = &me4000_ao_range;
335 s->insn_write = me4000_ao_insn_write;
336 s->insn_read = me4000_ao_insn_read;
337 } else {
338 s->type = COMEDI_SUBD_UNUSED;
339 }
340
341 /*=========================================================================
342 Digital I/O subdevice
343 ========================================================================*/
344
345 s = dev->subdevices + 2;
346
347 if (thisboard->dio.count) {
348 s->type = COMEDI_SUBD_DIO;
349 s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
350 s->n_chan = thisboard->dio.count * 8;
351 s->maxdata = 1;
352 s->range_table = &range_digital;
353 s->insn_bits = me4000_dio_insn_bits;
354 s->insn_config = me4000_dio_insn_config;
355 } else {
356 s->type = COMEDI_SUBD_UNUSED;
357 }
358
359 /*
360 * Check for optoisolated ME-4000 version. If one the first
361 * port is a fixed output port and the second is a fixed input port.
362 */
363 if (!me4000_inl(dev, info->dio_context.dir_reg)) {
364 s->io_bits |= 0xFF;
365 me4000_outl(dev, ME4000_DIO_CTRL_BIT_MODE_0,
0a85b6f0 366 info->dio_context.dir_reg);
e55c95a3
GG
367 }
368
369 /*=========================================================================
370 Counter subdevice
371 ========================================================================*/
372
373 s = dev->subdevices + 3;
374
375 if (thisboard->cnt.count) {
376 s->type = COMEDI_SUBD_COUNTER;
377 s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
378 s->n_chan = thisboard->cnt.count;
b6c77757 379 s->maxdata = 0xFFFF; /* 16 bit counters */
e55c95a3
GG
380 s->insn_read = me4000_cnt_insn_read;
381 s->insn_write = me4000_cnt_insn_write;
382 s->insn_config = me4000_cnt_insn_config;
383 } else {
384 s->type = COMEDI_SUBD_UNUSED;
385 }
386
387 return 0;
388}
389
0707bb04 390static int me4000_probe(struct comedi_device *dev, struct comedi_devconfig *it)
e55c95a3
GG
391{
392 struct pci_dev *pci_device;
393 int result, i;
27f4caaa 394 struct me4000_board *board;
e55c95a3
GG
395
396 CALL_PDEBUG("In me4000_probe()\n");
397
398 /* Allocate private memory */
63aa142a 399 if (alloc_private(dev, sizeof(struct me4000_info)) < 0)
e55c95a3 400 return -ENOMEM;
82675f35 401
e55c95a3
GG
402 /*
403 * Probe the device to determine what device in the series it is.
404 */
405 for (pci_device = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, NULL);
0a85b6f0
MT
406 pci_device != NULL;
407 pci_device = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pci_device)) {
e55c95a3
GG
408 if (pci_device->vendor == PCI_VENDOR_ID_MEILHAUS) {
409 for (i = 0; i < ME4000_BOARD_VERSIONS; i++) {
410 if (me4000_boards[i].device_id ==
0a85b6f0 411 pci_device->device) {
e55c95a3
GG
412 /* Was a particular bus/slot requested? */
413 if ((it->options[0] != 0)
0a85b6f0 414 || (it->options[1] != 0)) {
e55c95a3
GG
415 /* Are we on the wrong bus/slot? */
416 if (pci_device->bus->number !=
0a85b6f0
MT
417 it->options[0]
418 ||
419 PCI_SLOT(pci_device->devfn)
420 != it->options[1]) {
e55c95a3
GG
421 continue;
422 }
423 }
424 dev->board_ptr = me4000_boards + i;
0a85b6f0
MT
425 board =
426 (struct me4000_board *)
427 dev->board_ptr;
e55c95a3
GG
428 info->pci_dev_p = pci_device;
429 goto found;
430 }
431 }
432 }
433 }
434
435 printk(KERN_ERR
0a85b6f0
MT
436 "comedi%d: me4000: me4000_probe(): No supported board found (req. bus/slot : %d/%d)\n",
437 dev->minor, it->options[0], it->options[1]);
e55c95a3
GG
438 return -ENODEV;
439
0a85b6f0 440found:
e55c95a3
GG
441
442 printk(KERN_INFO
0a85b6f0
MT
443 "comedi%d: me4000: me4000_probe(): Found %s at PCI bus %d, slot %d\n",
444 dev->minor, me4000_boards[i].name, pci_device->bus->number,
445 PCI_SLOT(pci_device->devfn));
e55c95a3
GG
446
447 /* Set data in device structure */
448 dev->board_name = board->name;
449
450 /* Enable PCI device and request regions */
451 result = comedi_pci_enable(pci_device, dev->board_name);
452 if (result) {
453 printk(KERN_ERR
0a85b6f0
MT
454 "comedi%d: me4000: me4000_probe(): Cannot enable PCI device and request I/O regions\n",
455 dev->minor);
e55c95a3
GG
456 return result;
457 }
458
459 /* Get the PCI base registers */
460 result = get_registers(dev, pci_device);
461 if (result) {
462 printk(KERN_ERR
0a85b6f0
MT
463 "comedi%d: me4000: me4000_probe(): Cannot get registers\n",
464 dev->minor);
e55c95a3
GG
465 return result;
466 }
467 /* Initialize board info */
468 result = init_board_info(dev, pci_device);
469 if (result) {
470 printk(KERN_ERR
0a85b6f0
MT
471 "comedi%d: me4000: me4000_probe(): Cannot init baord info\n",
472 dev->minor);
e55c95a3
GG
473 return result;
474 }
475
476 /* Init analog output context */
477 result = init_ao_context(dev);
478 if (result) {
479 printk(KERN_ERR
0a85b6f0
MT
480 "comedi%d: me4000: me4000_probe(): Cannot init ao context\n",
481 dev->minor);
e55c95a3
GG
482 return result;
483 }
484
485 /* Init analog input context */
486 result = init_ai_context(dev);
487 if (result) {
488 printk(KERN_ERR
0a85b6f0
MT
489 "comedi%d: me4000: me4000_probe(): Cannot init ai context\n",
490 dev->minor);
e55c95a3
GG
491 return result;
492 }
493
494 /* Init digital I/O context */
495 result = init_dio_context(dev);
496 if (result) {
497 printk(KERN_ERR
0a85b6f0
MT
498 "comedi%d: me4000: me4000_probe(): Cannot init dio context\n",
499 dev->minor);
e55c95a3
GG
500 return result;
501 }
502
503 /* Init counter context */
504 result = init_cnt_context(dev);
505 if (result) {
506 printk(KERN_ERR
0a85b6f0
MT
507 "comedi%d: me4000: me4000_probe(): Cannot init cnt context\n",
508 dev->minor);
e55c95a3
GG
509 return result;
510 }
511
512 /* Download the xilinx firmware */
513 result = xilinx_download(dev);
514 if (result) {
515 printk(KERN_ERR
0a85b6f0
MT
516 "comedi%d: me4000: me4000_probe(): Can't download firmware\n",
517 dev->minor);
e55c95a3
GG
518 return result;
519 }
520
521 /* Make a hardware reset */
522 result = reset_board(dev);
523 if (result) {
524 printk(KERN_ERR
0a85b6f0
MT
525 "comedi%d: me4000: me4000_probe(): Can't reset board\n",
526 dev->minor);
e55c95a3
GG
527 return result;
528 }
529
530 return 0;
531}
532
71b5f4f1 533static int get_registers(struct comedi_device *dev, struct pci_dev *pci_dev_p)
e55c95a3
GG
534{
535
536 CALL_PDEBUG("In get_registers()\n");
537
538 /*--------------------------- plx regbase ---------------------------------*/
539
540 info->plx_regbase = pci_resource_start(pci_dev_p, 1);
541 if (info->plx_regbase == 0) {
542 printk(KERN_ERR
0a85b6f0
MT
543 "comedi%d: me4000: get_registers(): PCI base address 1 is not available\n",
544 dev->minor);
e55c95a3
GG
545 return -ENODEV;
546 }
547 info->plx_regbase_size = pci_resource_len(pci_dev_p, 1);
548
549 /*--------------------------- me4000 regbase ------------------------------*/
550
551 info->me4000_regbase = pci_resource_start(pci_dev_p, 2);
552 if (info->me4000_regbase == 0) {
553 printk(KERN_ERR
0a85b6f0
MT
554 "comedi%d: me4000: get_registers(): PCI base address 2 is not available\n",
555 dev->minor);
e55c95a3
GG
556 return -ENODEV;
557 }
558 info->me4000_regbase_size = pci_resource_len(pci_dev_p, 2);
559
560 /*--------------------------- timer regbase ------------------------------*/
561
562 info->timer_regbase = pci_resource_start(pci_dev_p, 3);
563 if (info->timer_regbase == 0) {
564 printk(KERN_ERR
0a85b6f0
MT
565 "comedi%d: me4000: get_registers(): PCI base address 3 is not available\n",
566 dev->minor);
e55c95a3
GG
567 return -ENODEV;
568 }
569 info->timer_regbase_size = pci_resource_len(pci_dev_p, 3);
570
571 /*--------------------------- program regbase ------------------------------*/
572
573 info->program_regbase = pci_resource_start(pci_dev_p, 5);
574 if (info->program_regbase == 0) {
575 printk(KERN_ERR
0a85b6f0
MT
576 "comedi%d: me4000: get_registers(): PCI base address 5 is not available\n",
577 dev->minor);
e55c95a3
GG
578 return -ENODEV;
579 }
580 info->program_regbase_size = pci_resource_len(pci_dev_p, 5);
581
582 return 0;
583}
584
71b5f4f1 585static int init_board_info(struct comedi_device *dev, struct pci_dev *pci_dev_p)
e55c95a3
GG
586{
587 int result;
588
589 CALL_PDEBUG("In init_board_info()\n");
590
591 /* Init spin locks */
b6c77757
BP
592 /* spin_lock_init(&info->preload_lock); */
593 /* spin_lock_init(&info->ai_ctrl_lock); */
e55c95a3
GG
594
595 /* Get the serial number */
596 result = pci_read_config_dword(pci_dev_p, 0x2C, &info->serial_no);
82675f35 597 if (result != PCIBIOS_SUCCESSFUL)
e55c95a3 598 return result;
e55c95a3
GG
599
600 /* Get the hardware revision */
601 result = pci_read_config_byte(pci_dev_p, 0x08, &info->hw_revision);
82675f35 602 if (result != PCIBIOS_SUCCESSFUL)
e55c95a3 603 return result;
e55c95a3
GG
604
605 /* Get the vendor id */
606 info->vendor_id = pci_dev_p->vendor;
607
608 /* Get the device id */
609 info->device_id = pci_dev_p->device;
610
611 /* Get the irq assigned to the board */
612 info->irq = pci_dev_p->irq;
613
614 return 0;
615}
616
71b5f4f1 617static int init_ao_context(struct comedi_device *dev)
e55c95a3
GG
618{
619 int i;
620
621 CALL_PDEBUG("In init_ao_context()\n");
622
623 for (i = 0; i < thisboard->ao.count; i++) {
b6c77757 624 /* spin_lock_init(&info->ao_context[i].use_lock); */
e55c95a3
GG
625 info->ao_context[i].irq = info->irq;
626
627 switch (i) {
628 case 0:
629 info->ao_context[i].ctrl_reg =
0a85b6f0 630 info->me4000_regbase + ME4000_AO_00_CTRL_REG;
e55c95a3 631 info->ao_context[i].status_reg =
0a85b6f0 632 info->me4000_regbase + ME4000_AO_00_STATUS_REG;
e55c95a3 633 info->ao_context[i].fifo_reg =
0a85b6f0 634 info->me4000_regbase + ME4000_AO_00_FIFO_REG;
e55c95a3 635 info->ao_context[i].single_reg =
0a85b6f0 636 info->me4000_regbase + ME4000_AO_00_SINGLE_REG;
e55c95a3 637 info->ao_context[i].timer_reg =
0a85b6f0 638 info->me4000_regbase + ME4000_AO_00_TIMER_REG;
e55c95a3 639 info->ao_context[i].irq_status_reg =
0a85b6f0 640 info->me4000_regbase + ME4000_IRQ_STATUS_REG;
e55c95a3 641 info->ao_context[i].preload_reg =
0a85b6f0 642 info->me4000_regbase + ME4000_AO_LOADSETREG_XX;
e55c95a3
GG
643 break;
644 case 1:
645 info->ao_context[i].ctrl_reg =
0a85b6f0 646 info->me4000_regbase + ME4000_AO_01_CTRL_REG;
e55c95a3 647 info->ao_context[i].status_reg =
0a85b6f0 648 info->me4000_regbase + ME4000_AO_01_STATUS_REG;
e55c95a3 649 info->ao_context[i].fifo_reg =
0a85b6f0 650 info->me4000_regbase + ME4000_AO_01_FIFO_REG;
e55c95a3 651 info->ao_context[i].single_reg =
0a85b6f0 652 info->me4000_regbase + ME4000_AO_01_SINGLE_REG;
e55c95a3 653 info->ao_context[i].timer_reg =
0a85b6f0 654 info->me4000_regbase + ME4000_AO_01_TIMER_REG;
e55c95a3 655 info->ao_context[i].irq_status_reg =
0a85b6f0 656 info->me4000_regbase + ME4000_IRQ_STATUS_REG;
e55c95a3 657 info->ao_context[i].preload_reg =
0a85b6f0 658 info->me4000_regbase + ME4000_AO_LOADSETREG_XX;
e55c95a3
GG
659 break;
660 case 2:
661 info->ao_context[i].ctrl_reg =
0a85b6f0 662 info->me4000_regbase + ME4000_AO_02_CTRL_REG;
e55c95a3 663 info->ao_context[i].status_reg =
0a85b6f0 664 info->me4000_regbase + ME4000_AO_02_STATUS_REG;
e55c95a3 665 info->ao_context[i].fifo_reg =
0a85b6f0 666 info->me4000_regbase + ME4000_AO_02_FIFO_REG;
e55c95a3 667 info->ao_context[i].single_reg =
0a85b6f0 668 info->me4000_regbase + ME4000_AO_02_SINGLE_REG;
e55c95a3 669 info->ao_context[i].timer_reg =
0a85b6f0 670 info->me4000_regbase + ME4000_AO_02_TIMER_REG;
e55c95a3 671 info->ao_context[i].irq_status_reg =
0a85b6f0 672 info->me4000_regbase + ME4000_IRQ_STATUS_REG;
e55c95a3 673 info->ao_context[i].preload_reg =
0a85b6f0 674 info->me4000_regbase + ME4000_AO_LOADSETREG_XX;
e55c95a3
GG
675 break;
676 case 3:
677 info->ao_context[i].ctrl_reg =
0a85b6f0 678 info->me4000_regbase + ME4000_AO_03_CTRL_REG;
e55c95a3 679 info->ao_context[i].status_reg =
0a85b6f0 680 info->me4000_regbase + ME4000_AO_03_STATUS_REG;
e55c95a3 681 info->ao_context[i].fifo_reg =
0a85b6f0 682 info->me4000_regbase + ME4000_AO_03_FIFO_REG;
e55c95a3 683 info->ao_context[i].single_reg =
0a85b6f0 684 info->me4000_regbase + ME4000_AO_03_SINGLE_REG;
e55c95a3 685 info->ao_context[i].timer_reg =
0a85b6f0 686 info->me4000_regbase + ME4000_AO_03_TIMER_REG;
e55c95a3 687 info->ao_context[i].irq_status_reg =
0a85b6f0 688 info->me4000_regbase + ME4000_IRQ_STATUS_REG;
e55c95a3 689 info->ao_context[i].preload_reg =
0a85b6f0 690 info->me4000_regbase + ME4000_AO_LOADSETREG_XX;
e55c95a3
GG
691 break;
692 default:
693 break;
694 }
695 }
696
697 return 0;
698}
699
71b5f4f1 700static int init_ai_context(struct comedi_device *dev)
e55c95a3
GG
701{
702
703 CALL_PDEBUG("In init_ai_context()\n");
704
705 info->ai_context.irq = info->irq;
706
707 info->ai_context.ctrl_reg = info->me4000_regbase + ME4000_AI_CTRL_REG;
708 info->ai_context.status_reg =
0a85b6f0 709 info->me4000_regbase + ME4000_AI_STATUS_REG;
e55c95a3 710 info->ai_context.channel_list_reg =
0a85b6f0 711 info->me4000_regbase + ME4000_AI_CHANNEL_LIST_REG;
e55c95a3
GG
712 info->ai_context.data_reg = info->me4000_regbase + ME4000_AI_DATA_REG;
713 info->ai_context.chan_timer_reg =
0a85b6f0 714 info->me4000_regbase + ME4000_AI_CHAN_TIMER_REG;
e55c95a3 715 info->ai_context.chan_pre_timer_reg =
0a85b6f0 716 info->me4000_regbase + ME4000_AI_CHAN_PRE_TIMER_REG;
e55c95a3 717 info->ai_context.scan_timer_low_reg =
0a85b6f0 718 info->me4000_regbase + ME4000_AI_SCAN_TIMER_LOW_REG;
e55c95a3 719 info->ai_context.scan_timer_high_reg =
0a85b6f0 720 info->me4000_regbase + ME4000_AI_SCAN_TIMER_HIGH_REG;
e55c95a3 721 info->ai_context.scan_pre_timer_low_reg =
0a85b6f0 722 info->me4000_regbase + ME4000_AI_SCAN_PRE_TIMER_LOW_REG;
e55c95a3 723 info->ai_context.scan_pre_timer_high_reg =
0a85b6f0 724 info->me4000_regbase + ME4000_AI_SCAN_PRE_TIMER_HIGH_REG;
e55c95a3
GG
725 info->ai_context.start_reg = info->me4000_regbase + ME4000_AI_START_REG;
726 info->ai_context.irq_status_reg =
0a85b6f0 727 info->me4000_regbase + ME4000_IRQ_STATUS_REG;
e55c95a3 728 info->ai_context.sample_counter_reg =
0a85b6f0 729 info->me4000_regbase + ME4000_AI_SAMPLE_COUNTER_REG;
e55c95a3
GG
730
731 return 0;
732}
733
71b5f4f1 734static int init_dio_context(struct comedi_device *dev)
e55c95a3
GG
735{
736
737 CALL_PDEBUG("In init_dio_context()\n");
738
739 info->dio_context.dir_reg = info->me4000_regbase + ME4000_DIO_DIR_REG;
740 info->dio_context.ctrl_reg = info->me4000_regbase + ME4000_DIO_CTRL_REG;
741 info->dio_context.port_0_reg =
0a85b6f0 742 info->me4000_regbase + ME4000_DIO_PORT_0_REG;
e55c95a3 743 info->dio_context.port_1_reg =
0a85b6f0 744 info->me4000_regbase + ME4000_DIO_PORT_1_REG;
e55c95a3 745 info->dio_context.port_2_reg =
0a85b6f0 746 info->me4000_regbase + ME4000_DIO_PORT_2_REG;
e55c95a3 747 info->dio_context.port_3_reg =
0a85b6f0 748 info->me4000_regbase + ME4000_DIO_PORT_3_REG;
e55c95a3
GG
749
750 return 0;
751}
752
71b5f4f1 753static int init_cnt_context(struct comedi_device *dev)
e55c95a3
GG
754{
755
756 CALL_PDEBUG("In init_cnt_context()\n");
757
758 info->cnt_context.ctrl_reg = info->timer_regbase + ME4000_CNT_CTRL_REG;
759 info->cnt_context.counter_0_reg =
0a85b6f0 760 info->timer_regbase + ME4000_CNT_COUNTER_0_REG;
e55c95a3 761 info->cnt_context.counter_1_reg =
0a85b6f0 762 info->timer_regbase + ME4000_CNT_COUNTER_1_REG;
e55c95a3 763 info->cnt_context.counter_2_reg =
0a85b6f0 764 info->timer_regbase + ME4000_CNT_COUNTER_2_REG;
e55c95a3
GG
765
766 return 0;
767}
768
769#define FIRMWARE_NOT_AVAILABLE 1
770#if FIRMWARE_NOT_AVAILABLE
771extern unsigned char *xilinx_firm;
772#endif
773
71b5f4f1 774static int xilinx_download(struct comedi_device *dev)
e55c95a3
GG
775{
776 u32 value = 0;
777 wait_queue_head_t queue;
778 int idx = 0;
779 int size = 0;
780
781 CALL_PDEBUG("In xilinx_download()\n");
782
783 init_waitqueue_head(&queue);
784
785 /*
786 * Set PLX local interrupt 2 polarity to high.
787 * Interrupt is thrown by init pin of xilinx.
788 */
789 outl(0x10, info->plx_regbase + PLX_INTCSR);
790
791 /* Set /CS and /WRITE of the Xilinx */
792 value = inl(info->plx_regbase + PLX_ICR);
793 value |= 0x100;
794 outl(value, info->plx_regbase + PLX_ICR);
795
796 /* Init Xilinx with CS1 */
797 inb(info->program_regbase + 0xC8);
798
799 /* Wait until /INIT pin is set */
800 udelay(20);
d86d3a01 801 if (!(inl(info->plx_regbase + PLX_INTCSR) & 0x20)) {
e55c95a3 802 printk(KERN_ERR
0a85b6f0
MT
803 "comedi%d: me4000: xilinx_download(): Can't init Xilinx\n",
804 dev->minor);
e55c95a3
GG
805 return -EIO;
806 }
807
808 /* Reset /CS and /WRITE of the Xilinx */
809 value = inl(info->plx_regbase + PLX_ICR);
810 value &= ~0x100;
811 outl(value, info->plx_regbase + PLX_ICR);
812 if (FIRMWARE_NOT_AVAILABLE) {
813 comedi_error(dev,
0a85b6f0 814 "xilinx firmware unavailable due to licensing, aborting");
e55c95a3
GG
815 return -EIO;
816 } else {
817 /* Download Xilinx firmware */
818 size = (xilinx_firm[0] << 24) + (xilinx_firm[1] << 16) +
0a85b6f0 819 (xilinx_firm[2] << 8) + xilinx_firm[3];
e55c95a3
GG
820 udelay(10);
821
822 for (idx = 0; idx < size; idx++) {
823 outb(xilinx_firm[16 + idx], info->program_regbase);
824 udelay(10);
825
826 /* Check if BUSY flag is low */
827 if (inl(info->plx_regbase + PLX_ICR) & 0x20) {
828 printk(KERN_ERR
0a85b6f0
MT
829 "comedi%d: me4000: xilinx_download(): Xilinx is still busy (idx = %d)\n",
830 dev->minor, idx);
e55c95a3
GG
831 return -EIO;
832 }
833 }
834 }
835
836 /* If done flag is high download was successful */
837 if (inl(info->plx_regbase + PLX_ICR) & 0x4) {
838 } else {
839 printk(KERN_ERR
0a85b6f0
MT
840 "comedi%d: me4000: xilinx_download(): DONE flag is not set\n",
841 dev->minor);
e55c95a3 842 printk(KERN_ERR
bbc9a991 843 "comedi%d: me4000: xilinx_download(): Download not successful\n",
0a85b6f0 844 dev->minor);
e55c95a3
GG
845 return -EIO;
846 }
847
848 /* Set /CS and /WRITE */
849 value = inl(info->plx_regbase + PLX_ICR);
850 value |= 0x100;
851 outl(value, info->plx_regbase + PLX_ICR);
852
853 return 0;
854}
855
71b5f4f1 856static int reset_board(struct comedi_device *dev)
e55c95a3
GG
857{
858 unsigned long icr;
859
860 CALL_PDEBUG("In reset_board()\n");
861
862 /* Make a hardware reset */
863 icr = me4000_inl(dev, info->plx_regbase + PLX_ICR);
864 icr |= 0x40000000;
865 me4000_outl(dev, icr, info->plx_regbase + PLX_ICR);
866 icr &= ~0x40000000;
867 me4000_outl(dev, icr, info->plx_regbase + PLX_ICR);
868
869 /* 0x8000 to the DACs means an output voltage of 0V */
870 me4000_outl(dev, 0x8000,
0a85b6f0 871 info->me4000_regbase + ME4000_AO_00_SINGLE_REG);
e55c95a3 872 me4000_outl(dev, 0x8000,
0a85b6f0 873 info->me4000_regbase + ME4000_AO_01_SINGLE_REG);
e55c95a3 874 me4000_outl(dev, 0x8000,
0a85b6f0 875 info->me4000_regbase + ME4000_AO_02_SINGLE_REG);
e55c95a3 876 me4000_outl(dev, 0x8000,
0a85b6f0 877 info->me4000_regbase + ME4000_AO_03_SINGLE_REG);
e55c95a3
GG
878
879 /* Set both stop bits in the analog input control register */
880 me4000_outl(dev,
0a85b6f0
MT
881 ME4000_AI_CTRL_BIT_IMMEDIATE_STOP | ME4000_AI_CTRL_BIT_STOP,
882 info->me4000_regbase + ME4000_AI_CTRL_REG);
e55c95a3
GG
883
884 /* Set both stop bits in the analog output control register */
885 me4000_outl(dev,
0a85b6f0
MT
886 ME4000_AO_CTRL_BIT_IMMEDIATE_STOP | ME4000_AO_CTRL_BIT_STOP,
887 info->me4000_regbase + ME4000_AO_00_CTRL_REG);
e55c95a3 888 me4000_outl(dev,
0a85b6f0
MT
889 ME4000_AO_CTRL_BIT_IMMEDIATE_STOP | ME4000_AO_CTRL_BIT_STOP,
890 info->me4000_regbase + ME4000_AO_01_CTRL_REG);
e55c95a3 891 me4000_outl(dev,
0a85b6f0
MT
892 ME4000_AO_CTRL_BIT_IMMEDIATE_STOP | ME4000_AO_CTRL_BIT_STOP,
893 info->me4000_regbase + ME4000_AO_02_CTRL_REG);
e55c95a3 894 me4000_outl(dev,
0a85b6f0
MT
895 ME4000_AO_CTRL_BIT_IMMEDIATE_STOP | ME4000_AO_CTRL_BIT_STOP,
896 info->me4000_regbase + ME4000_AO_03_CTRL_REG);
e55c95a3
GG
897
898 /* Enable interrupts on the PLX */
899 me4000_outl(dev, 0x43, info->plx_regbase + PLX_INTCSR);
900
901 /* Set the adustment register for AO demux */
902 me4000_outl(dev, ME4000_AO_DEMUX_ADJUST_VALUE,
0a85b6f0 903 info->me4000_regbase + ME4000_AO_DEMUX_ADJUST_REG);
e55c95a3
GG
904
905 /* Set digital I/O direction for port 0 to output on isolated versions */
906 if (!(me4000_inl(dev, info->me4000_regbase + ME4000_DIO_DIR_REG) & 0x1)) {
907 me4000_outl(dev, 0x1,
0a85b6f0 908 info->me4000_regbase + ME4000_DIO_CTRL_REG);
e55c95a3
GG
909 }
910
911 return 0;
912}
913
71b5f4f1 914static int me4000_detach(struct comedi_device *dev)
e55c95a3
GG
915{
916 CALL_PDEBUG("In me4000_detach()\n");
917
918 if (info) {
919 if (info->pci_dev_p) {
920 reset_board(dev);
82675f35 921 if (info->plx_regbase)
e55c95a3 922 comedi_pci_disable(info->pci_dev_p);
e55c95a3
GG
923 pci_dev_put(info->pci_dev_p);
924 }
925 }
926
927 return 0;
928}
929
930/*=============================================================================
931 Analog input section
932 ===========================================================================*/
933
71b5f4f1 934static int me4000_ai_insn_read(struct comedi_device *dev,
0a85b6f0
MT
935 struct comedi_subdevice *subdevice,
936 struct comedi_insn *insn, unsigned int *data)
e55c95a3
GG
937{
938
939 int chan = CR_CHAN(insn->chanspec);
940 int rang = CR_RANGE(insn->chanspec);
941 int aref = CR_AREF(insn->chanspec);
942
943 unsigned long entry = 0;
944 unsigned long tmp;
945 long lval;
946
947 CALL_PDEBUG("In me4000_ai_insn_read()\n");
948
949 if (insn->n == 0) {
950 return 0;
951 } else if (insn->n > 1) {
952 printk(KERN_ERR
0a85b6f0
MT
953 "comedi%d: me4000: me4000_ai_insn_read(): Invalid instruction length %d\n",
954 dev->minor, insn->n);
e55c95a3
GG
955 return -EINVAL;
956 }
957
958 switch (rang) {
959 case 0:
960 entry |= ME4000_AI_LIST_RANGE_UNIPOLAR_2_5;
961 break;
962 case 1:
963 entry |= ME4000_AI_LIST_RANGE_UNIPOLAR_10;
964 break;
965 case 2:
966 entry |= ME4000_AI_LIST_RANGE_BIPOLAR_2_5;
967 break;
968 case 3:
969 entry |= ME4000_AI_LIST_RANGE_BIPOLAR_10;
970 break;
971 default:
972 printk(KERN_ERR
0a85b6f0
MT
973 "comedi%d: me4000: me4000_ai_insn_read(): Invalid range specified\n",
974 dev->minor);
e55c95a3
GG
975 return -EINVAL;
976 }
977
978 switch (aref) {
979 case AREF_GROUND:
980 case AREF_COMMON:
981 if (chan >= thisboard->ai.count) {
982 printk(KERN_ERR
0a85b6f0
MT
983 "comedi%d: me4000: me4000_ai_insn_read(): Analog input is not available\n",
984 dev->minor);
e55c95a3
GG
985 return -EINVAL;
986 }
987 entry |= ME4000_AI_LIST_INPUT_SINGLE_ENDED | chan;
988 break;
989
990 case AREF_DIFF:
991 if (rang == 0 || rang == 1) {
992 printk(KERN_ERR
0a85b6f0
MT
993 "comedi%d: me4000: me4000_ai_insn_read(): Range must be bipolar when aref = diff\n",
994 dev->minor);
e55c95a3
GG
995 return -EINVAL;
996 }
997
998 if (chan >= thisboard->ai.diff_count) {
999 printk(KERN_ERR
0a85b6f0
MT
1000 "comedi%d: me4000: me4000_ai_insn_read(): Analog input is not available\n",
1001 dev->minor);
e55c95a3
GG
1002 return -EINVAL;
1003 }
1004 entry |= ME4000_AI_LIST_INPUT_DIFFERENTIAL | chan;
1005 break;
1006 default:
1007 printk(KERN_ERR
0a85b6f0
MT
1008 "comedi%d: me4000: me4000_ai_insn_read(): Invalid aref specified\n",
1009 dev->minor);
e55c95a3
GG
1010 return -EINVAL;
1011 }
1012
1013 entry |= ME4000_AI_LIST_LAST_ENTRY;
1014
1015 /* Clear channel list, data fifo and both stop bits */
1016 tmp = me4000_inl(dev, info->ai_context.ctrl_reg);
1017 tmp &= ~(ME4000_AI_CTRL_BIT_CHANNEL_FIFO |
0a85b6f0
MT
1018 ME4000_AI_CTRL_BIT_DATA_FIFO |
1019 ME4000_AI_CTRL_BIT_STOP | ME4000_AI_CTRL_BIT_IMMEDIATE_STOP);
e55c95a3
GG
1020 me4000_outl(dev, tmp, info->ai_context.ctrl_reg);
1021
1022 /* Set the acquisition mode to single */
1023 tmp &= ~(ME4000_AI_CTRL_BIT_MODE_0 | ME4000_AI_CTRL_BIT_MODE_1 |
0a85b6f0 1024 ME4000_AI_CTRL_BIT_MODE_2);
e55c95a3
GG
1025 me4000_outl(dev, tmp, info->ai_context.ctrl_reg);
1026
1027 /* Enable channel list and data fifo */
1028 tmp |= ME4000_AI_CTRL_BIT_CHANNEL_FIFO | ME4000_AI_CTRL_BIT_DATA_FIFO;
1029 me4000_outl(dev, tmp, info->ai_context.ctrl_reg);
1030
1031 /* Generate channel list entry */
1032 me4000_outl(dev, entry, info->ai_context.channel_list_reg);
1033
1034 /* Set the timer to maximum sample rate */
1035 me4000_outl(dev, ME4000_AI_MIN_TICKS, info->ai_context.chan_timer_reg);
1036 me4000_outl(dev, ME4000_AI_MIN_TICKS,
0a85b6f0 1037 info->ai_context.chan_pre_timer_reg);
e55c95a3
GG
1038
1039 /* Start conversion by dummy read */
1040 me4000_inl(dev, info->ai_context.start_reg);
1041
1042 /* Wait until ready */
1043 udelay(10);
0a85b6f0
MT
1044 if (!
1045 (me4000_inl(dev, info->ai_context.status_reg) &
1046 ME4000_AI_STATUS_BIT_EF_DATA)) {
e55c95a3 1047 printk(KERN_ERR
0a85b6f0
MT
1048 "comedi%d: me4000: me4000_ai_insn_read(): Value not available after wait\n",
1049 dev->minor);
e55c95a3
GG
1050 return -EIO;
1051 }
1052
1053 /* Read value from data fifo */
1054 lval = me4000_inl(dev, info->ai_context.data_reg) & 0xFFFF;
1055 data[0] = lval ^ 0x8000;
1056
1057 return 1;
1058}
1059
0a85b6f0
MT
1060static int me4000_ai_cancel(struct comedi_device *dev,
1061 struct comedi_subdevice *s)
e55c95a3
GG
1062{
1063 unsigned long tmp;
1064
1065 CALL_PDEBUG("In me4000_ai_cancel()\n");
1066
1067 /* Stop any running conversion */
1068 tmp = me4000_inl(dev, info->ai_context.ctrl_reg);
1069 tmp &= ~(ME4000_AI_CTRL_BIT_STOP | ME4000_AI_CTRL_BIT_IMMEDIATE_STOP);
1070 me4000_outl(dev, tmp, info->ai_context.ctrl_reg);
1071
1072 /* Clear the control register */
1073 me4000_outl(dev, 0x0, info->ai_context.ctrl_reg);
1074
1075 return 0;
1076}
1077
71b5f4f1 1078static int ai_check_chanlist(struct comedi_device *dev,
0a85b6f0 1079 struct comedi_subdevice *s, struct comedi_cmd *cmd)
e55c95a3
GG
1080{
1081 int aref;
1082 int i;
1083
1084 CALL_PDEBUG("In ai_check_chanlist()\n");
1085
1086 /* Check whether a channel list is available */
1087 if (!cmd->chanlist_len) {
1088 printk(KERN_ERR
0a85b6f0
MT
1089 "comedi%d: me4000: ai_check_chanlist(): No channel list available\n",
1090 dev->minor);
e55c95a3
GG
1091 return -EINVAL;
1092 }
1093
1094 /* Check the channel list size */
1095 if (cmd->chanlist_len > ME4000_AI_CHANNEL_LIST_COUNT) {
1096 printk(KERN_ERR
0a85b6f0
MT
1097 "comedi%d: me4000: ai_check_chanlist(): Channel list is to large\n",
1098 dev->minor);
e55c95a3
GG
1099 return -EINVAL;
1100 }
1101
1102 /* Check the pointer */
1103 if (!cmd->chanlist) {
1104 printk(KERN_ERR
0a85b6f0
MT
1105 "comedi%d: me4000: ai_check_chanlist(): NULL pointer to channel list\n",
1106 dev->minor);
e55c95a3
GG
1107 return -EFAULT;
1108 }
1109
1110 /* Check whether aref is equal for all entries */
1111 aref = CR_AREF(cmd->chanlist[0]);
1112 for (i = 0; i < cmd->chanlist_len; i++) {
1113 if (CR_AREF(cmd->chanlist[i]) != aref) {
1114 printk(KERN_ERR
0a85b6f0
MT
1115 "comedi%d: me4000: ai_check_chanlist(): Mode is not equal for all entries\n",
1116 dev->minor);
e55c95a3
GG
1117 return -EINVAL;
1118 }
1119 }
1120
1121 /* Check whether channels are available for this ending */
1122 if (aref == SDF_DIFF) {
1123 for (i = 0; i < cmd->chanlist_len; i++) {
1124 if (CR_CHAN(cmd->chanlist[i]) >=
0a85b6f0 1125 thisboard->ai.diff_count) {
e55c95a3 1126 printk(KERN_ERR
0a85b6f0
MT
1127 "comedi%d: me4000: ai_check_chanlist(): Channel number to high\n",
1128 dev->minor);
e55c95a3
GG
1129 return -EINVAL;
1130 }
1131 }
1132 } else {
1133 for (i = 0; i < cmd->chanlist_len; i++) {
1134 if (CR_CHAN(cmd->chanlist[i]) >= thisboard->ai.count) {
1135 printk(KERN_ERR
0a85b6f0
MT
1136 "comedi%d: me4000: ai_check_chanlist(): Channel number to high\n",
1137 dev->minor);
e55c95a3
GG
1138 return -EINVAL;
1139 }
1140 }
1141 }
1142
1143 /* Check if bipolar is set for all entries when in differential mode */
1144 if (aref == SDF_DIFF) {
1145 for (i = 0; i < cmd->chanlist_len; i++) {
1146 if (CR_RANGE(cmd->chanlist[i]) != 1 &&
0a85b6f0 1147 CR_RANGE(cmd->chanlist[i]) != 2) {
e55c95a3 1148 printk(KERN_ERR
0a85b6f0
MT
1149 "comedi%d: me4000: ai_check_chanlist(): Bipolar is not selected in differential mode\n",
1150 dev->minor);
e55c95a3
GG
1151 return -EINVAL;
1152 }
1153 }
1154 }
1155
1156 return 0;
1157}
1158
71b5f4f1 1159static int ai_round_cmd_args(struct comedi_device *dev,
0a85b6f0
MT
1160 struct comedi_subdevice *s,
1161 struct comedi_cmd *cmd,
1162 unsigned int *init_ticks,
1163 unsigned int *scan_ticks, unsigned int *chan_ticks)
e55c95a3
GG
1164{
1165
1166 int rest;
1167
1168 CALL_PDEBUG("In ai_round_cmd_args()\n");
1169
1170 *init_ticks = 0;
1171 *scan_ticks = 0;
1172 *chan_ticks = 0;
1173
1174 PDEBUG("ai_round_cmd_arg(): start_arg = %d\n", cmd->start_arg);
1175 PDEBUG("ai_round_cmd_arg(): scan_begin_arg = %d\n",
0a85b6f0 1176 cmd->scan_begin_arg);
e55c95a3
GG
1177 PDEBUG("ai_round_cmd_arg(): convert_arg = %d\n", cmd->convert_arg);
1178
1179 if (cmd->start_arg) {
1180 *init_ticks = (cmd->start_arg * 33) / 1000;
1181 rest = (cmd->start_arg * 33) % 1000;
1182
1183 if (cmd->flags & TRIG_ROUND_NEAREST) {
82675f35 1184 if (rest > 33)
e55c95a3 1185 (*init_ticks)++;
e55c95a3
GG
1186 } else if (cmd->flags & TRIG_ROUND_UP) {
1187 if (rest)
1188 (*init_ticks)++;
1189 }
1190 }
1191
1192 if (cmd->scan_begin_arg) {
1193 *scan_ticks = (cmd->scan_begin_arg * 33) / 1000;
1194 rest = (cmd->scan_begin_arg * 33) % 1000;
1195
1196 if (cmd->flags & TRIG_ROUND_NEAREST) {
82675f35 1197 if (rest > 33)
e55c95a3 1198 (*scan_ticks)++;
e55c95a3
GG
1199 } else if (cmd->flags & TRIG_ROUND_UP) {
1200 if (rest)
1201 (*scan_ticks)++;
1202 }
1203 }
1204
1205 if (cmd->convert_arg) {
1206 *chan_ticks = (cmd->convert_arg * 33) / 1000;
1207 rest = (cmd->convert_arg * 33) % 1000;
1208
1209 if (cmd->flags & TRIG_ROUND_NEAREST) {
82675f35 1210 if (rest > 33)
e55c95a3 1211 (*chan_ticks)++;
e55c95a3
GG
1212 } else if (cmd->flags & TRIG_ROUND_UP) {
1213 if (rest)
1214 (*chan_ticks)++;
1215 }
1216 }
1217
1218 PDEBUG("ai_round_cmd_args(): init_ticks = %d\n", *init_ticks);
1219 PDEBUG("ai_round_cmd_args(): scan_ticks = %d\n", *scan_ticks);
1220 PDEBUG("ai_round_cmd_args(): chan_ticks = %d\n", *chan_ticks);
1221
1222 return 0;
1223}
1224
71b5f4f1 1225static void ai_write_timer(struct comedi_device *dev,
0a85b6f0
MT
1226 unsigned int init_ticks,
1227 unsigned int scan_ticks, unsigned int chan_ticks)
e55c95a3
GG
1228{
1229
1230 CALL_PDEBUG("In ai_write_timer()\n");
1231
1232 me4000_outl(dev, init_ticks - 1,
0a85b6f0 1233 info->ai_context.scan_pre_timer_low_reg);
e55c95a3
GG
1234 me4000_outl(dev, 0x0, info->ai_context.scan_pre_timer_high_reg);
1235
1236 if (scan_ticks) {
1237 me4000_outl(dev, scan_ticks - 1,
0a85b6f0 1238 info->ai_context.scan_timer_low_reg);
e55c95a3
GG
1239 me4000_outl(dev, 0x0, info->ai_context.scan_timer_high_reg);
1240 }
1241
1242 me4000_outl(dev, chan_ticks - 1, info->ai_context.chan_pre_timer_reg);
1243 me4000_outl(dev, chan_ticks - 1, info->ai_context.chan_timer_reg);
1244}
1245
71b5f4f1 1246static int ai_prepare(struct comedi_device *dev,
0a85b6f0
MT
1247 struct comedi_subdevice *s,
1248 struct comedi_cmd *cmd,
1249 unsigned int init_ticks,
1250 unsigned int scan_ticks, unsigned int chan_ticks)
e55c95a3
GG
1251{
1252
1253 unsigned long tmp = 0;
1254
1255 CALL_PDEBUG("In ai_prepare()\n");
1256
1257 /* Write timer arguments */
1258 ai_write_timer(dev, init_ticks, scan_ticks, chan_ticks);
1259
1260 /* Reset control register */
1261 me4000_outl(dev, tmp, info->ai_context.ctrl_reg);
1262
1263 /* Start sources */
1264 if ((cmd->start_src == TRIG_EXT &&
0a85b6f0
MT
1265 cmd->scan_begin_src == TRIG_TIMER &&
1266 cmd->convert_src == TRIG_TIMER) ||
1267 (cmd->start_src == TRIG_EXT &&
1268 cmd->scan_begin_src == TRIG_FOLLOW &&
1269 cmd->convert_src == TRIG_TIMER)) {
e55c95a3 1270 tmp = ME4000_AI_CTRL_BIT_MODE_1 |
0a85b6f0
MT
1271 ME4000_AI_CTRL_BIT_CHANNEL_FIFO |
1272 ME4000_AI_CTRL_BIT_DATA_FIFO;
e55c95a3 1273 } else if (cmd->start_src == TRIG_EXT &&
0a85b6f0
MT
1274 cmd->scan_begin_src == TRIG_EXT &&
1275 cmd->convert_src == TRIG_TIMER) {
e55c95a3 1276 tmp = ME4000_AI_CTRL_BIT_MODE_2 |
0a85b6f0
MT
1277 ME4000_AI_CTRL_BIT_CHANNEL_FIFO |
1278 ME4000_AI_CTRL_BIT_DATA_FIFO;
e55c95a3 1279 } else if (cmd->start_src == TRIG_EXT &&
0a85b6f0
MT
1280 cmd->scan_begin_src == TRIG_EXT &&
1281 cmd->convert_src == TRIG_EXT) {
e55c95a3 1282 tmp = ME4000_AI_CTRL_BIT_MODE_0 |
0a85b6f0
MT
1283 ME4000_AI_CTRL_BIT_MODE_1 |
1284 ME4000_AI_CTRL_BIT_CHANNEL_FIFO |
1285 ME4000_AI_CTRL_BIT_DATA_FIFO;
e55c95a3
GG
1286 } else {
1287 tmp = ME4000_AI_CTRL_BIT_MODE_0 |
0a85b6f0
MT
1288 ME4000_AI_CTRL_BIT_CHANNEL_FIFO |
1289 ME4000_AI_CTRL_BIT_DATA_FIFO;
e55c95a3
GG
1290 }
1291
1292 /* Stop triggers */
1293 if (cmd->stop_src == TRIG_COUNT) {
1294 me4000_outl(dev, cmd->chanlist_len * cmd->stop_arg,
0a85b6f0 1295 info->ai_context.sample_counter_reg);
e55c95a3
GG
1296 tmp |= ME4000_AI_CTRL_BIT_HF_IRQ | ME4000_AI_CTRL_BIT_SC_IRQ;
1297 } else if (cmd->stop_src == TRIG_NONE &&
0a85b6f0 1298 cmd->scan_end_src == TRIG_COUNT) {
e55c95a3 1299 me4000_outl(dev, cmd->scan_end_arg,
0a85b6f0 1300 info->ai_context.sample_counter_reg);
e55c95a3
GG
1301 tmp |= ME4000_AI_CTRL_BIT_HF_IRQ | ME4000_AI_CTRL_BIT_SC_IRQ;
1302 } else {
1303 tmp |= ME4000_AI_CTRL_BIT_HF_IRQ;
1304 }
1305
1306 /* Write the setup to the control register */
1307 me4000_outl(dev, tmp, info->ai_context.ctrl_reg);
1308
1309 /* Write the channel list */
1310 ai_write_chanlist(dev, s, cmd);
1311
1312 return 0;
1313}
1314
71b5f4f1 1315static int ai_write_chanlist(struct comedi_device *dev,
0a85b6f0 1316 struct comedi_subdevice *s, struct comedi_cmd *cmd)
e55c95a3
GG
1317{
1318 unsigned int entry;
1319 unsigned int chan;
1320 unsigned int rang;
1321 unsigned int aref;
1322 int i;
1323
1324 CALL_PDEBUG("In ai_write_chanlist()\n");
1325
1326 for (i = 0; i < cmd->chanlist_len; i++) {
1327 chan = CR_CHAN(cmd->chanlist[i]);
1328 rang = CR_RANGE(cmd->chanlist[i]);
1329 aref = CR_AREF(cmd->chanlist[i]);
1330
1331 entry = chan;
1332
1333 if (rang == 0) {
1334 entry |= ME4000_AI_LIST_RANGE_UNIPOLAR_2_5;
1335 } else if (rang == 1) {
1336 entry |= ME4000_AI_LIST_RANGE_UNIPOLAR_10;
1337 } else if (rang == 2) {
1338 entry |= ME4000_AI_LIST_RANGE_BIPOLAR_2_5;
1339 } else {
1340 entry |= ME4000_AI_LIST_RANGE_BIPOLAR_10;
1341 }
1342
1343 if (aref == SDF_DIFF) {
1344 entry |= ME4000_AI_LIST_INPUT_DIFFERENTIAL;
1345 } else {
1346 entry |= ME4000_AI_LIST_INPUT_SINGLE_ENDED;
1347 }
1348
1349 me4000_outl(dev, entry, info->ai_context.channel_list_reg);
1350 }
1351
1352 return 0;
1353}
1354
0a85b6f0
MT
1355static int me4000_ai_do_cmd(struct comedi_device *dev,
1356 struct comedi_subdevice *s)
e55c95a3
GG
1357{
1358 int err;
1359 unsigned int init_ticks = 0;
1360 unsigned int scan_ticks = 0;
1361 unsigned int chan_ticks = 0;
ea6d0d4c 1362 struct comedi_cmd *cmd = &s->async->cmd;
e55c95a3
GG
1363
1364 CALL_PDEBUG("In me4000_ai_do_cmd()\n");
1365
1366 /* Reset the analog input */
1367 err = me4000_ai_cancel(dev, s);
1368 if (err)
1369 return err;
1370
1371 /* Round the timer arguments */
1372 err = ai_round_cmd_args(dev,
0a85b6f0 1373 s, cmd, &init_ticks, &scan_ticks, &chan_ticks);
e55c95a3
GG
1374 if (err)
1375 return err;
1376
1377 /* Prepare the AI for acquisition */
1378 err = ai_prepare(dev, s, cmd, init_ticks, scan_ticks, chan_ticks);
1379 if (err)
1380 return err;
1381
1382 /* Start acquistion by dummy read */
1383 me4000_inl(dev, info->ai_context.start_reg);
1384
1385 return 0;
1386}
1387
1388/*
1389 * me4000_ai_do_cmd_test():
1390 *
1391 * The demo cmd.c in ./comedilib/demo specifies 6 return values:
1392 * - success
1393 * - invalid source
1394 * - source conflict
1395 * - invalid argument
1396 * - argument conflict
1397 * - invalid chanlist
1398 * So I tried to adopt this scheme.
1399 */
71b5f4f1 1400static int me4000_ai_do_cmd_test(struct comedi_device *dev,
0a85b6f0
MT
1401 struct comedi_subdevice *s,
1402 struct comedi_cmd *cmd)
e55c95a3
GG
1403{
1404
1405 unsigned int init_ticks;
1406 unsigned int chan_ticks;
1407 unsigned int scan_ticks;
1408 int err = 0;
1409
1410 CALL_PDEBUG("In me4000_ai_do_cmd_test()\n");
1411
1412 PDEBUG("me4000_ai_do_cmd_test(): subdev = %d\n", cmd->subdev);
1413 PDEBUG("me4000_ai_do_cmd_test(): flags = %08X\n", cmd->flags);
1414 PDEBUG("me4000_ai_do_cmd_test(): start_src = %08X\n",
0a85b6f0 1415 cmd->start_src);
e55c95a3 1416 PDEBUG("me4000_ai_do_cmd_test(): start_arg = %d\n",
0a85b6f0 1417 cmd->start_arg);
e55c95a3 1418 PDEBUG("me4000_ai_do_cmd_test(): scan_begin_src = %08X\n",
0a85b6f0 1419 cmd->scan_begin_src);
e55c95a3 1420 PDEBUG("me4000_ai_do_cmd_test(): scan_begin_arg = %d\n",
0a85b6f0 1421 cmd->scan_begin_arg);
e55c95a3 1422 PDEBUG("me4000_ai_do_cmd_test(): convert_src = %08X\n",
0a85b6f0 1423 cmd->convert_src);
e55c95a3 1424 PDEBUG("me4000_ai_do_cmd_test(): convert_arg = %d\n",
0a85b6f0 1425 cmd->convert_arg);
e55c95a3 1426 PDEBUG("me4000_ai_do_cmd_test(): scan_end_src = %08X\n",
0a85b6f0 1427 cmd->scan_end_src);
e55c95a3 1428 PDEBUG("me4000_ai_do_cmd_test(): scan_end_arg = %d\n",
0a85b6f0 1429 cmd->scan_end_arg);
e55c95a3 1430 PDEBUG("me4000_ai_do_cmd_test(): stop_src = %08X\n",
0a85b6f0 1431 cmd->stop_src);
e55c95a3
GG
1432 PDEBUG("me4000_ai_do_cmd_test(): stop_arg = %d\n", cmd->stop_arg);
1433 PDEBUG("me4000_ai_do_cmd_test(): chanlist = %d\n",
0a85b6f0 1434 (unsigned int)cmd->chanlist);
e55c95a3 1435 PDEBUG("me4000_ai_do_cmd_test(): chanlist_len = %d\n",
0a85b6f0 1436 cmd->chanlist_len);
e55c95a3
GG
1437
1438 /* Only rounding flags are implemented */
1439 cmd->flags &= TRIG_ROUND_NEAREST | TRIG_ROUND_UP | TRIG_ROUND_DOWN;
1440
1441 /* Round the timer arguments */
1442 ai_round_cmd_args(dev, s, cmd, &init_ticks, &scan_ticks, &chan_ticks);
1443
1444 /*
1445 * Stage 1. Check if the trigger sources are generally valid.
1446 */
1447 switch (cmd->start_src) {
1448 case TRIG_NOW:
1449 case TRIG_EXT:
1450 break;
1451 case TRIG_ANY:
1452 cmd->start_src &= TRIG_NOW | TRIG_EXT;
1453 err++;
1454 break;
1455 default:
1456 printk(KERN_ERR
0a85b6f0
MT
1457 "comedi%d: me4000: me4000_ai_do_cmd_test(): Invalid start source\n",
1458 dev->minor);
e55c95a3
GG
1459 cmd->start_src = TRIG_NOW;
1460 err++;
1461 }
1462 switch (cmd->scan_begin_src) {
1463 case TRIG_FOLLOW:
1464 case TRIG_TIMER:
1465 case TRIG_EXT:
1466 break;
1467 case TRIG_ANY:
1468 cmd->scan_begin_src &= TRIG_FOLLOW | TRIG_TIMER | TRIG_EXT;
1469 err++;
1470 break;
1471 default:
1472 printk(KERN_ERR
0a85b6f0
MT
1473 "comedi%d: me4000: me4000_ai_do_cmd_test(): Invalid scan begin source\n",
1474 dev->minor);
e55c95a3
GG
1475 cmd->scan_begin_src = TRIG_FOLLOW;
1476 err++;
1477 }
1478 switch (cmd->convert_src) {
1479 case TRIG_TIMER:
1480 case TRIG_EXT:
1481 break;
1482 case TRIG_ANY:
1483 cmd->convert_src &= TRIG_TIMER | TRIG_EXT;
1484 err++;
1485 break;
1486 default:
1487 printk(KERN_ERR
0a85b6f0
MT
1488 "comedi%d: me4000: me4000_ai_do_cmd_test(): Invalid convert source\n",
1489 dev->minor);
e55c95a3
GG
1490 cmd->convert_src = TRIG_TIMER;
1491 err++;
1492 }
1493 switch (cmd->scan_end_src) {
1494 case TRIG_NONE:
1495 case TRIG_COUNT:
1496 break;
1497 case TRIG_ANY:
1498 cmd->scan_end_src &= TRIG_NONE | TRIG_COUNT;
1499 err++;
1500 break;
1501 default:
1502 printk(KERN_ERR
0a85b6f0
MT
1503 "comedi%d: me4000: me4000_ai_do_cmd_test(): Invalid scan end source\n",
1504 dev->minor);
e55c95a3
GG
1505 cmd->scan_end_src = TRIG_NONE;
1506 err++;
1507 }
1508 switch (cmd->stop_src) {
1509 case TRIG_NONE:
1510 case TRIG_COUNT:
1511 break;
1512 case TRIG_ANY:
1513 cmd->stop_src &= TRIG_NONE | TRIG_COUNT;
1514 err++;
1515 break;
1516 default:
1517 printk(KERN_ERR
0a85b6f0
MT
1518 "comedi%d: me4000: me4000_ai_do_cmd_test(): Invalid stop source\n",
1519 dev->minor);
e55c95a3
GG
1520 cmd->stop_src = TRIG_NONE;
1521 err++;
1522 }
82675f35 1523 if (err)
e55c95a3 1524 return 1;
e55c95a3
GG
1525
1526 /*
1527 * Stage 2. Check for trigger source conflicts.
1528 */
1529 if (cmd->start_src == TRIG_NOW &&
0a85b6f0
MT
1530 cmd->scan_begin_src == TRIG_TIMER &&
1531 cmd->convert_src == TRIG_TIMER) {
e55c95a3 1532 } else if (cmd->start_src == TRIG_NOW &&
0a85b6f0
MT
1533 cmd->scan_begin_src == TRIG_FOLLOW &&
1534 cmd->convert_src == TRIG_TIMER) {
e55c95a3 1535 } else if (cmd->start_src == TRIG_EXT &&
0a85b6f0
MT
1536 cmd->scan_begin_src == TRIG_TIMER &&
1537 cmd->convert_src == TRIG_TIMER) {
e55c95a3 1538 } else if (cmd->start_src == TRIG_EXT &&
0a85b6f0
MT
1539 cmd->scan_begin_src == TRIG_FOLLOW &&
1540 cmd->convert_src == TRIG_TIMER) {
e55c95a3 1541 } else if (cmd->start_src == TRIG_EXT &&
0a85b6f0
MT
1542 cmd->scan_begin_src == TRIG_EXT &&
1543 cmd->convert_src == TRIG_TIMER) {
e55c95a3 1544 } else if (cmd->start_src == TRIG_EXT &&
0a85b6f0
MT
1545 cmd->scan_begin_src == TRIG_EXT &&
1546 cmd->convert_src == TRIG_EXT) {
e55c95a3
GG
1547 } else {
1548 printk(KERN_ERR
0a85b6f0
MT
1549 "comedi%d: me4000: me4000_ai_do_cmd_test(): Invalid start trigger combination\n",
1550 dev->minor);
e55c95a3
GG
1551 cmd->start_src = TRIG_NOW;
1552 cmd->scan_begin_src = TRIG_FOLLOW;
1553 cmd->convert_src = TRIG_TIMER;
1554 err++;
1555 }
1556
1557 if (cmd->stop_src == TRIG_NONE && cmd->scan_end_src == TRIG_NONE) {
1558 } else if (cmd->stop_src == TRIG_COUNT &&
0a85b6f0 1559 cmd->scan_end_src == TRIG_NONE) {
e55c95a3 1560 } else if (cmd->stop_src == TRIG_NONE &&
0a85b6f0 1561 cmd->scan_end_src == TRIG_COUNT) {
e55c95a3 1562 } else if (cmd->stop_src == TRIG_COUNT &&
0a85b6f0 1563 cmd->scan_end_src == TRIG_COUNT) {
e55c95a3
GG
1564 } else {
1565 printk(KERN_ERR
0a85b6f0
MT
1566 "comedi%d: me4000: me4000_ai_do_cmd_test(): Invalid stop trigger combination\n",
1567 dev->minor);
e55c95a3
GG
1568 cmd->stop_src = TRIG_NONE;
1569 cmd->scan_end_src = TRIG_NONE;
1570 err++;
1571 }
82675f35 1572 if (err)
e55c95a3 1573 return 2;
e55c95a3
GG
1574
1575 /*
1576 * Stage 3. Check if arguments are generally valid.
1577 */
1578 if (cmd->chanlist_len < 1) {
1579 printk(KERN_ERR
0a85b6f0
MT
1580 "comedi%d: me4000: me4000_ai_do_cmd_test(): No channel list\n",
1581 dev->minor);
e55c95a3
GG
1582 cmd->chanlist_len = 1;
1583 err++;
1584 }
1585 if (init_ticks < 66) {
1586 printk(KERN_ERR
0a85b6f0
MT
1587 "comedi%d: me4000: me4000_ai_do_cmd_test(): Start arg to low\n",
1588 dev->minor);
e55c95a3
GG
1589 cmd->start_arg = 2000;
1590 err++;
1591 }
1592 if (scan_ticks && scan_ticks < 67) {
1593 printk(KERN_ERR
0a85b6f0
MT
1594 "comedi%d: me4000: me4000_ai_do_cmd_test(): Scan begin arg to low\n",
1595 dev->minor);
e55c95a3
GG
1596 cmd->scan_begin_arg = 2031;
1597 err++;
1598 }
1599 if (chan_ticks < 66) {
1600 printk(KERN_ERR
0a85b6f0
MT
1601 "comedi%d: me4000: me4000_ai_do_cmd_test(): Convert arg to low\n",
1602 dev->minor);
e55c95a3
GG
1603 cmd->convert_arg = 2000;
1604 err++;
1605 }
82675f35
BP
1606
1607 if (err)
e55c95a3 1608 return 3;
e55c95a3
GG
1609
1610 /*
1611 * Stage 4. Check for argument conflicts.
1612 */
1613 if (cmd->start_src == TRIG_NOW &&
0a85b6f0
MT
1614 cmd->scan_begin_src == TRIG_TIMER &&
1615 cmd->convert_src == TRIG_TIMER) {
e55c95a3
GG
1616
1617 /* Check timer arguments */
1618 if (init_ticks < ME4000_AI_MIN_TICKS) {
1619 printk(KERN_ERR
0a85b6f0
MT
1620 "comedi%d: me4000: me4000_ai_do_cmd_test(): Invalid start arg\n",
1621 dev->minor);
b6c77757 1622 cmd->start_arg = 2000; /* 66 ticks at least */
e55c95a3
GG
1623 err++;
1624 }
1625 if (chan_ticks < ME4000_AI_MIN_TICKS) {
1626 printk(KERN_ERR
0a85b6f0
MT
1627 "comedi%d: me4000: me4000_ai_do_cmd_test(): Invalid convert arg\n",
1628 dev->minor);
b6c77757 1629 cmd->convert_arg = 2000; /* 66 ticks at least */
e55c95a3
GG
1630 err++;
1631 }
1632 if (scan_ticks <= cmd->chanlist_len * chan_ticks) {
1633 printk(KERN_ERR
0a85b6f0
MT
1634 "comedi%d: me4000: me4000_ai_do_cmd_test(): Invalid scan end arg\n",
1635 dev->minor);
b6c77757 1636 cmd->scan_end_arg = 2000 * cmd->chanlist_len + 31; /* At least one tick more */
e55c95a3
GG
1637 err++;
1638 }
1639 } else if (cmd->start_src == TRIG_NOW &&
0a85b6f0
MT
1640 cmd->scan_begin_src == TRIG_FOLLOW &&
1641 cmd->convert_src == TRIG_TIMER) {
e55c95a3
GG
1642
1643 /* Check timer arguments */
1644 if (init_ticks < ME4000_AI_MIN_TICKS) {
1645 printk(KERN_ERR
0a85b6f0
MT
1646 "comedi%d: me4000: me4000_ai_do_cmd_test(): Invalid start arg\n",
1647 dev->minor);
b6c77757 1648 cmd->start_arg = 2000; /* 66 ticks at least */
e55c95a3
GG
1649 err++;
1650 }
1651 if (chan_ticks < ME4000_AI_MIN_TICKS) {
1652 printk(KERN_ERR
0a85b6f0
MT
1653 "comedi%d: me4000: me4000_ai_do_cmd_test(): Invalid convert arg\n",
1654 dev->minor);
b6c77757 1655 cmd->convert_arg = 2000; /* 66 ticks at least */
e55c95a3
GG
1656 err++;
1657 }
1658 } else if (cmd->start_src == TRIG_EXT &&
0a85b6f0
MT
1659 cmd->scan_begin_src == TRIG_TIMER &&
1660 cmd->convert_src == TRIG_TIMER) {
e55c95a3
GG
1661
1662 /* Check timer arguments */
1663 if (init_ticks < ME4000_AI_MIN_TICKS) {
1664 printk(KERN_ERR
0a85b6f0
MT
1665 "comedi%d: me4000: me4000_ai_do_cmd_test(): Invalid start arg\n",
1666 dev->minor);
b6c77757 1667 cmd->start_arg = 2000; /* 66 ticks at least */
e55c95a3
GG
1668 err++;
1669 }
1670 if (chan_ticks < ME4000_AI_MIN_TICKS) {
1671 printk(KERN_ERR
0a85b6f0
MT
1672 "comedi%d: me4000: me4000_ai_do_cmd_test(): Invalid convert arg\n",
1673 dev->minor);
b6c77757 1674 cmd->convert_arg = 2000; /* 66 ticks at least */
e55c95a3
GG
1675 err++;
1676 }
1677 if (scan_ticks <= cmd->chanlist_len * chan_ticks) {
1678 printk(KERN_ERR
0a85b6f0
MT
1679 "comedi%d: me4000: me4000_ai_do_cmd_test(): Invalid scan end arg\n",
1680 dev->minor);
b6c77757 1681 cmd->scan_end_arg = 2000 * cmd->chanlist_len + 31; /* At least one tick more */
e55c95a3
GG
1682 err++;
1683 }
1684 } else if (cmd->start_src == TRIG_EXT &&
0a85b6f0
MT
1685 cmd->scan_begin_src == TRIG_FOLLOW &&
1686 cmd->convert_src == TRIG_TIMER) {
e55c95a3
GG
1687
1688 /* Check timer arguments */
1689 if (init_ticks < ME4000_AI_MIN_TICKS) {
1690 printk(KERN_ERR
0a85b6f0
MT
1691 "comedi%d: me4000: me4000_ai_do_cmd_test(): Invalid start arg\n",
1692 dev->minor);
b6c77757 1693 cmd->start_arg = 2000; /* 66 ticks at least */
e55c95a3
GG
1694 err++;
1695 }
1696 if (chan_ticks < ME4000_AI_MIN_TICKS) {
1697 printk(KERN_ERR
0a85b6f0
MT
1698 "comedi%d: me4000: me4000_ai_do_cmd_test(): Invalid convert arg\n",
1699 dev->minor);
b6c77757 1700 cmd->convert_arg = 2000; /* 66 ticks at least */
e55c95a3
GG
1701 err++;
1702 }
1703 } else if (cmd->start_src == TRIG_EXT &&
0a85b6f0
MT
1704 cmd->scan_begin_src == TRIG_EXT &&
1705 cmd->convert_src == TRIG_TIMER) {
e55c95a3
GG
1706
1707 /* Check timer arguments */
1708 if (init_ticks < ME4000_AI_MIN_TICKS) {
1709 printk(KERN_ERR
0a85b6f0
MT
1710 "comedi%d: me4000: me4000_ai_do_cmd_test(): Invalid start arg\n",
1711 dev->minor);
b6c77757 1712 cmd->start_arg = 2000; /* 66 ticks at least */
e55c95a3
GG
1713 err++;
1714 }
1715 if (chan_ticks < ME4000_AI_MIN_TICKS) {
1716 printk(KERN_ERR
0a85b6f0
MT
1717 "comedi%d: me4000: me4000_ai_do_cmd_test(): Invalid convert arg\n",
1718 dev->minor);
b6c77757 1719 cmd->convert_arg = 2000; /* 66 ticks at least */
e55c95a3
GG
1720 err++;
1721 }
1722 } else if (cmd->start_src == TRIG_EXT &&
0a85b6f0
MT
1723 cmd->scan_begin_src == TRIG_EXT &&
1724 cmd->convert_src == TRIG_EXT) {
e55c95a3
GG
1725
1726 /* Check timer arguments */
1727 if (init_ticks < ME4000_AI_MIN_TICKS) {
1728 printk(KERN_ERR
0a85b6f0
MT
1729 "comedi%d: me4000: me4000_ai_do_cmd_test(): Invalid start arg\n",
1730 dev->minor);
b6c77757 1731 cmd->start_arg = 2000; /* 66 ticks at least */
e55c95a3
GG
1732 err++;
1733 }
1734 }
1735 if (cmd->stop_src == TRIG_COUNT) {
1736 if (cmd->stop_arg == 0) {
1737 printk(KERN_ERR
0a85b6f0
MT
1738 "comedi%d: me4000: me4000_ai_do_cmd_test(): Invalid stop arg\n",
1739 dev->minor);
e55c95a3
GG
1740 cmd->stop_arg = 1;
1741 err++;
1742 }
1743 }
1744 if (cmd->scan_end_src == TRIG_COUNT) {
1745 if (cmd->scan_end_arg == 0) {
1746 printk(KERN_ERR
0a85b6f0
MT
1747 "comedi%d: me4000: me4000_ai_do_cmd_test(): Invalid scan end arg\n",
1748 dev->minor);
e55c95a3
GG
1749 cmd->scan_end_arg = 1;
1750 err++;
1751 }
1752 }
82675f35
BP
1753
1754 if (err)
e55c95a3 1755 return 4;
e55c95a3
GG
1756
1757 /*
1758 * Stage 5. Check the channel list.
1759 */
1760 if (ai_check_chanlist(dev, s, cmd))
1761 return 5;
1762
1763 return 0;
1764}
1765
70265d24 1766static irqreturn_t me4000_ai_isr(int irq, void *dev_id)
e55c95a3
GG
1767{
1768 unsigned int tmp;
71b5f4f1 1769 struct comedi_device *dev = dev_id;
34c43922 1770 struct comedi_subdevice *s = dev->subdevices;
8b95a0e1 1771 struct me4000_ai_context *ai_context = &info->ai_context;
e55c95a3
GG
1772 int i;
1773 int c = 0;
1774 long lval;
1775
1776 ISR_PDEBUG("me4000_ai_isr() is executed\n");
1777
1778 if (!dev->attached) {
1779 ISR_PDEBUG("me4000_ai_isr() premature interrupt\n");
1780 return IRQ_NONE;
1781 }
1782
1783 /* Reset all events */
1784 s->async->events = 0;
1785
1786 /* Check if irq number is right */
1787 if (irq != ai_context->irq) {
1788 printk(KERN_ERR
0a85b6f0
MT
1789 "comedi%d: me4000: me4000_ai_isr(): Incorrect interrupt num: %d\n",
1790 dev->minor, irq);
e55c95a3
GG
1791 return IRQ_HANDLED;
1792 }
1793
1794 if (me4000_inl(dev,
0a85b6f0
MT
1795 ai_context->irq_status_reg) &
1796 ME4000_IRQ_STATUS_BIT_AI_HF) {
e55c95a3 1797 ISR_PDEBUG
0a85b6f0 1798 ("me4000_ai_isr(): Fifo half full interrupt occured\n");
e55c95a3
GG
1799
1800 /* Read status register to find out what happened */
1801 tmp = me4000_inl(dev, ai_context->ctrl_reg);
1802
1803 if (!(tmp & ME4000_AI_STATUS_BIT_FF_DATA) &&
0a85b6f0
MT
1804 !(tmp & ME4000_AI_STATUS_BIT_HF_DATA) &&
1805 (tmp & ME4000_AI_STATUS_BIT_EF_DATA)) {
e55c95a3
GG
1806 ISR_PDEBUG("me4000_ai_isr(): Fifo full\n");
1807 c = ME4000_AI_FIFO_COUNT;
1808
1809 /* FIFO overflow, so stop conversion and disable all interrupts */
1810 tmp |= ME4000_AI_CTRL_BIT_IMMEDIATE_STOP;
1811 tmp &= ~(ME4000_AI_CTRL_BIT_HF_IRQ |
0a85b6f0 1812 ME4000_AI_CTRL_BIT_SC_IRQ);
e55c95a3
GG
1813 me4000_outl(dev, tmp, ai_context->ctrl_reg);
1814
1815 s->async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
1816
1817 printk(KERN_ERR
0a85b6f0
MT
1818 "comedi%d: me4000: me4000_ai_isr(): FIFO overflow\n",
1819 dev->minor);
e55c95a3 1820 } else if ((tmp & ME4000_AI_STATUS_BIT_FF_DATA)
0a85b6f0
MT
1821 && !(tmp & ME4000_AI_STATUS_BIT_HF_DATA)
1822 && (tmp & ME4000_AI_STATUS_BIT_EF_DATA)) {
e55c95a3
GG
1823 ISR_PDEBUG("me4000_ai_isr(): Fifo half full\n");
1824
1825 s->async->events |= COMEDI_CB_BLOCK;
1826
1827 c = ME4000_AI_FIFO_COUNT / 2;
1828 } else {
1829 printk(KERN_ERR
0a85b6f0
MT
1830 "comedi%d: me4000: me4000_ai_isr(): Can't determine state of fifo\n",
1831 dev->minor);
e55c95a3
GG
1832 c = 0;
1833
1834 /* Undefined state, so stop conversion and disable all interrupts */
1835 tmp |= ME4000_AI_CTRL_BIT_IMMEDIATE_STOP;
1836 tmp &= ~(ME4000_AI_CTRL_BIT_HF_IRQ |
0a85b6f0 1837 ME4000_AI_CTRL_BIT_SC_IRQ);
e55c95a3
GG
1838 me4000_outl(dev, tmp, ai_context->ctrl_reg);
1839
1840 s->async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
1841
1842 printk(KERN_ERR
0a85b6f0
MT
1843 "comedi%d: me4000: me4000_ai_isr(): Undefined FIFO state\n",
1844 dev->minor);
e55c95a3
GG
1845 }
1846
1847 ISR_PDEBUG("me4000_ai_isr(): Try to read %d values\n", c);
1848
1849 for (i = 0; i < c; i++) {
1850 /* Read value from data fifo */
1851 lval = inl(ai_context->data_reg) & 0xFFFF;
1852 lval ^= 0x8000;
1853
1854 if (!comedi_buf_put(s->async, lval)) {
1855 /* Buffer overflow, so stop conversion and disable all interrupts */
1856 tmp |= ME4000_AI_CTRL_BIT_IMMEDIATE_STOP;
1857 tmp &= ~(ME4000_AI_CTRL_BIT_HF_IRQ |
0a85b6f0 1858 ME4000_AI_CTRL_BIT_SC_IRQ);
e55c95a3
GG
1859 me4000_outl(dev, tmp, ai_context->ctrl_reg);
1860
1861 s->async->events |= COMEDI_CB_OVERFLOW;
1862
1863 printk(KERN_ERR
0a85b6f0
MT
1864 "comedi%d: me4000: me4000_ai_isr(): Buffer overflow\n",
1865 dev->minor);
e55c95a3
GG
1866
1867 break;
1868 }
1869 }
1870
1871 /* Work is done, so reset the interrupt */
1872 ISR_PDEBUG("me4000_ai_isr(): Reset fifo half full interrupt\n");
1873 tmp |= ME4000_AI_CTRL_BIT_HF_IRQ_RESET;
1874 me4000_outl(dev, tmp, ai_context->ctrl_reg);
1875 tmp &= ~ME4000_AI_CTRL_BIT_HF_IRQ_RESET;
1876 me4000_outl(dev, tmp, ai_context->ctrl_reg);
1877 }
1878
1879 if (me4000_inl(dev,
0a85b6f0 1880 ai_context->irq_status_reg) & ME4000_IRQ_STATUS_BIT_SC) {
e55c95a3 1881 ISR_PDEBUG
0a85b6f0 1882 ("me4000_ai_isr(): Sample counter interrupt occured\n");
e55c95a3
GG
1883
1884 s->async->events |= COMEDI_CB_BLOCK | COMEDI_CB_EOA;
1885
1886 /* Acquisition is complete, so stop conversion and disable all interrupts */
1887 tmp = me4000_inl(dev, ai_context->ctrl_reg);
1888 tmp |= ME4000_AI_CTRL_BIT_IMMEDIATE_STOP;
1889 tmp &= ~(ME4000_AI_CTRL_BIT_HF_IRQ | ME4000_AI_CTRL_BIT_SC_IRQ);
1890 me4000_outl(dev, tmp, ai_context->ctrl_reg);
1891
1892 /* Poll data until fifo empty */
1893 while (inl(ai_context->ctrl_reg) & ME4000_AI_STATUS_BIT_EF_DATA) {
1894 /* Read value from data fifo */
1895 lval = inl(ai_context->data_reg) & 0xFFFF;
1896 lval ^= 0x8000;
1897
1898 if (!comedi_buf_put(s->async, lval)) {
1899 printk(KERN_ERR
0a85b6f0
MT
1900 "comedi%d: me4000: me4000_ai_isr(): Buffer overflow\n",
1901 dev->minor);
e55c95a3
GG
1902 s->async->events |= COMEDI_CB_OVERFLOW;
1903 break;
1904 }
1905 }
1906
1907 /* Work is done, so reset the interrupt */
1908 ISR_PDEBUG
0a85b6f0 1909 ("me4000_ai_isr(): Reset interrupt from sample counter\n");
e55c95a3
GG
1910 tmp |= ME4000_AI_CTRL_BIT_SC_IRQ_RESET;
1911 me4000_outl(dev, tmp, ai_context->ctrl_reg);
1912 tmp &= ~ME4000_AI_CTRL_BIT_SC_IRQ_RESET;
1913 me4000_outl(dev, tmp, ai_context->ctrl_reg);
1914 }
1915
1916 ISR_PDEBUG("me4000_ai_isr(): Events = 0x%X\n", s->async->events);
1917
1918 if (s->async->events)
1919 comedi_event(dev, s);
1920
1921 return IRQ_HANDLED;
1922}
1923
1924/*=============================================================================
1925 Analog output section
1926 ===========================================================================*/
1927
71b5f4f1 1928static int me4000_ao_insn_write(struct comedi_device *dev,
0a85b6f0
MT
1929 struct comedi_subdevice *s,
1930 struct comedi_insn *insn, unsigned int *data)
e55c95a3
GG
1931{
1932
1933 int chan = CR_CHAN(insn->chanspec);
1934 int rang = CR_RANGE(insn->chanspec);
1935 int aref = CR_AREF(insn->chanspec);
1936 unsigned long tmp;
1937
1938 CALL_PDEBUG("In me4000_ao_insn_write()\n");
1939
1940 if (insn->n == 0) {
1941 return 0;
1942 } else if (insn->n > 1) {
1943 printk(KERN_ERR
0a85b6f0
MT
1944 "comedi%d: me4000: me4000_ao_insn_write(): Invalid instruction length %d\n",
1945 dev->minor, insn->n);
e55c95a3
GG
1946 return -EINVAL;
1947 }
1948
1949 if (chan >= thisboard->ao.count) {
1950 printk(KERN_ERR
0a85b6f0
MT
1951 "comedi%d: me4000: me4000_ao_insn_write(): Invalid channel %d\n",
1952 dev->minor, insn->n);
e55c95a3
GG
1953 return -EINVAL;
1954 }
1955
1956 if (rang != 0) {
1957 printk(KERN_ERR
0a85b6f0
MT
1958 "comedi%d: me4000: me4000_ao_insn_write(): Invalid range %d\n",
1959 dev->minor, insn->n);
e55c95a3
GG
1960 return -EINVAL;
1961 }
1962
1963 if (aref != AREF_GROUND && aref != AREF_COMMON) {
1964 printk(KERN_ERR
0a85b6f0
MT
1965 "comedi%d: me4000: me4000_ao_insn_write(): Invalid aref %d\n",
1966 dev->minor, insn->n);
e55c95a3
GG
1967 return -EINVAL;
1968 }
1969
1970 /* Stop any running conversion */
1971 tmp = me4000_inl(dev, info->ao_context[chan].ctrl_reg);
1972 tmp |= ME4000_AO_CTRL_BIT_IMMEDIATE_STOP;
1973 me4000_outl(dev, tmp, info->ao_context[chan].ctrl_reg);
1974
1975 /* Clear control register and set to single mode */
1976 me4000_outl(dev, 0x0, info->ao_context[chan].ctrl_reg);
1977
1978 /* Write data value */
1979 me4000_outl(dev, data[0], info->ao_context[chan].single_reg);
1980
1981 /* Store in the mirror */
1982 info->ao_context[chan].mirror = data[0];
1983
1984 return 1;
1985}
1986
71b5f4f1 1987static int me4000_ao_insn_read(struct comedi_device *dev,
0a85b6f0
MT
1988 struct comedi_subdevice *s,
1989 struct comedi_insn *insn, unsigned int *data)
e55c95a3
GG
1990{
1991 int chan = CR_CHAN(insn->chanspec);
1992
1993 if (insn->n == 0) {
1994 return 0;
1995 } else if (insn->n > 1) {
0a85b6f0
MT
1996 printk
1997 ("comedi%d: me4000: me4000_ao_insn_read(): Invalid instruction length\n",
1998 dev->minor);
e55c95a3
GG
1999 return -EINVAL;
2000 }
2001
2002 data[0] = info->ao_context[chan].mirror;
2003
2004 return 1;
2005}
2006
2007/*=============================================================================
2008 Digital I/O section
2009 ===========================================================================*/
2010
71b5f4f1 2011static int me4000_dio_insn_bits(struct comedi_device *dev,
0a85b6f0
MT
2012 struct comedi_subdevice *s,
2013 struct comedi_insn *insn, unsigned int *data)
e55c95a3
GG
2014{
2015
2016 CALL_PDEBUG("In me4000_dio_insn_bits()\n");
2017
2018 /* Length of data must be 2 (mask and new data, see below) */
82675f35 2019 if (insn->n == 0)
e55c95a3 2020 return 0;
82675f35 2021
e55c95a3 2022 if (insn->n != 2) {
0a85b6f0
MT
2023 printk
2024 ("comedi%d: me4000: me4000_dio_insn_bits(): Invalid instruction length\n",
2025 dev->minor);
e55c95a3
GG
2026 return -EINVAL;
2027 }
2028
2029 /*
2030 * The insn data consists of a mask in data[0] and the new data
2031 * in data[1]. The mask defines which bits we are concerning about.
2032 * The new data must be anded with the mask.
2033 * Each channel corresponds to a bit.
2034 */
2035 if (data[0]) {
2036 /* Check if requested ports are configured for output */
2037 if ((s->io_bits & data[0]) != data[0])
2038 return -EIO;
2039
2040 s->state &= ~data[0];
2041 s->state |= data[0] & data[1];
2042
2043 /* Write out the new digital output lines */
2044 me4000_outl(dev, (s->state >> 0) & 0xFF,
0a85b6f0 2045 info->dio_context.port_0_reg);
e55c95a3 2046 me4000_outl(dev, (s->state >> 8) & 0xFF,
0a85b6f0 2047 info->dio_context.port_1_reg);
e55c95a3 2048 me4000_outl(dev, (s->state >> 16) & 0xFF,
0a85b6f0 2049 info->dio_context.port_2_reg);
e55c95a3 2050 me4000_outl(dev, (s->state >> 24) & 0xFF,
0a85b6f0 2051 info->dio_context.port_3_reg);
e55c95a3
GG
2052 }
2053
2054 /* On return, data[1] contains the value of
2055 the digital input and output lines. */
2056 data[1] =
0a85b6f0
MT
2057 ((me4000_inl(dev, info->dio_context.port_0_reg) & 0xFF) << 0) |
2058 ((me4000_inl(dev, info->dio_context.port_1_reg) & 0xFF) << 8) |
2059 ((me4000_inl(dev, info->dio_context.port_2_reg) & 0xFF) << 16) |
2060 ((me4000_inl(dev, info->dio_context.port_3_reg) & 0xFF) << 24);
e55c95a3
GG
2061
2062 return 2;
2063}
2064
71b5f4f1 2065static int me4000_dio_insn_config(struct comedi_device *dev,
0a85b6f0
MT
2066 struct comedi_subdevice *s,
2067 struct comedi_insn *insn, unsigned int *data)
e55c95a3
GG
2068{
2069 unsigned long tmp;
2070 int chan = CR_CHAN(insn->chanspec);
2071
2072 CALL_PDEBUG("In me4000_dio_insn_config()\n");
2073
2074 if (data[0] == INSN_CONFIG_DIO_QUERY) {
2075 data[1] =
0a85b6f0 2076 (s->io_bits & (1 << chan)) ? COMEDI_OUTPUT : COMEDI_INPUT;
e55c95a3
GG
2077 return insn->n;
2078 }
2079
2080 /*
2081 * The input or output configuration of each digital line is
2082 * configured by a special insn_config instruction. chanspec
2083 * contains the channel to be changed, and data[0] contains the
2084 * value COMEDI_INPUT or COMEDI_OUTPUT.
2085 * On the ME-4000 it is only possible to switch port wise (8 bit)
2086 */
2087
2088 tmp = me4000_inl(dev, info->dio_context.ctrl_reg);
2089
2090 if (data[0] == COMEDI_OUTPUT) {
2091 if (chan < 8) {
2092 s->io_bits |= 0xFF;
2093 tmp &= ~(ME4000_DIO_CTRL_BIT_MODE_0 |
0a85b6f0 2094 ME4000_DIO_CTRL_BIT_MODE_1);
e55c95a3
GG
2095 tmp |= ME4000_DIO_CTRL_BIT_MODE_0;
2096 } else if (chan < 16) {
2097 /*
2098 * Chech for optoisolated ME-4000 version. If one the first
2099 * port is a fixed output port and the second is a fixed input port.
2100 */
2101 if (!me4000_inl(dev, info->dio_context.dir_reg))
2102 return -ENODEV;
2103
2104 s->io_bits |= 0xFF00;
2105 tmp &= ~(ME4000_DIO_CTRL_BIT_MODE_2 |
0a85b6f0 2106 ME4000_DIO_CTRL_BIT_MODE_3);
e55c95a3
GG
2107 tmp |= ME4000_DIO_CTRL_BIT_MODE_2;
2108 } else if (chan < 24) {
2109 s->io_bits |= 0xFF0000;
2110 tmp &= ~(ME4000_DIO_CTRL_BIT_MODE_4 |
0a85b6f0 2111 ME4000_DIO_CTRL_BIT_MODE_5);
e55c95a3
GG
2112 tmp |= ME4000_DIO_CTRL_BIT_MODE_4;
2113 } else if (chan < 32) {
2114 s->io_bits |= 0xFF000000;
2115 tmp &= ~(ME4000_DIO_CTRL_BIT_MODE_6 |
0a85b6f0 2116 ME4000_DIO_CTRL_BIT_MODE_7);
e55c95a3
GG
2117 tmp |= ME4000_DIO_CTRL_BIT_MODE_6;
2118 } else {
2119 return -EINVAL;
2120 }
2121 } else {
2122 if (chan < 8) {
2123 /*
2124 * Chech for optoisolated ME-4000 version. If one the first
2125 * port is a fixed output port and the second is a fixed input port.
2126 */
2127 if (!me4000_inl(dev, info->dio_context.dir_reg))
2128 return -ENODEV;
2129
2130 s->io_bits &= ~0xFF;
2131 tmp &= ~(ME4000_DIO_CTRL_BIT_MODE_0 |
0a85b6f0 2132 ME4000_DIO_CTRL_BIT_MODE_1);
e55c95a3
GG
2133 } else if (chan < 16) {
2134 s->io_bits &= ~0xFF00;
2135 tmp &= ~(ME4000_DIO_CTRL_BIT_MODE_2 |
0a85b6f0 2136 ME4000_DIO_CTRL_BIT_MODE_3);
e55c95a3
GG
2137 } else if (chan < 24) {
2138 s->io_bits &= ~0xFF0000;
2139 tmp &= ~(ME4000_DIO_CTRL_BIT_MODE_4 |
0a85b6f0 2140 ME4000_DIO_CTRL_BIT_MODE_5);
e55c95a3
GG
2141 } else if (chan < 32) {
2142 s->io_bits &= ~0xFF000000;
2143 tmp &= ~(ME4000_DIO_CTRL_BIT_MODE_6 |
0a85b6f0 2144 ME4000_DIO_CTRL_BIT_MODE_7);
e55c95a3
GG
2145 } else {
2146 return -EINVAL;
2147 }
2148 }
2149
2150 me4000_outl(dev, tmp, info->dio_context.ctrl_reg);
2151
2152 return 1;
2153}
2154
2155/*=============================================================================
2156 Counter section
2157 ===========================================================================*/
2158
71b5f4f1 2159static int cnt_reset(struct comedi_device *dev, unsigned int channel)
e55c95a3
GG
2160{
2161
2162 CALL_PDEBUG("In cnt_reset()\n");
2163
2164 switch (channel) {
2165 case 0:
2166 me4000_outb(dev, 0x30, info->cnt_context.ctrl_reg);
2167 me4000_outb(dev, 0x00, info->cnt_context.counter_0_reg);
2168 me4000_outb(dev, 0x00, info->cnt_context.counter_0_reg);
2169 break;
2170 case 1:
2171 me4000_outb(dev, 0x70, info->cnt_context.ctrl_reg);
2172 me4000_outb(dev, 0x00, info->cnt_context.counter_1_reg);
2173 me4000_outb(dev, 0x00, info->cnt_context.counter_1_reg);
2174 break;
2175 case 2:
2176 me4000_outb(dev, 0xB0, info->cnt_context.ctrl_reg);
2177 me4000_outb(dev, 0x00, info->cnt_context.counter_2_reg);
2178 me4000_outb(dev, 0x00, info->cnt_context.counter_2_reg);
2179 break;
2180 default:
2181 printk(KERN_ERR
0a85b6f0
MT
2182 "comedi%d: me4000: cnt_reset(): Invalid channel\n",
2183 dev->minor);
e55c95a3
GG
2184 return -EINVAL;
2185 }
2186
2187 return 0;
2188}
2189
71b5f4f1 2190static int cnt_config(struct comedi_device *dev, unsigned int channel,
0a85b6f0 2191 unsigned int mode)
e55c95a3
GG
2192{
2193 int tmp = 0;
2194
2195 CALL_PDEBUG("In cnt_config()\n");
2196
2197 switch (channel) {
2198 case 0:
2199 tmp |= ME4000_CNT_COUNTER_0;
2200 break;
2201 case 1:
2202 tmp |= ME4000_CNT_COUNTER_1;
2203 break;
2204 case 2:
2205 tmp |= ME4000_CNT_COUNTER_2;
2206 break;
2207 default:
2208 printk(KERN_ERR
0a85b6f0
MT
2209 "comedi%d: me4000: cnt_config(): Invalid channel\n",
2210 dev->minor);
e55c95a3
GG
2211 return -EINVAL;
2212 }
2213
2214 switch (mode) {
2215 case 0:
2216 tmp |= ME4000_CNT_MODE_0;
2217 break;
2218 case 1:
2219 tmp |= ME4000_CNT_MODE_1;
2220 break;
2221 case 2:
2222 tmp |= ME4000_CNT_MODE_2;
2223 break;
2224 case 3:
2225 tmp |= ME4000_CNT_MODE_3;
2226 break;
2227 case 4:
2228 tmp |= ME4000_CNT_MODE_4;
2229 break;
2230 case 5:
2231 tmp |= ME4000_CNT_MODE_5;
2232 break;
2233 default:
2234 printk(KERN_ERR
0a85b6f0
MT
2235 "comedi%d: me4000: cnt_config(): Invalid counter mode\n",
2236 dev->minor);
e55c95a3
GG
2237 return -EINVAL;
2238 }
2239
2240 /* Write the control word */
2241 tmp |= 0x30;
2242 me4000_outb(dev, tmp, info->cnt_context.ctrl_reg);
2243
2244 return 0;
2245}
2246
71b5f4f1 2247static int me4000_cnt_insn_config(struct comedi_device *dev,
0a85b6f0
MT
2248 struct comedi_subdevice *s,
2249 struct comedi_insn *insn, unsigned int *data)
e55c95a3
GG
2250{
2251
2252 int err;
2253
2254 CALL_PDEBUG("In me4000_cnt_insn_config()\n");
2255
2256 switch (data[0]) {
2257 case GPCT_RESET:
2258 if (insn->n != 1) {
2259 printk(KERN_ERR
0a85b6f0
MT
2260 "comedi%d: me4000: me4000_cnt_insn_config(): Invalid instruction length%d\n",
2261 dev->minor, insn->n);
e55c95a3
GG
2262 return -EINVAL;
2263 }
2264
2265 err = cnt_reset(dev, insn->chanspec);
2266 if (err)
2267 return err;
2268 break;
2269 case GPCT_SET_OPERATION:
2270 if (insn->n != 2) {
2271 printk(KERN_ERR
0a85b6f0
MT
2272 "comedi%d: me4000: me4000_cnt_insn_config(): Invalid instruction length%d\n",
2273 dev->minor, insn->n);
e55c95a3
GG
2274 return -EINVAL;
2275 }
2276
2277 err = cnt_config(dev, insn->chanspec, data[1]);
2278 if (err)
2279 return err;
2280 break;
2281 default:
2282 printk(KERN_ERR
0a85b6f0
MT
2283 "comedi%d: me4000: me4000_cnt_insn_config(): Invalid instruction\n",
2284 dev->minor);
e55c95a3
GG
2285 return -EINVAL;
2286 }
2287
2288 return 2;
2289}
2290
71b5f4f1 2291static int me4000_cnt_insn_read(struct comedi_device *dev,
0a85b6f0
MT
2292 struct comedi_subdevice *s,
2293 struct comedi_insn *insn, unsigned int *data)
e55c95a3
GG
2294{
2295
2296 unsigned short tmp;
2297
2298 CALL_PDEBUG("In me4000_cnt_insn_read()\n");
2299
82675f35 2300 if (insn->n == 0)
e55c95a3 2301 return 0;
82675f35 2302
e55c95a3
GG
2303 if (insn->n > 1) {
2304 printk(KERN_ERR
0a85b6f0
MT
2305 "comedi%d: me4000: me4000_cnt_insn_read(): Invalid instruction length %d\n",
2306 dev->minor, insn->n);
e55c95a3
GG
2307 return -EINVAL;
2308 }
2309
2310 switch (insn->chanspec) {
2311 case 0:
2312 tmp = me4000_inb(dev, info->cnt_context.counter_0_reg);
2313 data[0] = tmp;
2314 tmp = me4000_inb(dev, info->cnt_context.counter_0_reg);
2315 data[0] |= tmp << 8;
2316 break;
2317 case 1:
2318 tmp = me4000_inb(dev, info->cnt_context.counter_1_reg);
2319 data[0] = tmp;
2320 tmp = me4000_inb(dev, info->cnt_context.counter_1_reg);
2321 data[0] |= tmp << 8;
2322 break;
2323 case 2:
2324 tmp = me4000_inb(dev, info->cnt_context.counter_2_reg);
2325 data[0] = tmp;
2326 tmp = me4000_inb(dev, info->cnt_context.counter_2_reg);
2327 data[0] |= tmp << 8;
2328 break;
2329 default:
2330 printk(KERN_ERR
0a85b6f0
MT
2331 "comedi%d: me4000: me4000_cnt_insn_read(): Invalid channel %d\n",
2332 dev->minor, insn->chanspec);
e55c95a3
GG
2333 return -EINVAL;
2334 }
2335
2336 return 1;
2337}
2338
71b5f4f1 2339static int me4000_cnt_insn_write(struct comedi_device *dev,
0a85b6f0
MT
2340 struct comedi_subdevice *s,
2341 struct comedi_insn *insn, unsigned int *data)
e55c95a3
GG
2342{
2343
2344 unsigned short tmp;
2345
2346 CALL_PDEBUG("In me4000_cnt_insn_write()\n");
2347
2348 if (insn->n == 0) {
2349 return 0;
2350 } else if (insn->n > 1) {
2351 printk(KERN_ERR
0a85b6f0
MT
2352 "comedi%d: me4000: me4000_cnt_insn_write(): Invalid instruction length %d\n",
2353 dev->minor, insn->n);
e55c95a3
GG
2354 return -EINVAL;
2355 }
2356
2357 switch (insn->chanspec) {
2358 case 0:
2359 tmp = data[0] & 0xFF;
2360 me4000_outb(dev, tmp, info->cnt_context.counter_0_reg);
2361 tmp = (data[0] >> 8) & 0xFF;
2362 me4000_outb(dev, tmp, info->cnt_context.counter_0_reg);
2363 break;
2364 case 1:
2365 tmp = data[0] & 0xFF;
2366 me4000_outb(dev, tmp, info->cnt_context.counter_1_reg);
2367 tmp = (data[0] >> 8) & 0xFF;
2368 me4000_outb(dev, tmp, info->cnt_context.counter_1_reg);
2369 break;
2370 case 2:
2371 tmp = data[0] & 0xFF;
2372 me4000_outb(dev, tmp, info->cnt_context.counter_2_reg);
2373 tmp = (data[0] >> 8) & 0xFF;
2374 me4000_outb(dev, tmp, info->cnt_context.counter_2_reg);
2375 break;
2376 default:
2377 printk(KERN_ERR
0a85b6f0
MT
2378 "comedi%d: me4000: me4000_cnt_insn_write(): Invalid channel %d\n",
2379 dev->minor, insn->chanspec);
e55c95a3
GG
2380 return -EINVAL;
2381 }
2382
2383 return 1;
2384}
2385
2386COMEDI_PCI_INITCLEANUP(driver_me4000, me4000_pci_table);