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/io/pci9080
  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 doesn't 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        { PCI_DEVICE(PCI_VENDOR_ID_RTD, 0x7520) },
 333        { PCI_DEVICE(PCI_VENDOR_ID_RTD, 0x4520) },
 334        { 0 }
 335};
 336
 337MODULE_DEVICE_TABLE(pci, rtd520_pci_table);
 338
 339/*
 340 * Useful for shorthand access to the particular board structure
 341 */
 342#define thisboard ((const struct rtdBoard *)dev->board_ptr)
 343
 344/*
 345   This structure is for data unique to this hardware driver.
 346   This is also unique for each board in the system.
 347*/
 348struct rtdPrivate {
 349        /* memory mapped board structures */
 350        void *las0;
 351        void *las1;
 352        void *lcfg;
 353
 354        unsigned long intCount; /* interrupt count */
 355        long aiCount;           /* total transfer size (samples) */
 356        int transCount;         /* # to tranfer data. 0->1/2FIFO */
 357        int flags;              /* flag event modes */
 358
 359        /* PCI device info */
 360        struct pci_dev *pci_dev;
 361        int got_regions;        /* non-zero if PCI regions owned */
 362
 363        /* channel list info */
 364        /* chanBipolar tracks whether a channel is bipolar (and needs +2048) */
 365        unsigned char chanBipolar[RTD_MAX_CHANLIST / 8];        /* bit array */
 366
 367        /* read back data */
 368        unsigned int aoValue[2];        /* Used for AO read back */
 369
 370        /* timer gate (when enabled) */
 371        u8 utcGate[4];          /* 1 extra allows simple range check */
 372
 373        /* shadow registers affect other registers, but can't be read back */
 374        /* The macros below update these on writes */
 375        u16 intMask;            /* interrupt mask */
 376        u16 intClearMask;       /* interrupt clear mask */
 377        u8 utcCtrl[4];          /* crtl mode for 3 utc + read back */
 378        u8 dioStatus;           /* could be read back (dio0Ctrl) */
 379#ifdef USE_DMA
 380        /* Always DMA 1/2 FIFO.  Buffer (dmaBuff?) is (at least) twice that size.
 381           After transferring, interrupt processes 1/2 FIFO and passes to comedi */
 382        s16 dma0Offset;         /* current processing offset (0, 1/2) */
 383        uint16_t *dma0Buff[DMA_CHAIN_COUNT];    /* DMA buffers (for ADC) */
 384        dma_addr_t dma0BuffPhysAddr[DMA_CHAIN_COUNT];   /* physical addresses */
 385        struct plx_dma_desc *dma0Chain; /* DMA descriptor ring for dmaBuff */
 386        dma_addr_t dma0ChainPhysAddr;   /* physical addresses */
 387        /* shadow registers */
 388        u8 dma0Control;
 389        u8 dma1Control;
 390#endif                          /* USE_DMA */
 391        unsigned fifoLen;
 392};
 393
 394/* bit defines for "flags" */
 395#define SEND_EOS        0x01    /* send End Of Scan events */
 396#define DMA0_ACTIVE     0x02    /* DMA0 is active */
 397#define DMA1_ACTIVE     0x04    /* DMA1 is active */
 398
 399/* Macros for accessing channel list bit array */
 400#define CHAN_ARRAY_TEST(array, index) \
 401        (((array)[(index)/8] >> ((index) & 0x7)) & 0x1)
 402#define CHAN_ARRAY_SET(array, index) \
 403        (((array)[(index)/8] |= 1 << ((index) & 0x7)))
 404#define CHAN_ARRAY_CLEAR(array, index) \
 405        (((array)[(index)/8] &= ~(1 << ((index) & 0x7))))
 406
 407/*
 408 * most drivers define the following macro to make it easy to
 409 * access the private structure.
 410 */
 411#define devpriv ((struct rtdPrivate *)dev->private)
 412
 413/* Macros to access registers */
 414
 415/* Reset board */
 416#define RtdResetBoard(dev) \
 417        writel(0, devpriv->las0+LAS0_BOARD_RESET)
 418
 419/* Reset channel gain table read pointer */
 420#define RtdResetCGT(dev) \
 421        writel(0, devpriv->las0+LAS0_CGT_RESET)
 422
 423/* Reset channel gain table read and write pointers */
 424#define RtdClearCGT(dev) \
 425        writel(0, devpriv->las0+LAS0_CGT_CLEAR)
 426
 427/* Reset channel gain table read and write pointers */
 428#define RtdEnableCGT(dev, v) \
 429        writel((v > 0) ? 1 : 0, devpriv->las0+LAS0_CGT_ENABLE)
 430
 431/* Write channel gain table entry */
 432#define RtdWriteCGTable(dev, v) \
 433        writel(v, devpriv->las0+LAS0_CGT_WRITE)
 434
 435/* Write Channel Gain Latch */
 436#define RtdWriteCGLatch(dev, v) \
 437        writel(v, devpriv->las0+LAS0_CGL_WRITE)
 438
 439/* Reset ADC FIFO */
 440#define RtdAdcClearFifo(dev) \
 441        writel(0, devpriv->las0+LAS0_ADC_FIFO_CLEAR)
 442
 443/* Set ADC start conversion source select (write only) */
 444#define RtdAdcConversionSource(dev, v) \
 445        writel(v, devpriv->las0+LAS0_ADC_CONVERSION)
 446
 447/* Set burst start source select (write only) */
 448#define RtdBurstStartSource(dev, v) \
 449        writel(v, devpriv->las0+LAS0_BURST_START)
 450
 451/* Set Pacer start source select (write only) */
 452#define RtdPacerStartSource(dev, v) \
 453        writel(v, devpriv->las0+LAS0_PACER_START)
 454
 455/* Set Pacer stop source select (write only) */
 456#define RtdPacerStopSource(dev, v) \
 457        writel(v, devpriv->las0+LAS0_PACER_STOP)
 458
 459/* Set Pacer clock source select (write only) 0=external 1=internal */
 460#define RtdPacerClockSource(dev, v) \
 461        writel((v > 0) ? 1 : 0, devpriv->las0+LAS0_PACER_SELECT)
 462
 463/* Set sample counter source select (write only) */
 464#define RtdAdcSampleCounterSource(dev, v) \
 465        writel(v, devpriv->las0+LAS0_ADC_SCNT_SRC)
 466
 467/* Set Pacer trigger mode select (write only) 0=single cycle, 1=repeat */
 468#define RtdPacerTriggerMode(dev, v) \
 469        writel((v > 0) ? 1 : 0, devpriv->las0+LAS0_PACER_REPEAT)
 470
 471/* Set About counter stop enable (write only) */
 472#define RtdAboutStopEnable(dev, v) \
 473        writel((v > 0) ? 1 : 0, devpriv->las0+LAS0_ACNT_STOP_ENABLE)
 474
 475/* Set external trigger polarity (write only) 0=positive edge, 1=negative */
 476#define RtdTriggerPolarity(dev, v) \
 477        writel((v > 0) ? 1 : 0, devpriv->las0+LAS0_ETRG_POLARITY)
 478
 479/* Start single ADC conversion */
 480#define RtdAdcStart(dev) \
 481        writew(0, devpriv->las0+LAS0_ADC)
 482
 483/* Read one ADC data value (12bit (with sign extend) as 16bit) */
 484/* Note: matches what DMA would get.  Actual value >> 3 */
 485#define RtdAdcFifoGet(dev) \
 486        readw(devpriv->las1+LAS1_ADC_FIFO)
 487
 488/* Read two ADC data values (DOESN'T WORK) */
 489#define RtdAdcFifoGet2(dev) \
 490        readl(devpriv->las1+LAS1_ADC_FIFO)
 491
 492/* FIFO status */
 493#define RtdFifoStatus(dev) \
 494        readl(devpriv->las0+LAS0_ADC)
 495
 496/* pacer start/stop read=start, write=stop*/
 497#define RtdPacerStart(dev) \
 498        readl(devpriv->las0+LAS0_PACER)
 499#define RtdPacerStop(dev) \
 500        writel(0, devpriv->las0+LAS0_PACER)
 501
 502/* Interrupt status */
 503#define RtdInterruptStatus(dev) \
 504        readw(devpriv->las0+LAS0_IT)
 505
 506/* Interrupt mask */
 507#define RtdInterruptMask(dev, v) \
 508        writew((devpriv->intMask = (v)), devpriv->las0+LAS0_IT)
 509
 510/* Interrupt status clear (only bits set in mask) */
 511#define RtdInterruptClear(dev) \
 512        readw(devpriv->las0+LAS0_CLEAR)
 513
 514/* Interrupt clear mask */
 515#define RtdInterruptClearMask(dev, v) \
 516        writew((devpriv->intClearMask = (v)), devpriv->las0+LAS0_CLEAR)
 517
 518/* Interrupt overrun status */
 519#define RtdInterruptOverrunStatus(dev) \
 520        readl(devpriv->las0+LAS0_OVERRUN)
 521
 522/* Interrupt overrun clear */
 523#define RtdInterruptOverrunClear(dev) \
 524        writel(0, devpriv->las0+LAS0_OVERRUN)
 525
 526/* Pacer counter, 24bit */
 527#define RtdPacerCount(dev) \
 528        readl(devpriv->las0+LAS0_PCLK)
 529#define RtdPacerCounter(dev, v) \
 530        writel((v) & 0xffffff, devpriv->las0+LAS0_PCLK)
 531
 532/* Burst counter, 10bit */
 533#define RtdBurstCount(dev) \
 534        readl(devpriv->las0+LAS0_BCLK)
 535#define RtdBurstCounter(dev, v) \
 536        writel((v) & 0x3ff, devpriv->las0+LAS0_BCLK)
 537
 538/* Delay counter, 16bit */
 539#define RtdDelayCount(dev) \
 540        readl(devpriv->las0+LAS0_DCLK)
 541#define RtdDelayCounter(dev, v) \
 542        writel((v) & 0xffff, devpriv->las0+LAS0_DCLK)
 543
 544/* About counter, 16bit */
 545#define RtdAboutCount(dev) \
 546        readl(devpriv->las0+LAS0_ACNT)
 547#define RtdAboutCounter(dev, v) \
 548        writel((v) & 0xffff, devpriv->las0+LAS0_ACNT)
 549
 550/* ADC sample counter, 10bit */
 551#define RtdAdcSampleCount(dev) \
 552        readl(devpriv->las0+LAS0_ADC_SCNT)
 553#define RtdAdcSampleCounter(dev, v) \
 554        writel((v) & 0x3ff, devpriv->las0+LAS0_ADC_SCNT)
 555
 556/* User Timer/Counter (8254) */
 557#define RtdUtcCounterGet(dev, n) \
 558        readb(devpriv->las0 \
 559                + ((n <= 0) ? LAS0_UTC0 : ((1 == n) ? LAS0_UTC1 : LAS0_UTC2)))
 560
 561#define RtdUtcCounterPut(dev, n, v) \
 562        writeb((v) & 0xff, devpriv->las0 \
 563                + ((n <= 0) ? LAS0_UTC0 : ((1 == n) ? LAS0_UTC1 : LAS0_UTC2)))
 564
 565/* Set UTC (8254) control byte  */
 566#define RtdUtcCtrlPut(dev, n, v) \
 567        writeb(devpriv->utcCtrl[(n) & 3] = (((n) & 3) << 6) | ((v) & 0x3f), \
 568                devpriv->las0 + LAS0_UTC_CTRL)
 569
 570/* Set UTCn clock source (write only) */
 571#define RtdUtcClockSource(dev, n, v) \
 572        writew(v, devpriv->las0 \
 573                + ((n <= 0) ? LAS0_UTC0_CLOCK : \
 574                        ((1 == n) ? LAS0_UTC1_CLOCK : LAS0_UTC2_CLOCK)))
 575
 576/* Set UTCn gate source (write only) */
 577#define RtdUtcGateSource(dev, n, v) \
 578        writew(v, devpriv->las0 \
 579                + ((n <= 0) ? LAS0_UTC0_GATE : \
 580                        ((1 == n) ? LAS0_UTC1_GATE : LAS0_UTC2_GATE)))
 581
 582/* User output N source select (write only) */
 583#define RtdUsrOutSource(dev, n, v) \
 584        writel(v, devpriv->las0+((n <= 0) ? LAS0_UOUT0_SELECT : LAS0_UOUT1_SELECT))
 585
 586/* Digital IO */
 587#define RtdDio0Read(dev) \
 588        (readw(devpriv->las0+LAS0_DIO0) & 0xff)
 589#define RtdDio0Write(dev, v) \
 590        writew((v) & 0xff, devpriv->las0+LAS0_DIO0)
 591
 592#define RtdDio1Read(dev) \
 593        (readw(devpriv->las0+LAS0_DIO1) & 0xff)
 594#define RtdDio1Write(dev, v) \
 595        writew((v) & 0xff, devpriv->las0+LAS0_DIO1)
 596
 597#define RtdDioStatusRead(dev) \
 598        (readw(devpriv->las0+LAS0_DIO_STATUS) & 0xff)
 599#define RtdDioStatusWrite(dev, v) \
 600        writew((devpriv->dioStatus = (v)), devpriv->las0+LAS0_DIO_STATUS)
 601
 602#define RtdDio0CtrlRead(dev) \
 603        (readw(devpriv->las0+LAS0_DIO0_CTRL) & 0xff)
 604#define RtdDio0CtrlWrite(dev, v) \
 605        writew((v) & 0xff, devpriv->las0+LAS0_DIO0_CTRL)
 606
 607/* Digital to Analog converter */
 608/* Write one data value (sign + 12bit + marker bits) */
 609/* Note: matches what DMA would put.  Actual value << 3 */
 610#define RtdDacFifoPut(dev, n, v) \
 611        writew((v), devpriv->las1 + (((n) == 0) ? LAS1_DAC1_FIFO : LAS1_DAC2_FIFO))
 612
 613/* Start single DAC conversion */
 614#define RtdDacUpdate(dev, n) \
 615        writew(0, devpriv->las0 + (((n) == 0) ? LAS0_DAC1 : LAS0_DAC2))
 616
 617/* Start single DAC conversion on both DACs */
 618#define RtdDacBothUpdate(dev) \
 619        writew(0, devpriv->las0+LAS0_DAC)
 620
 621/* Set DAC output type and range */
 622#define RtdDacRange(dev, n, v) \
 623        writew((v) & 7, devpriv->las0 \
 624                +(((n) == 0) ? LAS0_DAC1_CTRL : LAS0_DAC2_CTRL))
 625
 626/* Reset DAC FIFO */
 627#define RtdDacClearFifo(dev, n) \
 628        writel(0, devpriv->las0+(((n) == 0) ? LAS0_DAC1_RESET : LAS0_DAC2_RESET))
 629
 630/* Set source for DMA 0 (write only, shadow?) */
 631#define RtdDma0Source(dev, n) \
 632        writel((n) & 0xf, devpriv->las0+LAS0_DMA0_SRC)
 633
 634/* Set source for DMA 1 (write only, shadow?) */
 635#define RtdDma1Source(dev, n) \
 636        writel((n) & 0xf, devpriv->las0+LAS0_DMA1_SRC)
 637
 638/* Reset board state for DMA 0 */
 639#define RtdDma0Reset(dev) \
 640        writel(0, devpriv->las0+LAS0_DMA0_RESET)
 641
 642/* Reset board state for DMA 1 */
 643#define RtdDma1Reset(dev) \
 644        writel(0, devpriv->las0+LAS0_DMA1_SRC)
 645
 646/* PLX9080 interrupt mask and status */
 647#define RtdPlxInterruptRead(dev) \
 648        readl(devpriv->lcfg+LCFG_ITCSR)
 649#define RtdPlxInterruptWrite(dev, v) \
 650        writel(v, devpriv->lcfg+LCFG_ITCSR)
 651
 652/* Set  mode for DMA 0 */
 653#define RtdDma0Mode(dev, m) \
 654        writel((m), devpriv->lcfg+LCFG_DMAMODE0)
 655
 656/* Set PCI address for DMA 0 */
 657#define RtdDma0PciAddr(dev, a) \
 658        writel((a), devpriv->lcfg+LCFG_DMAPADR0)
 659
 660/* Set local address for DMA 0 */
 661#define RtdDma0LocalAddr(dev, a) \
 662        writel((a), devpriv->lcfg+LCFG_DMALADR0)
 663
 664/* Set byte count for DMA 0 */
 665#define RtdDma0Count(dev, c) \
 666        writel((c), devpriv->lcfg+LCFG_DMASIZ0)
 667
 668/* Set next descriptor for DMA 0 */
 669#define RtdDma0Next(dev, a) \
 670        writel((a), devpriv->lcfg+LCFG_DMADPR0)
 671
 672/* Set  mode for DMA 1 */
 673#define RtdDma1Mode(dev, m) \
 674        writel((m), devpriv->lcfg+LCFG_DMAMODE1)
 675
 676/* Set PCI address for DMA 1 */
 677#define RtdDma1PciAddr(dev, a) \
 678        writel((a), devpriv->lcfg+LCFG_DMAADR1)
 679
 680/* Set local address for DMA 1 */
 681#define RtdDma1LocalAddr(dev, a) \
 682        writel((a), devpriv->lcfg+LCFG_DMALADR1)
 683
 684/* Set byte count for DMA 1 */
 685#define RtdDma1Count(dev, c) \
 686        writel((c), devpriv->lcfg+LCFG_DMASIZ1)
 687
 688/* Set next descriptor for DMA 1 */
 689#define RtdDma1Next(dev, a) \
 690        writel((a), devpriv->lcfg+LCFG_DMADPR1)
 691
 692/* Set control for DMA 0 (write only, shadow?) */
 693#define RtdDma0Control(dev, n) \
 694        writeb(devpriv->dma0Control = (n), devpriv->lcfg+LCFG_DMACSR0)
 695
 696/* Get status for DMA 0 */
 697#define RtdDma0Status(dev) \
 698        readb(devpriv->lcfg+LCFG_DMACSR0)
 699
 700/* Set control for DMA 1 (write only, shadow?) */
 701#define RtdDma1Control(dev, n) \
 702        writeb(devpriv->dma1Control = (n), devpriv->lcfg+LCFG_DMACSR1)
 703
 704/* Get status for DMA 1 */
 705#define RtdDma1Status(dev) \
 706        readb(devpriv->lcfg+LCFG_DMACSR1)
 707
 708/*
 709 * The struct comedi_driver structure tells the Comedi core module
 710 * which functions to call to configure/deconfigure (attac/detach)
 711 * the board, and also about the kernel module that contains
 712 * the device code.
 713 */
 714static int rtd_attach(struct comedi_device *dev, struct comedi_devconfig *it);
 715static int rtd_detach(struct comedi_device *dev);
 716
 717static struct comedi_driver rtd520Driver = {
 718        .driver_name = DRV_NAME,
 719        .module = THIS_MODULE,
 720        .attach = rtd_attach,
 721        .detach = rtd_detach,
 722};
 723
 724static int rtd_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
 725                        struct comedi_insn *insn, unsigned int *data);
 726static int rtd_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
 727                        struct comedi_insn *insn, unsigned int *data);
 728static int rtd_ao_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
 729                        struct comedi_insn *insn, unsigned int *data);
 730static int rtd_dio_insn_bits(struct comedi_device *dev,
 731                             struct comedi_subdevice *s,
 732                             struct comedi_insn *insn, unsigned int *data);
 733static int rtd_dio_insn_config(struct comedi_device *dev,
 734                               struct comedi_subdevice *s,
 735                               struct comedi_insn *insn, unsigned int *data);
 736static int rtd_ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
 737                          struct comedi_cmd *cmd);
 738static int rtd_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s);
 739static int rtd_ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s);
 740/* static int rtd_ai_poll (struct comedi_device *dev,struct comedi_subdevice *s); */
 741static int rtd_ns_to_timer(unsigned int *ns, int roundMode);
 742static irqreturn_t rtd_interrupt(int irq, void *d);
 743static int rtd520_probe_fifo_depth(struct comedi_device *dev);
 744
 745/*
 746 * Attach is called by the Comedi core to configure the driver
 747 * for a particular board.  If you specified a board_name array
 748 * in the driver structure, dev->board_ptr contains that
 749 * address.
 750 */
 751static int rtd_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 752{                               /* board name and options flags */
 753        struct comedi_subdevice *s;
 754        struct pci_dev *pcidev;
 755        int ret;
 756        resource_size_t physLas0;       /* configuration */
 757        resource_size_t physLas1;       /* data area */
 758        resource_size_t physLcfg;       /* PLX9080 */
 759#ifdef USE_DMA
 760        int index;
 761#endif
 762
 763        printk(KERN_INFO "comedi%d: rtd520 attaching.\n", dev->minor);
 764
 765#if defined(CONFIG_COMEDI_DEBUG) && defined(USE_DMA)
 766        /* You can set this a load time: modprobe comedi comedi_debug=1 */
 767        if (0 == comedi_debug)  /* force DMA debug printks */
 768                comedi_debug = 1;
 769#endif
 770
 771        /*
 772         * Allocate the private structure area.  alloc_private() is a
 773         * convenient macro defined in comedidev.h.
 774         */
 775        if (alloc_private(dev, sizeof(struct rtdPrivate)) < 0)
 776                return -ENOMEM;
 777
 778        /*
 779         * Probe the device to determine what device in the series it is.
 780         */
 781        for (pcidev = pci_get_device(PCI_VENDOR_ID_RTD, PCI_ANY_ID, NULL);
 782             pcidev != NULL;
 783             pcidev = pci_get_device(PCI_VENDOR_ID_RTD, PCI_ANY_ID, pcidev)) {
 784                int i;
 785
 786                if (it->options[0] || it->options[1]) {
 787                        if (pcidev->bus->number != it->options[0]
 788                            || PCI_SLOT(pcidev->devfn) != it->options[1]) {
 789                                continue;
 790                        }
 791                }
 792                for (i = 0; i < ARRAY_SIZE(rtd520Boards); ++i) {
 793                        if (pcidev->device == rtd520Boards[i].device_id) {
 794                                dev->board_ptr = &rtd520Boards[i];
 795                                break;
 796                        }
 797                }
 798                if (dev->board_ptr)
 799                        break;  /* found one */
 800        }
 801        if (!pcidev) {
 802                if (it->options[0] && it->options[1]) {
 803                        printk(KERN_INFO "No RTD card at bus=%d slot=%d.\n",
 804                               it->options[0], it->options[1]);
 805                } else {
 806                        printk(KERN_INFO "No RTD card found.\n");
 807                }
 808                return -EIO;
 809        }
 810        devpriv->pci_dev = pcidev;
 811        dev->board_name = thisboard->name;
 812
 813        ret = comedi_pci_enable(pcidev, DRV_NAME);
 814        if (ret < 0) {
 815                printk(KERN_INFO "Failed to enable PCI device and request regions.\n");
 816                return ret;
 817        }
 818        devpriv->got_regions = 1;
 819
 820        /*
 821         * Initialize base addresses
 822         */
 823        /* Get the physical address from PCI config */
 824        physLas0 = pci_resource_start(devpriv->pci_dev, LAS0_PCIINDEX);
 825        physLas1 = pci_resource_start(devpriv->pci_dev, LAS1_PCIINDEX);
 826        physLcfg = pci_resource_start(devpriv->pci_dev, LCFG_PCIINDEX);
 827        /* Now have the kernel map this into memory */
 828        /* ASSUME page aligned */
 829        devpriv->las0 = ioremap_nocache(physLas0, LAS0_PCISIZE);
 830        devpriv->las1 = ioremap_nocache(physLas1, LAS1_PCISIZE);
 831        devpriv->lcfg = ioremap_nocache(physLcfg, LCFG_PCISIZE);
 832
 833        if (!devpriv->las0 || !devpriv->las1 || !devpriv->lcfg)
 834                return -ENOMEM;
 835
 836
 837        DPRINTK("%s: LAS0=%llx, LAS1=%llx, CFG=%llx.\n", dev->board_name,
 838                (unsigned long long)physLas0, (unsigned long long)physLas1,
 839                (unsigned long long)physLcfg);
 840        {                       /* The RTD driver does this */
 841                unsigned char pci_latency;
 842                u16 revision;
 843                /*uint32_t epld_version; */
 844
 845                pci_read_config_word(devpriv->pci_dev, PCI_REVISION_ID,
 846                                     &revision);
 847                DPRINTK("%s: PCI revision %d.\n", dev->board_name, revision);
 848
 849                pci_read_config_byte(devpriv->pci_dev,
 850                                     PCI_LATENCY_TIMER, &pci_latency);
 851                if (pci_latency < 32) {
 852                        printk(KERN_INFO "%s: PCI latency changed from %d to %d\n",
 853                               dev->board_name, pci_latency, 32);
 854                        pci_write_config_byte(devpriv->pci_dev,
 855                                              PCI_LATENCY_TIMER, 32);
 856                } else {
 857                        DPRINTK("rtd520: PCI latency = %d\n", pci_latency);
 858                }
 859
 860                /* Undocumented EPLD version (doesn't match RTD driver results) */
 861                /*DPRINTK ("rtd520: Reading epld from %p\n",
 862                   devpriv->las0+0);
 863                   epld_version = readl (devpriv->las0+0);
 864                   if ((epld_version & 0xF0) >> 4 == 0x0F) {
 865                   DPRINTK("rtd520: pre-v8 EPLD. (%x)\n", epld_version);
 866                   } else {
 867                   DPRINTK("rtd520: EPLD version %x.\n", epld_version >> 4);
 868                   } */
 869        }
 870
 871        /* Show board configuration */
 872        printk(KERN_INFO "%s:", dev->board_name);
 873
 874        /*
 875         * Allocate the subdevice structures.  alloc_subdevice() is a
 876         * convenient macro defined in comedidev.h.
 877         */
 878        if (alloc_subdevices(dev, 4) < 0)
 879                return -ENOMEM;
 880
 881
 882        s = dev->subdevices + 0;
 883        dev->read_subdev = s;
 884        /* analog input subdevice */
 885        s->type = COMEDI_SUBD_AI;
 886        s->subdev_flags =
 887            SDF_READABLE | SDF_GROUND | SDF_COMMON | SDF_DIFF | SDF_CMD_READ;
 888        s->n_chan = thisboard->aiChans;
 889        s->maxdata = (1 << thisboard->aiBits) - 1;
 890        if (thisboard->aiMaxGain <= 32)
 891                s->range_table = &rtd_ai_7520_range;
 892        else
 893                s->range_table = &rtd_ai_4520_range;
 894
 895        s->len_chanlist = RTD_MAX_CHANLIST;     /* devpriv->fifoLen */
 896        s->insn_read = rtd_ai_rinsn;
 897        s->do_cmd = rtd_ai_cmd;
 898        s->do_cmdtest = rtd_ai_cmdtest;
 899        s->cancel = rtd_ai_cancel;
 900        /* s->poll = rtd_ai_poll; *//* not ready yet */
 901
 902        s = dev->subdevices + 1;
 903        /* analog output subdevice */
 904        s->type = COMEDI_SUBD_AO;
 905        s->subdev_flags = SDF_WRITABLE;
 906        s->n_chan = 2;
 907        s->maxdata = (1 << thisboard->aiBits) - 1;
 908        s->range_table = &rtd_ao_range;
 909        s->insn_write = rtd_ao_winsn;
 910        s->insn_read = rtd_ao_rinsn;
 911
 912        s = dev->subdevices + 2;
 913        /* digital i/o subdevice */
 914        s->type = COMEDI_SUBD_DIO;
 915        s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
 916        /* we only support port 0 right now.  Ignoring port 1 and user IO */
 917        s->n_chan = 8;
 918        s->maxdata = 1;
 919        s->range_table = &range_digital;
 920        s->insn_bits = rtd_dio_insn_bits;
 921        s->insn_config = rtd_dio_insn_config;
 922
 923        /* timer/counter subdevices (not currently supported) */
 924        s = dev->subdevices + 3;
 925        s->type = COMEDI_SUBD_COUNTER;
 926        s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
 927        s->n_chan = 3;
 928        s->maxdata = 0xffff;
 929
 930        /* initialize board, per RTD spec */
 931        /* also, initialize shadow registers */
 932        RtdResetBoard(dev);
 933        udelay(100);            /* needed? */
 934        RtdPlxInterruptWrite(dev, 0);
 935        RtdInterruptMask(dev, 0);       /* and sets shadow */
 936        RtdInterruptClearMask(dev, ~0); /* and sets shadow */
 937        RtdInterruptClear(dev); /* clears bits set by mask */
 938        RtdInterruptOverrunClear(dev);
 939        RtdClearCGT(dev);
 940        RtdAdcClearFifo(dev);
 941        RtdDacClearFifo(dev, 0);
 942        RtdDacClearFifo(dev, 1);
 943        /* clear digital IO fifo */
 944        RtdDioStatusWrite(dev, 0);      /* safe state, set shadow */
 945        RtdUtcCtrlPut(dev, 0, 0x30);    /* safe state, set shadow */
 946        RtdUtcCtrlPut(dev, 1, 0x30);    /* safe state, set shadow */
 947        RtdUtcCtrlPut(dev, 2, 0x30);    /* safe state, set shadow */
 948        RtdUtcCtrlPut(dev, 3, 0);       /* safe state, set shadow */
 949        /* TODO: set user out source ??? */
 950
 951        /* check if our interrupt is available and get it */
 952        ret = request_irq(devpriv->pci_dev->irq, rtd_interrupt,
 953                          IRQF_SHARED, DRV_NAME, dev);
 954
 955        if (ret < 0) {
 956                printk("Could not get interrupt! (%u)\n",
 957                       devpriv->pci_dev->irq);
 958                return ret;
 959        }
 960        dev->irq = devpriv->pci_dev->irq;
 961        printk(KERN_INFO "( irq=%u )", dev->irq);
 962
 963        ret = rtd520_probe_fifo_depth(dev);
 964        if (ret < 0)
 965                return ret;
 966
 967        devpriv->fifoLen = ret;
 968        printk("( fifoLen=%d )", devpriv->fifoLen);
 969
 970#ifdef USE_DMA
 971        if (dev->irq > 0) {
 972                printk("( DMA buff=%d )\n", DMA_CHAIN_COUNT);
 973                /* The PLX9080 has 2 DMA controllers, but there could be 4 sources:
 974                   ADC, digital, DAC1, and DAC2.  Since only the ADC supports cmd mode
 975                   right now, this isn't an issue (yet) */
 976                devpriv->dma0Offset = 0;
 977
 978                for (index = 0; index < DMA_CHAIN_COUNT; index++) {
 979                        devpriv->dma0Buff[index] =
 980                            pci_alloc_consistent(devpriv->pci_dev,
 981                                                 sizeof(u16) *
 982                                                 devpriv->fifoLen / 2,
 983                                                 &devpriv->
 984                                                 dma0BuffPhysAddr[index]);
 985                        if (devpriv->dma0Buff[index] == NULL) {
 986                                ret = -ENOMEM;
 987                                goto rtd_attach_die_error;
 988                        }
 989                        /*DPRINTK ("buff[%d] @ %p virtual, %x PCI\n",
 990                           index,
 991                           devpriv->dma0Buff[index], devpriv->dma0BuffPhysAddr[index]); */
 992                }
 993
 994                /* setup DMA descriptor ring (use cpu_to_le32 for byte ordering?) */
 995                devpriv->dma0Chain =
 996                    pci_alloc_consistent(devpriv->pci_dev,
 997                                         sizeof(struct plx_dma_desc) *
 998                                         DMA_CHAIN_COUNT,
 999                                         &devpriv->dma0ChainPhysAddr);
1000                for (index = 0; index < DMA_CHAIN_COUNT; index++) {
1001                        devpriv->dma0Chain[index].pci_start_addr =
1002                            devpriv->dma0BuffPhysAddr[index];
1003                        devpriv->dma0Chain[index].local_start_addr =
1004                            DMALADDR_ADC;
1005                        devpriv->dma0Chain[index].transfer_size =
1006                            sizeof(u16) * devpriv->fifoLen / 2;
1007                        devpriv->dma0Chain[index].next =
1008                            (devpriv->dma0ChainPhysAddr + ((index +
1009                                                            1) %
1010                                                           (DMA_CHAIN_COUNT))
1011                             * sizeof(devpriv->dma0Chain[0]))
1012                            | DMA_TRANSFER_BITS;
1013                        /*DPRINTK ("ring[%d] @%lx PCI: %x, local: %x, N: 0x%x, next: %x\n",
1014                           index,
1015                           ((long)devpriv->dma0ChainPhysAddr
1016                           + (index * sizeof(devpriv->dma0Chain[0]))),
1017                           devpriv->dma0Chain[index].pci_start_addr,
1018                           devpriv->dma0Chain[index].local_start_addr,
1019                           devpriv->dma0Chain[index].transfer_size,
1020                           devpriv->dma0Chain[index].next); */
1021                }
1022
1023                if (devpriv->dma0Chain == NULL) {
1024                        ret = -ENOMEM;
1025                        goto rtd_attach_die_error;
1026                }
1027
1028                RtdDma0Mode(dev, DMA_MODE_BITS);
1029                /* set DMA trigger source */
1030                RtdDma0Source(dev, DMAS_ADFIFO_HALF_FULL);
1031        } else {
1032                printk(KERN_INFO "( 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(KERN_INFO "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                /* gain */
1207                r |= ((range - thisboard->range10Start) & 0x7) << 4;
1208                CHAN_ARRAY_SET(devpriv->chanBipolar, chanIndex);
1209        } else {                /* last batch is +10 */
1210                r |= 0x200;     /* +10 range */
1211                /* gain */
1212                r |= ((range - thisboard->rangeUniStart) & 0x7) << 4;
1213                CHAN_ARRAY_CLEAR(devpriv->chanBipolar, chanIndex);
1214        }
1215
1216        switch (aref) {
1217        case AREF_GROUND:       /* on-board ground */
1218                break;
1219
1220        case AREF_COMMON:
1221                r |= 0x80;      /* ref external analog common */
1222                break;
1223
1224        case AREF_DIFF:
1225                r |= 0x400;     /* differential inputs */
1226                break;
1227
1228        case AREF_OTHER:        /* ??? */
1229                break;
1230        }
1231        /*printk ("chan=%d r=%d a=%d -> 0x%x\n",
1232           chan, range, aref, r); */
1233        return r;
1234}
1235
1236/*
1237  Setup the channel-gain table from a comedi list
1238*/
1239static void rtd_load_channelgain_list(struct comedi_device *dev,
1240                                      unsigned int n_chan, unsigned int *list)
1241{
1242        if (n_chan > 1) {       /* setup channel gain table */
1243                int ii;
1244                RtdClearCGT(dev);
1245                RtdEnableCGT(dev, 1);   /* enable table */
1246                for (ii = 0; ii < n_chan; ii++) {
1247                        RtdWriteCGTable(dev, rtdConvertChanGain(dev, list[ii],
1248                                                                ii));
1249                }
1250        } else {                /* just use the channel gain latch */
1251                RtdEnableCGT(dev, 0);   /* disable table, enable latch */
1252                RtdWriteCGLatch(dev, rtdConvertChanGain(dev, list[0], 0));
1253        }
1254}
1255
1256/* determine fifo size by doing adc conversions until the fifo half
1257empty status flag clears */
1258static int rtd520_probe_fifo_depth(struct comedi_device *dev)
1259{
1260        unsigned int chanspec = CR_PACK(0, 0, AREF_GROUND);
1261        unsigned i;
1262        static const unsigned limit = 0x2000;
1263        unsigned fifo_size = 0;
1264
1265        RtdAdcClearFifo(dev);
1266        rtd_load_channelgain_list(dev, 1, &chanspec);
1267        RtdAdcConversionSource(dev, 0); /* software */
1268        /* convert  samples */
1269        for (i = 0; i < limit; ++i) {
1270                unsigned fifo_status;
1271                /* trigger conversion */
1272                RtdAdcStart(dev);
1273                udelay(1);
1274                fifo_status = RtdFifoStatus(dev);
1275                if ((fifo_status & FS_ADC_HEMPTY) == 0) {
1276                        fifo_size = 2 * i;
1277                        break;
1278                }
1279        }
1280        if (i == limit) {
1281                printk(KERN_INFO "\ncomedi: %s: failed to probe fifo size.\n", DRV_NAME);
1282                return -EIO;
1283        }
1284        RtdAdcClearFifo(dev);
1285        if (fifo_size != 0x400 && fifo_size != 0x2000) {
1286                printk
1287                    (KERN_INFO "\ncomedi: %s: unexpected fifo size of %i, expected 1024 or 8192.\n",
1288                     DRV_NAME, fifo_size);
1289                return -EIO;
1290        }
1291        return fifo_size;
1292}
1293
1294/*
1295  "instructions" read/write data in "one-shot" or "software-triggered"
1296  mode (simplest case).
1297  This doesn't use interrupts.
1298
1299  Note, we don't do any settling delays.  Use a instruction list to
1300  select, delay, then read.
1301 */
1302static int rtd_ai_rinsn(struct comedi_device *dev,
1303                        struct comedi_subdevice *s, struct comedi_insn *insn,
1304                        unsigned int *data)
1305{
1306        int n, ii;
1307        int stat;
1308
1309        /* clear any old fifo data */
1310        RtdAdcClearFifo(dev);
1311
1312        /* write channel to multiplexer and clear channel gain table */
1313        rtd_load_channelgain_list(dev, 1, &insn->chanspec);
1314
1315        /* set conversion source */
1316        RtdAdcConversionSource(dev, 0); /* software */
1317
1318        /* convert n samples */
1319        for (n = 0; n < insn->n; n++) {
1320                s16 d;
1321                /* trigger conversion */
1322                RtdAdcStart(dev);
1323
1324                for (ii = 0; ii < RTD_ADC_TIMEOUT; ++ii) {
1325                        stat = RtdFifoStatus(dev);
1326                        if (stat & FS_ADC_NOT_EMPTY)    /* 1 -> not empty */
1327                                break;
1328                        WAIT_QUIETLY;
1329                }
1330                if (ii >= RTD_ADC_TIMEOUT) {
1331                        DPRINTK
1332                            ("rtd520: Error: ADC never finished! FifoStatus=0x%x\n",
1333                             stat ^ 0x6666);
1334                        return -ETIMEDOUT;
1335                }
1336
1337                /* read data */
1338                d = RtdAdcFifoGet(dev); /* get 2s comp value */
1339                /*printk ("rtd520: Got 0x%x after %d usec\n", d, ii+1); */
1340                d = d >> 3;     /* low 3 bits are marker lines */
1341                if (CHAN_ARRAY_TEST(devpriv->chanBipolar, 0))
1342                        /* convert to comedi unsigned data */
1343                        data[n] = d + 2048;
1344                else
1345                        data[n] = d;
1346        }
1347
1348        /* return the number of samples read/written */
1349        return n;
1350}
1351
1352/*
1353  Get what we know is there.... Fast!
1354  This uses 1/2 the bus cycles of read_dregs (below).
1355
1356  The manual claims that we can do a lword read, but it doesn't work here.
1357*/
1358static int ai_read_n(struct comedi_device *dev, struct comedi_subdevice *s,
1359                     int count)
1360{
1361        int ii;
1362
1363        for (ii = 0; ii < count; ii++) {
1364                short sample;
1365                s16 d;
1366
1367                if (0 == devpriv->aiCount) {    /* done */
1368                        d = RtdAdcFifoGet(dev); /* Read N and discard */
1369                        continue;
1370                }
1371#if 0
1372                if (0 == (RtdFifoStatus(dev) & FS_ADC_NOT_EMPTY)) {     /* DEBUG */
1373                        DPRINTK("comedi: READ OOPS on %d of %d\n", ii + 1,
1374                                count);
1375                        break;
1376                }
1377#endif
1378                d = RtdAdcFifoGet(dev); /* get 2s comp value */
1379
1380                d = d >> 3;     /* low 3 bits are marker lines */
1381                if (CHAN_ARRAY_TEST(devpriv->chanBipolar, s->async->cur_chan))
1382                        sample = d + 2048;      /* convert to comedi unsigned data */
1383                else
1384                        sample = d;
1385
1386                if (!comedi_buf_put(s->async, sample))
1387                        return -1;
1388
1389                if (devpriv->aiCount > 0)       /* < 0, means read forever */
1390                        devpriv->aiCount--;
1391        }
1392        return 0;
1393}
1394
1395/*
1396  unknown amout of data is waiting in fifo.
1397*/
1398static int ai_read_dregs(struct comedi_device *dev, struct comedi_subdevice *s)
1399{
1400        while (RtdFifoStatus(dev) & FS_ADC_NOT_EMPTY) { /* 1 -> not empty */
1401                short sample;
1402                s16 d = RtdAdcFifoGet(dev);     /* get 2s comp value */
1403
1404                if (0 == devpriv->aiCount) {    /* done */
1405                        continue;       /* read rest */
1406                }
1407
1408                d = d >> 3;     /* low 3 bits are marker lines */
1409                if (CHAN_ARRAY_TEST(devpriv->chanBipolar, s->async->cur_chan))
1410                        sample = d + 2048;      /* convert to comedi unsigned data */
1411                else
1412                        sample = d;
1413
1414                if (!comedi_buf_put(s->async, sample))
1415                        return -1;
1416
1417                if (devpriv->aiCount > 0)       /* < 0, means read forever */
1418                        devpriv->aiCount--;
1419        }
1420        return 0;
1421}
1422
1423#ifdef USE_DMA
1424/*
1425  Terminate a DMA transfer and wait for everything to quiet down
1426*/
1427void abort_dma(struct comedi_device *dev, unsigned int channel)
1428{                               /* DMA channel 0, 1 */
1429        unsigned long dma_cs_addr;      /* the control/status register */
1430        uint8_t status;
1431        unsigned int ii;
1432        /* unsigned long flags; */
1433
1434        dma_cs_addr = (unsigned long)devpriv->lcfg
1435            + ((channel == 0) ? LCFG_DMACSR0 : LCFG_DMACSR1);
1436
1437        /*  spinlock for plx dma control/status reg */
1438        /* spin_lock_irqsave( &dev->spinlock, flags ); */
1439
1440        /*  abort dma transfer if necessary */
1441        status = readb(dma_cs_addr);
1442        if ((status & PLX_DMA_EN_BIT) == 0) {   /* not enabled (Error?) */
1443                DPRINTK("rtd520: AbortDma on non-active channel %d (0x%x)\n",
1444                        channel, status);
1445                goto abortDmaExit;
1446        }
1447
1448        /* wait to make sure done bit is zero (needed?) */
1449        for (ii = 0; (status & PLX_DMA_DONE_BIT) && ii < RTD_DMA_TIMEOUT; ii++) {
1450                WAIT_QUIETLY;
1451                status = readb(dma_cs_addr);
1452        }
1453        if (status & PLX_DMA_DONE_BIT) {
1454                printk("rtd520: Timeout waiting for dma %i done clear\n",
1455                       channel);
1456                goto abortDmaExit;
1457        }
1458
1459        /* disable channel (required) */
1460        writeb(0, dma_cs_addr);
1461        udelay(1);              /* needed?? */
1462        /* set abort bit for channel */
1463        writeb(PLX_DMA_ABORT_BIT, dma_cs_addr);
1464
1465        /*  wait for dma done bit to be set */
1466        status = readb(dma_cs_addr);
1467        for (ii = 0;
1468             (status & PLX_DMA_DONE_BIT) == 0 && ii < RTD_DMA_TIMEOUT; ii++) {
1469                status = readb(dma_cs_addr);
1470                WAIT_QUIETLY;
1471        }
1472        if ((status & PLX_DMA_DONE_BIT) == 0) {
1473                printk("rtd520: Timeout waiting for dma %i done set\n",
1474                       channel);
1475        }
1476
1477abortDmaExit:
1478        /* spin_unlock_irqrestore( &dev->spinlock, flags ); */
1479}
1480
1481/*
1482  Process what is in the DMA transfer buffer and pass to comedi
1483  Note: this is not re-entrant
1484*/
1485static int ai_process_dma(struct comedi_device *dev, struct comedi_subdevice *s)
1486{
1487        int ii, n;
1488        s16 *dp;
1489
1490        if (devpriv->aiCount == 0)      /* transfer already complete */
1491                return 0;
1492
1493        dp = devpriv->dma0Buff[devpriv->dma0Offset];
1494        for (ii = 0; ii < devpriv->fifoLen / 2;) {      /* convert samples */
1495                short sample;
1496
1497                if (CHAN_ARRAY_TEST(devpriv->chanBipolar, s->async->cur_chan)) {
1498                        sample = (*dp >> 3) + 2048;     /* convert to comedi unsigned data */
1499                else
1500                        sample = *dp >> 3;      /* low 3 bits are marker lines */
1501
1502                *dp++ = sample; /* put processed value back */
1503
1504                if (++s->async->cur_chan >= s->async->cmd.chanlist_len)
1505                        s->async->cur_chan = 0;
1506
1507                ++ii;           /* number ready to transfer */
1508                if (devpriv->aiCount > 0) {     /* < 0, means read forever */
1509                        if (--devpriv->aiCount == 0) {  /* done */
1510                                /*DPRINTK ("rtd520: Final %d samples\n", ii); */
1511                                break;
1512                        }
1513                }
1514        }
1515
1516        /* now pass the whole array to the comedi buffer */
1517        dp = devpriv->dma0Buff[devpriv->dma0Offset];
1518        n = comedi_buf_write_alloc(s->async, ii * sizeof(s16));
1519        if (n < (ii * sizeof(s16))) {   /* any residual is an error */
1520                DPRINTK("rtd520:ai_process_dma buffer overflow %d samples!\n",
1521                        ii - (n / sizeof(s16)));
1522                s->async->events |= COMEDI_CB_ERROR;
1523                return -1;
1524        }
1525        comedi_buf_memcpy_to(s->async, 0, dp, n);
1526        comedi_buf_write_free(s->async, n);
1527
1528        /* always at least 1 scan -- 1/2 FIFO is larger than our max scan list */
1529        s->async->events |= COMEDI_CB_BLOCK | COMEDI_CB_EOS;
1530
1531        if (++devpriv->dma0Offset >= DMA_CHAIN_COUNT) { /* next buffer */
1532                devpriv->dma0Offset = 0;
1533        }
1534        return 0;
1535}
1536#endif /* USE_DMA */
1537
1538/*
1539  Handle all rtd520 interrupts.
1540  Runs atomically and is never re-entered.
1541  This is a "slow handler";  other interrupts may be active.
1542  The data conversion may someday happen in a "bottom half".
1543*/
1544static irqreturn_t rtd_interrupt(int irq,       /* interrupt number (ignored) */
1545                                 void *d)
1546{                               /* our data *//* cpu context (ignored) */
1547        struct comedi_device *dev = d;  /* must be called "dev" for devpriv */
1548        u16 status;
1549        u16 fifoStatus;
1550        struct comedi_subdevice *s = dev->subdevices + 0;       /* analog in subdevice */
1551
1552        if (!dev->attached)
1553                return IRQ_NONE;
1554
1555        devpriv->intCount++;    /* DEBUG statistics */
1556
1557        fifoStatus = RtdFifoStatus(dev);
1558        /* check for FIFO full, this automatically halts the ADC! */
1559        if (!(fifoStatus & FS_ADC_NOT_FULL)) {  /* 0 -> full */
1560                DPRINTK("rtd520: FIFO full! fifo_status=0x%x\n", (fifoStatus ^ 0x6666) & 0x7777);       /* should be all 0s */
1561                goto abortTransfer;
1562        }
1563#ifdef USE_DMA
1564        if (devpriv->flags & DMA0_ACTIVE) {     /* Check DMA */
1565                u32 istatus = RtdPlxInterruptRead(dev);
1566
1567                if (istatus & ICS_DMA0_A) {
1568                        if (ai_process_dma(dev, s) < 0) {
1569                                DPRINTK
1570                                    ("rtd520: comedi read buffer overflow (DMA) with %ld to go!\n",
1571                                     devpriv->aiCount);
1572                                RtdDma0Control(dev,
1573                                               (devpriv->dma0Control &
1574                                                ~PLX_DMA_START_BIT)
1575                                               | PLX_CLEAR_DMA_INTR_BIT);
1576                                goto abortTransfer;
1577                        }
1578
1579                        /*DPRINTK ("rtd520: DMA transfer: %ld to go, istatus %x\n",
1580                           devpriv->aiCount, istatus); */
1581                        RtdDma0Control(dev,
1582                                       (devpriv->
1583                                        dma0Control & ~PLX_DMA_START_BIT)
1584                                       | PLX_CLEAR_DMA_INTR_BIT);
1585                        if (0 == devpriv->aiCount) {    /* counted down */
1586                                DPRINTK("rtd520: Samples Done (DMA).\n");
1587                                goto transferDone;
1588                        }
1589                        comedi_event(dev, s);
1590                } else {
1591                        /*DPRINTK ("rtd520: No DMA ready: istatus %x\n", istatus); */
1592                }
1593        }
1594        /* Fall through and check for other interrupt sources */
1595#endif /* USE_DMA */
1596
1597        status = RtdInterruptStatus(dev);
1598        /* if interrupt was not caused by our board, or handled above */
1599        if (0 == status)
1600                return IRQ_HANDLED;
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        tmp = cmd->scan_begin_src;
1742        cmd->scan_begin_src &= TRIG_TIMER | TRIG_EXT;
1743        if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
1744                err++;
1745
1746
1747        tmp = cmd->convert_src;
1748        cmd->convert_src &= TRIG_TIMER | TRIG_EXT;
1749        if (!cmd->convert_src || tmp != cmd->convert_src)
1750                err++;
1751
1752
1753        tmp = cmd->scan_end_src;
1754        cmd->scan_end_src &= TRIG_COUNT;
1755        if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
1756                err++;
1757
1758
1759        tmp = cmd->stop_src;
1760        cmd->stop_src &= TRIG_COUNT | TRIG_NONE;
1761        if (!cmd->stop_src || tmp != cmd->stop_src)
1762                err++;
1763
1764
1765        if (err)
1766                return 1;
1767
1768        /* step 2: make sure trigger sources are unique
1769           and mutually compatible */
1770        /* note that mutual compatibility is not an issue here */
1771        if (cmd->scan_begin_src != TRIG_TIMER &&
1772            cmd->scan_begin_src != TRIG_EXT) {
1773                err++;
1774        }
1775        if (cmd->convert_src != TRIG_TIMER && cmd->convert_src != TRIG_EXT)
1776                err++;
1777
1778        if (cmd->stop_src != TRIG_COUNT && cmd->stop_src != TRIG_NONE)
1779                err++;
1780
1781        if (err)
1782                return 2;
1783
1784        /* step 3: make sure arguments are trivially compatible */
1785
1786        if (cmd->start_arg != 0) {
1787                cmd->start_arg = 0;
1788                err++;
1789        }
1790
1791        if (cmd->scan_begin_src == TRIG_TIMER) {
1792                /* Note: these are time periods, not actual rates */
1793                if (1 == cmd->chanlist_len) {   /* no scanning */
1794                        if (cmd->scan_begin_arg < RTD_MAX_SPEED_1) {
1795                                cmd->scan_begin_arg = RTD_MAX_SPEED_1;
1796                                rtd_ns_to_timer(&cmd->scan_begin_arg,
1797                                                TRIG_ROUND_UP);
1798                                err++;
1799                        }
1800                        if (cmd->scan_begin_arg > RTD_MIN_SPEED_1) {
1801                                cmd->scan_begin_arg = RTD_MIN_SPEED_1;
1802                                rtd_ns_to_timer(&cmd->scan_begin_arg,
1803                                                TRIG_ROUND_DOWN);
1804                                err++;
1805                        }
1806                } else {
1807                        if (cmd->scan_begin_arg < RTD_MAX_SPEED) {
1808                                cmd->scan_begin_arg = RTD_MAX_SPEED;
1809                                rtd_ns_to_timer(&cmd->scan_begin_arg,
1810                                                TRIG_ROUND_UP);
1811                                err++;
1812                        }
1813                        if (cmd->scan_begin_arg > RTD_MIN_SPEED) {
1814                                cmd->scan_begin_arg = RTD_MIN_SPEED;
1815                                rtd_ns_to_timer(&cmd->scan_begin_arg,
1816                                                TRIG_ROUND_DOWN);
1817                                err++;
1818                        }
1819                }
1820        } else {
1821                /* external trigger */
1822                /* should be level/edge, hi/lo specification here */
1823                /* should specify multiple external triggers */
1824                if (cmd->scan_begin_arg > 9) {
1825                        cmd->scan_begin_arg = 9;
1826                        err++;
1827                }
1828        }
1829        if (cmd->convert_src == TRIG_TIMER) {
1830                if (1 == cmd->chanlist_len) {   /* no scanning */
1831                        if (cmd->convert_arg < RTD_MAX_SPEED_1) {
1832                                cmd->convert_arg = RTD_MAX_SPEED_1;
1833                                rtd_ns_to_timer(&cmd->convert_arg,
1834                                                TRIG_ROUND_UP);
1835                                err++;
1836                        }
1837                        if (cmd->convert_arg > RTD_MIN_SPEED_1) {
1838                                cmd->convert_arg = RTD_MIN_SPEED_1;
1839                                rtd_ns_to_timer(&cmd->convert_arg,
1840                                                TRIG_ROUND_DOWN);
1841                                err++;
1842                        }
1843                } else {
1844                        if (cmd->convert_arg < RTD_MAX_SPEED) {
1845                                cmd->convert_arg = RTD_MAX_SPEED;
1846                                rtd_ns_to_timer(&cmd->convert_arg,
1847                                                TRIG_ROUND_UP);
1848                                err++;
1849                        }
1850                        if (cmd->convert_arg > RTD_MIN_SPEED) {
1851                                cmd->convert_arg = RTD_MIN_SPEED;
1852                                rtd_ns_to_timer(&cmd->convert_arg,
1853                                                TRIG_ROUND_DOWN);
1854                                err++;
1855                        }
1856                }
1857        } else {
1858                /* external trigger */
1859                /* see above */
1860                if (cmd->convert_arg > 9) {
1861                        cmd->convert_arg = 9;
1862                        err++;
1863                }
1864        }
1865
1866#if 0
1867        if (cmd->scan_end_arg != cmd->chanlist_len) {
1868                cmd->scan_end_arg = cmd->chanlist_len;
1869                err++;
1870        }
1871#endif
1872        if (cmd->stop_src == TRIG_COUNT) {
1873                /* TODO check for rounding error due to counter wrap */
1874
1875        } else {
1876                /* TRIG_NONE */
1877                if (cmd->stop_arg != 0) {
1878                        cmd->stop_arg = 0;
1879                        err++;
1880                }
1881        }
1882
1883        if (err)
1884                return 3;
1885
1886
1887        /* step 4: fix up any arguments */
1888
1889        if (cmd->chanlist_len > RTD_MAX_CHANLIST) {
1890                cmd->chanlist_len = RTD_MAX_CHANLIST;
1891                err++;
1892        }
1893        if (cmd->scan_begin_src == TRIG_TIMER) {
1894                tmp = cmd->scan_begin_arg;
1895                rtd_ns_to_timer(&cmd->scan_begin_arg,
1896                                cmd->flags & TRIG_ROUND_MASK);
1897                if (tmp != cmd->scan_begin_arg)
1898                        err++;
1899
1900        }
1901        if (cmd->convert_src == TRIG_TIMER) {
1902                tmp = cmd->convert_arg;
1903                rtd_ns_to_timer(&cmd->convert_arg,
1904                                cmd->flags & TRIG_ROUND_MASK);
1905                if (tmp != cmd->convert_arg)
1906                        err++;
1907
1908                if (cmd->scan_begin_src == TRIG_TIMER
1909                    && (cmd->scan_begin_arg
1910                        < (cmd->convert_arg * cmd->scan_end_arg))) {
1911                        cmd->scan_begin_arg =
1912                            cmd->convert_arg * cmd->scan_end_arg;
1913                        err++;
1914                }
1915        }
1916
1917        if (err)
1918                return 4;
1919
1920        return 0;
1921}
1922
1923/*
1924  Execute a analog in command with many possible triggering options.
1925  The data get stored in the async structure of the subdevice.
1926  This is usually done by an interrupt handler.
1927  Userland gets to the data using read calls.
1928*/
1929static int rtd_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
1930{
1931        struct comedi_cmd *cmd = &s->async->cmd;
1932        int timer;
1933
1934        /* stop anything currently running */
1935        RtdPacerStopSource(dev, 0);     /* stop on SOFTWARE stop */
1936        RtdPacerStop(dev);      /* make sure PACER is stopped */
1937        RtdAdcConversionSource(dev, 0); /* software trigger only */
1938        RtdInterruptMask(dev, 0);
1939#ifdef USE_DMA
1940        if (devpriv->flags & DMA0_ACTIVE) {     /* cancel anything running */
1941                RtdPlxInterruptWrite(dev,       /* disable any more interrupts */
1942                                     RtdPlxInterruptRead(dev) & ~ICS_DMA0_E);
1943                abort_dma(dev, 0);
1944                devpriv->flags &= ~DMA0_ACTIVE;
1945                if (RtdPlxInterruptRead(dev) & ICS_DMA0_A) {    /*clear pending int */
1946                        RtdDma0Control(dev, PLX_CLEAR_DMA_INTR_BIT);
1947                }
1948        }
1949        RtdDma0Reset(dev);      /* reset onboard state */
1950#endif /* USE_DMA */
1951        RtdAdcClearFifo(dev);   /* clear any old data */
1952        RtdInterruptOverrunClear(dev);
1953        devpriv->intCount = 0;
1954
1955        if (!dev->irq) {        /* we need interrupts for this */
1956                DPRINTK("rtd520: ERROR! No interrupt available!\n");
1957                return -ENXIO;
1958        }
1959
1960        /* start configuration */
1961        /* load channel list and reset CGT */
1962        rtd_load_channelgain_list(dev, cmd->chanlist_len, cmd->chanlist);
1963
1964        /* setup the common case and override if needed */
1965        if (cmd->chanlist_len > 1) {
1966                /*DPRINTK ("rtd520: Multi channel setup\n"); */
1967                RtdPacerStartSource(dev, 0);    /* software triggers pacer */
1968                RtdBurstStartSource(dev, 1);    /* PACER triggers burst */
1969                RtdAdcConversionSource(dev, 2); /* BURST triggers ADC */
1970        } else {                /* single channel */
1971                /*DPRINTK ("rtd520: single channel setup\n"); */
1972                RtdPacerStartSource(dev, 0);    /* software triggers pacer */
1973                RtdAdcConversionSource(dev, 1); /* PACER triggers ADC */
1974        }
1975        RtdAboutCounter(dev, devpriv->fifoLen / 2 - 1); /* 1/2 FIFO */
1976
1977        if (TRIG_TIMER == cmd->scan_begin_src) {
1978                /* scan_begin_arg is in nanoseconds */
1979                /* find out how many samples to wait before transferring */
1980                if (cmd->flags & TRIG_WAKE_EOS) {
1981                        /* this may generate un-sustainable interrupt rates */
1982                        /* the application is responsible for doing the right thing */
1983                        devpriv->transCount = cmd->chanlist_len;
1984                        devpriv->flags |= SEND_EOS;
1985                } else {
1986                        /* arrange to transfer data periodically */
1987                        devpriv->transCount
1988                            =
1989                            (TRANS_TARGET_PERIOD * cmd->chanlist_len) /
1990                            cmd->scan_begin_arg;
1991                        if (devpriv->transCount < cmd->chanlist_len) {
1992                                /* tranfer after each scan (and avoid 0) */
1993                                devpriv->transCount = cmd->chanlist_len;
1994                        } else {        /* make a multiple of scan length */
1995                                devpriv->transCount =
1996                                    (devpriv->transCount +
1997                                     cmd->chanlist_len - 1)
1998                                    / cmd->chanlist_len;
1999                                devpriv->transCount *= cmd->chanlist_len;
2000                        }
2001                        devpriv->flags |= SEND_EOS;
2002                }
2003                if (devpriv->transCount >= (devpriv->fifoLen / 2)) {
2004                        /* out of counter range, use 1/2 fifo instead */
2005                        devpriv->transCount = 0;
2006                        devpriv->flags &= ~SEND_EOS;
2007                } else {
2008                        /* interrupt for each tranfer */
2009                        RtdAboutCounter(dev, devpriv->transCount - 1);
2010                }
2011
2012                DPRINTK
2013                    ("rtd520: scanLen=%d tranferCount=%d fifoLen=%d\n  scanTime(ns)=%d flags=0x%x\n",
2014                     cmd->chanlist_len, devpriv->transCount, devpriv->fifoLen,
2015                     cmd->scan_begin_arg, devpriv->flags);
2016        } else {                /* unknown timing, just use 1/2 FIFO */
2017                devpriv->transCount = 0;
2018                devpriv->flags &= ~SEND_EOS;
2019        }
2020        RtdPacerClockSource(dev, 1);    /* use INTERNAL 8Mhz clock source */
2021        RtdAboutStopEnable(dev, 1);     /* just interrupt, dont stop */
2022
2023        /* BUG??? these look like enumerated values, but they are bit fields */
2024
2025        /* First, setup when to stop */
2026        switch (cmd->stop_src) {
2027        case TRIG_COUNT:        /* stop after N scans */
2028                devpriv->aiCount = cmd->stop_arg * cmd->chanlist_len;
2029                if ((devpriv->transCount > 0)
2030                    && (devpriv->transCount > devpriv->aiCount)) {
2031                        devpriv->transCount = devpriv->aiCount;
2032                }
2033                break;
2034
2035        case TRIG_NONE: /* stop when cancel is called */
2036                devpriv->aiCount = -1;  /* read forever */
2037                break;
2038
2039        default:
2040                DPRINTK("rtd520: Warning! ignoring stop_src mode %d\n",
2041                        cmd->stop_src);
2042        }
2043
2044        /* Scan timing */
2045        switch (cmd->scan_begin_src) {
2046        case TRIG_TIMER:        /* periodic scanning */
2047                timer = rtd_ns_to_timer(&cmd->scan_begin_arg,
2048                                        TRIG_ROUND_NEAREST);
2049                /* set PACER clock */
2050                /*DPRINTK ("rtd520: loading %d into pacer\n", timer); */
2051                RtdPacerCounter(dev, timer);
2052
2053                break;
2054
2055        case TRIG_EXT:
2056                RtdPacerStartSource(dev, 1);    /* EXTERNALy trigger pacer */
2057                break;
2058
2059        default:
2060                DPRINTK("rtd520: Warning! ignoring scan_begin_src mode %d\n",
2061                        cmd->scan_begin_src);
2062        }
2063
2064        /* Sample timing within a scan */
2065        switch (cmd->convert_src) {
2066        case TRIG_TIMER:        /* periodic */
2067                if (cmd->chanlist_len > 1) {    /* only needed for multi-channel */
2068                        timer = rtd_ns_to_timer(&cmd->convert_arg,
2069                                                TRIG_ROUND_NEAREST);
2070                        /* setup BURST clock */
2071                        /*DPRINTK ("rtd520: loading %d into burst\n", timer); */
2072                        RtdBurstCounter(dev, timer);
2073                }
2074
2075                break;
2076
2077        case TRIG_EXT:          /* external */
2078                RtdBurstStartSource(dev, 2);    /* EXTERNALy trigger burst */
2079                break;
2080
2081        default:
2082                DPRINTK("rtd520: Warning! ignoring convert_src mode %d\n",
2083                        cmd->convert_src);
2084        }
2085        /* end configuration */
2086
2087        /* This doesn't seem to work.  There is no way to clear an interrupt
2088           that the priority controller has queued! */
2089        RtdInterruptClearMask(dev, ~0); /* clear any existing flags */
2090        RtdInterruptClear(dev);
2091
2092        /* TODO: allow multiple interrupt sources */
2093        if (devpriv->transCount > 0) {  /* transfer every N samples */
2094                RtdInterruptMask(dev, IRQM_ADC_ABOUT_CNT);
2095                DPRINTK("rtd520: Transferring every %d\n", devpriv->transCount);
2096        } else {                /* 1/2 FIFO transfers */
2097#ifdef USE_DMA
2098                devpriv->flags |= DMA0_ACTIVE;
2099
2100                /* point to first transfer in ring */
2101                devpriv->dma0Offset = 0;
2102                RtdDma0Mode(dev, DMA_MODE_BITS);
2103                RtdDma0Next(dev,        /* point to first block */
2104                            devpriv->dma0Chain[DMA_CHAIN_COUNT - 1].next);
2105                RtdDma0Source(dev, DMAS_ADFIFO_HALF_FULL);      /* set DMA trigger source */
2106
2107                RtdPlxInterruptWrite(dev,       /* enable interrupt */
2108                                     RtdPlxInterruptRead(dev) | ICS_DMA0_E);
2109                /* Must be 2 steps.  See PLX app note about "Starting a DMA transfer" */
2110                RtdDma0Control(dev, PLX_DMA_EN_BIT);    /* enable DMA (clear INTR?) */
2111                RtdDma0Control(dev, PLX_DMA_EN_BIT | PLX_DMA_START_BIT);        /*start DMA */
2112                DPRINTK("rtd520: Using DMA0 transfers. plxInt %x RtdInt %x\n",
2113                        RtdPlxInterruptRead(dev), devpriv->intMask);
2114#else /* USE_DMA */
2115                RtdInterruptMask(dev, IRQM_ADC_ABOUT_CNT);
2116                DPRINTK("rtd520: Transferring every 1/2 FIFO\n");
2117#endif /* USE_DMA */
2118        }
2119
2120        /* BUG: start_src is ASSUMED to be TRIG_NOW */
2121        /* BUG? it seems like things are running before the "start" */
2122        RtdPacerStart(dev);     /* Start PACER */
2123        return 0;
2124}
2125
2126/*
2127  Stop a running data acquisition.
2128*/
2129static int rtd_ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
2130{
2131        u16 status;
2132
2133        RtdPacerStopSource(dev, 0);     /* stop on SOFTWARE stop */
2134        RtdPacerStop(dev);      /* Stop PACER */
2135        RtdAdcConversionSource(dev, 0); /* software trigger only */
2136        RtdInterruptMask(dev, 0);
2137        devpriv->aiCount = 0;   /* stop and don't transfer any more */
2138#ifdef USE_DMA
2139        if (devpriv->flags & DMA0_ACTIVE) {
2140                RtdPlxInterruptWrite(dev,       /* disable any more interrupts */
2141                                     RtdPlxInterruptRead(dev) & ~ICS_DMA0_E);
2142                abort_dma(dev, 0);
2143                devpriv->flags &= ~DMA0_ACTIVE;
2144        }
2145#endif /* USE_DMA */
2146        status = RtdInterruptStatus(dev);
2147        DPRINTK
2148            ("rtd520: Acquisition canceled. %ld ints, intStat=%x, overStat=%x\n",
2149             devpriv->intCount, status,
2150             0xffff & RtdInterruptOverrunStatus(dev));
2151        return 0;
2152}
2153
2154/*
2155  Given a desired period and the clock period (both in ns),
2156  return the proper counter value (divider-1).
2157  Sets the original period to be the true value.
2158  Note: you have to check if the value is larger than the counter range!
2159*/
2160static int rtd_ns_to_timer_base(unsigned int *nanosec,  /* desired period (in ns) */
2161                                int round_mode, int base)
2162{                               /* clock period (in ns) */
2163        int divider;
2164
2165        switch (round_mode) {
2166        case TRIG_ROUND_NEAREST:
2167        default:
2168                divider = (*nanosec + base / 2) / base;
2169                break;
2170        case TRIG_ROUND_DOWN:
2171                divider = (*nanosec) / base;
2172                break;
2173        case TRIG_ROUND_UP:
2174                divider = (*nanosec + base - 1) / base;
2175                break;
2176        }
2177        if (divider < 2)
2178                divider = 2;    /* min is divide by 2 */
2179
2180        /* Note: we don't check for max, because different timers
2181           have different ranges */
2182
2183        *nanosec = base * divider;
2184        return divider - 1;     /* countdown is divisor+1 */
2185}
2186
2187/*
2188  Given a desired period (in ns),
2189  return the proper counter value (divider-1) for the internal clock.
2190  Sets the original period to be the true value.
2191*/
2192static int rtd_ns_to_timer(unsigned int *ns, int round_mode)
2193{
2194        return rtd_ns_to_timer_base(ns, round_mode, RTD_CLOCK_BASE);
2195}
2196
2197/*
2198  Output one (or more) analog values to a single port as fast as possible.
2199*/
2200static int rtd_ao_winsn(struct comedi_device *dev,
2201                        struct comedi_subdevice *s, struct comedi_insn *insn,
2202                        unsigned int *data)
2203{
2204        int i;
2205        int chan = CR_CHAN(insn->chanspec);
2206        int range = CR_RANGE(insn->chanspec);
2207
2208        /* Configure the output range (table index matches the range values) */
2209        RtdDacRange(dev, chan, range);
2210
2211        /* Writing a list of values to an AO channel is probably not
2212         * very useful, but that's how the interface is defined. */
2213        for (i = 0; i < insn->n; ++i) {
2214                int val = data[i] << 3;
2215                int stat = 0;   /* initialize to avoid bogus warning */
2216                int ii;
2217
2218                /* VERIFY: comedi range and offset conversions */
2219
2220                if ((range > 1) /* bipolar */
2221                    && (data[i] < 2048)) {
2222                        /* offset and sign extend */
2223                        val = (((int)data[i]) - 2048) << 3;
2224                } else {        /* unipolor */
2225                        val = data[i] << 3;
2226                }
2227
2228                DPRINTK
2229                    ("comedi: rtd520 DAC chan=%d range=%d writing %d as 0x%x\n",
2230                     chan, range, data[i], val);
2231
2232                /* a typical programming sequence */
2233                RtdDacFifoPut(dev, chan, val);  /* put the value in */
2234                RtdDacUpdate(dev, chan);        /* trigger the conversion */
2235
2236                devpriv->aoValue[chan] = data[i];       /* save for read back */
2237
2238                for (ii = 0; ii < RTD_DAC_TIMEOUT; ++ii) {
2239                        stat = RtdFifoStatus(dev);
2240                        /* 1 -> not empty */
2241                        if (stat & ((0 == chan) ? FS_DAC1_NOT_EMPTY :
2242                                    FS_DAC2_NOT_EMPTY))
2243                                break;
2244                        WAIT_QUIETLY;
2245                }
2246                if (ii >= RTD_DAC_TIMEOUT) {
2247                        DPRINTK
2248                            ("rtd520: Error: DAC never finished! FifoStatus=0x%x\n",
2249                             stat ^ 0x6666);
2250                        return -ETIMEDOUT;
2251                }
2252        }
2253
2254        /* return the number of samples read/written */
2255        return i;
2256}
2257
2258/* AO subdevices should have a read insn as well as a write insn.
2259 * Usually this means copying a value stored in devpriv. */
2260static int rtd_ao_rinsn(struct comedi_device *dev,
2261                        struct comedi_subdevice *s, struct comedi_insn *insn,
2262                        unsigned int *data)
2263{
2264        int i;
2265        int chan = CR_CHAN(insn->chanspec);
2266
2267        for (i = 0; i < insn->n; i++)
2268                data[i] = devpriv->aoValue[chan];
2269
2270
2271        return i;
2272}
2273
2274/*
2275   Write a masked set of bits and the read back the port.
2276   We track what the bits should be (i.e. we don't read the port first).
2277
2278   DIO devices are slightly special.  Although it is possible to
2279 * implement the insn_read/insn_write interface, it is much more
2280 * useful to applications if you implement the insn_bits interface.
2281 * This allows packed reading/writing of the DIO channels.  The
2282 * comedi core can convert between insn_bits and insn_read/write
2283 */
2284static int rtd_dio_insn_bits(struct comedi_device *dev,
2285                             struct comedi_subdevice *s,
2286                             struct comedi_insn *insn, unsigned int *data)
2287{
2288        if (insn->n != 2)
2289                return -EINVAL;
2290
2291        /* The insn data is a mask in data[0] and the new data
2292         * in data[1], each channel cooresponding to a bit. */
2293        if (data[0]) {
2294                s->state &= ~data[0];
2295                s->state |= data[0] & data[1];
2296
2297                /* Write out the new digital output lines */
2298                RtdDio0Write(dev, s->state);
2299        }
2300        /* on return, data[1] contains the value of the digital
2301         * input lines. */
2302        data[1] = RtdDio0Read(dev);
2303
2304        /*DPRINTK("rtd520:port_0 wrote: 0x%x read: 0x%x\n", s->state, data[1]); */
2305
2306        return 2;
2307}
2308
2309/*
2310  Configure one bit on a IO port as Input or Output (hence the name :-).
2311*/
2312static int rtd_dio_insn_config(struct comedi_device *dev,
2313                               struct comedi_subdevice *s,
2314                               struct comedi_insn *insn, unsigned int *data)
2315{
2316        int chan = CR_CHAN(insn->chanspec);
2317
2318        /* The input or output configuration of each digital line is
2319         * configured by a special insn_config instruction.  chanspec
2320         * contains the channel to be changed, and data[0] contains the
2321         * value COMEDI_INPUT or COMEDI_OUTPUT. */
2322        switch (data[0]) {
2323        case INSN_CONFIG_DIO_OUTPUT:
2324                s->io_bits |= 1 << chan;        /* 1 means Out */
2325                break;
2326        case INSN_CONFIG_DIO_INPUT:
2327                s->io_bits &= ~(1 << chan);
2328                break;
2329        case INSN_CONFIG_DIO_QUERY:
2330                data[1] =
2331                    (s->io_bits & (1 << chan)) ? COMEDI_OUTPUT : COMEDI_INPUT;
2332                return insn->n;
2333                break;
2334        default:
2335                return -EINVAL;
2336        }
2337
2338        DPRINTK("rtd520: port_0_direction=0x%x (1 means out)\n", s->io_bits);
2339        /* TODO support digital match interrupts and strobes */
2340        RtdDioStatusWrite(dev, 0x01);   /* make Dio0Ctrl point to direction */
2341        RtdDio0CtrlWrite(dev, s->io_bits);      /* set direction 1 means Out */
2342        RtdDioStatusWrite(dev, 0);      /* make Dio0Ctrl clear interrupts */
2343
2344        /* port1 can only be all input or all output */
2345
2346        /* there are also 2 user input lines and 2 user output lines */
2347
2348        return 1;
2349}
2350
2351/*
2352 * A convenient macro that defines init_module() and cleanup_module(),
2353 * as necessary.
2354 */
2355static int __devinit rtd520Driver_pci_probe(struct pci_dev *dev,
2356                                            const struct pci_device_id *ent)
2357{
2358        return comedi_pci_auto_config(dev, rtd520Driver.driver_name);
2359}
2360
2361static void __devexit rtd520Driver_pci_remove(struct pci_dev *dev)
2362{
2363        comedi_pci_auto_unconfig(dev);
2364}
2365
2366static struct pci_driver rtd520Driver_pci_driver = {
2367        .id_table = rtd520_pci_table,
2368        .probe = &rtd520Driver_pci_probe,
2369        .remove = __devexit_p(&rtd520Driver_pci_remove)
2370};
2371
2372static int __init rtd520Driver_init_module(void)
2373{
2374        int retval;
2375
2376        retval = comedi_driver_register(&rtd520Driver);
2377        if (retval < 0)
2378                return retval;
2379
2380        rtd520Driver_pci_driver.name = (char *)rtd520Driver.driver_name;
2381        return pci_register_driver(&rtd520Driver_pci_driver);
2382}
2383
2384static void __exit rtd520Driver_cleanup_module(void)
2385{
2386        pci_unregister_driver(&rtd520Driver_pci_driver);
2387        comedi_driver_unregister(&rtd520Driver);
2388}
2389
2390module_init(rtd520Driver_init_module);
2391module_exit(rtd520Driver_cleanup_module);
2392
2393MODULE_AUTHOR("Comedi http://www.comedi.org");
2394MODULE_DESCRIPTION("Comedi low-level driver");
2395MODULE_LICENSE("GPL");
2396
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.