Version:  2.0.40 2.2.26 2.4.37 3.8 3.9 3.10 3.11 3.12 3.13 3.14 3.15 3.16 3.17 3.18 3.19 4.0 4.1 4.2 4.3 4.4

Linux/drivers/staging/comedi/drivers/me4000.c

  1 /*
  2  * 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 
 19 /*
 20  * Driver: me4000
 21  * Description: Meilhaus ME-4000 series boards
 22  * Devices: [Meilhaus] ME-4650 (me4000), ME-4670i, ME-4680, ME-4680i,
 23  *          ME-4680is
 24  * Author: gg (Guenter Gebhardt <g.gebhardt@meilhaus.com>)
 25  * Updated: Mon, 18 Mar 2002 15:34:01 -0800
 26  * Status: untested
 27  *
 28  * Supports:
 29  *      - Analog Input
 30  *      - Analog Output
 31  *      - Digital I/O
 32  *      - Counter
 33  *
 34  * Configuration Options: not applicable, uses PCI auto config
 35  *
 36  * The firmware required by these boards is available in the
 37  * comedi_nonfree_firmware tarball available from
 38  * http://www.comedi.org.
 39  */
 40 
 41 #include <linux/module.h>
 42 #include <linux/delay.h>
 43 #include <linux/interrupt.h>
 44 
 45 #include "../comedi_pci.h"
 46 
 47 #include "comedi_8254.h"
 48 #include "plx9052.h"
 49 
 50 #define ME4000_FIRMWARE         "me4000_firmware.bin"
 51 
 52 /*
 53  * ME4000 Register map and bit defines
 54  */
 55 #define ME4000_AO_CHAN(x)                       ((x) * 0x18)
 56 
 57 #define ME4000_AO_CTRL_REG(x)                   (0x00 + ME4000_AO_CHAN(x))
 58 #define ME4000_AO_CTRL_MODE_0                   BIT(0)
 59 #define ME4000_AO_CTRL_MODE_1                   BIT(1)
 60 #define ME4000_AO_CTRL_STOP                     BIT(2)
 61 #define ME4000_AO_CTRL_ENABLE_FIFO              BIT(3)
 62 #define ME4000_AO_CTRL_ENABLE_EX_TRIG           BIT(4)
 63 #define ME4000_AO_CTRL_EX_TRIG_EDGE             BIT(5)
 64 #define ME4000_AO_CTRL_IMMEDIATE_STOP           BIT(7)
 65 #define ME4000_AO_CTRL_ENABLE_DO                BIT(8)
 66 #define ME4000_AO_CTRL_ENABLE_IRQ               BIT(9)
 67 #define ME4000_AO_CTRL_RESET_IRQ                BIT(10)
 68 #define ME4000_AO_STATUS_REG(x)                 (0x04 + ME4000_AO_CHAN(x))
 69 #define ME4000_AO_STATUS_FSM                    BIT(0)
 70 #define ME4000_AO_STATUS_FF                     BIT(1)
 71 #define ME4000_AO_STATUS_HF                     BIT(2)
 72 #define ME4000_AO_STATUS_EF                     BIT(3)
 73 #define ME4000_AO_FIFO_REG(x)                   (0x08 + ME4000_AO_CHAN(x))
 74 #define ME4000_AO_SINGLE_REG(x)                 (0x0c + ME4000_AO_CHAN(x))
 75 #define ME4000_AO_TIMER_REG(x)                  (0x10 + ME4000_AO_CHAN(x))
 76 #define ME4000_AI_CTRL_REG                      0x74
 77 #define ME4000_AI_STATUS_REG                    0x74
 78 #define ME4000_AI_CTRL_MODE_0                   BIT(0)
 79 #define ME4000_AI_CTRL_MODE_1                   BIT(1)
 80 #define ME4000_AI_CTRL_MODE_2                   BIT(2)
 81 #define ME4000_AI_CTRL_SAMPLE_HOLD              BIT(3)
 82 #define ME4000_AI_CTRL_IMMEDIATE_STOP           BIT(4)
 83 #define ME4000_AI_CTRL_STOP                     BIT(5)
 84 #define ME4000_AI_CTRL_CHANNEL_FIFO             BIT(6)
 85 #define ME4000_AI_CTRL_DATA_FIFO                BIT(7)
 86 #define ME4000_AI_CTRL_FULLSCALE                BIT(8)
 87 #define ME4000_AI_CTRL_OFFSET                   BIT(9)
 88 #define ME4000_AI_CTRL_EX_TRIG_ANALOG           BIT(10)
 89 #define ME4000_AI_CTRL_EX_TRIG                  BIT(11)
 90 #define ME4000_AI_CTRL_EX_TRIG_FALLING          BIT(12)
 91 #define ME4000_AI_CTRL_EX_IRQ                   BIT(13)
 92 #define ME4000_AI_CTRL_EX_IRQ_RESET             BIT(14)
 93 #define ME4000_AI_CTRL_LE_IRQ                   BIT(15)
 94 #define ME4000_AI_CTRL_LE_IRQ_RESET             BIT(16)
 95 #define ME4000_AI_CTRL_HF_IRQ                   BIT(17)
 96 #define ME4000_AI_CTRL_HF_IRQ_RESET             BIT(18)
 97 #define ME4000_AI_CTRL_SC_IRQ                   BIT(19)
 98 #define ME4000_AI_CTRL_SC_IRQ_RESET             BIT(20)
 99 #define ME4000_AI_CTRL_SC_RELOAD                BIT(21)
