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