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