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