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