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