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