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