linux/drivers/staging/comedi/drivers/me4000.c
<<
>>
Prefs
   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
 162struct 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
 170enum 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
 186struct 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
 197static 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 */
 308static 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
 317static 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
 394static 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
 407static 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
 446static 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
 456static 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
 469static 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
 535static 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
 543static 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
 585static 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
 636static 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
 660static 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
 713static 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
 929static 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
1001static 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
1026static 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
1050static 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
1104static 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
1234static 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
1245static 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
1252static 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
1258static 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};
1274MODULE_DEVICE_TABLE(pci, me4000_pci_table);
1275
1276static 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};
1282module_comedi_pci_driver(me4000_driver, me4000_pci_driver);
1283
1284MODULE_AUTHOR("Comedi http://www.comedi.org");
1285MODULE_DESCRIPTION("Comedi driver for Meilhaus ME-4000 series boards");
1286MODULE_LICENSE("GPL");
1287MODULE_FIRMWARE(ME4000_FIRMWARE);
1288
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.