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