root/drivers/staging/comedi/drivers/me4000.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. me4000_xilinx_download
  2. me4000_ai_reset
  3. me4000_reset
  4. me4000_ai_get_sample
  5. me4000_ai_eoc
  6. me4000_ai_insn_read
  7. me4000_ai_cancel
  8. me4000_ai_check_chanlist
  9. me4000_ai_round_cmd_args
  10. me4000_ai_write_chanlist
  11. me4000_ai_do_cmd
  12. me4000_ai_do_cmd_test
  13. me4000_ai_isr
  14. me4000_ao_insn_write
  15. me4000_dio_insn_bits
  16. me4000_dio_insn_config
  17. me4000_auto_attach
  18. me4000_detach
  19. me4000_pci_probe

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

/* [<][>][^][v][top][bottom][index][help] */