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