linux/drivers/staging/comedi/drivers/rtd520.c
<<
>>
Prefs
   1/*
   2    comedi/drivers/rtd520.c
   3    Comedi driver for Real Time Devices (RTD) PCI4520/DM7520
   4
   5    COMEDI - Linux Control and Measurement Device Interface
   6    Copyright (C) 2001 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/*
  23Driver: rtd520
  24Description: Real Time Devices PCI4520/DM7520
  25Author: Dan Christian
  26Devices: [Real Time Devices] DM7520HR-1 (rtd520), DM7520HR-8,
  27  PCI4520, PCI4520-8
  28Status: Works.  Only tested on DM7520-8.  Not SMP safe.
  29
  30Configuration options:
  31  [0] - PCI bus of device (optional)
  32          If bus/slot is not specified, the first available PCI
  33          device will be used.
  34  [1] - PCI slot of device (optional)
  35*/
  36/*
  37    Created by Dan Christian, NASA Ames Research Center.
  38
  39    The PCI4520 is a PCI card.  The DM7520 is a PC/104-plus card.
  40    Both have:
  41    8/16 12 bit ADC with FIFO and channel gain table
  42    8 bits high speed digital out (for external MUX) (or 8 in or 8 out)
  43    8 bits high speed digital in with FIFO and interrupt on change (or 8 IO)
  44    2 12 bit DACs with FIFOs
  45    2 bits output
  46    2 bits input
  47    bus mastering DMA
  48    timers: ADC sample, pacer, burst, about, delay, DA1, DA2
  49    sample counter
  50    3 user timer/counters (8254)
  51    external interrupt
  52
  53    The DM7520 has slightly fewer features (fewer gain steps).
  54
  55    These boards can support external multiplexors and multi-board
  56    synchronization, but this driver doesn't support that.
  57
  58    Board docs: http://www.rtdusa.com/PC104/DM/analog%20IO/dm7520.htm
  59    Data sheet: http://www.rtdusa.com/pdf/dm7520.pdf
  60    Example source: http://www.rtdusa.com/examples/dm/dm7520.zip
  61    Call them and ask for the register level manual.
  62    PCI chip: http://www.plxtech.com/products/toolbox/9080.htm
  63
  64    Notes:
  65    This board is memory mapped.  There is some IO stuff, but it isn't needed.
  66
  67    I use a pretty loose naming style within the driver (rtd_blah).
  68    All externally visible names should be rtd520_blah.
  69    I use camelCase for structures (and inside them).
  70    I may also use upper CamelCase for function names (old habit).
  71
  72    This board is somewhat related to the RTD PCI4400 board.
  73
  74    I borrowed heavily from the ni_mio_common, ni_atmio16d, mite, and
  75    das1800, since they have the best documented code.  Driver
  76    cb_pcidas64.c uses the same DMA controller.
  77
  78    As far as I can tell, the About interrupt doesnt work if Sample is
  79    also enabled.  It turns out that About really isn't needed, since
  80    we always count down samples read.
  81
  82    There was some timer/counter code, but it didn't follow the right API.
  83
  84*/
  85
  86/*
  87  driver status:
  88
  89  Analog-In supports instruction and command mode.
  90
  91  With DMA, you can sample at 1.15Mhz with 70% idle on a 400Mhz K6-2
  92  (single channel, 64K read buffer).  I get random system lockups when
  93  using DMA with ALI-15xx based systems.  I haven't been able to test
  94  any other chipsets.  The lockups happen soon after the start of an
  95  acquistion, not in the middle of a long run.
  96
  97  Without DMA, you can do 620Khz sampling with 20% idle on a 400Mhz K6-2
  98  (with a 256K read buffer).
  99
 100  Digital-IO and Analog-Out only support instruction mode.
 101
 102*/
 103
 104#include <linux/interrupt.h>
 105#include <linux/delay.h>
 106
 107#include "../comedidev.h"
 108#include "comedi_pci.h"
 109
 110#define DRV_NAME "rtd520"
 111
 112/*======================================================================
 113  Driver specific stuff (tunable)
 114======================================================================*/
 115/* Enable this to test the new DMA support. You may get hard lock ups */
 116/*#define USE_DMA*/
 117
 118/* We really only need 2 buffers.  More than that means being much
 119   smarter about knowing which ones are full. */
 120#define DMA_CHAIN_COUNT 2       /* max DMA segments/buffers in a ring (min 2) */
 121
 122/* Target period for periodic transfers.  This sets the user read latency. */
 123/* Note: There are certain rates where we give this up and transfer 1/2 FIFO */
 124/* If this is too low, efficiency is poor */
 125#define TRANS_TARGET_PERIOD 10000000    /* 10 ms (in nanoseconds) */
 126
 127/* Set a practical limit on how long a list to support (affects memory use) */
 128/* The board support a channel list up to the FIFO length (1K or 8K) */
 129#define RTD_MAX_CHANLIST        128     /* max channel list that we allow */
 130
 131/* tuning for ai/ao instruction done polling */
 132#ifdef FAST_SPIN
 133#define WAIT_QUIETLY            /* as nothing, spin on done bit */
 134#define RTD_ADC_TIMEOUT 66000   /* 2 msec at 33mhz bus rate */
 135#define RTD_DAC_TIMEOUT 66000
 136#define RTD_DMA_TIMEOUT 33000   /* 1 msec */
 137#else
 138/* by delaying, power and electrical noise are reduced somewhat */
 139#define WAIT_QUIETLY    udelay (1)
 140#define RTD_ADC_TIMEOUT 2000    /* in usec */
 141#define RTD_DAC_TIMEOUT 2000    /* in usec */
 142#define RTD_DMA_TIMEOUT 1000    /* in usec */
 143#endif
 144
 145/*======================================================================
 146  Board specific stuff
 147======================================================================*/
 148
 149/* registers  */
 150#define PCI_VENDOR_ID_RTD       0x1435
 151/*
 152  The board has three memory windows: las0, las1, and lcfg (the PCI chip)
 153  Las1 has the data and can be burst DMAed 32bits at a time.
 154*/
 155#define LCFG_PCIINDEX   0
 156/* PCI region 1 is a 256 byte IO space mapping.  Use??? */
 157#define LAS0_PCIINDEX   2       /* PCI memory resources */
 158#define LAS1_PCIINDEX   3
 159#define LCFG_PCISIZE    0x100
 160#define LAS0_PCISIZE    0x200
 161#define LAS1_PCISIZE    0x10
 162
 163#define RTD_CLOCK_RATE  8000000 /* 8Mhz onboard clock */
 164#define RTD_CLOCK_BASE  125     /* clock period in ns */
 165
 166/* Note: these speed are slower than the spec, but fit the counter resolution*/
 167#define RTD_MAX_SPEED   1625    /* when sampling, in nanoseconds */
 168/* max speed if we don't have to wait for settling */
 169#define RTD_MAX_SPEED_1 875     /* if single channel, in nanoseconds */
 170
 171#define RTD_MIN_SPEED   2097151875      /* (24bit counter) in nanoseconds */
 172/* min speed when only 1 channel (no burst counter) */
 173#define RTD_MIN_SPEED_1 5000000 /* 200Hz, in nanoseconds */
 174
 175#include "rtd520.h"
 176#include "plx9080.h"
 177
 178/* Setup continuous ring of 1/2 FIFO transfers.  See RTD manual p91 */
 179#define DMA_MODE_BITS (\
 180                       PLX_LOCAL_BUS_16_WIDE_BITS \
 181                       | PLX_DMA_EN_READYIN_BIT \
 182                       | PLX_DMA_LOCAL_BURST_EN_BIT \
 183                       | PLX_EN_CHAIN_BIT \
 184                       | PLX_DMA_INTR_PCI_BIT \
 185                       | PLX_LOCAL_ADDR_CONST_BIT \
 186                       | PLX_DEMAND_MODE_BIT)
 187
 188#define DMA_TRANSFER_BITS (\
 189/* descriptors in PCI memory*/  PLX_DESC_IN_PCI_BIT \
 190/* interrupt at end of block */ | PLX_INTR_TERM_COUNT \
 191/* from board to PCI */         | PLX_XFER_LOCAL_TO_PCI)
 192
 193/*======================================================================
 194  Comedi specific stuff
 195======================================================================*/
 196
 197/*
 198  The board has 3 input modes and the gains of 1,2,4,...32 (, 64, 128)
 199*/
 200static const struct comedi_lrange rtd_ai_7520_range = { 18, {
 201                                                             /* +-5V input range gain steps */
 202                                                             BIP_RANGE(5.0),
 203                                                             BIP_RANGE(5.0 / 2),
 204                                                             BIP_RANGE(5.0 / 4),
 205                                                             BIP_RANGE(5.0 / 8),
 206                                                             BIP_RANGE(5.0 /
 207                                                                       16),
 208                                                             BIP_RANGE(5.0 /
 209                                                                       32),
 210                                                             /* +-10V input range gain steps */
 211                                                             BIP_RANGE(10.0),
 212                                                             BIP_RANGE(10.0 /
 213                                                                       2),
 214                                                             BIP_RANGE(10.0 /
 215                                                                       4),
 216                                                             BIP_RANGE(10.0 /
 217                                                                       8),
 218                                                             BIP_RANGE(10.0 /
 219                                                                       16),
 220                                                             BIP_RANGE(10.0 /
 221                                                                       32),
 222                                                             /* +10V input range gain steps */
 223                                                             UNI_RANGE(10.0),
 224                                                             UNI_RANGE(10.0 /
 225                                                                       2),
 226                                                             UNI_RANGE(10.0 /
 227                                                                       4),
 228                                                             UNI_RANGE(10.0 /
 229                                                                       8),
 230                                                             UNI_RANGE(10.0 /
 231                                                                       16),
 232                                                             UNI_RANGE(10.0 /
 233                                                                       32),
 234
 235                                                             }
 236};
 237
 238/* PCI4520 has two more gains (6 more entries) */
 239static const struct comedi_lrange rtd_ai_4520_range = { 24, {
 240                                                             /* +-5V input range gain steps */
 241                                                             BIP_RANGE(5.0),
 242                                                             BIP_RANGE(5.0 / 2),
 243                                                             BIP_RANGE(5.0 / 4),
 244                                                             BIP_RANGE(5.0 / 8),
 245                                                             BIP_RANGE(5.0 /
 246                                                                       16),
 247                                                             BIP_RANGE(5.0 /
 248                                                                       32),
 249                                                             BIP_RANGE(5.0 /
 250                                                                       64),
 251                                                             BIP_RANGE(5.0 /
 252                                                                       128),
 253                                                             /* +-10V input range gain steps */
 254                                                             BIP_RANGE(10.0),
 255                                                             BIP_RANGE(10.0 /
 256                                                                       2),
 257                                                             BIP_RANGE(10.0 /
 258                                                                       4),
 259                                                             BIP_RANGE(10.0 /
 260                                                                       8),
 261                                                             BIP_RANGE(10.0 /
 262                                                                       16),
 263                                                             BIP_RANGE(10.0 /
 264                                                                       32),
 265                                                             BIP_RANGE(10.0 /
 266                                                                       64),
 267                                                             BIP_RANGE(10.0 /
 268                                                                       128),
 269                                                             /* +10V input range gain steps */
 270                                                             UNI_RANGE(10.0),
 271                                                             UNI_RANGE(10.0 /
 272                                                                       2),
 273                                                             UNI_RANGE(10.0 /
 274                                                                       4),
 275                                                             UNI_RANGE(10.0 /
 276                                                                       8),
 277                                                             UNI_RANGE(10.0 /
 278                                                                       16),
 279                                                             UNI_RANGE(10.0 /
 280                                                                       32),
 281                                                             UNI_RANGE(10.0 /
 282                                                                       64),
 283                                                             UNI_RANGE(10.0 /
 284                                                                       128),
 285                                                             }
 286};
 287
 288/* Table order matches range values */
 289static const struct comedi_lrange rtd_ao_range = { 4, {
 290                                                       RANGE(0, 5),
 291                                                       RANGE(0, 10),
 292                                                       RANGE(-5, 5),
 293                                                       RANGE(-10, 10),
 294                                                       }
 295};
 296
 297/*
 298  Board descriptions
 299 */
 300struct rtdBoard {
 301        const char *name;       /* must be first */
 302        int device_id;
 303        int aiChans;
 304        int aiBits;
 305        int aiMaxGain;
 306        int range10Start;       /* start of +-10V range */
 307        int rangeUniStart;      /* start of +10V range */
 308};
 309
 310static const struct rtdBoard rtd520Boards[] = {
 311        {
 312         .name = "DM7520",
 313         .device_id = 0x7520,
 314         .aiChans = 16,
 315         .aiBits = 12,
 316         .aiMaxGain = 32,
 317         .range10Start = 6,
 318         .rangeUniStart = 12,
 319         },
 320        {
 321         .name = "PCI4520",
 322         .device_id = 0x4520,
 323         .aiChans = 16,
 324         .aiBits = 12,
 325         .aiMaxGain = 128,
 326         .range10Start = 8,
 327         .rangeUniStart = 16,
 328         },
 329};
 330
 331static DEFINE_PCI_DEVICE_TABLE(rtd520_pci_table) = {
 332        {
 333        PCI_VENDOR_ID_RTD, 0x7520, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {
 334        PCI_VENDOR_ID_RTD, 0x4520, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {
 335        0}
 336};
 337
 338MODULE_DEVICE_TABLE(pci, rtd520_pci_table);
 339
 340/*
 341 * Useful for shorthand access to the particular board structure
 342 */
 343#define thisboard ((const struct rtdBoard *)dev->board_ptr)
 344
 345/*
 346   This structure is for data unique to this hardware driver.
 347   This is also unique for each board in the system.
 348*/
 349struct rtdPrivate {
 350        /* memory mapped board structures */
 351        void *las0;
 352        void *las1;
 353        void *lcfg;
 354
 355        unsigned long intCount; /* interrupt count */
 356        long aiCount;           /* total transfer size (samples) */
 357        int transCount;         /* # to tranfer data. 0->1/2FIFO */
 358        int flags;              /* flag event modes */
 359
 360        /* PCI device info */
 361        struct pci_dev *pci_dev;
 362        int got_regions;        /* non-zero if PCI regions owned */
 363
 364        /* channel list info */
 365        /* chanBipolar tracks whether a channel is bipolar (and needs +2048) */
 366        unsigned char chanBipolar[RTD_MAX_CHANLIST / 8];        /* bit array */
 367
 368        /* read back data */
 369        unsigned int aoValue[2];        /* Used for AO read back */
 370
 371        /* timer gate (when enabled) */
 372        u8 utcGate[4];          /* 1 extra allows simple range check */
 373
 374        /* shadow registers affect other registers, but cant be read back */
 375        /* The macros below update these on writes */
 376        u16 intMask;            /* interrupt mask */
 377        u16 intClearMask;       /* interrupt clear mask */
 378        u8 utcCtrl[4];          /* crtl mode for 3 utc + read back */
 379        u8 dioStatus;           /* could be read back (dio0Ctrl) */
 380#ifdef USE_DMA
 381        /* Always DMA 1/2 FIFO.  Buffer (dmaBuff?) is (at least) twice that size.
 382           After transferring, interrupt processes 1/2 FIFO and passes to comedi */
 383        s16 dma0Offset;         /* current processing offset (0, 1/2) */
 384        uint16_t *dma0Buff[DMA_CHAIN_COUNT];    /* DMA buffers (for ADC) */
 385        dma_addr_t dma0BuffPhysAddr[DMA_CHAIN_COUNT];   /* physical addresses */
 386        struct plx_dma_desc *dma0Chain; /* DMA descriptor ring for dmaBuff */
 387        dma_addr_t dma0ChainPhysAddr;   /* physical addresses */
 388        /* shadow registers */
 389        u8 dma0Control;
 390        u8 dma1Control;
 391#endif                          /* USE_DMA */
 392        unsigned fifoLen;
 393};
 394
 395/* bit defines for "flags" */
 396#define SEND_EOS        0x01    /* send End Of Scan events */
 397#define DMA0_ACTIVE     0x02    /* DMA0 is active */
 398#define DMA1_ACTIVE     0x04    /* DMA1 is active */
 399
 400/* Macros for accessing channel list bit array */
 401#define CHAN_ARRAY_TEST(array, index) \
 402        (((array)[(index)/8] >> ((index) & 0x7)) & 0x1)
 403#define CHAN_ARRAY_SET(array, index) \
 404        (((array)[(index)/8] |= 1 << ((index) & 0x7)))
 405#define CHAN_ARRAY_CLEAR(array, index) \
 406        (((array)[(index)/8] &= ~(1 << ((index) & 0x7))))
 407
 408/*
 409 * most drivers define the following macro to make it easy to
 410 * access the private structure.
 411 */
 412#define devpriv ((struct rtdPrivate *)dev->private)
 413
 414/* Macros to access registers */
 415
 416/* Reset board */
 417#define RtdResetBoard(dev) \
 418    writel (0, devpriv->las0+LAS0_BOARD_RESET)
 419
 420/* Reset channel gain table read pointer */
 421#define RtdResetCGT(dev) \
 422    writel (0, devpriv->las0+LAS0_CGT_RESET)
 423
 424/* Reset channel gain table read and write pointers */
 425#define RtdClearCGT(dev) \
 426    writel (0, devpriv->las0+LAS0_CGT_CLEAR)
 427
 428/* Reset channel gain table read and write pointers */
 429#define RtdEnableCGT(dev, v) \
 430    writel ((v > 0) ? 1 : 0, devpriv->las0+LAS0_CGT_ENABLE)
 431
 432/* Write channel gain table entry */
 433#define RtdWriteCGTable(dev, v) \
 434    writel (v, devpriv->las0+LAS0_CGT_WRITE)
 435
 436/* Write Channel Gain Latch */
 437#define RtdWriteCGLatch(dev, v) \
 438    writel (v, devpriv->las0+LAS0_CGL_WRITE)
 439
 440/* Reset ADC FIFO */
 441#define RtdAdcClearFifo(dev) \
 442    writel (0, devpriv->las0+LAS0_ADC_FIFO_CLEAR)
 443
 444/* Set ADC start conversion source select (write only) */
 445#define RtdAdcConversionSource(dev, v) \
 446    writel (v, devpriv->las0+LAS0_ADC_CONVERSION)
 447
 448/* Set burst start source select (write only) */
 449#define RtdBurstStartSource(dev, v) \
 450    writel (v, devpriv->las0+LAS0_BURST_START)
 451
 452/* Set Pacer start source select (write only) */
 453#define RtdPacerStartSource(dev, v) \
 454    writel (v, devpriv->las0+LAS0_PACER_START)
 455
 456/* Set Pacer stop source select (write only) */
 457#define RtdPacerStopSource(dev, v) \
 458    writel (v, devpriv->las0+LAS0_PACER_STOP)
 459
 460/* Set Pacer clock source select (write only) 0=external 1=internal */
 461#define RtdPacerClockSource(dev, v) \
 462    writel ((v > 0) ? 1 : 0, devpriv->las0+LAS0_PACER_SELECT)
 463
 464/* Set sample counter source select (write only) */
 465#define RtdAdcSampleCounterSource(dev, v) \
 466    writel (v, devpriv->las0+LAS0_ADC_SCNT_SRC)
 467
 468/* Set Pacer trigger mode select (write only) 0=single cycle, 1=repeat */
 469#define RtdPacerTriggerMode(dev, v) \
 470    writel ((v > 0) ? 1 : 0, devpriv->las0+LAS0_PACER_REPEAT)
 471
 472/* Set About counter stop enable (write only) */
 473#define RtdAboutStopEnable(dev, v) \
 474    writel ((v > 0) ? 1 : 0, devpriv->las0+LAS0_ACNT_STOP_ENABLE)
 475
 476/* Set external trigger polarity (write only) 0=positive edge, 1=negative */
 477#define RtdTriggerPolarity(dev, v) \
 478    writel ((v > 0) ? 1 : 0, devpriv->las0+LAS0_ETRG_POLARITY)
 479
 480/* Start single ADC conversion */
 481#define RtdAdcStart(dev) \
 482    writew (0, devpriv->las0+LAS0_ADC)
 483
 484/* Read one ADC data value (12bit (with sign extend) as 16bit) */
 485/* Note: matches what DMA would get.  Actual value >> 3 */
 486#define RtdAdcFifoGet(dev) \
 487    readw (devpriv->las1+LAS1_ADC_FIFO)
 488
 489/* Read two ADC data values (DOESNT WORK) */
 490#define RtdAdcFifoGet2(dev) \
 491    readl (devpriv->las1+LAS1_ADC_FIFO)
 492
 493/* FIFO status */
 494#define RtdFifoStatus(dev) \
 495    readl (devpriv->las0+LAS0_ADC)
 496
 497/* pacer start/stop read=start, write=stop*/
 498#define RtdPacerStart(dev) \
 499    readl (devpriv->las0+LAS0_PACER)
 500#define RtdPacerStop(dev) \
 501    writel (0, devpriv->las0+LAS0_PACER)
 502
 503/* Interrupt status */
 504#define RtdInterruptStatus(dev) \
 505    readw (devpriv->las0+LAS0_IT)
 506
 507/* Interrupt mask */
 508#define RtdInterruptMask(dev, v) \
 509    writew ((devpriv->intMask = (v)), devpriv->las0+LAS0_IT)
 510
 511/* Interrupt status clear (only bits set in mask) */
 512#define RtdInterruptClear(dev) \
 513    readw (devpriv->las0+LAS0_CLEAR)
 514
 515/* Interrupt clear mask */
 516#define RtdInterruptClearMask(dev, v) \
 517    writew ((devpriv->intClearMask = (v)), devpriv->las0+LAS0_CLEAR)
 518
 519/* Interrupt overrun status */
 520#define RtdInterruptOverrunStatus(dev) \
 521    readl (devpriv->las0+LAS0_OVERRUN)
 522
 523/* Interrupt overrun clear */
 524#define RtdInterruptOverrunClear(dev) \
 525    writel (0, devpriv->las0+LAS0_OVERRUN)
 526
 527/* Pacer counter, 24bit */
 528#define RtdPacerCount(dev) \
 529    readl (devpriv->las0+LAS0_PCLK)
 530#define RtdPacerCounter(dev, v) \
 531    writel ((v) & 0xffffff, devpriv->las0+LAS0_PCLK)
 532
 533/* Burst counter, 10bit */
 534#define RtdBurstCount(dev) \
 535    readl (devpriv->las0+LAS0_BCLK)
 536#define RtdBurstCounter(dev, v) \
 537    writel ((v) & 0x3ff, devpriv->las0+LAS0_BCLK)
 538
 539/* Delay counter, 16bit */
 540#define RtdDelayCount(dev) \
 541    readl (devpriv->las0+LAS0_DCLK)
 542#define RtdDelayCounter(dev, v) \
 543    writel ((v) & 0xffff, devpriv->las0+LAS0_DCLK)
 544
 545/* About counter, 16bit */
 546#define RtdAboutCount(dev) \
 547    readl (devpriv->las0+LAS0_ACNT)
 548#define RtdAboutCounter(dev, v) \
 549    writel ((v) & 0xffff, devpriv->las0+LAS0_ACNT)
 550
 551/* ADC sample counter, 10bit */
 552#define RtdAdcSampleCount(dev) \
 553    readl (devpriv->las0+LAS0_ADC_SCNT)
 554#define RtdAdcSampleCounter(dev, v) \
 555    writel ((v) & 0x3ff, devpriv->las0+LAS0_ADC_SCNT)
 556
 557/* User Timer/Counter (8254) */
 558#define RtdUtcCounterGet(dev, n) \
 559    readb (devpriv->las0 \
 560        + ((n <= 0) ? LAS0_UTC0 : ((1 == n) ? LAS0_UTC1 : LAS0_UTC2)))
 561
 562#define RtdUtcCounterPut(dev, n, v) \
 563    writeb ((v) & 0xff, devpriv->las0 \
 564        + ((n <= 0) ? LAS0_UTC0 : ((1 == n) ? LAS0_UTC1 : LAS0_UTC2)))
 565
 566/* Set UTC (8254) control byte  */
 567#define RtdUtcCtrlPut(dev, n, v) \
 568    writeb (devpriv->utcCtrl[(n) & 3] = (((n) & 3) << 6) | ((v) & 0x3f), \
 569      devpriv->las0 + LAS0_UTC_CTRL)
 570
 571/* Set UTCn clock source (write only) */
 572#define RtdUtcClockSource(dev, n, v) \
 573    writew (v, devpriv->las0 \
 574        + ((n <= 0) ? LAS0_UTC0_CLOCK : \
 575           ((1 == n) ? LAS0_UTC1_CLOCK : LAS0_UTC2_CLOCK)))
 576
 577/* Set UTCn gate source (write only) */
 578#define RtdUtcGateSource(dev, n, v) \
 579    writew (v, devpriv->las0 \
 580        + ((n <= 0) ? LAS0_UTC0_GATE : \
 581           ((1 == n) ? LAS0_UTC1_GATE : LAS0_UTC2_GATE)))
 582
 583/* User output N source select (write only) */
 584#define RtdUsrOutSource(dev, n, v) \
 585    writel (v, devpriv->las0+((n <= 0) ? LAS0_UOUT0_SELECT : LAS0_UOUT1_SELECT))
 586
 587/* Digital IO */
 588#define RtdDio0Read(dev) \
 589    (readw (devpriv->las0+LAS0_DIO0) & 0xff)
 590#define RtdDio0Write(dev, v) \
 591    writew ((v) & 0xff, devpriv->las0+LAS0_DIO0)
 592
 593#define RtdDio1Read(dev) \
 594    (readw (devpriv->las0+LAS0_DIO1) & 0xff)
 595#define RtdDio1Write(dev, v) \
 596    writew ((v) & 0xff, devpriv->las0+LAS0_DIO1)
 597
 598#define RtdDioStatusRead(dev) \
 599    (readw (devpriv->las0+LAS0_DIO_STATUS) & 0xff)
 600#define RtdDioStatusWrite(dev, v) \
 601    writew ((devpriv->dioStatus = (v)), devpriv->las0+LAS0_DIO_STATUS)
 602
 603#define RtdDio0CtrlRead(dev) \
 604    (readw (devpriv->las0+LAS0_DIO0_CTRL) & 0xff)
 605#define RtdDio0CtrlWrite(dev, v) \
 606    writew ((v) & 0xff, devpriv->las0+LAS0_DIO0_CTRL)
 607
 608/* Digital to Analog converter */
 609/* Write one data value (sign + 12bit + marker bits) */
 610/* Note: matches what DMA would put.  Actual value << 3 */
 611#define RtdDacFifoPut(dev, n, v) \
 612    writew ((v), devpriv->las1 +(((n) == 0) ? LAS1_DAC1_FIFO : LAS1_DAC2_FIFO))
 613
 614/* Start single DAC conversion */
 615#define RtdDacUpdate(dev, n) \
 616    writew (0, devpriv->las0 +(((n) == 0) ? LAS0_DAC1 : LAS0_DAC2))
 617
 618/* Start single DAC conversion on both DACs */
 619#define RtdDacBothUpdate(dev) \
 620    writew (0, devpriv->las0+LAS0_DAC)
 621
 622/* Set DAC output type and range */
 623#define RtdDacRange(dev, n, v) \
 624    writew ((v) & 7, devpriv->las0 \
 625        +(((n) == 0) ? LAS0_DAC1_CTRL : LAS0_DAC2_CTRL))
 626
 627/* Reset DAC FIFO */
 628#define RtdDacClearFifo(dev, n) \
 629    writel (0, devpriv->las0+(((n) == 0) ? LAS0_DAC1_RESET : LAS0_DAC2_RESET))
 630
 631/* Set source for DMA 0 (write only, shadow?) */
 632#define RtdDma0Source(dev, n) \
 633    writel ((n) & 0xf, devpriv->las0+LAS0_DMA0_SRC)
 634
 635/* Set source for DMA 1 (write only, shadow?) */
 636#define RtdDma1Source(dev, n) \
 637    writel ((n) & 0xf, devpriv->las0+LAS0_DMA1_SRC)
 638
 639/* Reset board state for DMA 0 */
 640#define RtdDma0Reset(dev) \
 641    writel (0, devpriv->las0+LAS0_DMA0_RESET)
 642
 643/* Reset board state for DMA 1 */
 644#define RtdDma1Reset(dev) \
 645    writel (0, devpriv->las0+LAS0_DMA1_SRC)
 646
 647/* PLX9080 interrupt mask and status */
 648#define RtdPlxInterruptRead(dev) \
 649    readl (devpriv->lcfg+LCFG_ITCSR)
 650#define RtdPlxInterruptWrite(dev, v) \
 651    writel (v, devpriv->lcfg+LCFG_ITCSR)
 652
 653/* Set  mode for DMA 0 */
 654#define RtdDma0Mode(dev, m) \
 655    writel ((m), devpriv->lcfg+LCFG_DMAMODE0)
 656
 657/* Set PCI address for DMA 0 */
 658#define RtdDma0PciAddr(dev, a) \
 659    writel ((a), devpriv->lcfg+LCFG_DMAPADR0)
 660
 661/* Set local address for DMA 0 */
 662#define RtdDma0LocalAddr(dev, a) \
 663    writel ((a), devpriv->lcfg+LCFG_DMALADR0)
 664
 665/* Set byte count for DMA 0 */
 666#define RtdDma0Count(dev, c) \
 667    writel ((c), devpriv->lcfg+LCFG_DMASIZ0)
 668
 669/* Set next descriptor for DMA 0 */
 670#define RtdDma0Next(dev, a) \
 671    writel ((a), devpriv->lcfg+LCFG_DMADPR0)
 672
 673/* Set  mode for DMA 1 */
 674#define RtdDma1Mode(dev, m) \
 675    writel ((m), devpriv->lcfg+LCFG_DMAMODE1)
 676
 677/* Set PCI address for DMA 1 */
 678#define RtdDma1PciAddr(dev, a) \
 679    writel ((a), devpriv->lcfg+LCFG_DMAADR1)
 680
 681/* Set local address for DMA 1 */
 682#define RtdDma1LocalAddr(dev, a) \
 683    writel ((a), devpriv->lcfg+LCFG_DMALADR1)
 684
 685/* Set byte count for DMA 1 */
 686#define RtdDma1Count(dev, c) \
 687    writel ((c), devpriv->lcfg+LCFG_DMASIZ1)
 688
 689/* Set next descriptor for DMA 1 */
 690#define RtdDma1Next(dev, a) \
 691    writel ((a), devpriv->lcfg+LCFG_DMADPR1)
 692
 693/* Set control for DMA 0 (write only, shadow?) */
 694#define RtdDma0Control(dev, n) \
 695    writeb (devpriv->dma0Control = (n), devpriv->lcfg+LCFG_DMACSR0)
 696
 697/* Get status for DMA 0 */
 698#define RtdDma0Status(dev) \
 699    readb (devpriv->lcfg+LCFG_DMACSR0)
 700
 701/* Set control for DMA 1 (write only, shadow?) */
 702#define RtdDma1Control(dev, n) \
 703    writeb (devpriv->dma1Control = (n), devpriv->lcfg+LCFG_DMACSR1)
 704
 705/* Get status for DMA 1 */
 706#define RtdDma1Status(dev) \
 707    readb (devpriv->lcfg+LCFG_DMACSR1)
 708
 709/*
 710 * The struct comedi_driver structure tells the Comedi core module
 711 * which functions to call to configure/deconfigure (attac/detach)
 712 * the board, and also about the kernel module that contains
 713 * the device code.
 714 */
 715static int rtd_attach(struct comedi_device *dev, struct comedi_devconfig *it);
 716static int rtd_detach(struct comedi_device *dev);
 717
 718static struct comedi_driver rtd520Driver = {
 719        .driver_name = DRV_NAME,
 720        .module = THIS_MODULE,
 721        .attach = rtd_attach,
 722        .detach = rtd_detach,
 723};
 724
 725static int rtd_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
 726                        struct comedi_insn *insn, unsigned int *data);
 727static int rtd_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
 728                        struct comedi_insn *insn, unsigned int *data);
 729static int rtd_ao_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
 730                        struct comedi_insn *insn, unsigned int *data);
 731static int rtd_dio_insn_bits(struct comedi_device *dev,
 732                             struct comedi_subdevice *s,
 733                             struct comedi_insn *insn, unsigned int *data);
 734static int rtd_dio_insn_config(struct comedi_device *dev,
 735                               struct comedi_subdevice *s,
 736                               struct comedi_insn *insn, unsigned int *data);
 737static int rtd_ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
 738                          struct comedi_cmd *cmd);
 739static int rtd_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s);
 740static int rtd_ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s);
 741/* static int rtd_ai_poll (struct comedi_device *dev,struct comedi_subdevice *s); */
 742static int rtd_ns_to_timer(unsigned int *ns, int roundMode);
 743static irqreturn_t rtd_interrupt(int irq, void *d);
 744static int rtd520_probe_fifo_depth(struct comedi_device *dev);
 745
 746/*
 747 * Attach is called by the Comedi core to configure the driver
 748 * for a particular board.  If you specified a board_name array
 749 * in the driver structure, dev->board_ptr contains that
 750 * address.
 751 */
 752static int rtd_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 753{                               /* board name and options flags */
 754        struct comedi_subdevice *s;
 755        struct pci_dev *pcidev;
 756        int ret;
 757        resource_size_t physLas0;       /* configuation */
 758        resource_size_t physLas1;       /* data area */
 759        resource_size_t physLcfg;       /* PLX9080 */
 760#ifdef USE_DMA
 761        int index;
 762#endif
 763
 764        printk("comedi%d: rtd520 attaching.\n", dev->minor);
 765
 766#if defined (CONFIG_COMEDI_DEBUG) && defined (USE_DMA)
 767        /* You can set this a load time: modprobe comedi comedi_debug=1 */
 768        if (0 == comedi_debug)  /* force DMA debug printks */
 769                comedi_debug = 1;
 770#endif
 771
 772        /*
 773         * Allocate the private structure area.  alloc_private() is a
 774         * convenient macro defined in comedidev.h.
 775         */
 776        if (alloc_private(dev, sizeof(struct rtdPrivate)) < 0)
 777                return -ENOMEM;
 778
 779        /*
 780         * Probe the device to determine what device in the series it is.
 781         */
 782        for (pcidev = pci_get_device(PCI_VENDOR_ID_RTD, PCI_ANY_ID, NULL);
 783             pcidev != NULL;
 784             pcidev = pci_get_device(PCI_VENDOR_ID_RTD, PCI_ANY_ID, pcidev)) {
 785                int i;
 786
 787                if (it->options[0] || it->options[1]) {
 788                        if (pcidev->bus->number != it->options[0]
 789                            || PCI_SLOT(pcidev->devfn) != it->options[1]) {
 790                                continue;
 791                        }
 792                }
 793                for (i = 0; i < ARRAY_SIZE(rtd520Boards); ++i) {
 794                        if (pcidev->device == rtd520Boards[i].device_id) {
 795                                dev->board_ptr = &rtd520Boards[i];
 796                                break;
 797                        }
 798                }
 799                if (dev->board_ptr)
 800                        break;  /* found one */
 801        }
 802        if (!pcidev) {
 803                if (it->options[0] && it->options[1]) {
 804                        printk("No RTD card at bus=%d slot=%d.\n",
 805                               it->options[0], it->options[1]);
 806                } else {
 807                        printk("No RTD card found.\n");
 808                }
 809                return -EIO;
 810        }
 811        devpriv->pci_dev = pcidev;
 812        dev->board_name = thisboard->name;
 813
 814        ret = comedi_pci_enable(pcidev, DRV_NAME);
 815        if (ret < 0) {
 816                printk("Failed to enable PCI device and request regions.\n");
 817                return ret;
 818        }
 819        devpriv->got_regions = 1;
 820
 821        /*
 822         * Initialize base addresses
 823         */
 824        /* Get the physical address from PCI config */
 825        physLas0 = pci_resource_start(devpriv->pci_dev, LAS0_PCIINDEX);
 826        physLas1 = pci_resource_start(devpriv->pci_dev, LAS1_PCIINDEX);
 827        physLcfg = pci_resource_start(devpriv->pci_dev, LCFG_PCIINDEX);
 828        /* Now have the kernel map this into memory */
 829        /* ASSUME page aligned */
 830        devpriv->las0 = ioremap_nocache(physLas0, LAS0_PCISIZE);
 831        devpriv->las1 = ioremap_nocache(physLas1, LAS1_PCISIZE);
 832        devpriv->lcfg = ioremap_nocache(physLcfg, LCFG_PCISIZE);
 833
 834        if (!devpriv->las0 || !devpriv->las1 || !devpriv->lcfg) {
 835                return -ENOMEM;
 836        }
 837
 838        DPRINTK("%s: LAS0=%llx, LAS1=%llx, CFG=%llx.\n", dev->board_name,
 839                (unsigned long long)physLas0, (unsigned long long)physLas1,
 840                (unsigned long long)physLcfg);
 841        {                       /* The RTD driver does this */
 842                unsigned char pci_latency;
 843                u16 revision;
 844                /*uint32_t epld_version; */
 845
 846                pci_read_config_word(devpriv->pci_dev, PCI_REVISION_ID,
 847                                     &revision);
 848                DPRINTK("%s: PCI revision %d.\n", dev->board_name, revision);
 849
 850                pci_read_config_byte(devpriv->pci_dev,
 851                                     PCI_LATENCY_TIMER, &pci_latency);
 852                if (pci_latency < 32) {
 853                        printk("%s: PCI latency changed from %d to %d\n",
 854                               dev->board_name, pci_latency, 32);
 855                        pci_write_config_byte(devpriv->pci_dev,
 856                                              PCI_LATENCY_TIMER, 32);
 857                } else {
 858                        DPRINTK("rtd520: PCI latency = %d\n", pci_latency);
 859                }
 860
 861                /* Undocumented EPLD version (doesnt match RTD driver results) */
 862                /*DPRINTK ("rtd520: Reading epld from %p\n",
 863                   devpriv->las0+0);
 864                   epld_version = readl (devpriv->las0+0);
 865                   if ((epld_version & 0xF0) >> 4 == 0x0F) {
 866                   DPRINTK("rtd520: pre-v8 EPLD. (%x)\n", epld_version);
 867                   } else {
 868                   DPRINTK("rtd520: EPLD version %x.\n", epld_version >> 4);
 869                   } */
 870        }
 871
 872        /* Show board configuration */
 873        printk("%s:", dev->board_name);
 874
 875        /*
 876         * Allocate the subdevice structures.  alloc_subdevice() is a
 877         * convenient macro defined in comedidev.h.
 878         */
 879        if (alloc_subdevices(dev, 4) < 0) {
 880                return -ENOMEM;
 881        }
 882
 883        s = dev->subdevices + 0;
 884        dev->read_subdev = s;
 885        /* analog input subdevice */
 886        s->type = COMEDI_SUBD_AI;
 887        s->subdev_flags =
 888            SDF_READABLE | SDF_GROUND | SDF_COMMON | SDF_DIFF | SDF_CMD_READ;
 889        s->n_chan = thisboard->aiChans;
 890        s->maxdata = (1 << thisboard->aiBits) - 1;
 891        if (thisboard->aiMaxGain <= 32) {
 892                s->range_table = &rtd_ai_7520_range;
 893        } else {
 894                s->range_table = &rtd_ai_4520_range;
 895        }
 896        s->len_chanlist = RTD_MAX_CHANLIST;     /* devpriv->fifoLen */
 897        s->insn_read = rtd_ai_rinsn;
 898        s->do_cmd = rtd_ai_cmd;
 899        s->do_cmdtest = rtd_ai_cmdtest;
 900        s->cancel = rtd_ai_cancel;
 901        /* s->poll = rtd_ai_poll; *//* not ready yet */
 902
 903        s = dev->subdevices + 1;
 904        /* analog output subdevice */
 905        s->type = COMEDI_SUBD_AO;
 906        s->subdev_flags = SDF_WRITABLE;
 907        s->n_chan = 2;
 908        s->maxdata = (1 << thisboard->aiBits) - 1;
 909        s->range_table = &rtd_ao_range;
 910        s->insn_write = rtd_ao_winsn;
 911        s->insn_read = rtd_ao_rinsn;
 912
 913        s = dev->subdevices + 2;
 914        /* digital i/o subdevice */
 915        s->type = COMEDI_SUBD_DIO;
 916        s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
 917        /* we only support port 0 right now.  Ignoring port 1 and user IO */
 918        s->n_chan = 8;
 919        s->maxdata = 1;
 920        s->range_table = &range_digital;
 921        s->insn_bits = rtd_dio_insn_bits;
 922        s->insn_config = rtd_dio_insn_config;
 923
 924        /* timer/counter subdevices (not currently supported) */
 925        s = dev->subdevices + 3;
 926        s->type = COMEDI_SUBD_COUNTER;
 927        s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
 928        s->n_chan = 3;
 929        s->maxdata = 0xffff;
 930
 931        /* initialize board, per RTD spec */
 932        /* also, initialize shadow registers */
 933        RtdResetBoard(dev);
 934        udelay(100);            /* needed? */
 935        RtdPlxInterruptWrite(dev, 0);
 936        RtdInterruptMask(dev, 0);       /* and sets shadow */
 937        RtdInterruptClearMask(dev, ~0); /* and sets shadow */
 938        RtdInterruptClear(dev); /* clears bits set by mask */
 939        RtdInterruptOverrunClear(dev);
 940        RtdClearCGT(dev);
 941        RtdAdcClearFifo(dev);
 942        RtdDacClearFifo(dev, 0);
 943        RtdDacClearFifo(dev, 1);
 944        /* clear digital IO fifo */
 945        RtdDioStatusWrite(dev, 0);      /* safe state, set shadow */
 946        RtdUtcCtrlPut(dev, 0, 0x30);    /* safe state, set shadow */
 947        RtdUtcCtrlPut(dev, 1, 0x30);    /* safe state, set shadow */
 948        RtdUtcCtrlPut(dev, 2, 0x30);    /* safe state, set shadow */
 949        RtdUtcCtrlPut(dev, 3, 0);       /* safe state, set shadow */
 950        /* TODO: set user out source ??? */
 951
 952        /* check if our interrupt is available and get it */
 953        ret = request_irq(devpriv->pci_dev->irq, rtd_interrupt,
 954                          IRQF_SHARED, DRV_NAME, dev);
 955
 956        if (ret < 0) {
 957                printk("Could not get interrupt! (%u)\n",
 958                       devpriv->pci_dev->irq);
 959                return ret;
 960        }
 961        dev->irq = devpriv->pci_dev->irq;
 962        printk("( irq=%u )", dev->irq);
 963
 964        ret = rtd520_probe_fifo_depth(dev);
 965        if (ret < 0) {
 966                return ret;
 967        }
 968        devpriv->fifoLen = ret;
 969        printk("( fifoLen=%d )", devpriv->fifoLen);
 970
 971#ifdef USE_DMA
 972        if (dev->irq > 0) {
 973                printk("( DMA buff=%d )\n", DMA_CHAIN_COUNT);
 974                /* The PLX9080 has 2 DMA controllers, but there could be 4 sources:
 975                   ADC, digital, DAC1, and DAC2.  Since only the ADC supports cmd mode
 976                   right now, this isn't an issue (yet) */
 977                devpriv->dma0Offset = 0;
 978
 979                for (index = 0; index < DMA_CHAIN_COUNT; index++) {
 980                        devpriv->dma0Buff[index] =
 981                            pci_alloc_consistent(devpriv->pci_dev,
 982                                                 sizeof(u16) *
 983                                                 devpriv->fifoLen / 2,
 984                                                 &devpriv->
 985                                                 dma0BuffPhysAddr[index]);
 986                        if (devpriv->dma0Buff[index] == NULL) {
 987                                ret = -ENOMEM;
 988                                goto rtd_attach_die_error;
 989                        }
 990                        /*DPRINTK ("buff[%d] @ %p virtual, %x PCI\n",
 991                           index,
 992                           devpriv->dma0Buff[index], devpriv->dma0BuffPhysAddr[index]); */
 993                }
 994
 995                /* setup DMA descriptor ring (use cpu_to_le32 for byte ordering?) */
 996                devpriv->dma0Chain =
 997                    pci_alloc_consistent(devpriv->pci_dev,
 998                                         sizeof(struct plx_dma_desc) *
 999                                         DMA_CHAIN_COUNT,
1000                                         &devpriv->dma0ChainPhysAddr);
1001                for (index = 0; index < DMA_CHAIN_COUNT; index++) {
1002                        devpriv->dma0Chain[index].pci_start_addr =
1003                            devpriv->dma0BuffPhysAddr[index];
1004                        devpriv->dma0Chain[index].local_start_addr =
1005                            DMALADDR_ADC;
1006                        devpriv->dma0Chain[index].transfer_size =
1007                            sizeof(u16) * devpriv->fifoLen / 2;
1008                        devpriv->dma0Chain[index].next =
1009                            (devpriv->dma0ChainPhysAddr + ((index +
1010                                                            1) %
1011                                                           (DMA_CHAIN_COUNT))
1012                             * sizeof(devpriv->dma0Chain[0]))
1013                            | DMA_TRANSFER_BITS;
1014                        /*DPRINTK ("ring[%d] @%lx PCI: %x, local: %x, N: 0x%x, next: %x\n",
1015                           index,
1016                           ((long)devpriv->dma0ChainPhysAddr
1017                           + (index * sizeof(devpriv->dma0Chain[0]))),
1018                           devpriv->dma0Chain[index].pci_start_addr,
1019                           devpriv->dma0Chain[index].local_start_addr,
1020                           devpriv->dma0Chain[index].transfer_size,
1021                           devpriv->dma0Chain[index].next); */
1022                }
1023
1024                if (devpriv->dma0Chain == NULL) {
1025                        ret = -ENOMEM;
1026                        goto rtd_attach_die_error;
1027                }
1028
1029                RtdDma0Mode(dev, DMA_MODE_BITS);
1030                RtdDma0Source(dev, DMAS_ADFIFO_HALF_FULL);      /* set DMA trigger source */
1031        } else {
1032                printk("( no IRQ->no DMA )");
1033        }
1034#endif /* USE_DMA */
1035
1036        if (dev->irq) {         /* enable plx9080 interrupts */
1037                RtdPlxInterruptWrite(dev, ICS_PIE | ICS_PLIE);
1038        }
1039
1040        printk("\ncomedi%d: rtd520 driver attached.\n", dev->minor);
1041
1042        return 1;
1043
1044#if 0
1045        /* hit an error, clean up memory and return ret */
1046/* rtd_attach_die_error: */
1047#ifdef USE_DMA
1048        for (index = 0; index < DMA_CHAIN_COUNT; index++) {
1049                if (NULL != devpriv->dma0Buff[index]) { /* free buffer memory */
1050                        pci_free_consistent(devpriv->pci_dev,
1051                                            sizeof(u16) * devpriv->fifoLen / 2,
1052                                            devpriv->dma0Buff[index],
1053                                            devpriv->dma0BuffPhysAddr[index]);
1054                        devpriv->dma0Buff[index] = NULL;
1055                }
1056        }
1057        if (NULL != devpriv->dma0Chain) {
1058                pci_free_consistent(devpriv->pci_dev,
1059                                    sizeof(struct plx_dma_desc)
1060                                    * DMA_CHAIN_COUNT,
1061                                    devpriv->dma0Chain,
1062                                    devpriv->dma0ChainPhysAddr);
1063                devpriv->dma0Chain = NULL;
1064        }
1065#endif /* USE_DMA */
1066        /* subdevices and priv are freed by the core */
1067        if (dev->irq) {
1068                /* disable interrupt controller */
1069                RtdPlxInterruptWrite(dev, RtdPlxInterruptRead(dev)
1070                                     & ~(ICS_PLIE | ICS_DMA0_E | ICS_DMA1_E));
1071                free_irq(dev->irq, dev);
1072        }
1073
1074        /* release all regions that were allocated */
1075        if (devpriv->las0) {
1076                iounmap(devpriv->las0);
1077        }
1078        if (devpriv->las1) {
1079                iounmap(devpriv->las1);
1080        }
1081        if (devpriv->lcfg) {
1082                iounmap(devpriv->lcfg);
1083        }
1084        if (devpriv->pci_dev) {
1085                pci_dev_put(devpriv->pci_dev);
1086        }
1087        return ret;
1088#endif
1089}
1090
1091/*
1092 * _detach is called to deconfigure a device.  It should deallocate
1093 * resources.
1094 * This function is also called when _attach() fails, so it should be
1095 * careful not to release resources that were not necessarily
1096 * allocated by _attach().  dev->private and dev->subdevices are
1097 * deallocated automatically by the core.
1098 */
1099static int rtd_detach(struct comedi_device *dev)
1100{
1101#ifdef USE_DMA
1102        int index;
1103#endif
1104
1105        DPRINTK("comedi%d: rtd520: removing (%ld ints)\n",
1106                dev->minor, (devpriv ? devpriv->intCount : 0L));
1107        if (devpriv && devpriv->lcfg) {
1108                DPRINTK
1109                    ("(int status 0x%x, overrun status 0x%x, fifo status 0x%x)...\n",
1110                     0xffff & RtdInterruptStatus(dev),
1111                     0xffff & RtdInterruptOverrunStatus(dev),
1112                     (0xffff & RtdFifoStatus(dev)) ^ 0x6666);
1113        }
1114
1115        if (devpriv) {
1116                /* Shut down any board ops by resetting it */
1117#ifdef USE_DMA
1118                if (devpriv->lcfg) {
1119                        RtdDma0Control(dev, 0); /* disable DMA */
1120                        RtdDma1Control(dev, 0); /* disable DMA */
1121                        RtdPlxInterruptWrite(dev, ICS_PIE | ICS_PLIE);
1122                }
1123#endif /* USE_DMA */
1124                if (devpriv->las0) {
1125                        RtdResetBoard(dev);
1126                        RtdInterruptMask(dev, 0);
1127                        RtdInterruptClearMask(dev, ~0);
1128                        RtdInterruptClear(dev); /* clears bits set by mask */
1129                }
1130#ifdef USE_DMA
1131                /* release DMA */
1132                for (index = 0; index < DMA_CHAIN_COUNT; index++) {
1133                        if (NULL != devpriv->dma0Buff[index]) {
1134                                pci_free_consistent(devpriv->pci_dev,
1135                                                    sizeof(u16) *
1136                                                    devpriv->fifoLen / 2,
1137                                                    devpriv->dma0Buff[index],
1138                                                    devpriv->
1139                                                    dma0BuffPhysAddr[index]);
1140                                devpriv->dma0Buff[index] = NULL;
1141                        }
1142                }
1143                if (NULL != devpriv->dma0Chain) {
1144                        pci_free_consistent(devpriv->pci_dev,
1145                                            sizeof(struct plx_dma_desc) *
1146                                            DMA_CHAIN_COUNT, devpriv->dma0Chain,
1147                                            devpriv->dma0ChainPhysAddr);
1148                        devpriv->dma0Chain = NULL;
1149                }
1150#endif /* USE_DMA */
1151
1152                /* release IRQ */
1153                if (dev->irq) {
1154                        /* disable interrupt controller */
1155                        RtdPlxInterruptWrite(dev, RtdPlxInterruptRead(dev)
1156                                             & ~(ICS_PLIE | ICS_DMA0_E |
1157                                                 ICS_DMA1_E));
1158                        free_irq(dev->irq, dev);
1159                }
1160
1161                /* release all regions that were allocated */
1162                if (devpriv->las0) {
1163                        iounmap(devpriv->las0);
1164                }
1165                if (devpriv->las1) {
1166                        iounmap(devpriv->las1);
1167                }
1168                if (devpriv->lcfg) {
1169                        iounmap(devpriv->lcfg);
1170                }
1171                if (devpriv->pci_dev) {
1172                        if (devpriv->got_regions) {
1173                                comedi_pci_disable(devpriv->pci_dev);
1174                        }
1175                        pci_dev_put(devpriv->pci_dev);
1176                }
1177        }
1178
1179        printk("comedi%d: rtd520: removed.\n", dev->minor);
1180
1181        return 0;
1182}
1183
1184/*
1185  Convert a single comedi channel-gain entry to a RTD520 table entry
1186*/
1187static unsigned short rtdConvertChanGain(struct comedi_device *dev,
1188                                         unsigned int comediChan, int chanIndex)
1189{                               /* index in channel list */
1190        unsigned int chan, range, aref;
1191        unsigned short r = 0;
1192
1193        chan = CR_CHAN(comediChan);
1194        range = CR_RANGE(comediChan);
1195        aref = CR_AREF(comediChan);
1196
1197        r |= chan & 0xf;
1198
1199        /* Note: we also setup the channel list bipolar flag array */
1200        if (range < thisboard->range10Start) {  /* first batch are +-5 */
1201                r |= 0x000;     /* +-5 range */
1202                r |= (range & 0x7) << 4;        /* gain */
1203                CHAN_ARRAY_SET(devpriv->chanBipolar, chanIndex);
1204        } else if (range < thisboard->rangeUniStart) {  /* second batch are +-10 */
1205                r |= 0x100;     /* +-10 range */
1206                r |= ((range - thisboard->range10Start) & 0x7) << 4;    /* gain */
1207                CHAN_ARRAY_SET(devpriv->chanBipolar, chanIndex);
1208        } else {                /* last batch is +10 */
1209                r |= 0x200;     /* +10 range */
1210                r |= ((range - thisboard->rangeUniStart) & 0x7) << 4;   /* gain */
1211                CHAN_ARRAY_CLEAR(devpriv->chanBipolar, chanIndex);
1212        }
1213
1214        switch (aref) {
1215        case AREF_GROUND:       /* on-board ground */
1216                break;
1217
1218        case AREF_COMMON:
1219                r |= 0x80;      /* ref external analog common */
1220                break;
1221
1222        case AREF_DIFF:
1223                r |= 0x400;     /* differential inputs */
1224                break;
1225
1226        case AREF_OTHER:        /* ??? */
1227                break;
1228        }
1229        /*printk ("chan=%d r=%d a=%d -> 0x%x\n",
1230           chan, range, aref, r); */
1231        return r;
1232}
1233
1234/*
1235  Setup the channel-gain table from a comedi list
1236*/
1237static void rtd_load_channelgain_list(struct comedi_device *dev,
1238                                      unsigned int n_chan, unsigned int *list)
1239{
1240        if (n_chan > 1) {       /* setup channel gain table */
1241                int ii;
1242                RtdClearCGT(dev);
1243                RtdEnableCGT(dev, 1);   /* enable table */
1244                for (ii = 0; ii < n_chan; ii++) {
1245                        RtdWriteCGTable(dev, rtdConvertChanGain(dev, list[ii],
1246                                                                ii));
1247                }
1248        } else {                /* just use the channel gain latch */
1249                RtdEnableCGT(dev, 0);   /* disable table, enable latch */
1250                RtdWriteCGLatch(dev, rtdConvertChanGain(dev, list[0], 0));
1251        }
1252}
1253
1254/* determine fifo size by doing adc conversions until the fifo half
1255empty status flag clears */
1256static int rtd520_probe_fifo_depth(struct comedi_device *dev)
1257{
1258        unsigned int chanspec = CR_PACK(0, 0, AREF_GROUND);
1259        unsigned i;
1260        static const unsigned limit = 0x2000;
1261        unsigned fifo_size = 0;
1262
1263        RtdAdcClearFifo(dev);
1264        rtd_load_channelgain_list(dev, 1, &chanspec);
1265        RtdAdcConversionSource(dev, 0); /* software */
1266        /* convert  samples */
1267        for (i = 0; i < limit; ++i) {
1268                unsigned fifo_status;
1269                /* trigger conversion */
1270                RtdAdcStart(dev);
1271                udelay(1);
1272                fifo_status = RtdFifoStatus(dev);
1273                if ((fifo_status & FS_ADC_HEMPTY) == 0) {
1274                        fifo_size = 2 * i;
1275                        break;
1276                }
1277        }
1278        if (i == limit) {
1279                printk("\ncomedi: %s: failed to probe fifo size.\n", DRV_NAME);
1280                return -EIO;
1281        }
1282        RtdAdcClearFifo(dev);
1283        if (fifo_size != 0x400 && fifo_size != 0x2000) {
1284                printk
1285                    ("\ncomedi: %s: unexpected fifo size of %i, expected 1024 or 8192.\n",
1286                     DRV_NAME, fifo_size);
1287                return -EIO;
1288        }
1289        return fifo_size;
1290}
1291
1292/*
1293  "instructions" read/write data in "one-shot" or "software-triggered"
1294  mode (simplest case).
1295  This doesnt use interrupts.
1296
1297  Note, we don't do any settling delays.  Use a instruction list to
1298  select, delay, then read.
1299 */
1300static int rtd_ai_rinsn(struct comedi_device *dev,
1301                        struct comedi_subdevice *s, struct comedi_insn *insn,
1302                        unsigned int *data)
1303{
1304        int n, ii;
1305        int stat;
1306
1307        /* clear any old fifo data */
1308        RtdAdcClearFifo(dev);
1309
1310        /* write channel to multiplexer and clear channel gain table */
1311        rtd_load_channelgain_list(dev, 1, &insn->chanspec);
1312
1313        /* set conversion source */
1314        RtdAdcConversionSource(dev, 0); /* software */
1315
1316        /* convert n samples */
1317        for (n = 0; n < insn->n; n++) {
1318                s16 d;
1319                /* trigger conversion */
1320                RtdAdcStart(dev);
1321
1322                for (ii = 0; ii < RTD_ADC_TIMEOUT; ++ii) {
1323                        stat = RtdFifoStatus(dev);
1324                        if (stat & FS_ADC_NOT_EMPTY)    /* 1 -> not empty */
1325                                break;
1326                        WAIT_QUIETLY;
1327                }
1328                if (ii >= RTD_ADC_TIMEOUT) {
1329                        DPRINTK
1330                            ("rtd520: Error: ADC never finished! FifoStatus=0x%x\n",
1331                             stat ^ 0x6666);
1332                        return -ETIMEDOUT;
1333                }
1334
1335                /* read data */
1336                d = RtdAdcFifoGet(dev); /* get 2s comp value */
1337                /*printk ("rtd520: Got 0x%x after %d usec\n", d, ii+1); */
1338                d = d >> 3;     /* low 3 bits are marker lines */
1339                if (CHAN_ARRAY_TEST(devpriv->chanBipolar, 0)) {
1340                        data[n] = d + 2048;     /* convert to comedi unsigned data */
1341                } else {
1342                        data[n] = d;
1343                }
1344        }
1345
1346        /* return the number of samples read/written */
1347        return n;
1348}
1349
1350/*
1351  Get what we know is there.... Fast!
1352  This uses 1/2 the bus cycles of read_dregs (below).
1353
1354  The manual claims that we can do a lword read, but it doesn't work here.
1355*/
1356static int ai_read_n(struct comedi_device *dev, struct comedi_subdevice *s,
1357                     int count)
1358{
1359        int ii;
1360
1361        for (ii = 0; ii < count; ii++) {
1362                short sample;
1363                s16 d;
1364
1365                if (0 == devpriv->aiCount) {    /* done */
1366                        d = RtdAdcFifoGet(dev); /* Read N and discard */
1367                        continue;
1368                }
1369#if 0
1370                if (0 == (RtdFifoStatus(dev) & FS_ADC_NOT_EMPTY)) {     /* DEBUG */
1371                        DPRINTK("comedi: READ OOPS on %d of %d\n", ii + 1,
1372                                count);
1373                        break;
1374                }
1375#endif
1376                d = RtdAdcFifoGet(dev); /* get 2s comp value */
1377
1378                d = d >> 3;     /* low 3 bits are marker lines */
1379                if (CHAN_ARRAY_TEST(devpriv->chanBipolar, s->async->cur_chan)) {
1380                        sample = d + 2048;      /* convert to comedi unsigned data */
1381                } else {
1382                        sample = d;
1383                }
1384                if (!comedi_buf_put(s->async, sample))
1385                        return -1;
1386
1387                if (devpriv->aiCount > 0)       /* < 0, means read forever */
1388                        devpriv->aiCount--;
1389        }
1390        return 0;
1391}
1392
1393/*
1394  unknown amout of data is waiting in fifo.
1395*/
1396static int ai_read_dregs(struct comedi_device *dev, struct comedi_subdevice *s)
1397{
1398        while (RtdFifoStatus(dev) & FS_ADC_NOT_EMPTY) { /* 1 -> not empty */
1399                short sample;
1400                s16 d = RtdAdcFifoGet(dev);     /* get 2s comp value */
1401
1402                if (0 == devpriv->aiCount) {    /* done */
1403                        continue;       /* read rest */
1404                }
1405
1406                d = d >> 3;     /* low 3 bits are marker lines */
1407                if (CHAN_ARRAY_TEST(devpriv->chanBipolar, s->async->cur_chan)) {
1408                        sample = d + 2048;      /* convert to comedi unsigned data */
1409                } else {
1410                        sample = d;
1411                }
1412                if (!comedi_buf_put(s->async, sample))
1413                        return -1;
1414
1415                if (devpriv->aiCount > 0)       /* < 0, means read forever */
1416                        devpriv->aiCount--;
1417        }
1418        return 0;
1419}
1420
1421#ifdef USE_DMA
1422/*
1423  Terminate a DMA transfer and wait for everything to quiet down
1424*/
1425void abort_dma(struct comedi_device *dev, unsigned int channel)
1426{                               /* DMA channel 0, 1 */
1427        unsigned long dma_cs_addr;      /* the control/status register */
1428        uint8_t status;
1429        unsigned int ii;
1430        /* unsigned long flags; */
1431
1432        dma_cs_addr = (unsigned long)devpriv->lcfg
1433            + ((channel == 0) ? LCFG_DMACSR0 : LCFG_DMACSR1);
1434
1435        /*  spinlock for plx dma control/status reg */
1436        /* spin_lock_irqsave( &dev->spinlock, flags ); */
1437
1438        /*  abort dma transfer if necessary */
1439        status = readb(dma_cs_addr);
1440        if ((status & PLX_DMA_EN_BIT) == 0) {   /* not enabled (Error?) */
1441                DPRINTK("rtd520: AbortDma on non-active channel %d (0x%x)\n",
1442                        channel, status);
1443                goto abortDmaExit;
1444        }
1445
1446        /* wait to make sure done bit is zero (needed?) */
1447        for (ii = 0; (status & PLX_DMA_DONE_BIT) && ii < RTD_DMA_TIMEOUT; ii++) {
1448                WAIT_QUIETLY;
1449                status = readb(dma_cs_addr);
1450        }
1451        if (status & PLX_DMA_DONE_BIT) {
1452                printk("rtd520: Timeout waiting for dma %i done clear\n",
1453                       channel);
1454                goto abortDmaExit;
1455        }
1456
1457        /* disable channel (required) */
1458        writeb(0, dma_cs_addr);
1459        udelay(1);              /* needed?? */
1460        /* set abort bit for channel */
1461        writeb(PLX_DMA_ABORT_BIT, dma_cs_addr);
1462
1463        /*  wait for dma done bit to be set */
1464        status = readb(dma_cs_addr);
1465        for (ii = 0;
1466             (status & PLX_DMA_DONE_BIT) == 0 && ii < RTD_DMA_TIMEOUT; ii++) {
1467                status = readb(dma_cs_addr);
1468                WAIT_QUIETLY;
1469        }
1470        if ((status & PLX_DMA_DONE_BIT) == 0) {
1471                printk("rtd520: Timeout waiting for dma %i done set\n",
1472                       channel);
1473        }
1474
1475abortDmaExit:
1476        /* spin_unlock_irqrestore( &dev->spinlock, flags ); */
1477}
1478
1479/*
1480  Process what is in the DMA transfer buffer and pass to comedi
1481  Note: this is not re-entrant
1482*/
1483static int ai_process_dma(struct comedi_device *dev, struct comedi_subdevice *s)
1484{
1485        int ii, n;
1486        s16 *dp;
1487
1488        if (devpriv->aiCount == 0)      /* transfer already complete */
1489                return 0;
1490
1491        dp = devpriv->dma0Buff[devpriv->dma0Offset];
1492        for (ii = 0; ii < devpriv->fifoLen / 2;) {      /* convert samples */
1493                short sample;
1494
1495                if (CHAN_ARRAY_TEST(devpriv->chanBipolar, s->async->cur_chan)) {
1496                        sample = (*dp >> 3) + 2048;     /* convert to comedi unsigned data */
1497                } else {
1498                        sample = *dp >> 3;      /* low 3 bits are marker lines */
1499                }
1500                *dp++ = sample; /* put processed value back */
1501
1502                if (++s->async->cur_chan >= s->async->cmd.chanlist_len)
1503                        s->async->cur_chan = 0;
1504
1505                ++ii;           /* number ready to transfer */
1506                if (devpriv->aiCount > 0) {     /* < 0, means read forever */
1507                        if (--devpriv->aiCount == 0) {  /* done */
1508                                /*DPRINTK ("rtd520: Final %d samples\n", ii); */
1509                                break;
1510                        }
1511                }
1512        }
1513
1514        /* now pass the whole array to the comedi buffer */
1515        dp = devpriv->dma0Buff[devpriv->dma0Offset];
1516        n = comedi_buf_write_alloc(s->async, ii * sizeof(s16));
1517        if (n < (ii * sizeof(s16))) {   /* any residual is an error */
1518                DPRINTK("rtd520:ai_process_dma buffer overflow %d samples!\n",
1519                        ii - (n / sizeof(s16)));
1520                s->async->events |= COMEDI_CB_ERROR;
1521                return -1;
1522        }
1523        comedi_buf_memcpy_to(s->async, 0, dp, n);
1524        comedi_buf_write_free(s->async, n);
1525
1526        /* always at least 1 scan -- 1/2 FIFO is larger than our max scan list */
1527        s->async->events |= COMEDI_CB_BLOCK | COMEDI_CB_EOS;
1528
1529        if (++devpriv->dma0Offset >= DMA_CHAIN_COUNT) { /* next buffer */
1530                devpriv->dma0Offset = 0;
1531        }
1532        return 0;
1533}
1534#endif /* USE_DMA */
1535
1536/*
1537  Handle all rtd520 interrupts.
1538  Runs atomically and is never re-entered.
1539  This is a "slow handler";  other interrupts may be active.
1540  The data conversion may someday happen in a "bottom half".
1541*/
1542static irqreturn_t rtd_interrupt(int irq,       /* interrupt number (ignored) */
1543                                 void *d)
1544{                               /* our data *//* cpu context (ignored) */
1545        struct comedi_device *dev = d;  /* must be called "dev" for devpriv */
1546        u16 status;
1547        u16 fifoStatus;
1548        struct comedi_subdevice *s = dev->subdevices + 0;       /* analog in subdevice */
1549
1550        if (!dev->attached) {
1551                return IRQ_NONE;
1552        }
1553
1554        devpriv->intCount++;    /* DEBUG statistics */
1555
1556        fifoStatus = RtdFifoStatus(dev);
1557        /* check for FIFO full, this automatically halts the ADC! */
1558        if (!(fifoStatus & FS_ADC_NOT_FULL)) {  /* 0 -> full */
1559                DPRINTK("rtd520: FIFO full! fifo_status=0x%x\n", (fifoStatus ^ 0x6666) & 0x7777);       /* should be all 0s */
1560                goto abortTransfer;
1561        }
1562#ifdef USE_DMA
1563        if (devpriv->flags & DMA0_ACTIVE) {     /* Check DMA */
1564                u32 istatus = RtdPlxInterruptRead(dev);
1565
1566                if (istatus & ICS_DMA0_A) {
1567                        if (ai_process_dma(dev, s) < 0) {
1568                                DPRINTK
1569                                    ("rtd520: comedi read buffer overflow (DMA) with %ld to go!\n",
1570                                     devpriv->aiCount);
1571                                RtdDma0Control(dev,
1572                                               (devpriv->dma0Control &
1573                                                ~PLX_DMA_START_BIT)
1574                                               | PLX_CLEAR_DMA_INTR_BIT);
1575                                goto abortTransfer;
1576                        }
1577
1578                        /*DPRINTK ("rtd520: DMA transfer: %ld to go, istatus %x\n",
1579                           devpriv->aiCount, istatus); */
1580                        RtdDma0Control(dev,
1581                                       (devpriv->
1582                                        dma0Control & ~PLX_DMA_START_BIT)
1583                                       | PLX_CLEAR_DMA_INTR_BIT);
1584                        if (0 == devpriv->aiCount) {    /* counted down */
1585                                DPRINTK("rtd520: Samples Done (DMA).\n");
1586                                goto transferDone;
1587                        }
1588                        comedi_event(dev, s);
1589                } else {
1590                        /*DPRINTK ("rtd520: No DMA ready: istatus %x\n", istatus); */
1591                }
1592        }
1593        /* Fall through and check for other interrupt sources */
1594#endif /* USE_DMA */
1595
1596        status = RtdInterruptStatus(dev);
1597        /* if interrupt was not caused by our board, or handled above */
1598        if (0 == status) {
1599                return IRQ_HANDLED;
1600        }
1601
1602        if (status & IRQM_ADC_ABOUT_CNT) {      /* sample count -> read FIFO */
1603                /* since the priority interrupt controller may have queued a sample
1604                   counter interrupt, even though we have already finished,
1605                   we must handle the possibility that there is no data here */
1606                if (!(fifoStatus & FS_ADC_HEMPTY)) {    /* 0 -> 1/2 full */
1607                        /*DPRINTK("rtd520: Sample int, reading 1/2FIFO.  fifo_status 0x%x\n",
1608                           (fifoStatus ^ 0x6666) & 0x7777); */
1609                        if (ai_read_n(dev, s, devpriv->fifoLen / 2) < 0) {
1610                                DPRINTK
1611                                    ("rtd520: comedi read buffer overflow (1/2FIFO) with %ld to go!\n",
1612                                     devpriv->aiCount);
1613                                goto abortTransfer;
1614                        }
1615                        if (0 == devpriv->aiCount) {    /* counted down */
1616                                DPRINTK("rtd520: Samples Done (1/2). fifo_status was 0x%x\n", (fifoStatus ^ 0x6666) & 0x7777);  /* should be all 0s */
1617                                goto transferDone;
1618                        }
1619                        comedi_event(dev, s);
1620                } else if (devpriv->transCount > 0) {   /* read often */
1621                        /*DPRINTK("rtd520: Sample int, reading %d  fifo_status 0x%x\n",
1622                           devpriv->transCount, (fifoStatus ^ 0x6666) & 0x7777); */
1623                        if (fifoStatus & FS_ADC_NOT_EMPTY) {    /* 1 -> not empty */
1624                                if (ai_read_n(dev, s, devpriv->transCount) < 0) {
1625                                        DPRINTK
1626                                            ("rtd520: comedi read buffer overflow (N) with %ld to go!\n",
1627                                             devpriv->aiCount);
1628                                        goto abortTransfer;
1629                                }
1630                                if (0 == devpriv->aiCount) {    /* counted down */
1631                                        DPRINTK
1632                                            ("rtd520: Samples Done (N). fifo_status was 0x%x\n",
1633                                             (fifoStatus ^ 0x6666) & 0x7777);
1634                                        goto transferDone;
1635                                }
1636                                comedi_event(dev, s);
1637                        }
1638                } else {        /* wait for 1/2 FIFO (old) */
1639                        DPRINTK
1640                            ("rtd520: Sample int.  Wait for 1/2. fifo_status 0x%x\n",
1641                             (fifoStatus ^ 0x6666) & 0x7777);
1642                }
1643        } else {
1644                DPRINTK("rtd520: unknown interrupt source!\n");
1645        }
1646
1647        if (0xffff & RtdInterruptOverrunStatus(dev)) {  /* interrupt overrun */
1648                DPRINTK
1649                    ("rtd520: Interrupt overrun with %ld to go! over_status=0x%x\n",
1650                     devpriv->aiCount, 0xffff & RtdInterruptOverrunStatus(dev));
1651                goto abortTransfer;
1652        }
1653
1654        /* clear the interrupt */
1655        RtdInterruptClearMask(dev, status);
1656        RtdInterruptClear(dev);
1657        return IRQ_HANDLED;
1658
1659abortTransfer:
1660        RtdAdcClearFifo(dev);   /* clears full flag */
1661        s->async->events |= COMEDI_CB_ERROR;
1662        devpriv->aiCount = 0;   /* stop and don't transfer any more */
1663        /* fall into transferDone */
1664
1665transferDone:
1666        RtdPacerStopSource(dev, 0);     /* stop on SOFTWARE stop */
1667        RtdPacerStop(dev);      /* Stop PACER */
1668        RtdAdcConversionSource(dev, 0); /* software trigger only */
1669        RtdInterruptMask(dev, 0);       /* mask out SAMPLE */
1670#ifdef USE_DMA
1671        if (devpriv->flags & DMA0_ACTIVE) {
1672                RtdPlxInterruptWrite(dev,       /* disable any more interrupts */
1673                                     RtdPlxInterruptRead(dev) & ~ICS_DMA0_E);
1674                abort_dma(dev, 0);
1675                devpriv->flags &= ~DMA0_ACTIVE;
1676                /* if Using DMA, then we should have read everything by now */
1677                if (devpriv->aiCount > 0) {
1678                        DPRINTK("rtd520: Lost DMA data! %ld remain\n",
1679                                devpriv->aiCount);
1680                }
1681        }
1682#endif /* USE_DMA */
1683
1684        if (devpriv->aiCount > 0) {     /* there shouldn't be anything left */
1685                fifoStatus = RtdFifoStatus(dev);
1686                DPRINTK("rtd520: Finishing up. %ld remain, fifoStat=%x\n", devpriv->aiCount, (fifoStatus ^ 0x6666) & 0x7777);   /* should read all 0s */
1687                ai_read_dregs(dev, s);  /* read anything left in FIFO */
1688        }
1689
1690        s->async->events |= COMEDI_CB_EOA;      /* signal end to comedi */
1691        comedi_event(dev, s);
1692
1693        /* clear the interrupt */
1694        status = RtdInterruptStatus(dev);
1695        RtdInterruptClearMask(dev, status);
1696        RtdInterruptClear(dev);
1697
1698        fifoStatus = RtdFifoStatus(dev);        /* DEBUG */
1699        DPRINTK
1700            ("rtd520: Acquisition complete. %ld ints, intStat=%x, overStat=%x\n",
1701             devpriv->intCount, status,
1702             0xffff & RtdInterruptOverrunStatus(dev));
1703
1704        return IRQ_HANDLED;
1705}
1706
1707#if 0
1708/*
1709  return the number of samples available
1710*/
1711static int rtd_ai_poll(struct comedi_device *dev, struct comedi_subdevice *s)
1712{
1713        /* TODO: This needs to mask interrupts, read_dregs, and then re-enable */
1714        /* Not sure what to do if DMA is active */
1715        return s->async->buf_write_count - s->async->buf_read_count;
1716}
1717#endif
1718
1719/*
1720  cmdtest tests a particular command to see if it is valid.
1721  Using the cmdtest ioctl, a user can create a valid cmd
1722  and then have it executed by the cmd ioctl (asyncronously).
1723
1724  cmdtest returns 1,2,3,4 or 0, depending on which tests
1725  the command passes.
1726*/
1727
1728static int rtd_ai_cmdtest(struct comedi_device *dev,
1729                          struct comedi_subdevice *s, struct comedi_cmd *cmd)
1730{
1731        int err = 0;
1732        int tmp;
1733
1734        /* step 1: make sure trigger sources are trivially valid */
1735
1736        tmp = cmd->start_src;
1737        cmd->start_src &= TRIG_NOW;
1738        if (!cmd->start_src || tmp != cmd->start_src) {
1739                err++;
1740        }
1741
1742        tmp = cmd->scan_begin_src;
1743        cmd->scan_begin_src &= TRIG_TIMER | TRIG_EXT;
1744        if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src) {
1745                err++;
1746        }
1747
1748        tmp = cmd->convert_src;
1749        cmd->convert_src &= TRIG_TIMER | TRIG_EXT;
1750        if (!cmd->convert_src || tmp != cmd->convert_src) {
1751                err++;
1752        }
1753
1754        tmp = cmd->scan_end_src;
1755        cmd->scan_end_src &= TRIG_COUNT;
1756        if (!cmd->scan_end_src || tmp != cmd->scan_end_src) {
1757                err++;
1758        }
1759
1760        tmp = cmd->stop_src;
1761        cmd->stop_src &= TRIG_COUNT | TRIG_NONE;
1762        if (!cmd->stop_src || tmp != cmd->stop_src) {
1763                err++;
1764        }
1765
1766        if (err)
1767                return 1;
1768
1769        /* step 2: make sure trigger sources are unique
1770           and mutually compatible */
1771        /* note that mutual compatiblity is not an issue here */
1772        if (cmd->scan_begin_src != TRIG_TIMER &&
1773            cmd->scan_begin_src != TRIG_EXT) {
1774                err++;
1775        }
1776        if (cmd->convert_src != TRIG_TIMER && cmd->convert_src != TRIG_EXT) {
1777                err++;
1778        }
1779        if (cmd->stop_src != TRIG_COUNT && cmd->stop_src != TRIG_NONE) {
1780                err++;
1781        }
1782
1783        if (err) {
1784                return 2;
1785        }
1786
1787        /* step 3: make sure arguments are trivially compatible */
1788
1789        if (cmd->start_arg != 0) {
1790                cmd->start_arg = 0;
1791                err++;
1792        }
1793
1794        if (cmd->scan_begin_src == TRIG_TIMER) {
1795                /* Note: these are time periods, not actual rates */
1796                if (1 == cmd->chanlist_len) {   /* no scanning */
1797                        if (cmd->scan_begin_arg < RTD_MAX_SPEED_1) {
1798                                cmd->scan_begin_arg = RTD_MAX_SPEED_1;
1799                                rtd_ns_to_timer(&cmd->scan_begin_arg,
1800                                                TRIG_ROUND_UP);
1801                                err++;
1802                        }
1803                        if (cmd->scan_begin_arg > RTD_MIN_SPEED_1) {
1804                                cmd->scan_begin_arg = RTD_MIN_SPEED_1;
1805                                rtd_ns_to_timer(&cmd->scan_begin_arg,
1806                                                TRIG_ROUND_DOWN);
1807                                err++;
1808                        }
1809                } else {
1810                        if (cmd->scan_begin_arg < RTD_MAX_SPEED) {
1811                                cmd->scan_begin_arg = RTD_MAX_SPEED;
1812                                rtd_ns_to_timer(&cmd->scan_begin_arg,
1813                                                TRIG_ROUND_UP);
1814                                err++;
1815                        }
1816                        if (cmd->scan_begin_arg > RTD_MIN_SPEED) {
1817                                cmd->scan_begin_arg = RTD_MIN_SPEED;
1818                                rtd_ns_to_timer(&cmd->scan_begin_arg,
1819                                                TRIG_ROUND_DOWN);
1820                                err++;
1821                        }
1822                }
1823        } else {
1824                /* external trigger */
1825                /* should be level/edge, hi/lo specification here */
1826                /* should specify multiple external triggers */
1827                if (cmd->scan_begin_arg > 9) {
1828                        cmd->scan_begin_arg = 9;
1829                        err++;
1830                }
1831        }
1832        if (cmd->convert_src == TRIG_TIMER) {
1833                if (1 == cmd->chanlist_len) {   /* no scanning */
1834                        if (cmd->convert_arg < RTD_MAX_SPEED_1) {
1835                                cmd->convert_arg = RTD_MAX_SPEED_1;
1836                                rtd_ns_to_timer(&cmd->convert_arg,
1837                                                TRIG_ROUND_UP);
1838                                err++;
1839                        }
1840                        if (cmd->convert_arg > RTD_MIN_SPEED_1) {
1841                                cmd->convert_arg = RTD_MIN_SPEED_1;
1842                                rtd_ns_to_timer(&cmd->convert_arg,
1843                                                TRIG_ROUND_DOWN);
1844                                err++;
1845                        }
1846                } else {
1847                        if (cmd->convert_arg < RTD_MAX_SPEED) {
1848                                cmd->convert_arg = RTD_MAX_SPEED;
1849                                rtd_ns_to_timer(&cmd->convert_arg,
1850                                                TRIG_ROUND_UP);
1851                                err++;
1852                        }
1853                        if (cmd->convert_arg > RTD_MIN_SPEED) {
1854                                cmd->convert_arg = RTD_MIN_SPEED;
1855                                rtd_ns_to_timer(&cmd->convert_arg,
1856                                                TRIG_ROUND_DOWN);
1857                                err++;
1858                        }
1859                }
1860        } else {
1861                /* external trigger */
1862                /* see above */
1863                if (cmd->convert_arg > 9) {
1864                        cmd->convert_arg = 9;
1865                        err++;
1866                }
1867        }
1868
1869#if 0
1870        if (cmd->scan_end_arg != cmd->chanlist_len) {
1871                cmd->scan_end_arg = cmd->chanlist_len;
1872                err++;
1873        }
1874#endif
1875        if (cmd->stop_src == TRIG_COUNT) {
1876                /* TODO check for rounding error due to counter wrap */
1877
1878        } else {
1879                /* TRIG_NONE */
1880                if (cmd->stop_arg != 0) {
1881                        cmd->stop_arg = 0;
1882                        err++;
1883                }
1884        }
1885
1886        if (err) {
1887                return 3;
1888        }
1889
1890        /* step 4: fix up any arguments */
1891
1892        if (cmd->chanlist_len > RTD_MAX_CHANLIST) {
1893                cmd->chanlist_len = RTD_MAX_CHANLIST;
1894                err++;
1895        }
1896        if (cmd->scan_begin_src == TRIG_TIMER) {
1897                tmp = cmd->scan_begin_arg;
1898                rtd_ns_to_timer(&cmd->scan_begin_arg,
1899                                cmd->flags & TRIG_ROUND_MASK);
1900                if (tmp != cmd->scan_begin_arg) {
1901                        err++;
1902                }
1903        }
1904        if (cmd->convert_src == TRIG_TIMER) {
1905                tmp = cmd->convert_arg;
1906                rtd_ns_to_timer(&cmd->convert_arg,
1907                                cmd->flags & TRIG_ROUND_MASK);
1908                if (tmp != cmd->convert_arg) {
1909                        err++;
1910                }
1911                if (cmd->scan_begin_src == TRIG_TIMER
1912                    && (cmd->scan_begin_arg
1913                        < (cmd->convert_arg * cmd->scan_end_arg))) {
1914                        cmd->scan_begin_arg =
1915                            cmd->convert_arg * cmd->scan_end_arg;
1916                        err++;
1917                }
1918        }
1919
1920        if (err) {
1921                return 4;
1922        }
1923
1924        return 0;
1925}
1926
1927/*
1928  Execute a analog in command with many possible triggering options.
1929  The data get stored in the async structure of the subdevice.
1930  This is usually done by an interrupt handler.
1931  Userland gets to the data using read calls.
1932*/
1933static int rtd_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
1934{
1935        struct comedi_cmd *cmd = &s->async->cmd;
1936        int timer;
1937
1938        /* stop anything currently running */
1939        RtdPacerStopSource(dev, 0);     /* stop on SOFTWARE stop */
1940        RtdPacerStop(dev);      /* make sure PACER is stopped */
1941        RtdAdcConversionSource(dev, 0); /* software trigger only */
1942        RtdInterruptMask(dev, 0);
1943#ifdef USE_DMA
1944        if (devpriv->flags & DMA0_ACTIVE) {     /* cancel anything running */
1945                RtdPlxInterruptWrite(dev,       /* disable any more interrupts */
1946                                     RtdPlxInterruptRead(dev) & ~ICS_DMA0_E);
1947                abort_dma(dev, 0);
1948                devpriv->flags &= ~DMA0_ACTIVE;
1949                if (RtdPlxInterruptRead(dev) & ICS_DMA0_A) {    /*clear pending int */
1950                        RtdDma0Control(dev, PLX_CLEAR_DMA_INTR_BIT);
1951                }
1952        }
1953        RtdDma0Reset(dev);      /* reset onboard state */
1954#endif /* USE_DMA */
1955        RtdAdcClearFifo(dev);   /* clear any old data */
1956        RtdInterruptOverrunClear(dev);
1957        devpriv->intCount = 0;
1958
1959        if (!dev->irq) {        /* we need interrupts for this */
1960                DPRINTK("rtd520: ERROR! No interrupt available!\n");
1961                return -ENXIO;
1962        }
1963
1964        /* start configuration */
1965        /* load channel list and reset CGT */
1966        rtd_load_channelgain_list(dev, cmd->chanlist_len, cmd->chanlist);
1967
1968        /* setup the common case and override if needed */
1969        if (cmd->chanlist_len > 1) {
1970                /*DPRINTK ("rtd520: Multi channel setup\n"); */
1971                RtdPacerStartSource(dev, 0);    /* software triggers pacer */
1972                RtdBurstStartSource(dev, 1);    /* PACER triggers burst */
1973                RtdAdcConversionSource(dev, 2); /* BURST triggers ADC */
1974        } else {                /* single channel */
1975                /*DPRINTK ("rtd520: single channel setup\n"); */
1976                RtdPacerStartSource(dev, 0);    /* software triggers pacer */
1977                RtdAdcConversionSource(dev, 1); /* PACER triggers ADC */
1978        }
1979        RtdAboutCounter(dev, devpriv->fifoLen / 2 - 1); /* 1/2 FIFO */
1980
1981        if (TRIG_TIMER == cmd->scan_begin_src) {
1982                /* scan_begin_arg is in nanoseconds */
1983                /* find out how many samples to wait before transferring */
1984                if (cmd->flags & TRIG_WAKE_EOS) {
1985                        /* this may generate un-sustainable interrupt rates */
1986                        /* the application is responsible for doing the right thing */
1987                        devpriv->transCount = cmd->chanlist_len;
1988                        devpriv->flags |= SEND_EOS;
1989                } else {
1990                        /* arrange to transfer data periodically */
1991                        devpriv->transCount
1992                            =
1993                            (TRANS_TARGET_PERIOD * cmd->chanlist_len) /
1994                            cmd->scan_begin_arg;
1995                        if (devpriv->transCount < cmd->chanlist_len) {
1996                                /* tranfer after each scan (and avoid 0) */
1997                                devpriv->transCount = cmd->chanlist_len;
1998                        } else {        /* make a multiple of scan length */
1999                                devpriv->transCount =
2000                                    (devpriv->transCount +
2001                                     cmd->chanlist_len - 1)
2002                                    / cmd->chanlist_len;
2003                                devpriv->transCount *= cmd->chanlist_len;
2004                        }
2005                        devpriv->flags |= SEND_EOS;
2006                }
2007                if (devpriv->transCount >= (devpriv->fifoLen / 2)) {
2008                        /* out of counter range, use 1/2 fifo instead */
2009                        devpriv->transCount = 0;
2010                        devpriv->flags &= ~SEND_EOS;
2011                } else {
2012                        /* interrupt for each tranfer */
2013                        RtdAboutCounter(dev, devpriv->transCount - 1);
2014                }
2015
2016                DPRINTK
2017                    ("rtd520: scanLen=%d tranferCount=%d fifoLen=%d\n  scanTime(ns)=%d flags=0x%x\n",
2018                     cmd->chanlist_len, devpriv->transCount, devpriv->fifoLen,
2019                     cmd->scan_begin_arg, devpriv->flags);
2020        } else {                /* unknown timing, just use 1/2 FIFO */
2021                devpriv->transCount = 0;
2022                devpriv->flags &= ~SEND_EOS;
2023        }
2024        RtdPacerClockSource(dev, 1);    /* use INTERNAL 8Mhz clock source */
2025        RtdAboutStopEnable(dev, 1);     /* just interrupt, dont stop */
2026
2027        /* BUG??? these look like enumerated values, but they are bit fields */
2028
2029        /* First, setup when to stop */
2030        switch (cmd->stop_src) {
2031        case TRIG_COUNT:        /* stop after N scans */
2032                devpriv->aiCount = cmd->stop_arg * cmd->chanlist_len;
2033                if ((devpriv->transCount > 0)
2034                    && (devpriv->transCount > devpriv->aiCount)) {
2035                        devpriv->transCount = devpriv->aiCount;
2036                }
2037                break;
2038
2039        case TRIG_NONE: /* stop when cancel is called */
2040                devpriv->aiCount = -1;  /* read forever */
2041                break;
2042
2043        default:
2044                DPRINTK("rtd520: Warning! ignoring stop_src mode %d\n",
2045                        cmd->stop_src);
2046        }
2047
2048        /* Scan timing */
2049        switch (cmd->scan_begin_src) {
2050        case TRIG_TIMER:        /* periodic scanning */
2051                timer = rtd_ns_to_timer(&cmd->scan_begin_arg,
2052                                        TRIG_ROUND_NEAREST);
2053                /* set PACER clock */
2054                /*DPRINTK ("rtd520: loading %d into pacer\n", timer); */
2055                RtdPacerCounter(dev, timer);
2056
2057                break;
2058
2059        case TRIG_EXT:
2060                RtdPacerStartSource(dev, 1);    /* EXTERNALy trigger pacer */
2061                break;
2062
2063        default:
2064                DPRINTK("rtd520: Warning! ignoring scan_begin_src mode %d\n",
2065                        cmd->scan_begin_src);
2066        }
2067
2068        /* Sample timing within a scan */
2069        switch (cmd->convert_src) {
2070        case TRIG_TIMER:        /* periodic */
2071                if (cmd->chanlist_len > 1) {    /* only needed for multi-channel */
2072                        timer = rtd_ns_to_timer(&cmd->convert_arg,
2073                                                TRIG_ROUND_NEAREST);
2074                        /* setup BURST clock */
2075                        /*DPRINTK ("rtd520: loading %d into burst\n", timer); */
2076                        RtdBurstCounter(dev, timer);
2077                }
2078
2079                break;
2080
2081        case TRIG_EXT:          /* external */
2082                RtdBurstStartSource(dev, 2);    /* EXTERNALy trigger burst */
2083                break;
2084
2085        default:
2086                DPRINTK("rtd520: Warning! ignoring convert_src mode %d\n",
2087                        cmd->convert_src);
2088        }
2089        /* end configuration */
2090
2091        /* This doesn't seem to work.  There is no way to clear an interrupt
2092           that the priority controller has queued! */
2093        RtdInterruptClearMask(dev, ~0); /* clear any existing flags */
2094        RtdInterruptClear(dev);
2095
2096        /* TODO: allow multiple interrupt sources */
2097        if (devpriv->transCount > 0) {  /* transfer every N samples */
2098                RtdInterruptMask(dev, IRQM_ADC_ABOUT_CNT);
2099                DPRINTK("rtd520: Transferring every %d\n", devpriv->transCount);
2100        } else {                /* 1/2 FIFO transfers */
2101#ifdef USE_DMA
2102                devpriv->flags |= DMA0_ACTIVE;
2103
2104                /* point to first transfer in ring */
2105                devpriv->dma0Offset = 0;
2106                RtdDma0Mode(dev, DMA_MODE_BITS);
2107                RtdDma0Next(dev,        /* point to first block */
2108                            devpriv->dma0Chain[DMA_CHAIN_COUNT - 1].next);
2109                RtdDma0Source(dev, DMAS_ADFIFO_HALF_FULL);      /* set DMA trigger source */
2110
2111                RtdPlxInterruptWrite(dev,       /* enable interrupt */
2112                                     RtdPlxInterruptRead(dev) | ICS_DMA0_E);
2113                /* Must be 2 steps.  See PLX app note about "Starting a DMA transfer" */
2114                RtdDma0Control(dev, PLX_DMA_EN_BIT);    /* enable DMA (clear INTR?) */
2115                RtdDma0Control(dev, PLX_DMA_EN_BIT | PLX_DMA_START_BIT);        /*start DMA */
2116                DPRINTK("rtd520: Using DMA0 transfers. plxInt %x RtdInt %x\n",
2117                        RtdPlxInterruptRead(dev), devpriv->intMask);
2118#else /* USE_DMA */
2119                RtdInterruptMask(dev, IRQM_ADC_ABOUT_CNT);
2120                DPRINTK("rtd520: Transferring every 1/2 FIFO\n");
2121#endif /* USE_DMA */
2122        }
2123
2124        /* BUG: start_src is ASSUMED to be TRIG_NOW */
2125        /* BUG? it seems like things are running before the "start" */
2126        RtdPacerStart(dev);     /* Start PACER */
2127        return 0;
2128}
2129
2130/*
2131  Stop a running data aquisition.
2132*/
2133static int rtd_ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
2134{
2135        u16 status;
2136
2137        RtdPacerStopSource(dev, 0);     /* stop on SOFTWARE stop */
2138        RtdPacerStop(dev);      /* Stop PACER */
2139        RtdAdcConversionSource(dev, 0); /* software trigger only */
2140        RtdInterruptMask(dev, 0);
2141        devpriv->aiCount = 0;   /* stop and don't transfer any more */
2142#ifdef USE_DMA
2143        if (devpriv->flags & DMA0_ACTIVE) {
2144                RtdPlxInterruptWrite(dev,       /* disable any more interrupts */
2145                                     RtdPlxInterruptRead(dev) & ~ICS_DMA0_E);
2146                abort_dma(dev, 0);
2147                devpriv->flags &= ~DMA0_ACTIVE;
2148        }
2149#endif /* USE_DMA */
2150        status = RtdInterruptStatus(dev);
2151        DPRINTK
2152            ("rtd520: Acquisition canceled. %ld ints, intStat=%x, overStat=%x\n",
2153             devpriv->intCount, status,
2154             0xffff & RtdInterruptOverrunStatus(dev));
2155        return 0;
2156}
2157
2158/*
2159  Given a desired period and the clock period (both in ns),
2160  return the proper counter value (divider-1).
2161  Sets the original period to be the true value.
2162  Note: you have to check if the value is larger than the counter range!
2163*/
2164static int rtd_ns_to_timer_base(unsigned int *nanosec,  /* desired period (in ns) */
2165                                int round_mode, int base)
2166{                               /* clock period (in ns) */
2167        int divider;
2168
2169        switch (round_mode) {
2170        case TRIG_ROUND_NEAREST:
2171        default:
2172                divider = (*nanosec + base / 2) / base;
2173                break;
2174        case TRIG_ROUND_DOWN:
2175                divider = (*nanosec) / base;
2176                break;
2177        case TRIG_ROUND_UP:
2178                divider = (*nanosec + base - 1) / base;
2179                break;
2180        }
2181        if (divider < 2)
2182                divider = 2;    /* min is divide by 2 */
2183
2184        /* Note: we don't check for max, because different timers
2185           have different ranges */
2186
2187        *nanosec = base * divider;
2188        return divider - 1;     /* countdown is divisor+1 */
2189}
2190
2191/*
2192  Given a desired period (in ns),
2193  return the proper counter value (divider-1) for the internal clock.
2194  Sets the original period to be the true value.
2195*/
2196static int rtd_ns_to_timer(unsigned int *ns, int round_mode)
2197{
2198        return rtd_ns_to_timer_base(ns, round_mode, RTD_CLOCK_BASE);
2199}
2200
2201/*
2202  Output one (or more) analog values to a single port as fast as possible.
2203*/
2204static int rtd_ao_winsn(struct comedi_device *dev,
2205                        struct comedi_subdevice *s, struct comedi_insn *insn,
2206                        unsigned int *data)
2207{
2208        int i;
2209        int chan = CR_CHAN(insn->chanspec);
2210        int range = CR_RANGE(insn->chanspec);
2211
2212        /* Configure the output range (table index matches the range values) */
2213        RtdDacRange(dev, chan, range);
2214
2215        /* Writing a list of values to an AO channel is probably not
2216         * very useful, but that's how the interface is defined. */
2217        for (i = 0; i < insn->n; ++i) {
2218                int val = data[i] << 3;
2219                int stat = 0;   /* initialize to avoid bogus warning */
2220                int ii;
2221
2222                /* VERIFY: comedi range and offset conversions */
2223
2224                if ((range > 1) /* bipolar */
2225                    &&(data[i] < 2048)) {
2226                        /* offset and sign extend */
2227                        val = (((int)data[i]) - 2048) << 3;
2228                } else {        /* unipolor */
2229                        val = data[i] << 3;
2230                }
2231
2232                DPRINTK
2233                    ("comedi: rtd520 DAC chan=%d range=%d writing %d as 0x%x\n",
2234                     chan, range, data[i], val);
2235
2236                /* a typical programming sequence */
2237                RtdDacFifoPut(dev, chan, val);  /* put the value in */
2238                RtdDacUpdate(dev, chan);        /* trigger the conversion */
2239
2240                devpriv->aoValue[chan] = data[i];       /* save for read back */
2241
2242                for (ii = 0; ii < RTD_DAC_TIMEOUT; ++ii) {
2243                        stat = RtdFifoStatus(dev);
2244                        /* 1 -> not empty */
2245                        if (stat & ((0 == chan) ? FS_DAC1_NOT_EMPTY :
2246                                    FS_DAC2_NOT_EMPTY))
2247                                break;
2248                        WAIT_QUIETLY;
2249                }
2250                if (ii >= RTD_DAC_TIMEOUT) {
2251                        DPRINTK
2252                            ("rtd520: Error: DAC never finished! FifoStatus=0x%x\n",
2253                             stat ^ 0x6666);
2254                        return -ETIMEDOUT;
2255                }
2256        }
2257
2258        /* return the number of samples read/written */
2259        return i;
2260}
2261
2262/* AO subdevices should have a read insn as well as a write insn.
2263 * Usually this means copying a value stored in devpriv. */
2264static int rtd_ao_rinsn(struct comedi_device *dev,
2265                        struct comedi_subdevice *s, struct comedi_insn *insn,
2266                        unsigned int *data)
2267{
2268        int i;
2269        int chan = CR_CHAN(insn->chanspec);
2270
2271        for (i = 0; i < insn->n; i++) {
2272                data[i] = devpriv->aoValue[chan];
2273        }
2274
2275        return i;
2276}
2277
2278/*
2279   Write a masked set of bits and the read back the port.
2280   We track what the bits should be (i.e. we don't read the port first).
2281
2282   DIO devices are slightly special.  Although it is possible to
2283 * implement the insn_read/insn_write interface, it is much more
2284 * useful to applications if you implement the insn_bits interface.
2285 * This allows packed reading/writing of the DIO channels.  The
2286 * comedi core can convert between insn_bits and insn_read/write
2287 */
2288static int rtd_dio_insn_bits(struct comedi_device *dev,
2289                             struct comedi_subdevice *s,
2290                             struct comedi_insn *insn, unsigned int *data)
2291{
2292        if (insn->n != 2)
2293                return -EINVAL;
2294
2295        /* The insn data is a mask in data[0] and the new data
2296         * in data[1], each channel cooresponding to a bit. */
2297        if (data[0]) {
2298                s->state &= ~data[0];
2299                s->state |= data[0] & data[1];
2300
2301                /* Write out the new digital output lines */
2302                RtdDio0Write(dev, s->state);
2303        }
2304        /* on return, data[1] contains the value of the digital
2305         * input lines. */
2306        data[1] = RtdDio0Read(dev);
2307
2308        /*DPRINTK("rtd520:port_0 wrote: 0x%x read: 0x%x\n", s->state, data[1]); */
2309
2310        return 2;
2311}
2312
2313/*
2314  Configure one bit on a IO port as Input or Output (hence the name :-).
2315*/
2316static int rtd_dio_insn_config(struct comedi_device *dev,
2317                               struct comedi_subdevice *s,
2318                               struct comedi_insn *insn, unsigned int *data)
2319{
2320        int chan = CR_CHAN(insn->chanspec);
2321
2322        /* The input or output configuration of each digital line is
2323         * configured by a special insn_config instruction.  chanspec
2324         * contains the channel to be changed, and data[0] contains the
2325         * value COMEDI_INPUT or COMEDI_OUTPUT. */
2326        switch (data[0]) {
2327        case INSN_CONFIG_DIO_OUTPUT:
2328                s->io_bits |= 1 << chan;        /* 1 means Out */
2329                break;
2330        case INSN_CONFIG_DIO_INPUT:
2331                s->io_bits &= ~(1 << chan);
2332                break;
2333        case INSN_CONFIG_DIO_QUERY:
2334                data[1] =
2335                    (s->io_bits & (1 << chan)) ? COMEDI_OUTPUT : COMEDI_INPUT;
2336                return insn->n;
2337                break;
2338        default:
2339                return -EINVAL;
2340        }
2341
2342        DPRINTK("rtd520: port_0_direction=0x%x (1 means out)\n", s->io_bits);
2343        /* TODO support digital match interrupts and strobes */
2344        RtdDioStatusWrite(dev, 0x01);   /* make Dio0Ctrl point to direction */
2345        RtdDio0CtrlWrite(dev, s->io_bits);      /* set direction 1 means Out */
2346        RtdDioStatusWrite(dev, 0);      /* make Dio0Ctrl clear interrupts */
2347
2348        /* port1 can only be all input or all output */
2349
2350        /* there are also 2 user input lines and 2 user output lines */
2351
2352        return 1;
2353}
2354
2355/*
2356 * A convenient macro that defines init_module() and cleanup_module(),
2357 * as necessary.
2358 */
2359COMEDI_PCI_INITCLEANUP(rtd520Driver, rtd520_pci_table);
2360