100 #define ME4000_AI_STATUS_EF_CHANNEL             BIT(22)
101 #define ME4000_AI_STATUS_HF_CHANNEL             BIT(23)
102 #define ME4000_AI_STATUS_FF_CHANNEL             BIT(24)
103 #define ME4000_AI_STATUS_EF_DATA                BIT(25)
104 #define ME4000_AI_STATUS_HF_DATA                BIT(26)
105 #define ME4000_AI_STATUS_FF_DATA                BIT(27)
106 #define ME4000_AI_STATUS_LE                     BIT(28)
107 #define ME4000_AI_STATUS_FSM                    BIT(29)
108 #define ME4000_AI_CTRL_EX_TRIG_BOTH             BIT(31)
109 #define ME4000_AI_CHANNEL_LIST_REG              0x78
110 #define ME4000_AI_LIST_INPUT_DIFFERENTIAL       BIT(5)
111 #define ME4000_AI_LIST_RANGE(x)                 ((3 - ((x) & 3)) << 6)
112 #define ME4000_AI_LIST_LAST_ENTRY               BIT(8)
113 #define ME4000_AI_DATA_REG                      0x7c
114 #define ME4000_AI_CHAN_TIMER_REG                0x80
115 #define ME4000_AI_CHAN_PRE_TIMER_REG            0x84
116 #define ME4000_AI_SCAN_TIMER_LOW_REG            0x88
117 #define ME4000_AI_SCAN_TIMER_HIGH_REG           0x8c
118 #define ME4000_AI_SCAN_PRE_TIMER_LOW_REG        0x90
119 #define ME4000_AI_SCAN_PRE_TIMER_HIGH_REG       0x94
120 #define ME4000_AI_START_REG                     0x98
121 #define ME4000_IRQ_STATUS_REG                   0x9c
122 #define ME4000_IRQ_STATUS_EX                    BIT(0)
123 #define ME4000_IRQ_STATUS_LE                    BIT(1)
124 #define ME4000_IRQ_STATUS_AI_HF                 BIT(2)
125 #define ME4000_IRQ_STATUS_AO_0_HF               BIT(3)
126 #define ME4000_IRQ_STATUS_AO_1_HF               BIT(4)
127 #define ME4000_IRQ_STATUS_AO_2_HF               BIT(5)
128 #define ME4000_IRQ_STATUS_AO_3_HF               BIT(6)
129 #define ME4000_IRQ_STATUS_SC                    BIT(7)
130 #define ME4000_DIO_PORT_0_REG                   0xa0
131 #define ME4000_DIO_PORT_1_REG                   0xa4
132 #define ME4000_DIO_PORT_2_REG                   0xa8
133 #define ME4000_DIO_PORT_3_REG                   0xac
134 #define ME4000_DIO_DIR_REG                      0xb0
135 #define ME4000_AO_LOADSETREG_XX                 0xb4
136 #define ME4000_DIO_CTRL_REG                     0xb8
137 #define ME4000_DIO_CTRL_MODE_0                  BIT(0)
138 #define ME4000_DIO_CTRL_MODE_1                  BIT(1)
139 #define ME4000_DIO_CTRL_MODE_2                  BIT(2)
140 #define ME4000_DIO_CTRL_MODE_3                  BIT(3)
141 #define ME4000_DIO_CTRL_MODE_4                  BIT(4)
142 #define ME4000_DIO_CTRL_MODE_5                  BIT(5)
143 #define ME4000_DIO_CTRL_MODE_6                  BIT(6)
144 #define ME4000_DIO_CTRL_MODE_7                  BIT(7)
145 #define ME4000_DIO_CTRL_FUNCTION_0              BIT(8)
146 #define ME4000_DIO_CTRL_FUNCTION_1              BIT(9)
147 #define ME4000_DIO_CTRL_FIFO_HIGH_0             BIT(10)
148 #define ME4000_DIO_CTRL_FIFO_HIGH_1             BIT(11)
149 #define ME4000_DIO_CTRL_FIFO_HIGH_2             BIT(12)
150 #define ME4000_DIO_CTRL_FIFO_HIGH_3             BIT(13)
151 #define ME4000_AO_DEMUX_ADJUST_REG              0xbc
152 #define ME4000_AO_DEMUX_ADJUST_VALUE            0x4c
153 #define ME4000_AI_SAMPLE_COUNTER_REG            0xc0
154 
155 #define ME4000_AI_FIFO_COUNT                    2048
156 
157 #define ME4000_AI_MIN_TICKS                     66
158 #define ME4000_AI_MIN_SAMPLE_TIME               2000
159 
160 #define ME4000_AI_CHANNEL_LIST_COUNT            1024
161 
162 struct me4000_private {
163         unsigned long plx_regbase;
164         unsigned int ai_ctrl_mode;
165         unsigned int ai_init_ticks;
166         unsigned int ai_scan_ticks;
167         unsigned int ai_chan_ticks;
168 };
169 
170 enum me4000_boardid {
171         BOARD_ME4650,
172         BOARD_ME4660,
173         BOARD_ME4660I,
174         BOARD_ME4660S,
175         BOARD_ME4660IS,
176         BOARD_ME4670,
177         BOARD_ME4670I,
178         BOARD_ME4670S,
179         BOARD_ME4670IS,
180         BOARD_ME4680,
181         BOARD_ME4680I,
182         BOARD_ME4680S,
183         BOARD_ME4680IS,
184 };
185 
186 struct me4000_board {
187         const char *name;
188         int ai_nchan;
189         unsigned int can_do_diff_ai:1;
190         unsigned int can_do_sh_ai:1;    /* sample & hold (8 channels) */
191         unsigned int ex_trig_analog:1;
192         unsigned int has_ao:1;
193         unsigned int has_ao_fifo:1;
194         unsigned int has_counter:1;
195 };
196 
197 static const struct me4000_board me4000_boards[] = {
198         [BOARD_ME4650] = {
199                 .name           = "ME-4650",
200                 .ai_nchan       = 16,
201         },
202         [BOARD_ME4660] = {
203                 .name           = "ME-4660",
204                 .ai_nchan       = 32,
205                 .can_do_diff_ai = 1,
206                 .has_counter    = 1,
207         },
208         [BOARD_ME4660I] = {
209                 .name           = "ME-4660i",
210                 .ai_nchan       = 32,
211                 .can_do_diff_ai = 1,
212                 .has_counter    = 1,
213         },
214         [BOARD_ME4660S] = {
215                 .name           = "ME-4660s",
216                 .ai_nchan       = 32,
217                 .can_do_diff_ai = 1,
218                 .can_do_sh_ai   = 1,
219                 .has_counter    = 1,
220         },
221         [BOARD_ME4660IS] = {
222                 .name           = "ME-4660is",
223                 .ai_nchan       = 32,
224                 .can_do_diff_ai = 1,
225                 .can_do_sh_ai   = 1,
226                 .has_counter    = 1,
227         },
228         [BOARD_ME4670] = {
229                 .name           = "ME-4670",
230                 .ai_nchan       = 32,
231                 .can_do_diff_ai = 1,
232                 .ex_trig_analog = 1,
233                 .has_ao         = 1,
234                 .has_counter    = 1,
235         },
236         [BOARD_ME4670I] = {
237                 .name           = "ME-4670i",
238                 .ai_nchan       = 32,
239                 .can_do_diff_ai = 1,
240                 .ex_trig_analog = 1,
241                 .has_ao         = 1,
242                 .has_counter    = 1,
243         },
244         [BOARD_ME4670S] = {
245                 .name           = "ME-4670s",
246                 .ai_nchan       = 32,
247                 .can_do_diff_ai = 1,
248                 .can_do_sh_ai   = 1,
249                 .ex_trig_analog = 1,
250                 .has_ao         = 1,
251                 .has_counter    = 1,
252         },
253         [BOARD_ME4670IS] = {
254                 .name           = "ME-4670is",
255                 .ai_nchan       = 32,
256                 .can_do_diff_ai = 1,
257                 .can_do_sh_ai   = 1,
258                 .ex_trig_analog = 1,
259                 .has_ao         = 1,
260                 .has_counter    = 1,
261         },
262         [BOARD_ME4680] = {
263                 .name           = "ME-4680",
264                 .ai_nchan       = 32,
265                 .can_do_diff_ai = 1,
266                 .ex_trig_analog = 1,
267                 .has_ao         = 1,
268                 .has_ao_fifo    = 1,
269                 .has_counter    = 1,
270         },
271         [BOARD_ME4680I] = {
272                 .name           = "ME-4680i",
273                 .ai_nchan       = 32,
274                 .can_do_diff_ai = 1,
275                 .ex_trig_analog = 1,
276                 .has_ao         = 1,
277                 .has_ao_fifo    = 1,
278                 .has_counter    = 1,
279         },
280         [BOARD_ME4680S] = {
281                 .name           = "ME-4680s",
282                 .ai_nchan       = 32,
283                 .can_do_diff_ai = 1,
284                 .can_do_sh_ai   = 1,
285                 .ex_trig_analog = 1,
286                 .has_ao         = 1,
287                 .has_ao_fifo    = 1,
288                 .has_counter    = 1,
289         },
290         [BOARD_ME4680IS] = {
291                 .name           = "ME-4680is",
292                 .ai_nchan       = 32,
293                 .can_do_diff_ai = 1,
294                 .can_do_sh_ai   = 1,
295                 .ex_trig_analog = 1,
296                 .has_ao         = 1,
297                 .has_ao_fifo    = 1,
298                 .has_counter    = 1,
299         },
300 };
301 
302 /*
303  * NOTE: the ranges here are inverted compared to the values
304  * written to the ME4000_AI_CHANNEL_LIST_REG,
305  *
306  * The ME4000_AI_LIST_RANGE() macro handles the inversion.
307  */
308 static const struct comedi_lrange me4000_ai_range = {
309         4, {
310                 UNI_RANGE(2.5),
311                 UNI_RANGE(10),
312                 BIP_RANGE(2.5),
313                 BIP_RANGE(10)
314         }
315 };
316 
317 static int me4000_xilinx_download(struct comedi_device *dev,
318                                   const u8 *data, size_t size,
319                                   unsigned long context)
320 {
321         struct pci_dev *pcidev = comedi_to_pci_dev(dev);
322         struct me4000_private *devpriv = dev->private;
323         unsigned long xilinx_iobase = pci_resource_start(pcidev, 5);
324         unsigned int file_length;
325         unsigned int val;
326         unsigned int i;
327 
328         if (!xilinx_iobase)
329                 return -ENODEV;
330 
331         /*
332          * Set PLX local interrupt 2 polarity to high.
333          * Interrupt is thrown by init pin of xilinx.
334          */
335         outl(PLX9052_INTCSR_LI2POL, devpriv->plx_regbase + PLX9052_INTCSR);
336 
337         /* Set /CS and /WRITE of the Xilinx */
338         val = inl(devpriv->plx_regbase + PLX9052_CNTRL);
339         val |= PLX9052_CNTRL_UIO2_DATA;
340         outl(val, devpriv->plx_regbase + PLX9052_CNTRL);
341 
342         /* Init Xilinx with CS1 */
343         inb(xilinx_iobase + 0xC8);
344 
345         /* Wait until /INIT pin is set */
346         usleep_range(20, 1000);
347         val = inl(devpriv->plx_regbase + PLX9052_INTCSR);
348         if (!(val & PLX9052_INTCSR_LI2STAT)) {
349                 dev_err(dev->class_dev, "Can't init Xilinx\n");
350                 return -EIO;
351         }
352 
353         /* Reset /CS and /WRITE of the Xilinx */
354         val = inl(devpriv->plx_regbase + PLX9052_CNTRL);
355         val &= ~PLX9052_CNTRL_UIO2_DATA;
356         outl(val, devpriv->plx_regbase + PLX9052_CNTRL);
357 
358         /* Download Xilinx firmware */
359         file_length = (((unsigned int)data[0] & 0xff) << 24) +
360                       (((unsigned int)data[1] & 0xff) << 16) +
361                       (((unsigned int)data[2] & 0xff) << 8) +
362                       ((unsigned int)data[3] & 0xff);
363         usleep_range(10, 1000);
364 
365         for (i = 0; i < file_length; i++) {
366                 outb(data[16 + i], xilinx_iobase);
367                 usleep_range(10, 1000);
368 
369                 /* Check if BUSY flag is low */
370                 val = inl(devpriv->plx_regbase + PLX9052_CNTRL);
371                 if (val & PLX9052_CNTRL_UIO1_DATA) {
372                         dev_err(dev->class_dev,
373                                 "Xilinx is still busy (i = %d)\n", i);
374                         return -EIO;
375                 }
376         }
377 
378         /* If done flag is high download was successful */
379         val = inl(devpriv->plx_regbase + PLX9052_CNTRL);
380         if (!(val & PLX9052_CNTRL_UIO0_DATA)) {
381                 dev_err(dev->class_dev, "DONE flag is not set\n");
382                 dev_err(dev->class_dev, "Download not successful\n");
383                 return -EIO;
384         }
385 
386         /* Set /CS and /WRITE */
387         val = inl(devpriv->plx_regbase + PLX9052_CNTRL);
388         val |= PLX9052_CNTRL_UIO2_DATA;
389         outl(val, devpriv->plx_regbase + PLX9052_CNTRL);
390 
391         return 0;
392 }
393 
394 static void me4000_ai_reset(struct comedi_device *dev)
395 {
396         unsigned int ctrl;
397 
398         /* Stop any running conversion */
399         ctrl = inl(dev->iobase + ME4000_AI_CTRL_REG);
400         ctrl |= ME4000_AI_CTRL_STOP | ME4000_AI_CTRL_IMMEDIATE_STOP;
401         outl(ctrl, dev->iobase + ME4000_AI_CTRL_REG);
402 
403         /* Clear the control register */
404         outl(0x0, dev->iobase + ME4000_AI_CTRL_REG);
405 }
406 
407 static void me4000_reset(struct comedi_device *dev)
408 {
409         struct me4000_private *devpriv = dev->private;
410         unsigned int val;
411         int chan;
412 
413         /* Disable interrupts on the PLX */
414         outl(0, devpriv->plx_regbase + PLX9052_INTCSR);
415 
416         /* Software reset the PLX */
417         val = inl(devpriv->plx_regbase + PLX9052_CNTRL);
418         val |= PLX9052_CNTRL_PCI_RESET;
419         outl(val, devpriv->plx_regbase + PLX9052_CNTRL);
420         val &= ~PLX9052_CNTRL_PCI_RESET;
421         outl(val, devpriv->plx_regbase + PLX9052_CNTRL);
422 
423         /* 0x8000 to the DACs means an output voltage of 0V */
424         for (chan = 0; chan < 4; chan++)
425                 outl(0x8000, dev->iobase + ME4000_AO_SINGLE_REG(chan));
426 
427         me4000_ai_reset(dev);
428 
429         /* Set both stop bits in the analog output control register */
430         val = ME4000_AO_CTRL_IMMEDIATE_STOP | ME4000_AO_CTRL_STOP;
431         for (chan = 0; chan < 4; chan++)
432                 outl(val, dev->iobase + ME4000_AO_CTRL_REG(chan));
433 
434         /* Set the adustment register for AO demux */
435         outl(ME4000_AO_DEMUX_ADJUST_VALUE,
436              dev->iobase + ME4000_AO_DEMUX_ADJUST_REG);
437 
438         /*
439          * Set digital I/O direction for port 0
440          * to output on isolated versions
441          */
442         if (!(inl(dev->iobase + ME4000_DIO_DIR_REG) & 0x1))
443                 outl(0x1, dev->iobase + ME4000_DIO_CTRL_REG);
444 }
445 
446 static unsigned int me4000_ai_get_sample(struct comedi_device *dev,
447                                          struct comedi_subdevice *s)
448 {
449         unsigned int val;
450 
451         /* read two's complement value and munge to offset binary */
452         val = inl(dev->iobase + ME4000_AI_DATA_REG);
453         return comedi_offset_munge(s, val);
454 }
455 
456 static int me4000_ai_eoc(struct comedi_device *dev,
457                          struct comedi_subdevice *s,
458                          struct comedi_insn *insn,
459                          unsigned long context)
460 {
461         unsigned int status;
462 
463         status = inl(dev->iobase + ME4000_AI_STATUS_REG);
464         if (status & ME4000_AI_STATUS_EF_DATA)
465                 return 0;
466         return -EBUSY;
467 }
468 
469 static int me4000_ai_insn_read(struct comedi_device *dev,
470                                struct comedi_subdevice *s,
471                                struct comedi_insn *insn,
472                                unsigned int *data)
473 {
474         unsigned int chan = CR_CHAN(insn->chanspec);
475         unsigned int range = CR_RANGE(insn->chanspec);
476         unsigned int aref = CR_AREF(insn->chanspec);
477         unsigned int entry;
478         int ret = 0;
479         int i;
480 
481         entry = chan | ME4000_AI_LIST_RANGE(range);
482         if (aref == AREF_DIFF) {
483                 if (!(s->subdev_flags & SDF_DIFF)) {
484                         dev_err(dev->class_dev,
485                                 "Differential inputs are not available\n");
486                         return -EINVAL;
487                 }
488 
489                 if (!comedi_range_is_bipolar(s, range)) {
490                         dev_err(dev->class_dev,
491                                 "Range must be bipolar when aref = diff\n");
492                         return -EINVAL;
493                 }
494 
495                 if (chan >= (s->n_chan / 2)) {
496                         dev_err(dev->class_dev,
497                                 "Analog input is not available\n");
498                         return -EINVAL;
499                 }
500                 entry |= ME4000_AI_LIST_INPUT_DIFFERENTIAL;
501         }
502 
503         entry |= ME4000_AI_LIST_LAST_ENTRY;
504 
505         /* Enable channel list and data fifo for single acquisition mode */
506         outl(ME4000_AI_CTRL_CHANNEL_FIFO | ME4000_AI_CTRL_DATA_FIFO,
507              dev->iobase + ME4000_AI_CTRL_REG);
508 
509         /* Generate channel list entry */
510         outl(entry, dev->iobase + ME4000_AI_CHANNEL_LIST_REG);
511 
512         /* Set the timer to maximum sample rate */
513         outl(ME4000_AI_MIN_TICKS, dev->iobase + ME4000_AI_CHAN_TIMER_REG);
514         outl(ME4000_AI_MIN_TICKS, dev->iobase + ME4000_AI_CHAN_PRE_TIMER_REG);
515 
516         for (i = 0; i < insn->n; i++) {
517                 unsigned int val;
518 
519                 /* start conversion by dummy read */
520                 inl(dev->iobase + ME4000_AI_START_REG);
521 
522                 ret = comedi_timeout(dev, s, insn, me4000_ai_eoc, 0);
523                 if (ret)
524                         break;
525 
526                 val = me4000_ai_get_sample(dev, s);
527                 data[i] = comedi_offset_munge(s, val);
528         }
529 
530         me4000_ai_reset(dev);
531 
532         return ret ? ret : insn->n;
533 }
534 
535 static int me4000_ai_cancel(struct comedi_device *dev,
536                             struct comedi_subdevice *s)
537 {
538         me4000_ai_reset(dev);
539 
540         return 0;
541 }
542 
543 static int me4000_ai_check_chanlist(struct comedi_device *dev,
544                                     struct comedi_subdevice *s,
545                                     struct comedi_cmd *cmd)
546 {
547         unsigned int aref0 = CR_AREF(cmd->chanlist[0]);
548         int i;
549 
550         for (i = 0; i < cmd->chanlist_len; i++) {
551                 unsigned int chan = CR_CHAN(cmd->chanlist[i]);
552                 unsigned int range = CR_RANGE(cmd->chanlist[i]);
553                 unsigned int aref = CR_AREF(cmd->chanlist[i]);
554 
555                 if (aref != aref0) {
556                         dev_dbg(dev->class_dev,
557                                 "Mode is not equal for all entries\n");
558                         return -EINVAL;
559                 }
560 
561                 if (aref == AREF_DIFF) {
562                         if (!(s->subdev_flags & SDF_DIFF)) {
563                                 dev_err(dev->class_dev,
564                                         "Differential inputs are not available\n");
565                                 return -EINVAL;
566                         }
567 
568                         if (chan >= (s->n_chan / 2)) {
569                                 dev_dbg(dev->class_dev,
570                                         "Channel number to high\n");
571                                 return -EINVAL;
572                         }
573 
574                         if (!comedi_range_is_bipolar(s, range)) {
575                                 dev_dbg(dev->class_dev,
576                                         "Bipolar is not selected in differential mode\n");
577                                 return -EINVAL;
578                         }
579                 }
580         }
581 
582         return 0;
583 }
584 
585 static void me4000_ai_round_cmd_args(struct comedi_device *dev,
586                                      struct comedi_subdevice *s,
587                                      struct comedi_cmd *cmd)
588 {
589         struct me4000_private *devpriv = dev->private;
590         int rest;
591 
592         devpriv->ai_init_ticks = 0;
593         devpriv->ai_scan_ticks = 0;
594         devpriv->ai_chan_ticks = 0;
595 
596         if (cmd->start_arg) {
597                 devpriv->ai_init_ticks = (cmd->start_arg * 33) / 1000;
598                 rest = (cmd->start_arg * 33) % 1000;
599 
600                 if ((cmd->flags & CMDF_ROUND_MASK) == CMDF_ROUND_NEAREST) {
601                         if (rest > 33)
602                                 devpriv->ai_init_ticks++;
603                 } else if ((cmd->flags & CMDF_ROUND_MASK) == CMDF_ROUND_UP) {
604                         if (rest)
605                                 devpriv->ai_init_ticks++;
606                 }
607         }
608 
609         if (cmd->scan_begin_arg) {
610                 devpriv->ai_scan_ticks = (cmd->scan_begin_arg * 33) / 1000;
611                 rest = (cmd->scan_begin_arg * 33) % 1000;
612 
613                 if ((cmd->flags & CMDF_ROUND_MASK) == CMDF_ROUND_NEAREST) {
614                         if (rest > 33)
615                                 devpriv->ai_scan_ticks++;
616                 } else if ((cmd->flags & CMDF_ROUND_MASK) == CMDF_ROUND_UP) {
617                         if (rest)
618                                 devpriv->ai_scan_ticks++;
619                 }
620         }
621 
622         if (cmd->convert_arg) {
623                 devpriv->ai_chan_ticks = (cmd->convert_arg * 33) / 1000;
624                 rest = (cmd->convert_arg * 33) % 1000;
625 
626                 if ((cmd->flags & CMDF_ROUND_MASK) == CMDF_ROUND_NEAREST) {
627                         if (rest > 33)
628                                 devpriv->ai_chan_ticks++;
629                 } else if ((cmd->flags & CMDF_ROUND_MASK) == CMDF_ROUND_UP) {
630                         if (rest)
631                                 devpriv->ai_chan_ticks++;
632                 }
633         }
634 }
635 
636 static void me4000_ai_write_chanlist(struct comedi_device *dev,
637                                      struct comedi_subdevice *s,
638                                      struct comedi_cmd *cmd)
639 {
640         int i;
641 
642         for (i = 0; i < cmd->chanlist_len; i++) {
643                 unsigned int chan = CR_CHAN(cmd->chanlist[i]);
644                 unsigned int range = CR_RANGE(cmd->chanlist[i]);
645                 unsigned int aref = CR_AREF(cmd->chanlist[i]);
646                 unsigned int entry;
647 
648                 entry = chan | ME4000_AI_LIST_RANGE(range);
649 
650                 if (aref == AREF_DIFF)
651                         entry |= ME4000_AI_LIST_INPUT_DIFFERENTIAL;
652 
653                 if (i == (cmd->chanlist_len - 1))
654                         entry |= ME4000_AI_LIST_LAST_ENTRY;
655 
656                 outl(entry, dev->iobase + ME4000_AI_CHANNEL_LIST_REG);
657         }
658 }
659 
660 static int me4000_ai_do_cmd(struct comedi_device *dev,
661                             struct comedi_subdevice *s)
662 {
663         struct me4000_private *devpriv = dev->private;
664         struct comedi_cmd *cmd = &s->async->cmd;
665         unsigned int ctrl;
666 
667         /* Write timer arguments */
668         outl(devpriv->ai_init_ticks - 1,
669              dev->iobase + ME4000_AI_SCAN_PRE_TIMER_LOW_REG);
670         outl(0x0, dev->iobase + ME4000_AI_SCAN_PRE_TIMER_HIGH_REG);
671 
672         if (devpriv->ai_scan_ticks) {
673                 outl(devpriv->ai_scan_ticks - 1,
674                      dev->iobase + ME4000_AI_SCAN_TIMER_LOW_REG);
675                 outl(0x0, dev->iobase + ME4000_AI_SCAN_TIMER_HIGH_REG);
676         }
677 
678         outl(devpriv->ai_chan_ticks - 1,
679              dev->iobase + ME4000_AI_CHAN_PRE_TIMER_REG);
680         outl(devpriv->ai_chan_ticks - 1,
681              dev->iobase + ME4000_AI_CHAN_TIMER_REG);
682 
683         /* Start sources */
684         ctrl = devpriv->ai_ctrl_mode |
685                ME4000_AI_CTRL_CHANNEL_FIFO |
686                ME4000_AI_CTRL_DATA_FIFO;
687 
688         /* Stop triggers */
689         if (cmd->stop_src == TRIG_COUNT) {
690                 outl(cmd->chanlist_len * cmd->stop_arg,
691                      dev->iobase + ME4000_AI_SAMPLE_COUNTER_REG);
692                 ctrl |= ME4000_AI_CTRL_SC_IRQ;
693         } else if (cmd->stop_src == TRIG_NONE &&
694                    cmd->scan_end_src == TRIG_COUNT) {
695                 outl(cmd->scan_end_arg,
696                      dev->iobase + ME4000_AI_SAMPLE_COUNTER_REG);
697                 ctrl |= ME4000_AI_CTRL_SC_IRQ;
698         }
699         ctrl |= ME4000_AI_CTRL_HF_IRQ;
700 
701         /* Write the setup to the control register */
702         outl(ctrl, dev->iobase + ME4000_AI_CTRL_REG);
703 
704         /* Write the channel list */
705         me4000_ai_write_chanlist(dev, s, cmd);
706 
707         /* Start acquistion by dummy read */
708         inl(dev->iobase + ME4000_AI_START_REG);
709 
710         return 0;
711 }
712 
713 static int me4000_ai_do_cmd_test(struct comedi_device *dev,
714                                  struct comedi_subdevice *s,
715                                  struct comedi_cmd *cmd)
716 {
717         struct me4000_private *devpriv = dev->private;
718         int err = 0;
719 
720         /* Step 1 : check if triggers are trivially valid */
721 
722         err |= comedi_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_EXT);
723         err |= comedi_check_trigger_src(&cmd->scan_begin_src,
724                                         TRIG_FOLLOW | TRIG_TIMER | TRIG_EXT);
725         err |= comedi_check_trigger_src(&cmd->convert_src,
726                                         TRIG_TIMER | TRIG_EXT);
727         err |= comedi_check_trigger_src(&cmd->scan_end_src,
728                                         TRIG_NONE | TRIG_COUNT);
729         err |= comedi_check_trigger_src(&cmd->stop_src, TRIG_NONE | TRIG_COUNT);
730 
731         if (err)
732                 return 1;
733 
734         /* Step 2a : make sure trigger sources are unique */
735 
736         err |= comedi_check_trigger_is_unique(cmd->start_src);
737         err |= comedi_check_trigger_is_unique(cmd->scan_begin_src);
738         err |= comedi_check_trigger_is_unique(cmd->convert_src);
739         err |= comedi_check_trigger_is_unique(cmd->scan_end_src);
740         err |= comedi_check_trigger_is_unique(cmd->stop_src);
741 
742         /* Step 2b : and mutually compatible */
743 
744         if (cmd->start_src == TRIG_NOW &&
745             cmd->scan_begin_src == TRIG_TIMER &&
746             cmd->convert_src == TRIG_TIMER) {
747                 devpriv->ai_ctrl_mode = ME4000_AI_CTRL_MODE_0;
748         } else if (cmd->start_src == TRIG_NOW &&
749                    cmd->scan_begin_src == TRIG_FOLLOW &&
750                    cmd->convert_src == TRIG_TIMER) {
751                 devpriv->ai_ctrl_mode = ME4000_AI_CTRL_MODE_0;
752         } else if (cmd->start_src == TRIG_EXT &&
753                    cmd->scan_begin_src == TRIG_TIMER &&
754                    cmd->convert_src == TRIG_TIMER) {
755                 devpriv->ai_ctrl_mode = ME4000_AI_CTRL_MODE_1;
756         } else if (cmd->start_src == TRIG_EXT &&
757                    cmd->scan_begin_src == TRIG_FOLLOW &&
758                    cmd->convert_src == TRIG_TIMER) {
759                 devpriv->ai_ctrl_mode = ME4000_AI_CTRL_MODE_1;
760         } else if (cmd->start_src == TRIG_EXT &&
761                    cmd->scan_begin_src == TRIG_EXT &&
762                    cmd->convert_src == TRIG_TIMER) {
763                 devpriv->ai_ctrl_mode = ME4000_AI_CTRL_MODE_2;
764         } else if (cmd->start_src == TRIG_EXT &&
765                    cmd->scan_begin_src == TRIG_EXT &&
766                    cmd->convert_src == TRIG_EXT) {
767                 devpriv->ai_ctrl_mode = ME4000_AI_CTRL_MODE_0 |
768                                         ME4000_AI_CTRL_MODE_1;
769         } else {
770                 err |= -EINVAL;
771         }
772 
773         if (err)
774                 return 2;
775 
776         /* Step 3: check if arguments are trivially valid */
777 
778         err |= comedi_check_trigger_arg_is(&cmd->start_arg, 0);
779 
780         if (cmd->chanlist_len < 1) {
781                 cmd->chanlist_len = 1;
782                 err |= -EINVAL;
783         }
784 
785         /* Round the timer arguments */
786         me4000_ai_round_cmd_args(dev, s, cmd);
787 
788         if (devpriv->ai_init_ticks < 66) {
789                 cmd->start_arg = 2000;
790                 err |= -EINVAL;
791         }
792         if (devpriv->ai_scan_ticks && devpriv->ai_scan_ticks < 67) {
793                 cmd->scan_begin_arg = 2031;
794                 err |= -EINVAL;
795         }
796         if (devpriv->ai_chan_ticks < 66) {
797                 cmd->convert_arg = 2000;
798                 err |= -EINVAL;
799         }
800 
801         if (cmd->stop_src == TRIG_COUNT)
802                 err |= comedi_check_trigger_arg_min(&cmd->stop_arg, 1);
803         else    /* TRIG_NONE */
804                 err |= comedi_check_trigger_arg_is(&cmd->stop_arg, 0);
805 
806         if (err)
807                 return 3;
808 
809         /*
810          * Stage 4. Check for argument conflicts.
811          */
812         if (cmd->start_src == TRIG_NOW &&
813             cmd->scan_begin_src == TRIG_TIMER &&
814             cmd->convert_src == TRIG_TIMER) {
815                 /* Check timer arguments */
816                 if (devpriv->ai_init_ticks < ME4000_AI_MIN_TICKS) {
817                         dev_err(dev->class_dev, "Invalid start arg\n");
818                         cmd->start_arg = 2000;  /*  66 ticks at least */
819                         err++;
820                 }
821                 if (devpriv->ai_chan_ticks < ME4000_AI_MIN_TICKS) {
822                         dev_err(dev->class_dev, "Invalid convert arg\n");
823                         cmd->convert_arg = 2000;        /*  66 ticks at least */
824                         err++;
825                 }
826                 if (devpriv->ai_scan_ticks <=
827                     cmd->chanlist_len * devpriv->ai_chan_ticks) {
828                         dev_err(dev->class_dev, "Invalid scan end arg\n");
829 
830                         /*  At least one tick more */
831                         cmd->scan_end_arg = 2000 * cmd->chanlist_len + 31;
832                         err++;
833                 }
834         } else if (cmd->start_src == TRIG_NOW &&
835                    cmd->scan_begin_src == TRIG_FOLLOW &&
836                    cmd->convert_src == TRIG_TIMER) {
837                 /* Check timer arguments */
838                 if (devpriv->ai_init_ticks < ME4000_AI_MIN_TICKS) {
839                         dev_err(dev->class_dev, "Invalid start arg\n");
840                         cmd->start_arg = 2000;  /*  66 ticks at least */
841                         err++;
842                 }
843                 if (devpriv->ai_chan_ticks < ME4000_AI_MIN_TICKS) {
844                         dev_err(dev->class_dev, "Invalid convert arg\n");
845                         cmd->convert_arg = 2000;        /*  66 ticks at least */
846                         err++;
847                 }
848         } else if (cmd->start_src == TRIG_EXT &&
849                    cmd->scan_begin_src == TRIG_TIMER &&
850                    cmd->convert_src == TRIG_TIMER) {
851                 /* Check timer arguments */
852                 if (devpriv->ai_init_ticks < ME4000_AI_MIN_TICKS) {
853                         dev_err(dev->class_dev, "Invalid start arg\n");
854                         cmd->start_arg = 2000;  /*  66 ticks at least */
855                         err++;
856                 }
857                 if (devpriv->ai_chan_ticks < ME4000_AI_MIN_TICKS) {
858                         dev_err(dev->class_dev, "Invalid convert arg\n");
859                         cmd->convert_arg = 2000;        /*  66 ticks at least */
860                         err++;
861                 }
862                 if (devpriv->ai_scan_ticks <=
863                     cmd->chanlist_len * devpriv->ai_chan_ticks) {
864                         dev_err(dev->class_dev, "Invalid scan end arg\n");
865 
866                         /*  At least one tick more */
867                         cmd->scan_end_arg = 2000 * cmd->chanlist_len + 31;
868                         err++;
869                 }
870         } else if (cmd->start_src == TRIG_EXT &&
871                    cmd->scan_begin_src == TRIG_FOLLOW &&
872                    cmd->convert_src == TRIG_TIMER) {
873                 /* Check timer arguments */
874                 if (devpriv->ai_init_ticks < ME4000_AI_MIN_TICKS) {
875                         dev_err(dev->class_dev, "Invalid start arg\n");
876                         cmd->start_arg = 2000;  /*  66 ticks at least */
877                         err++;
878                 }
879                 if (devpriv->ai_chan_ticks < ME4000_AI_MIN_TICKS) {
880                         dev_err(dev->class_dev, "Invalid convert arg\n");
881                         cmd->convert_arg = 2000;        /*  66 ticks at least */
882                         err++;
883                 }
884         } else if (cmd->start_src == TRIG_EXT &&
885                    cmd->scan_begin_src == TRIG_EXT &&
886                    cmd->convert_src == TRIG_TIMER) {
887                 /* Check timer arguments */
888                 if (devpriv->ai_init_ticks < ME4000_AI_MIN_TICKS) {
889                         dev_err(dev->class_dev, "Invalid start arg\n");
890                         cmd->start_arg = 2000;  /*  66 ticks at least */
891                         err++;
892                 }
893                 if (devpriv->ai_chan_ticks < ME4000_AI_MIN_TICKS) {
894                         dev_err(dev->class_dev, "Invalid convert arg\n");
895                         cmd->convert_arg = 2000;        /*  66 ticks at least */
896                         err++;
897                 }
898         } else if (cmd->start_src == TRIG_EXT &&
899                    cmd->scan_begin_src == TRIG_EXT &&
900                    cmd->convert_src == TRIG_EXT) {
901                 /* Check timer arguments */
902                 if (devpriv->ai_init_ticks < ME4000_AI_MIN_TICKS) {
903                         dev_err(dev->class_dev, "Invalid start arg\n");
904                         cmd->start_arg = 2000;  /*  66 ticks at least */
905                         err++;
906                 }
907         }
908         if (cmd->scan_end_src == TRIG_COUNT) {
909                 if (cmd->scan_end_arg == 0) {
910                         dev_err(dev->class_dev, "Invalid scan end arg\n");
911                         cmd->scan_end_arg = 1;
912                         err++;
913                 }
914         }
915 
916         if (err)
917                 return 4;
918 
919         /* Step 5: check channel list if it exists */
920         if (cmd->chanlist && cmd->chanlist_len > 0)
921                 err |= me4000_ai_check_chanlist(dev, s, cmd);
922 
923         if (err)
924                 return 5;
925 
926         return 0;
927 }
928 
929 static irqreturn_t me4000_ai_isr(int irq, void *dev_id)
930 {
931         unsigned int tmp;
932         struct comedi_device *dev = dev_id;
933         struct comedi_subdevice *s = dev->read_subdev;
934         int i;
935         int c = 0;
936         unsigned int lval;
937 
938         if (!dev->attached)
939                 return IRQ_NONE;
940 
941         if (inl(dev->iobase + ME4000_IRQ_STATUS_REG) &
942             ME4000_IRQ_STATUS_AI_HF) {
943                 /* Read status register to find out what happened */
944                 tmp = inl(dev->iobase + ME4000_AI_STATUS_REG);
945 
946                 if (!(tmp & ME4000_AI_STATUS_FF_DATA) &&
947                     !(tmp & ME4000_AI_STATUS_HF_DATA) &&
948                     (tmp & ME4000_AI_STATUS_EF_DATA)) {
949                         dev_err(dev->class_dev, "FIFO overflow\n");
950                         s->async->events |= COMEDI_CB_ERROR;
951                         c = ME4000_AI_FIFO_COUNT;
952                 } else if ((tmp & ME4000_AI_STATUS_FF_DATA) &&
953                            !(tmp & ME4000_AI_STATUS_HF_DATA) &&
954                            (tmp & ME4000_AI_STATUS_EF_DATA)) {
955                         c = ME4000_AI_FIFO_COUNT / 2;
956                 } else {
957                         dev_err(dev->class_dev, "Undefined FIFO state\n");
958                         s->async->events |= COMEDI_CB_ERROR;
959                         c = 0;
960                 }
961 
962                 for (i = 0; i < c; i++) {
963                         lval = me4000_ai_get_sample(dev, s);
964                         if (!comedi_buf_write_samples(s, &lval, 1))
965                                 break;
966                 }
967 
968                 /* Work is done, so reset the interrupt */
969                 tmp |= ME4000_AI_CTRL_HF_IRQ_RESET;
970                 outl(tmp, dev->iobase + ME4000_AI_CTRL_REG);
971                 tmp &= ~ME4000_AI_CTRL_HF_IRQ_RESET;
972                 outl(tmp, dev->iobase + ME4000_AI_CTRL_REG);
973         }
974 
975         if (inl(dev->iobase + ME4000_IRQ_STATUS_REG) &
976             ME4000_IRQ_STATUS_SC) {
977                 /* Acquisition is complete */
978                 s->async->events |= COMEDI_CB_EOA;
979 
980                 /* Poll data until fifo empty */
981                 while (inl(dev->iobase + ME4000_AI_STATUS_REG) &
982                        ME4000_AI_STATUS_EF_DATA) {
983                         lval = me4000_ai_get_sample(dev, s);
984                         if (!comedi_buf_write_samples(s, &lval, 1))
985                                 break;
986                 }
987 
988                 /* Work is done, so reset the interrupt */
989                 tmp = inl(dev->iobase + ME4000_AI_CTRL_REG);
990                 tmp |= ME4000_AI_CTRL_SC_IRQ_RESET;
991                 outl(tmp, dev->iobase + ME4000_AI_CTRL_REG);
992                 tmp &= ~ME4000_AI_CTRL_SC_IRQ_RESET;
993                 outl(tmp, dev->iobase + ME4000_AI_CTRL_REG);
994         }
995 
996         comedi_handle_events(dev, s);
997 
998         return IRQ_HANDLED;
999 }
1000 
1001 static int me4000_ao_insn_write(struct comedi_device *dev,
1002                                 struct comedi_subdevice *s,
1003                                 struct comedi_insn *insn,
1004                                 unsigned int *data)
1005 {
1006         unsigned int chan = CR_CHAN(insn->chanspec);
1007         unsigned int tmp;
1008 
1009         /* Stop any running conversion */
1010         tmp = inl(dev->iobase + ME4000_AO_CTRL_REG(chan));
1011         tmp |= ME4000_AO_CTRL_IMMEDIATE_STOP;
1012         outl(tmp, dev->iobase + ME4000_AO_CTRL_REG(chan));
1013 
1014         /* Clear control register and set to single mode */
1015         outl(0x0, dev->iobase + ME4000_AO_CTRL_REG(chan));
1016 
1017         /* Write data value */
1018         outl(data[0], dev->iobase + ME4000_AO_SINGLE_REG(chan));
1019 
1020         /* Store in the mirror */
1021         s->readback[chan] = data[0];
1022 
1023         return 1;
1024 }
1025 
1026 static int me4000_dio_insn_bits(struct comedi_device *dev,
1027                                 struct comedi_subdevice *s,
1028                                 struct comedi_insn *insn,
1029                                 unsigned int *data)
1030 {
1031         if (comedi_dio_update_state(s, data)) {
1032                 outl((s->state >> 0) & 0xFF,
1033                      dev->iobase + ME4000_DIO_PORT_0_REG);
1034                 outl((s->state >> 8) & 0xFF,
1035                      dev->iobase + ME4000_DIO_PORT_1_REG);
1036                 outl((s->state >> 16) & 0xFF,
1037                      dev->iobase + ME4000_DIO_PORT_2_REG);
1038                 outl((s->state >> 24) & 0xFF,
1039                      dev->iobase + ME4000_DIO_PORT_3_REG);
1040         }
1041 
1042         data[1] = ((inl(dev->iobase + ME4000_DIO_PORT_0_REG) & 0xFF) << 0) |
1043                   ((inl(dev->iobase + ME4000_DIO_PORT_1_REG) & 0xFF) << 8) |
1044                   ((inl(dev->iobase + ME4000_DIO_PORT_2_REG) & 0xFF) << 16) |
1045                   ((inl(dev->iobase + ME4000_DIO_PORT_3_REG) & 0xFF) << 24);
1046 
1047         return insn->n;
1048 }
1049 
1050 static int me4000_dio_insn_config(struct comedi_device *dev,
1051                                   struct comedi_subdevice *s,
1052                                   struct comedi_insn *insn,
1053                                   unsigned int *data)
1054 {
1055         unsigned int chan = CR_CHAN(insn->chanspec);
1056         unsigned int mask;
1057         unsigned int tmp;
1058         int ret;
1059 
1060         if (chan < 8)
1061                 mask = 0x000000ff;
1062         else if (chan < 16)
1063                 mask = 0x0000ff00;
1064         else if (chan < 24)
1065                 mask = 0x00ff0000;
1066         else
1067                 mask = 0xff000000;
1068 
1069         ret = comedi_dio_insn_config(dev, s, insn, data, mask);
1070         if (ret)
1071                 return ret;
1072 
1073         tmp = inl(dev->iobase + ME4000_DIO_CTRL_REG);
1074         tmp &= ~(ME4000_DIO_CTRL_MODE_0 | ME4000_DIO_CTRL_MODE_1 |
1075                  ME4000_DIO_CTRL_MODE_2 | ME4000_DIO_CTRL_MODE_3 |
1076                  ME4000_DIO_CTRL_MODE_4 | ME4000_DIO_CTRL_MODE_5 |
1077                  ME4000_DIO_CTRL_MODE_6 | ME4000_DIO_CTRL_MODE_7);
1078         if (s->io_bits & 0x000000ff)
1079                 tmp |= ME4000_DIO_CTRL_MODE_0;
1080         if (s->io_bits & 0x0000ff00)
1081                 tmp |= ME4000_DIO_CTRL_MODE_2;
1082         if (s->io_bits & 0x00ff0000)
1083                 tmp |= ME4000_DIO_CTRL_MODE_4;
1084         if (s->io_bits & 0xff000000)
1085                 tmp |= ME4000_DIO_CTRL_MODE_6;
1086 
1087         /*
1088          * Check for optoisolated ME-4000 version.
1089          * If one the first port is a fixed output
1090          * port and the second is a fixed input port.
1091          */
1092         if (inl(dev->iobase + ME4000_DIO_DIR_REG)) {
1093                 s->io_bits |= 0x000000ff;
1094                 s->io_bits &= ~0x0000ff00;
1095                 tmp |= ME4000_DIO_CTRL_MODE_0;
1096                 tmp &= ~(ME4000_DIO_CTRL_MODE_2 | ME4000_DIO_CTRL_MODE_3);
1097         }
1098 
1099         outl(tmp, dev->iobase + ME4000_DIO_CTRL_REG);
1100 
1101         return insn->n;
1102 }
1103 
1104 static int me4000_auto_attach(struct comedi_device *dev,
1105                               unsigned long context)
1106 {
1107         struct pci_dev *pcidev = comedi_to_pci_dev(dev);
1108         const struct me4000_board *board = NULL;
1109         struct me4000_private *devpriv;
1110         struct comedi_subdevice *s;
1111         int result;
1112 
1113         if (context < ARRAY_SIZE(me4000_boards))
1114                 board = &me4000_boards[context];
1115         if (!board)
1116                 return -ENODEV;
1117         dev->board_ptr = board;
1118         dev->board_name = board->name;
1119 
1120         devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
1121         if (!devpriv)
1122                 return -ENOMEM;
1123 
1124         result = comedi_pci_enable(dev);
1125         if (result)
1126                 return result;
1127 
1128         devpriv->plx_regbase = pci_resource_start(pcidev, 1);
1129         dev->iobase = pci_resource_start(pcidev, 2);
1130         if (!devpriv->plx_regbase || !dev->iobase)
1131                 return -ENODEV;
1132 
1133         result = comedi_load_firmware(dev, &pcidev->dev, ME4000_FIRMWARE,
1134                                       me4000_xilinx_download, 0);
1135         if (result < 0)
1136                 return result;
1137 
1138         me4000_reset(dev);
1139 
1140         if (pcidev->irq > 0) {
1141                 result = request_irq(pcidev->irq, me4000_ai_isr, IRQF_SHARED,
1142                                      dev->board_name, dev);
1143                 if (result == 0) {
1144                         dev->irq = pcidev->irq;
1145 
1146                         /* Enable interrupts on the PLX */
1147                         outl(PLX9052_INTCSR_LI1ENAB | PLX9052_INTCSR_LI1POL |
1148                              PLX9052_INTCSR_PCIENAB,
1149                              devpriv->plx_regbase + PLX9052_INTCSR);
1150                 }
1151         }
1152 
1153         result = comedi_alloc_subdevices(dev, 4);
1154         if (result)
1155                 return result;
1156 
1157         /* Analog Input subdevice */
1158         s = &dev->subdevices[0];
1159         s->type         = COMEDI_SUBD_AI;
1160         s->subdev_flags = SDF_READABLE | SDF_COMMON | SDF_GROUND;
1161         if (board->can_do_diff_ai)
1162                 s->subdev_flags |= SDF_DIFF;
1163         s->n_chan       = board->ai_nchan;
1164         s->maxdata      = 0xffff;
1165         s->len_chanlist = ME4000_AI_CHANNEL_LIST_COUNT;
1166         s->range_table  = &me4000_ai_range;
1167         s->insn_read    = me4000_ai_insn_read;
1168 
1169         if (dev->irq) {
1170                 dev->read_subdev = s;
1171                 s->subdev_flags |= SDF_CMD_READ;
1172                 s->cancel       = me4000_ai_cancel;
1173                 s->do_cmdtest   = me4000_ai_do_cmd_test;
1174                 s->do_cmd       = me4000_ai_do_cmd;
1175         }
1176 
1177         /* Analog Output subdevice */
1178         s = &dev->subdevices[1];
1179         if (board->has_ao) {
1180                 s->type         = COMEDI_SUBD_AO;
1181                 s->subdev_flags = SDF_WRITABLE | SDF_COMMON | SDF_GROUND;
1182                 s->n_chan       = 4;
1183                 s->maxdata      = 0xffff;
1184                 s->range_table  = &range_bipolar10;
1185                 s->insn_write   = me4000_ao_insn_write;
1186 
1187                 result = comedi_alloc_subdev_readback(s);
1188                 if (result)
1189                         return result;
1190         } else {
1191                 s->type         = COMEDI_SUBD_UNUSED;
1192         }
1193 
1194         /* Digital I/O subdevice */
1195         s = &dev->subdevices[2];
1196         s->type         = COMEDI_SUBD_DIO;
1197         s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
1198         s->n_chan       = 32;
1199         s->maxdata      = 1;
1200         s->range_table  = &range_digital;
1201         s->insn_bits    = me4000_dio_insn_bits;
1202         s->insn_config  = me4000_dio_insn_config;
1203 
1204         /*
1205          * Check for optoisolated ME-4000 version. If one the first
1206          * port is a fixed output port and the second is a fixed input port.
1207          */
1208         if (!inl(dev->iobase + ME4000_DIO_DIR_REG)) {
1209                 s->io_bits |= 0xFF;
1210                 outl(ME4000_DIO_CTRL_MODE_0,
1211                      dev->iobase + ME4000_DIO_DIR_REG);
1212         }
1213 
1214         /* Counter subdevice (8254) */
1215         s = &dev->subdevices[3];
1216         if (board->has_counter) {
1217                 unsigned long timer_base = pci_resource_start(pcidev, 3);
1218 
1219                 if (!timer_base)
1220                         return -ENODEV;
1221 
1222                 dev->pacer = comedi_8254_init(timer_base, 0, I8254_IO8, 0);
1223                 if (!dev->pacer)
1224                         return -ENOMEM;
1225 
1226                 comedi_8254_subdevice_init(s, dev->pacer);
1227         } else {
1228                 s->type = COMEDI_SUBD_UNUSED;
1229         }
1230 
1231         return 0;
1232 }
1233 
1234 static void me4000_detach(struct comedi_device *dev)
1235 {
1236         if (dev->irq) {
1237                 struct me4000_private *devpriv = dev->private;
1238 
1239                 /* Disable interrupts on the PLX */
1240                 outl(0, devpriv->plx_regbase + PLX9052_INTCSR);
1241         }
1242         comedi_pci_detach(dev);
1243 }
1244 
1245 static struct comedi_driver me4000_driver = {
1246         .driver_name    = "me4000",
1247         .module         = THIS_MODULE,
1248         .auto_attach    = me4000_auto_attach,
1249         .detach         = me4000_detach,
1250 };
1251 
1252 static int me4000_pci_probe(struct pci_dev *dev,
1253                             const struct pci_device_id *id)
1254 {
1255         return comedi_pci_auto_config(dev, &me4000_driver, id->driver_data);
1256 }
1257 
1258 static const struct pci_device_id me4000_pci_table[] = {
1259         { PCI_VDEVICE(MEILHAUS, 0x4650), BOARD_ME4650 },
1260         { PCI_VDEVICE(MEILHAUS, 0x4660), BOARD_ME4660 },
1261         { PCI_VDEVICE(MEILHAUS, 0x4661), BOARD_ME4660I },
1262         { PCI_VDEVICE(MEILHAUS, 0x4662), BOARD_ME4660S },
1263         { PCI_VDEVICE(MEILHAUS, 0x4663), BOARD_ME4660IS },
1264         { PCI_VDEVICE(MEILHAUS, 0x4670), BOARD_ME4670 },
1265         { PCI_VDEVICE(MEILHAUS, 0x4671), BOARD_ME4670I },
1266         { PCI_VDEVICE(MEILHAUS, 0x4672), BOARD_ME4670S },
1267         { PCI_VDEVICE(MEILHAUS, 0x4673), BOARD_ME4670IS },
1268         { PCI_VDEVICE(MEILHAUS, 0x4680), BOARD_ME4680 },
1269         { PCI_VDEVICE(MEILHAUS, 0x4681), BOARD_ME4680I },
1270         { PCI_VDEVICE(MEILHAUS, 0x4682), BOARD_ME4680S },
1271         { PCI_VDEVICE(MEILHAUS, 0x4683), BOARD_ME4680IS },
1272         { 0 }
1273 };
1274 MODULE_DEVICE_TABLE(pci, me4000_pci_table);
1275 
1276 static struct pci_driver me4000_pci_driver = {
1277         .name           = "me4000",
1278         .id_table       = me4000_pci_table,
1279         .probe          = me4000_pci_probe,
1280         .remove         = comedi_pci_auto_unconfig,
1281 };
1282 module_comedi_pci_driver(me4000_driver, me4000_pci_driver);
1283 
1284 MODULE_AUTHOR("Comedi http://www.comedi.org");
1285 MODULE_DESCRIPTION("Comedi driver for Meilhaus ME-4000 series boards");
1286 MODULE_LICENSE("GPL");
1287 MODULE_FIRMWARE(ME4000_FIRMWARE);
1288 

This page was automatically generated by LXR 0.3.1 (source).  •  Linux is a registered trademark of Linus Torvalds  •  Contact us