linux/drivers/comedi/drivers/ni_pcidio.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * Comedi driver for National Instruments PCI-DIO-32HS
   4 *
   5 * COMEDI - Linux Control and Measurement Device Interface
   6 * Copyright (C) 1999,2002 David A. Schleef <ds@schleef.org>
   7 */
   8
   9/*
  10 * Driver: ni_pcidio
  11 * Description: National Instruments PCI-DIO32HS, PCI-6533
  12 * Author: ds
  13 * Status: works
  14 * Devices: [National Instruments] PCI-DIO-32HS (ni_pcidio)
  15 *   [National Instruments] PXI-6533, PCI-6533 (pxi-6533)
  16 *   [National Instruments] PCI-6534 (pci-6534)
  17 * Updated: Mon, 09 Jan 2012 14:27:23 +0000
  18 *
  19 * The DIO32HS board appears as one subdevice, with 32 channels. Each
  20 * channel is individually I/O configurable. The channel order is 0=A0,
  21 * 1=A1, 2=A2, ... 8=B0, 16=C0, 24=D0. The driver only supports simple
  22 * digital I/O; no handshaking is supported.
  23 *
  24 * DMA mostly works for the PCI-DIO32HS, but only in timed input mode.
  25 *
  26 * The PCI-DIO-32HS/PCI-6533 has a configurable external trigger. Setting
  27 * scan_begin_arg to 0 or CR_EDGE triggers on the leading edge. Setting
  28 * scan_begin_arg to CR_INVERT or (CR_EDGE | CR_INVERT) triggers on the
  29 * trailing edge.
  30 *
  31 * This driver could be easily modified to support AT-MIO32HS and AT-MIO96.
  32 *
  33 * The PCI-6534 requires a firmware upload after power-up to work, the
  34 * firmware data and instructions for loading it with comedi_config
  35 * it are contained in the comedi_nonfree_firmware tarball available from
  36 * https://www.comedi.org
  37 */
  38
  39#define USE_DMA
  40
  41#include <linux/module.h>
  42#include <linux/delay.h>
  43#include <linux/interrupt.h>
  44#include <linux/sched.h>
  45
  46#include "../comedi_pci.h"
  47
  48#include "mite.h"
  49
  50/* defines for the PCI-DIO-32HS */
  51
  52#define WINDOW_ADDRESS                  4       /* W */
  53#define INTERRUPT_AND_WINDOW_STATUS     4       /* R */
  54#define INT_STATUS_1                            BIT(0)
  55#define INT_STATUS_2                            BIT(1)
  56#define WINDOW_ADDRESS_STATUS_MASK              0x7c
  57
  58#define MASTER_DMA_AND_INTERRUPT_CONTROL 5      /* W */
  59#define INTERRUPT_LINE(x)                       ((x) & 3)
  60#define OPEN_INT                                BIT(2)
  61#define GROUP_STATUS                    5       /* R */
  62#define DATA_LEFT                               BIT(0)
  63#define REQ                                     BIT(2)
  64#define STOP_TRIG                               BIT(3)
  65
  66#define GROUP_1_FLAGS                   6       /* R */
  67#define GROUP_2_FLAGS                   7       /* R */
  68#define TRANSFER_READY                          BIT(0)
  69#define COUNT_EXPIRED                           BIT(1)
  70#define WAITED                                  BIT(5)
  71#define PRIMARY_TC                              BIT(6)
  72#define SECONDARY_TC                            BIT(7)
  73  /* #define SerialRose */
  74  /* #define ReqRose */
  75  /* #define Paused */
  76
  77#define GROUP_1_FIRST_CLEAR             6       /* W */
  78#define GROUP_2_FIRST_CLEAR             7       /* W */
  79#define CLEAR_WAITED                            BIT(3)
  80#define CLEAR_PRIMARY_TC                        BIT(4)
  81#define CLEAR_SECONDARY_TC                      BIT(5)
  82#define DMA_RESET                               BIT(6)
  83#define FIFO_RESET                              BIT(7)
  84#define CLEAR_ALL                               0xf8
  85
  86#define GROUP_1_FIFO                    8       /* W */
  87#define GROUP_2_FIFO                    12      /* W */
  88
  89#define TRANSFER_COUNT                  20
  90#define CHIP_ID_D                       24
  91#define CHIP_ID_I                       25
  92#define CHIP_ID_O                       26
  93#define CHIP_VERSION                    27
  94#define PORT_IO(x)                      (28 + (x))
  95#define PORT_PIN_DIRECTIONS(x)          (32 + (x))
  96#define PORT_PIN_MASK(x)                (36 + (x))
  97#define PORT_PIN_POLARITIES(x)          (40 + (x))
  98
  99#define MASTER_CLOCK_ROUTING            45
 100#define RTSI_CLOCKING(x)                        (((x) & 3) << 4)
 101
 102#define GROUP_1_SECOND_CLEAR            46      /* W */
 103#define GROUP_2_SECOND_CLEAR            47      /* W */
 104#define CLEAR_EXPIRED                           BIT(0)
 105
 106#define PORT_PATTERN(x)                 (48 + (x))
 107
 108#define DATA_PATH                       64
 109#define FIFO_ENABLE_A           BIT(0)
 110#define FIFO_ENABLE_B           BIT(1)
 111#define FIFO_ENABLE_C           BIT(2)
 112#define FIFO_ENABLE_D           BIT(3)
 113#define FUNNELING(x)            (((x) & 3) << 4)
 114#define GROUP_DIRECTION         BIT(7)
 115
 116#define PROTOCOL_REGISTER_1             65
 117#define OP_MODE                 PROTOCOL_REGISTER_1
 118#define RUN_MODE(x)             ((x) & 7)
 119#define NUMBERED                BIT(3)
 120
 121#define PROTOCOL_REGISTER_2             66
 122#define CLOCK_REG                       PROTOCOL_REGISTER_2
 123#define CLOCK_LINE(x)           (((x) & 3) << 5)
 124#define INVERT_STOP_TRIG                BIT(7)
 125#define DATA_LATCHING(x)       (((x) & 3) << 5)
 126
 127#define PROTOCOL_REGISTER_3             67
 128#define SEQUENCE                        PROTOCOL_REGISTER_3
 129
 130#define PROTOCOL_REGISTER_14            68      /* 16 bit */
 131#define CLOCK_SPEED                     PROTOCOL_REGISTER_14
 132
 133#define PROTOCOL_REGISTER_4             70
 134#define REQ_REG                 PROTOCOL_REGISTER_4
 135#define REQ_CONDITIONING(x)     (((x) & 7) << 3)
 136
 137#define PROTOCOL_REGISTER_5             71
 138#define BLOCK_MODE                      PROTOCOL_REGISTER_5
 139
 140#define FIFO_Control                    72
 141#define READY_LEVEL(x)          ((x) & 7)
 142
 143#define PROTOCOL_REGISTER_6             73
 144#define LINE_POLARITIES         PROTOCOL_REGISTER_6
 145#define INVERT_ACK              BIT(0)
 146#define INVERT_REQ              BIT(1)
 147#define INVERT_CLOCK            BIT(2)
 148#define INVERT_SERIAL           BIT(3)
 149#define OPEN_ACK                BIT(4)
 150#define OPEN_CLOCK              BIT(5)
 151
 152#define PROTOCOL_REGISTER_7             74
 153#define ACK_SER                 PROTOCOL_REGISTER_7
 154#define ACK_LINE(x)             (((x) & 3) << 2)
 155#define EXCHANGE_PINS           BIT(7)
 156
 157#define INTERRUPT_CONTROL               75
 158/* bits same as flags */
 159
 160#define DMA_LINE_CONTROL_GROUP1         76
 161#define DMA_LINE_CONTROL_GROUP2         108
 162
 163/* channel zero is none */
 164static inline unsigned int primary_DMAChannel_bits(unsigned int channel)
 165{
 166        return channel & 0x3;
 167}
 168
 169static inline unsigned int secondary_DMAChannel_bits(unsigned int channel)
 170{
 171        return (channel << 2) & 0xc;
 172}
 173
 174#define TRANSFER_SIZE_CONTROL           77
 175#define TRANSFER_WIDTH(x)       ((x) & 3)
 176#define TRANSFER_LENGTH(x)      (((x) & 3) << 3)
 177#define REQUIRE_R_LEVEL        BIT(5)
 178
 179#define PROTOCOL_REGISTER_15            79
 180#define DAQ_OPTIONS                     PROTOCOL_REGISTER_15
 181#define START_SOURCE(x)                 ((x) & 0x3)
 182#define INVERT_START                            BIT(2)
 183#define STOP_SOURCE(x)                          (((x) & 0x3) << 3)
 184#define REQ_START                               BIT(6)
 185#define PRE_START                               BIT(7)
 186
 187#define PATTERN_DETECTION               81
 188#define DETECTION_METHOD                        BIT(0)
 189#define INVERT_MATCH                            BIT(1)
 190#define IE_PATTERN_DETECTION                    BIT(2)
 191
 192#define PROTOCOL_REGISTER_9             82
 193#define REQ_DELAY                       PROTOCOL_REGISTER_9
 194
 195#define PROTOCOL_REGISTER_10            83
 196#define REQ_NOT_DELAY                   PROTOCOL_REGISTER_10
 197
 198#define PROTOCOL_REGISTER_11            84
 199#define ACK_DELAY                       PROTOCOL_REGISTER_11
 200
 201#define PROTOCOL_REGISTER_12            85
 202#define ACK_NOT_DELAY                   PROTOCOL_REGISTER_12
 203
 204#define PROTOCOL_REGISTER_13            86
 205#define DATA_1_DELAY                    PROTOCOL_REGISTER_13
 206
 207#define PROTOCOL_REGISTER_8             88      /* 32 bit */
 208#define START_DELAY                     PROTOCOL_REGISTER_8
 209
 210/* Firmware files for PCI-6524 */
 211#define FW_PCI_6534_MAIN                "ni6534a.bin"
 212#define FW_PCI_6534_SCARAB_DI           "niscrb01.bin"
 213#define FW_PCI_6534_SCARAB_DO           "niscrb02.bin"
 214MODULE_FIRMWARE(FW_PCI_6534_MAIN);
 215MODULE_FIRMWARE(FW_PCI_6534_SCARAB_DI);
 216MODULE_FIRMWARE(FW_PCI_6534_SCARAB_DO);
 217
 218enum pci_6534_firmware_registers {      /* 16 bit */
 219        Firmware_Control_Register = 0x100,
 220        Firmware_Status_Register = 0x104,
 221        Firmware_Data_Register = 0x108,
 222        Firmware_Mask_Register = 0x10c,
 223        Firmware_Debug_Register = 0x110,
 224};
 225
 226/* main fpga registers (32 bit)*/
 227enum pci_6534_fpga_registers {
 228        FPGA_Control1_Register = 0x200,
 229        FPGA_Control2_Register = 0x204,
 230        FPGA_Irq_Mask_Register = 0x208,
 231        FPGA_Status_Register = 0x20c,
 232        FPGA_Signature_Register = 0x210,
 233        FPGA_SCALS_Counter_Register = 0x280,    /*write-clear */
 234        FPGA_SCAMS_Counter_Register = 0x284,    /*write-clear */
 235        FPGA_SCBLS_Counter_Register = 0x288,    /*write-clear */
 236        FPGA_SCBMS_Counter_Register = 0x28c,    /*write-clear */
 237        FPGA_Temp_Control_Register = 0x2a0,
 238        FPGA_DAR_Register = 0x2a8,
 239        FPGA_ELC_Read_Register = 0x2b8,
 240        FPGA_ELC_Write_Register = 0x2bc,
 241};
 242
 243enum FPGA_Control_Bits {
 244        FPGA_Enable_Bit = 0x8000,
 245};
 246
 247#define TIMER_BASE 50           /* nanoseconds */
 248
 249#ifdef USE_DMA
 250#define INT_EN (COUNT_EXPIRED | WAITED | PRIMARY_TC | SECONDARY_TC)
 251#else
 252#define INT_EN (TRANSFER_READY | COUNT_EXPIRED | WAITED \
 253                | PRIMARY_TC | SECONDARY_TC)
 254#endif
 255
 256enum nidio_boardid {
 257        BOARD_PCIDIO_32HS,
 258        BOARD_PXI6533,
 259        BOARD_PCI6534,
 260};
 261
 262struct nidio_board {
 263        const char *name;
 264        unsigned int uses_firmware:1;
 265        unsigned int dio_speed;
 266};
 267
 268static const struct nidio_board nidio_boards[] = {
 269        [BOARD_PCIDIO_32HS] = {
 270                .name           = "pci-dio-32hs",
 271                .dio_speed      = 50,
 272        },
 273        [BOARD_PXI6533] = {
 274                .name           = "pxi-6533",
 275                .dio_speed      = 50,
 276        },
 277        [BOARD_PCI6534] = {
 278                .name           = "pci-6534",
 279                .uses_firmware  = 1,
 280                .dio_speed      = 50,
 281        },
 282};
 283
 284struct nidio96_private {
 285        struct mite *mite;
 286        int boardtype;
 287        int dio;
 288        unsigned short OP_MODEBits;
 289        struct mite_channel *di_mite_chan;
 290        struct mite_ring *di_mite_ring;
 291        spinlock_t mite_channel_lock;
 292};
 293
 294static int ni_pcidio_request_di_mite_channel(struct comedi_device *dev)
 295{
 296        struct nidio96_private *devpriv = dev->private;
 297        unsigned long flags;
 298
 299        spin_lock_irqsave(&devpriv->mite_channel_lock, flags);
 300        BUG_ON(devpriv->di_mite_chan);
 301        devpriv->di_mite_chan =
 302            mite_request_channel_in_range(devpriv->mite,
 303                                          devpriv->di_mite_ring, 1, 2);
 304        if (!devpriv->di_mite_chan) {
 305                spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags);
 306                dev_err(dev->class_dev, "failed to reserve mite dma channel\n");
 307                return -EBUSY;
 308        }
 309        devpriv->di_mite_chan->dir = COMEDI_INPUT;
 310        writeb(primary_DMAChannel_bits(devpriv->di_mite_chan->channel) |
 311               secondary_DMAChannel_bits(devpriv->di_mite_chan->channel),
 312               dev->mmio + DMA_LINE_CONTROL_GROUP1);
 313        spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags);
 314        return 0;
 315}
 316
 317static void ni_pcidio_release_di_mite_channel(struct comedi_device *dev)
 318{
 319        struct nidio96_private *devpriv = dev->private;
 320        unsigned long flags;
 321
 322        spin_lock_irqsave(&devpriv->mite_channel_lock, flags);
 323        if (devpriv->di_mite_chan) {
 324                mite_release_channel(devpriv->di_mite_chan);
 325                devpriv->di_mite_chan = NULL;
 326                writeb(primary_DMAChannel_bits(0) |
 327                       secondary_DMAChannel_bits(0),
 328                       dev->mmio + DMA_LINE_CONTROL_GROUP1);
 329        }
 330        spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags);
 331}
 332
 333static int setup_mite_dma(struct comedi_device *dev, struct comedi_subdevice *s)
 334{
 335        struct nidio96_private *devpriv = dev->private;
 336        int retval;
 337        unsigned long flags;
 338
 339        retval = ni_pcidio_request_di_mite_channel(dev);
 340        if (retval)
 341                return retval;
 342
 343        /* write alloc the entire buffer */
 344        comedi_buf_write_alloc(s, s->async->prealloc_bufsz);
 345
 346        spin_lock_irqsave(&devpriv->mite_channel_lock, flags);
 347        if (devpriv->di_mite_chan) {
 348                mite_prep_dma(devpriv->di_mite_chan, 32, 32);
 349                mite_dma_arm(devpriv->di_mite_chan);
 350        } else {
 351                retval = -EIO;
 352        }
 353        spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags);
 354
 355        return retval;
 356}
 357
 358static int ni_pcidio_poll(struct comedi_device *dev, struct comedi_subdevice *s)
 359{
 360        struct nidio96_private *devpriv = dev->private;
 361        unsigned long irq_flags;
 362        int count;
 363
 364        spin_lock_irqsave(&dev->spinlock, irq_flags);
 365        spin_lock(&devpriv->mite_channel_lock);
 366        if (devpriv->di_mite_chan)
 367                mite_sync_dma(devpriv->di_mite_chan, s);
 368        spin_unlock(&devpriv->mite_channel_lock);
 369        count = comedi_buf_n_bytes_ready(s);
 370        spin_unlock_irqrestore(&dev->spinlock, irq_flags);
 371        return count;
 372}
 373
 374static irqreturn_t nidio_interrupt(int irq, void *d)
 375{
 376        struct comedi_device *dev = d;
 377        struct nidio96_private *devpriv = dev->private;
 378        struct comedi_subdevice *s = dev->read_subdev;
 379        struct comedi_async *async = s->async;
 380        unsigned int auxdata;
 381        int flags;
 382        int status;
 383        int work = 0;
 384
 385        /* interrupcions parasites */
 386        if (!dev->attached) {
 387                /* assume it's from another card */
 388                return IRQ_NONE;
 389        }
 390
 391        /* Lock to avoid race with comedi_poll */
 392        spin_lock(&dev->spinlock);
 393
 394        status = readb(dev->mmio + INTERRUPT_AND_WINDOW_STATUS);
 395        flags = readb(dev->mmio + GROUP_1_FLAGS);
 396
 397        spin_lock(&devpriv->mite_channel_lock);
 398        if (devpriv->di_mite_chan) {
 399                mite_ack_linkc(devpriv->di_mite_chan, s, false);
 400                /* XXX need to byteswap sync'ed dma */
 401        }
 402        spin_unlock(&devpriv->mite_channel_lock);
 403
 404        while (status & DATA_LEFT) {
 405                work++;
 406                if (work > 20) {
 407                        dev_dbg(dev->class_dev, "too much work in interrupt\n");
 408                        writeb(0x00,
 409                               dev->mmio + MASTER_DMA_AND_INTERRUPT_CONTROL);
 410                        break;
 411                }
 412
 413                flags &= INT_EN;
 414
 415                if (flags & TRANSFER_READY) {
 416                        while (flags & TRANSFER_READY) {
 417                                work++;
 418                                if (work > 100) {
 419                                        dev_dbg(dev->class_dev,
 420                                                "too much work in interrupt\n");
 421                                        writeb(0x00, dev->mmio +
 422                                               MASTER_DMA_AND_INTERRUPT_CONTROL
 423                                              );
 424                                        goto out;
 425                                }
 426                                auxdata = readl(dev->mmio + GROUP_1_FIFO);
 427                                comedi_buf_write_samples(s, &auxdata, 1);
 428                                flags = readb(dev->mmio + GROUP_1_FLAGS);
 429                        }
 430                }
 431
 432                if (flags & COUNT_EXPIRED) {
 433                        writeb(CLEAR_EXPIRED, dev->mmio + GROUP_1_SECOND_CLEAR);
 434                        async->events |= COMEDI_CB_EOA;
 435
 436                        writeb(0x00, dev->mmio + OP_MODE);
 437                        break;
 438                } else if (flags & WAITED) {
 439                        writeb(CLEAR_WAITED, dev->mmio + GROUP_1_FIRST_CLEAR);
 440                        async->events |= COMEDI_CB_ERROR;
 441                        break;
 442                } else if (flags & PRIMARY_TC) {
 443                        writeb(CLEAR_PRIMARY_TC,
 444                               dev->mmio + GROUP_1_FIRST_CLEAR);
 445                        async->events |= COMEDI_CB_EOA;
 446                } else if (flags & SECONDARY_TC) {
 447                        writeb(CLEAR_SECONDARY_TC,
 448                               dev->mmio + GROUP_1_FIRST_CLEAR);
 449                        async->events |= COMEDI_CB_EOA;
 450                }
 451
 452                flags = readb(dev->mmio + GROUP_1_FLAGS);
 453                status = readb(dev->mmio + INTERRUPT_AND_WINDOW_STATUS);
 454        }
 455
 456out:
 457        comedi_handle_events(dev, s);
 458#if 0
 459        if (!tag)
 460                writeb(0x03, dev->mmio + MASTER_DMA_AND_INTERRUPT_CONTROL);
 461#endif
 462
 463        spin_unlock(&dev->spinlock);
 464        return IRQ_HANDLED;
 465}
 466
 467static int ni_pcidio_insn_config(struct comedi_device *dev,
 468                                 struct comedi_subdevice *s,
 469                                 struct comedi_insn *insn,
 470                                 unsigned int *data)
 471{
 472        int ret;
 473
 474        if (data[0] == INSN_CONFIG_GET_CMD_TIMING_CONSTRAINTS) {
 475                const struct nidio_board *board = dev->board_ptr;
 476
 477                /* we don't care about actual channels */
 478                data[1] = board->dio_speed;
 479                data[2] = 0;
 480                return 0;
 481        }
 482
 483        ret = comedi_dio_insn_config(dev, s, insn, data, 0);
 484        if (ret)
 485                return ret;
 486
 487        writel(s->io_bits, dev->mmio + PORT_PIN_DIRECTIONS(0));
 488
 489        return insn->n;
 490}
 491
 492static int ni_pcidio_insn_bits(struct comedi_device *dev,
 493                               struct comedi_subdevice *s,
 494                               struct comedi_insn *insn,
 495                               unsigned int *data)
 496{
 497        if (comedi_dio_update_state(s, data))
 498                writel(s->state, dev->mmio + PORT_IO(0));
 499
 500        data[1] = readl(dev->mmio + PORT_IO(0));
 501
 502        return insn->n;
 503}
 504
 505static int ni_pcidio_ns_to_timer(int *nanosec, unsigned int flags)
 506{
 507        int divider, base;
 508
 509        base = TIMER_BASE;
 510
 511        switch (flags & CMDF_ROUND_MASK) {
 512        case CMDF_ROUND_NEAREST:
 513        default:
 514                divider = DIV_ROUND_CLOSEST(*nanosec, base);
 515                break;
 516        case CMDF_ROUND_DOWN:
 517                divider = (*nanosec) / base;
 518                break;
 519        case CMDF_ROUND_UP:
 520                divider = DIV_ROUND_UP(*nanosec, base);
 521                break;
 522        }
 523
 524        *nanosec = base * divider;
 525        return divider;
 526}
 527
 528static int ni_pcidio_cmdtest(struct comedi_device *dev,
 529                             struct comedi_subdevice *s, struct comedi_cmd *cmd)
 530{
 531        int err = 0;
 532        unsigned int arg;
 533
 534        /* Step 1 : check if triggers are trivially valid */
 535
 536        err |= comedi_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_INT);
 537        err |= comedi_check_trigger_src(&cmd->scan_begin_src,
 538                                        TRIG_TIMER | TRIG_EXT);
 539        err |= comedi_check_trigger_src(&cmd->convert_src, TRIG_NOW);
 540        err |= comedi_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
 541        err |= comedi_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE);
 542
 543        if (err)
 544                return 1;
 545
 546        /* Step 2a : make sure trigger sources are unique */
 547
 548        err |= comedi_check_trigger_is_unique(cmd->start_src);
 549        err |= comedi_check_trigger_is_unique(cmd->scan_begin_src);
 550        err |= comedi_check_trigger_is_unique(cmd->stop_src);
 551
 552        /* Step 2b : and mutually compatible */
 553
 554        if (err)
 555                return 2;
 556
 557        /* Step 3: check if arguments are trivially valid */
 558
 559        err |= comedi_check_trigger_arg_is(&cmd->start_arg, 0);
 560
 561#define MAX_SPEED       (TIMER_BASE)    /* in nanoseconds */
 562
 563        if (cmd->scan_begin_src == TRIG_TIMER) {
 564                err |= comedi_check_trigger_arg_min(&cmd->scan_begin_arg,
 565                                                    MAX_SPEED);
 566                /* no minimum speed */
 567        } else {
 568                /* TRIG_EXT */
 569                /* should be level/edge, hi/lo specification here */
 570                if ((cmd->scan_begin_arg & ~(CR_EDGE | CR_INVERT)) != 0) {
 571                        cmd->scan_begin_arg &= (CR_EDGE | CR_INVERT);
 572                        err |= -EINVAL;
 573                }
 574        }
 575
 576        err |= comedi_check_trigger_arg_is(&cmd->convert_arg, 0);
 577        err |= comedi_check_trigger_arg_is(&cmd->scan_end_arg,
 578                                           cmd->chanlist_len);
 579
 580        if (cmd->stop_src == TRIG_COUNT)
 581                err |= comedi_check_trigger_arg_min(&cmd->stop_arg, 1);
 582        else    /* TRIG_NONE */
 583                err |= comedi_check_trigger_arg_is(&cmd->stop_arg, 0);
 584
 585        if (err)
 586                return 3;
 587
 588        /* step 4: fix up any arguments */
 589
 590        if (cmd->scan_begin_src == TRIG_TIMER) {
 591                arg = cmd->scan_begin_arg;
 592                ni_pcidio_ns_to_timer(&arg, cmd->flags);
 593                err |= comedi_check_trigger_arg_is(&cmd->scan_begin_arg, arg);
 594        }
 595
 596        if (err)
 597                return 4;
 598
 599        return 0;
 600}
 601
 602static int ni_pcidio_inttrig(struct comedi_device *dev,
 603                             struct comedi_subdevice *s,
 604                             unsigned int trig_num)
 605{
 606        struct nidio96_private *devpriv = dev->private;
 607        struct comedi_cmd *cmd = &s->async->cmd;
 608
 609        if (trig_num != cmd->start_arg)
 610                return -EINVAL;
 611
 612        writeb(devpriv->OP_MODEBits, dev->mmio + OP_MODE);
 613        s->async->inttrig = NULL;
 614
 615        return 1;
 616}
 617
 618static int ni_pcidio_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 619{
 620        struct nidio96_private *devpriv = dev->private;
 621        struct comedi_cmd *cmd = &s->async->cmd;
 622
 623        /* XXX configure ports for input */
 624        writel(0x0000, dev->mmio + PORT_PIN_DIRECTIONS(0));
 625
 626        if (1) {
 627                /* enable fifos A B C D */
 628                writeb(0x0f, dev->mmio + DATA_PATH);
 629
 630                /* set transfer width a 32 bits */
 631                writeb(TRANSFER_WIDTH(0) | TRANSFER_LENGTH(0),
 632                       dev->mmio + TRANSFER_SIZE_CONTROL);
 633        } else {
 634                writeb(0x03, dev->mmio + DATA_PATH);
 635                writeb(TRANSFER_WIDTH(3) | TRANSFER_LENGTH(0),
 636                       dev->mmio + TRANSFER_SIZE_CONTROL);
 637        }
 638
 639        /* protocol configuration */
 640        if (cmd->scan_begin_src == TRIG_TIMER) {
 641                /* page 4-5, "input with internal REQs" */
 642                writeb(0, dev->mmio + OP_MODE);
 643                writeb(0x00, dev->mmio + CLOCK_REG);
 644                writeb(1, dev->mmio + SEQUENCE);
 645                writeb(0x04, dev->mmio + REQ_REG);
 646                writeb(4, dev->mmio + BLOCK_MODE);
 647                writeb(3, dev->mmio + LINE_POLARITIES);
 648                writeb(0xc0, dev->mmio + ACK_SER);
 649                writel(ni_pcidio_ns_to_timer(&cmd->scan_begin_arg,
 650                                             CMDF_ROUND_NEAREST),
 651                       dev->mmio + START_DELAY);
 652                writeb(1, dev->mmio + REQ_DELAY);
 653                writeb(1, dev->mmio + REQ_NOT_DELAY);
 654                writeb(1, dev->mmio + ACK_DELAY);
 655                writeb(0x0b, dev->mmio + ACK_NOT_DELAY);
 656                writeb(0x01, dev->mmio + DATA_1_DELAY);
 657                /*
 658                 * manual, page 4-5:
 659                 * CLOCK_SPEED comment is incorrectly listed on DAQ_OPTIONS
 660                 */
 661                writew(0, dev->mmio + CLOCK_SPEED);
 662                writeb(0, dev->mmio + DAQ_OPTIONS);
 663        } else {
 664                /* TRIG_EXT */
 665                /* page 4-5, "input with external REQs" */
 666                writeb(0, dev->mmio + OP_MODE);
 667                writeb(0x00, dev->mmio + CLOCK_REG);
 668                writeb(0, dev->mmio + SEQUENCE);
 669                writeb(0x00, dev->mmio + REQ_REG);
 670                writeb(4, dev->mmio + BLOCK_MODE);
 671                if (!(cmd->scan_begin_arg & CR_INVERT)) /* Leading Edge */
 672                        writeb(0, dev->mmio + LINE_POLARITIES);
 673                else                                    /* Trailing Edge */
 674                        writeb(2, dev->mmio + LINE_POLARITIES);
 675                writeb(0x00, dev->mmio + ACK_SER);
 676                writel(1, dev->mmio + START_DELAY);
 677                writeb(1, dev->mmio + REQ_DELAY);
 678                writeb(1, dev->mmio + REQ_NOT_DELAY);
 679                writeb(1, dev->mmio + ACK_DELAY);
 680                writeb(0x0C, dev->mmio + ACK_NOT_DELAY);
 681                writeb(0x10, dev->mmio + DATA_1_DELAY);
 682                writew(0, dev->mmio + CLOCK_SPEED);
 683                writeb(0x60, dev->mmio + DAQ_OPTIONS);
 684        }
 685
 686        if (cmd->stop_src == TRIG_COUNT) {
 687                writel(cmd->stop_arg,
 688                       dev->mmio + TRANSFER_COUNT);
 689        } else {
 690                /* XXX */
 691        }
 692
 693#ifdef USE_DMA
 694        writeb(CLEAR_PRIMARY_TC | CLEAR_SECONDARY_TC,
 695               dev->mmio + GROUP_1_FIRST_CLEAR);
 696
 697        {
 698                int retval = setup_mite_dma(dev, s);
 699
 700                if (retval)
 701                        return retval;
 702        }
 703#else
 704        writeb(0x00, dev->mmio + DMA_LINE_CONTROL_GROUP1);
 705#endif
 706        writeb(0x00, dev->mmio + DMA_LINE_CONTROL_GROUP2);
 707
 708        /* clear and enable interrupts */
 709        writeb(0xff, dev->mmio + GROUP_1_FIRST_CLEAR);
 710        /* writeb(CLEAR_EXPIRED, dev->mmio+GROUP_1_SECOND_CLEAR); */
 711
 712        writeb(INT_EN, dev->mmio + INTERRUPT_CONTROL);
 713        writeb(0x03, dev->mmio + MASTER_DMA_AND_INTERRUPT_CONTROL);
 714
 715        if (cmd->stop_src == TRIG_NONE) {
 716                devpriv->OP_MODEBits = DATA_LATCHING(0) | RUN_MODE(7);
 717        } else {                /* TRIG_TIMER */
 718                devpriv->OP_MODEBits = NUMBERED | RUN_MODE(7);
 719        }
 720        if (cmd->start_src == TRIG_NOW) {
 721                /* start */
 722                writeb(devpriv->OP_MODEBits, dev->mmio + OP_MODE);
 723                s->async->inttrig = NULL;
 724        } else {
 725                /* TRIG_INT */
 726                s->async->inttrig = ni_pcidio_inttrig;
 727        }
 728
 729        return 0;
 730}
 731
 732static int ni_pcidio_cancel(struct comedi_device *dev,
 733                            struct comedi_subdevice *s)
 734{
 735        writeb(0x00, dev->mmio + MASTER_DMA_AND_INTERRUPT_CONTROL);
 736        ni_pcidio_release_di_mite_channel(dev);
 737
 738        return 0;
 739}
 740
 741static int ni_pcidio_change(struct comedi_device *dev,
 742                            struct comedi_subdevice *s)
 743{
 744        struct nidio96_private *devpriv = dev->private;
 745        int ret;
 746
 747        ret = mite_buf_change(devpriv->di_mite_ring, s);
 748        if (ret < 0)
 749                return ret;
 750
 751        memset(s->async->prealloc_buf, 0xaa, s->async->prealloc_bufsz);
 752
 753        return 0;
 754}
 755
 756static int pci_6534_load_fpga(struct comedi_device *dev,
 757                              const u8 *data, size_t data_len,
 758                              unsigned long context)
 759{
 760        static const int timeout = 1000;
 761        int fpga_index = context;
 762        int i;
 763        size_t j;
 764
 765        writew(0x80 | fpga_index, dev->mmio + Firmware_Control_Register);
 766        writew(0xc0 | fpga_index, dev->mmio + Firmware_Control_Register);
 767        for (i = 0;
 768             (readw(dev->mmio + Firmware_Status_Register) & 0x2) == 0 &&
 769             i < timeout; ++i) {
 770                udelay(1);
 771        }
 772        if (i == timeout) {
 773                dev_warn(dev->class_dev,
 774                         "ni_pcidio: failed to load fpga %i, waiting for status 0x2\n",
 775                         fpga_index);
 776                return -EIO;
 777        }
 778        writew(0x80 | fpga_index, dev->mmio + Firmware_Control_Register);
 779        for (i = 0;
 780             readw(dev->mmio + Firmware_Status_Register) != 0x3 &&
 781             i < timeout; ++i) {
 782                udelay(1);
 783        }
 784        if (i == timeout) {
 785                dev_warn(dev->class_dev,
 786                         "ni_pcidio: failed to load fpga %i, waiting for status 0x3\n",
 787                         fpga_index);
 788                return -EIO;
 789        }
 790        for (j = 0; j + 1 < data_len;) {
 791                unsigned int value = data[j++];
 792
 793                value |= data[j++] << 8;
 794                writew(value, dev->mmio + Firmware_Data_Register);
 795                for (i = 0;
 796                     (readw(dev->mmio + Firmware_Status_Register) & 0x2) == 0
 797                     && i < timeout; ++i) {
 798                        udelay(1);
 799                }
 800                if (i == timeout) {
 801                        dev_warn(dev->class_dev,
 802                                 "ni_pcidio: failed to load word into fpga %i\n",
 803                                 fpga_index);
 804                        return -EIO;
 805                }
 806                if (need_resched())
 807                        schedule();
 808        }
 809        writew(0x0, dev->mmio + Firmware_Control_Register);
 810        return 0;
 811}
 812
 813static int pci_6534_reset_fpga(struct comedi_device *dev, int fpga_index)
 814{
 815        return pci_6534_load_fpga(dev, NULL, 0, fpga_index);
 816}
 817
 818static int pci_6534_reset_fpgas(struct comedi_device *dev)
 819{
 820        int ret;
 821        int i;
 822
 823        writew(0x0, dev->mmio + Firmware_Control_Register);
 824        for (i = 0; i < 3; ++i) {
 825                ret = pci_6534_reset_fpga(dev, i);
 826                if (ret < 0)
 827                        break;
 828        }
 829        writew(0x0, dev->mmio + Firmware_Mask_Register);
 830        return ret;
 831}
 832
 833static void pci_6534_init_main_fpga(struct comedi_device *dev)
 834{
 835        writel(0, dev->mmio + FPGA_Control1_Register);
 836        writel(0, dev->mmio + FPGA_Control2_Register);
 837        writel(0, dev->mmio + FPGA_SCALS_Counter_Register);
 838        writel(0, dev->mmio + FPGA_SCAMS_Counter_Register);
 839        writel(0, dev->mmio + FPGA_SCBLS_Counter_Register);
 840        writel(0, dev->mmio + FPGA_SCBMS_Counter_Register);
 841}
 842
 843static int pci_6534_upload_firmware(struct comedi_device *dev)
 844{
 845        struct nidio96_private *devpriv = dev->private;
 846        static const char *const fw_file[3] = {
 847                FW_PCI_6534_SCARAB_DI,  /* loaded into scarab A for DI */
 848                FW_PCI_6534_SCARAB_DO,  /* loaded into scarab B for DO */
 849                FW_PCI_6534_MAIN,       /* loaded into main FPGA */
 850        };
 851        int ret;
 852        int n;
 853
 854        ret = pci_6534_reset_fpgas(dev);
 855        if (ret < 0)
 856                return ret;
 857        /* load main FPGA first, then the two scarabs */
 858        for (n = 2; n >= 0; n--) {
 859                ret = comedi_load_firmware(dev, &devpriv->mite->pcidev->dev,
 860                                           fw_file[n],
 861                                           pci_6534_load_fpga, n);
 862                if (ret == 0 && n == 2)
 863                        pci_6534_init_main_fpga(dev);
 864                if (ret < 0)
 865                        break;
 866        }
 867        return ret;
 868}
 869
 870static void nidio_reset_board(struct comedi_device *dev)
 871{
 872        writel(0, dev->mmio + PORT_IO(0));
 873        writel(0, dev->mmio + PORT_PIN_DIRECTIONS(0));
 874        writel(0, dev->mmio + PORT_PIN_MASK(0));
 875
 876        /* disable interrupts on board */
 877        writeb(0, dev->mmio + MASTER_DMA_AND_INTERRUPT_CONTROL);
 878}
 879
 880static int nidio_auto_attach(struct comedi_device *dev,
 881                             unsigned long context)
 882{
 883        struct pci_dev *pcidev = comedi_to_pci_dev(dev);
 884        const struct nidio_board *board = NULL;
 885        struct nidio96_private *devpriv;
 886        struct comedi_subdevice *s;
 887        int ret;
 888        unsigned int irq;
 889
 890        if (context < ARRAY_SIZE(nidio_boards))
 891                board = &nidio_boards[context];
 892        if (!board)
 893                return -ENODEV;
 894        dev->board_ptr = board;
 895        dev->board_name = board->name;
 896
 897        ret = comedi_pci_enable(dev);
 898        if (ret)
 899                return ret;
 900
 901        devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
 902        if (!devpriv)
 903                return -ENOMEM;
 904
 905        spin_lock_init(&devpriv->mite_channel_lock);
 906
 907        devpriv->mite = mite_attach(dev, false);        /* use win0 */
 908        if (!devpriv->mite)
 909                return -ENOMEM;
 910
 911        devpriv->di_mite_ring = mite_alloc_ring(devpriv->mite);
 912        if (!devpriv->di_mite_ring)
 913                return -ENOMEM;
 914
 915        if (board->uses_firmware) {
 916                ret = pci_6534_upload_firmware(dev);
 917                if (ret < 0)
 918                        return ret;
 919        }
 920
 921        nidio_reset_board(dev);
 922
 923        ret = comedi_alloc_subdevices(dev, 1);
 924        if (ret)
 925                return ret;
 926
 927        dev_info(dev->class_dev, "%s rev=%d\n", dev->board_name,
 928                 readb(dev->mmio + CHIP_VERSION));
 929
 930        s = &dev->subdevices[0];
 931
 932        dev->read_subdev = s;
 933        s->type = COMEDI_SUBD_DIO;
 934        s->subdev_flags =
 935                SDF_READABLE | SDF_WRITABLE | SDF_LSAMPL | SDF_PACKED |
 936                SDF_CMD_READ;
 937        s->n_chan = 32;
 938        s->range_table = &range_digital;
 939        s->maxdata = 1;
 940        s->insn_config = &ni_pcidio_insn_config;
 941        s->insn_bits = &ni_pcidio_insn_bits;
 942        s->do_cmd = &ni_pcidio_cmd;
 943        s->do_cmdtest = &ni_pcidio_cmdtest;
 944        s->cancel = &ni_pcidio_cancel;
 945        s->len_chanlist = 32;   /* XXX */
 946        s->buf_change = &ni_pcidio_change;
 947        s->async_dma_dir = DMA_BIDIRECTIONAL;
 948        s->poll = &ni_pcidio_poll;
 949
 950        irq = pcidev->irq;
 951        if (irq) {
 952                ret = request_irq(irq, nidio_interrupt, IRQF_SHARED,
 953                                  dev->board_name, dev);
 954                if (ret == 0)
 955                        dev->irq = irq;
 956        }
 957
 958        return 0;
 959}
 960
 961static void nidio_detach(struct comedi_device *dev)
 962{
 963        struct nidio96_private *devpriv = dev->private;
 964
 965        if (dev->irq)
 966                free_irq(dev->irq, dev);
 967        if (devpriv) {
 968                if (devpriv->di_mite_ring) {
 969                        mite_free_ring(devpriv->di_mite_ring);
 970                        devpriv->di_mite_ring = NULL;
 971                }
 972                mite_detach(devpriv->mite);
 973        }
 974        if (dev->mmio)
 975                iounmap(dev->mmio);
 976        comedi_pci_disable(dev);
 977}
 978
 979static struct comedi_driver ni_pcidio_driver = {
 980        .driver_name    = "ni_pcidio",
 981        .module         = THIS_MODULE,
 982        .auto_attach    = nidio_auto_attach,
 983        .detach         = nidio_detach,
 984};
 985
 986static int ni_pcidio_pci_probe(struct pci_dev *dev,
 987                               const struct pci_device_id *id)
 988{
 989        return comedi_pci_auto_config(dev, &ni_pcidio_driver, id->driver_data);
 990}
 991
 992static const struct pci_device_id ni_pcidio_pci_table[] = {
 993        { PCI_VDEVICE(NI, 0x1150), BOARD_PCIDIO_32HS },
 994        { PCI_VDEVICE(NI, 0x12b0), BOARD_PCI6534 },
 995        { PCI_VDEVICE(NI, 0x1320), BOARD_PXI6533 },
 996        { 0 }
 997};
 998MODULE_DEVICE_TABLE(pci, ni_pcidio_pci_table);
 999
1000static struct pci_driver ni_pcidio_pci_driver = {
1001        .name           = "ni_pcidio",
1002        .id_table       = ni_pcidio_pci_table,
1003        .probe          = ni_pcidio_pci_probe,
1004        .remove         = comedi_pci_auto_unconfig,
1005};
1006module_comedi_pci_driver(ni_pcidio_driver, ni_pcidio_pci_driver);
1007
1008MODULE_AUTHOR("Comedi https://www.comedi.org");
1009MODULE_DESCRIPTION("Comedi low-level driver");
1010MODULE_LICENSE("GPL");
1011
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.