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