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