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