linux/drivers/staging/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 * http://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 IntStatus1                              BIT(0)
  55#define IntStatus2                              BIT(1)
  56#define WindowAddressStatus_mask                0x7c
  57
  58#define Master_DMA_And_Interrupt_Control 5      /* W */
  59#define InterruptLine(x)                        ((x) & 3)
  60#define OpenInt                         BIT(2)
  61#define Group_Status                    5       /* R */
  62#define DataLeft                                BIT(0)
  63#define Req                                     BIT(2)
  64#define StopTrig                                BIT(3)
  65
  66#define Group_1_Flags                   6       /* R */
  67#define Group_2_Flags                   7       /* R */
  68#define TransferReady                           BIT(0)
  69#define CountExpired                            BIT(1)
  70#define Waited                                  BIT(5)
  71#define PrimaryTC                               BIT(6)
  72#define SecondaryTC                             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 ClearWaited                             BIT(3)
  80#define ClearPrimaryTC                          BIT(4)
  81#define ClearSecondaryTC                        BIT(5)
  82#define DMAReset                                BIT(6)
  83#define FIFOReset                               BIT(7)
  84#define ClearAll                                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 RTSIClocking(x)                 (((x) & 3) << 4)
 101
 102#define Group_1_Second_Clear            46      /* W */
 103#define Group_2_Second_Clear            47      /* W */
 104#define ClearExpired                            BIT(0)
 105
 106#define Port_Pattern(x)                 (48 + (x))
 107
 108#define Data_Path                       64
 109#define FIFOEnableA             BIT(0)
 110#define FIFOEnableB             BIT(1)
 111#define FIFOEnableC             BIT(2)
 112#define FIFOEnableD             BIT(3)
 113#define Funneling(x)            (((x) & 3) << 4)
 114#define GroupDirection          BIT(7)
 115
 116#define Protocol_Register_1             65
 117#define OpMode                          Protocol_Register_1
 118#define RunMode(x)              ((x) & 7)
 119#define Numbered                BIT(3)
 120
 121#define Protocol_Register_2             66
 122#define ClockReg                        Protocol_Register_2
 123#define ClockLine(x)            (((x) & 3) << 5)
 124#define InvertStopTrig          BIT(7)
 125#define DataLatching(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 ClockSpeed                      Protocol_Register_14
 132
 133#define Protocol_Register_4             70
 134#define ReqReg                          Protocol_Register_4
 135#define ReqConditioning(x)      (((x) & 7) << 3)
 136
 137#define Protocol_Register_5             71
 138#define BlockMode                       Protocol_Register_5
 139
 140#define FIFO_Control                    72
 141#define ReadyLevel(x)           ((x) & 7)
 142
 143#define Protocol_Register_6             73
 144#define LinePolarities                  Protocol_Register_6
 145#define InvertAck               BIT(0)
 146#define InvertReq               BIT(1)
 147#define InvertClock             BIT(2)
 148#define InvertSerial            BIT(3)
 149#define OpenAck         BIT(4)
 150#define OpenClock               BIT(5)
 151
 152#define Protocol_Register_7             74
 153#define AckSer                          Protocol_Register_7
 154#define AckLine(x)              (((x) & 3) << 2)
 155#define ExchangePins            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/* channel zero is none */
 163static inline unsigned int primary_DMAChannel_bits(unsigned int channel)
 164{
 165        return channel & 0x3;
 166}
 167
 168static inline unsigned int secondary_DMAChannel_bits(unsigned int channel)
 169{
 170        return (channel << 2) & 0xc;
 171}
 172
 173#define Transfer_Size_Control           77
 174#define TransferWidth(x)        ((x) & 3)
 175#define TransferLength(x)       (((x) & 3) << 3)
 176#define RequireRLevel           BIT(5)
 177
 178#define Protocol_Register_15            79
 179#define DAQOptions                      Protocol_Register_15
 180#define StartSource(x)                  ((x) & 0x3)
 181#define InvertStart                             BIT(2)
 182#define StopSource(x)                           (((x) & 0x3) << 3)
 183#define ReqStart                                BIT(6)
 184#define PreStart                                BIT(7)
 185
 186#define Pattern_Detection               81
 187#define DetectionMethod                 BIT(0)
 188#define InvertMatch                             BIT(1)
 189#define IE_Pattern_Detection                    BIT(2)
 190
 191#define Protocol_Register_9             82
 192#define ReqDelay                        Protocol_Register_9
 193
 194#define Protocol_Register_10            83
 195#define ReqNotDelay                     Protocol_Register_10
 196
 197#define Protocol_Register_11            84
 198#define AckDelay                        Protocol_Register_11
 199
 200#define Protocol_Register_12            85
 201#define AckNotDelay                     Protocol_Register_12
 202
 203#define Protocol_Register_13            86
 204#define Data1Delay                      Protocol_Register_13
 205
 206#define Protocol_Register_8             88      /* 32 bit */
 207#define StartDelay                      Protocol_Register_8
 208
 209/* Firmware files for PCI-6524 */
 210#define FW_PCI_6534_MAIN                "ni6534a.bin"
 211#define FW_PCI_6534_SCARAB_DI           "niscrb01.bin"
 212#define FW_PCI_6534_SCARAB_DO           "niscrb02.bin"
 213MODULE_FIRMWARE(FW_PCI_6534_MAIN);
 214MODULE_FIRMWARE(FW_PCI_6534_SCARAB_DI);
 215MODULE_FIRMWARE(FW_PCI_6534_SCARAB_DO);
 216
 217enum pci_6534_firmware_registers {      /* 16 bit */
 218        Firmware_Control_Register = 0x100,
 219        Firmware_Status_Register = 0x104,
 220        Firmware_Data_Register = 0x108,
 221        Firmware_Mask_Register = 0x10c,
 222        Firmware_Debug_Register = 0x110,
 223};
 224
 225/* main fpga registers (32 bit)*/
 226enum pci_6534_fpga_registers {
 227        FPGA_Control1_Register = 0x200,
 228        FPGA_Control2_Register = 0x204,
 229        FPGA_Irq_Mask_Register = 0x208,
 230        FPGA_Status_Register = 0x20c,
 231        FPGA_Signature_Register = 0x210,
 232        FPGA_SCALS_Counter_Register = 0x280,    /*write-clear */
 233        FPGA_SCAMS_Counter_Register = 0x284,    /*write-clear */
 234        FPGA_SCBLS_Counter_Register = 0x288,    /*write-clear */
 235        FPGA_SCBMS_Counter_Register = 0x28c,    /*write-clear */
 236        FPGA_Temp_Control_Register = 0x2a0,
 237        FPGA_DAR_Register = 0x2a8,
 238        FPGA_ELC_Read_Register = 0x2b8,
 239        FPGA_ELC_Write_Register = 0x2bc,
 240};
 241
 242enum FPGA_Control_Bits {
 243        FPGA_Enable_Bit = 0x8000,
 244};
 245
 246#define TIMER_BASE 50           /* nanoseconds */
 247
 248#ifdef USE_DMA
 249#define IntEn (CountExpired | Waited | PrimaryTC | SecondaryTC)
 250#else
 251#define IntEn (TransferReady | CountExpired | Waited | PrimaryTC | SecondaryTC)
 252#endif
 253
 254enum nidio_boardid {
 255        BOARD_PCIDIO_32HS,
 256        BOARD_PXI6533,
 257        BOARD_PCI6534,
 258};
 259
 260struct nidio_board {
 261        const char *name;
 262        unsigned int uses_firmware:1;
 263};
 264
 265static const struct nidio_board nidio_boards[] = {
 266        [BOARD_PCIDIO_32HS] = {
 267                .name           = "pci-dio-32hs",
 268        },
 269        [BOARD_PXI6533] = {
 270                .name           = "pxi-6533",
 271        },
 272        [BOARD_PCI6534] = {
 273                .name           = "pci-6534",
 274                .uses_firmware  = 1,
 275        },
 276};
 277
 278struct nidio96_private {
 279        struct mite *mite;
 280        int boardtype;
 281        int dio;
 282        unsigned short OpModeBits;
 283        struct mite_channel *di_mite_chan;
 284        struct mite_ring *di_mite_ring;
 285        spinlock_t mite_channel_lock;
 286};
 287
 288static int ni_pcidio_request_di_mite_channel(struct comedi_device *dev)
 289{
 290        struct nidio96_private *devpriv = dev->private;
 291        unsigned long flags;
 292
 293        spin_lock_irqsave(&devpriv->mite_channel_lock, flags);
 294        BUG_ON(devpriv->di_mite_chan);
 295        devpriv->di_mite_chan =
 296            mite_request_channel_in_range(devpriv->mite,
 297                                          devpriv->di_mite_ring, 1, 2);
 298        if (!devpriv->di_mite_chan) {
 299                spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags);
 300                dev_err(dev->class_dev, "failed to reserve mite dma channel\n");
 301                return -EBUSY;
 302        }
 303        devpriv->di_mite_chan->dir = COMEDI_INPUT;
 304        writeb(primary_DMAChannel_bits(devpriv->di_mite_chan->channel) |
 305               secondary_DMAChannel_bits(devpriv->di_mite_chan->channel),
 306               dev->mmio + DMA_Line_Control_Group1);
 307        spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags);
 308        return 0;
 309}
 310
 311static void ni_pcidio_release_di_mite_channel(struct comedi_device *dev)
 312{
 313        struct nidio96_private *devpriv = dev->private;
 314        unsigned long flags;
 315
 316        spin_lock_irqsave(&devpriv->mite_channel_lock, flags);
 317        if (devpriv->di_mite_chan) {
 318                mite_release_channel(devpriv->di_mite_chan);
 319                devpriv->di_mite_chan = NULL;
 320                writeb(primary_DMAChannel_bits(0) |
 321                       secondary_DMAChannel_bits(0),
 322                       dev->mmio + DMA_Line_Control_Group1);
 323        }
 324        spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags);
 325}
 326
 327static int setup_mite_dma(struct comedi_device *dev, struct comedi_subdevice *s)
 328{
 329        struct nidio96_private *devpriv = dev->private;
 330        int retval;
 331        unsigned long flags;
 332
 333        retval = ni_pcidio_request_di_mite_channel(dev);
 334        if (retval)
 335                return retval;
 336
 337        /* write alloc the entire buffer */
 338        comedi_buf_write_alloc(s, s->async->prealloc_bufsz);
 339
 340        spin_lock_irqsave(&devpriv->mite_channel_lock, flags);
 341        if (devpriv->di_mite_chan) {
 342                mite_prep_dma(devpriv->di_mite_chan, 32, 32);
 343                mite_dma_arm(devpriv->di_mite_chan);
 344        } else {
 345                retval = -EIO;
 346        }
 347        spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags);
 348
 349        return retval;
 350}
 351
 352static int ni_pcidio_poll(struct comedi_device *dev, struct comedi_subdevice *s)
 353{
 354        struct nidio96_private *devpriv = dev->private;
 355        unsigned long irq_flags;
 356        int count;
 357
 358        spin_lock_irqsave(&dev->spinlock, irq_flags);
 359        spin_lock(&devpriv->mite_channel_lock);
 360        if (devpriv->di_mite_chan)
 361                mite_sync_dma(devpriv->di_mite_chan, s);
 362        spin_unlock(&devpriv->mite_channel_lock);
 363        count = comedi_buf_n_bytes_ready(s);
 364        spin_unlock_irqrestore(&dev->spinlock, irq_flags);
 365        return count;
 366}
 367
 368static irqreturn_t nidio_interrupt(int irq, void *d)
 369{
 370        struct comedi_device *dev = d;
 371        struct nidio96_private *devpriv = dev->private;
 372        struct comedi_subdevice *s = dev->read_subdev;
 373        struct comedi_async *async = s->async;
 374        unsigned int auxdata;
 375        int flags;
 376        int status;
 377        int work = 0;
 378
 379        /* interrupcions parasites */
 380        if (!dev->attached) {
 381                /* assume it's from another card */
 382                return IRQ_NONE;
 383        }
 384
 385        /* Lock to avoid race with comedi_poll */
 386        spin_lock(&dev->spinlock);
 387
 388        status = readb(dev->mmio + Interrupt_And_Window_Status);
 389        flags = readb(dev->mmio + Group_1_Flags);
 390
 391        spin_lock(&devpriv->mite_channel_lock);
 392        if (devpriv->di_mite_chan) {
 393                mite_ack_linkc(devpriv->di_mite_chan, s, false);
 394                /* XXX need to byteswap sync'ed dma */
 395        }
 396        spin_unlock(&devpriv->mite_channel_lock);
 397
 398        while (status & DataLeft) {
 399                work++;
 400                if (work > 20) {
 401                        dev_dbg(dev->class_dev, "too much work in interrupt\n");
 402                        writeb(0x00,
 403                               dev->mmio + Master_DMA_And_Interrupt_Control);
 404                        break;
 405                }
 406
 407                flags &= IntEn;
 408
 409                if (flags & TransferReady) {
 410                        while (flags & TransferReady) {
 411                                work++;
 412                                if (work > 100) {
 413                                        dev_dbg(dev->class_dev,
 414                                                "too much work in interrupt\n");
 415                                        writeb(0x00, dev->mmio +
 416                                               Master_DMA_And_Interrupt_Control
 417                                              );
 418                                        goto out;
 419                                }
 420                                auxdata = readl(dev->mmio + Group_1_FIFO);
 421                                comedi_buf_write_samples(s, &auxdata, 1);
 422                                flags = readb(dev->mmio + Group_1_Flags);
 423                        }
 424                }
 425
 426                if (flags & CountExpired) {
 427                        writeb(ClearExpired, dev->mmio + Group_1_Second_Clear);
 428                        async->events |= COMEDI_CB_EOA;
 429
 430                        writeb(0x00, dev->mmio + OpMode);
 431                        break;
 432                } else if (flags & Waited) {
 433                        writeb(ClearWaited, dev->mmio + Group_1_First_Clear);
 434                        async->events |= COMEDI_CB_ERROR;
 435                        break;
 436                } else if (flags & PrimaryTC) {
 437                        writeb(ClearPrimaryTC,
 438                               dev->mmio + Group_1_First_Clear);
 439                        async->events |= COMEDI_CB_EOA;
 440                } else if (flags & SecondaryTC) {
 441                        writeb(ClearSecondaryTC,
 442                               dev->mmio + Group_1_First_Clear);
 443                        async->events |= COMEDI_CB_EOA;
 444                }
 445
 446                flags = readb(dev->mmio + Group_1_Flags);
 447                status = readb(dev->mmio + Interrupt_And_Window_Status);
 448        }
 449
 450out:
 451        comedi_handle_events(dev, s);
 452#if 0
 453        if (!tag)
 454                writeb(0x03, dev->mmio + Master_DMA_And_Interrupt_Control);
 455#endif
 456
 457        spin_unlock(&dev->spinlock);
 458        return IRQ_HANDLED;
 459}
 460
 461static int ni_pcidio_insn_config(struct comedi_device *dev,
 462                                 struct comedi_subdevice *s,
 463                                 struct comedi_insn *insn,
 464                                 unsigned int *data)
 465{
 466        int ret;
 467
 468        ret = comedi_dio_insn_config(dev, s, insn, data, 0);
 469        if (ret)
 470                return ret;
 471
 472        writel(s->io_bits, dev->mmio + Port_Pin_Directions(0));
 473
 474        return insn->n;
 475}
 476
 477static int ni_pcidio_insn_bits(struct comedi_device *dev,
 478                               struct comedi_subdevice *s,
 479                               struct comedi_insn *insn,
 480                               unsigned int *data)
 481{
 482        if (comedi_dio_update_state(s, data))
 483                writel(s->state, dev->mmio + Port_IO(0));
 484
 485        data[1] = readl(dev->mmio + Port_IO(0));
 486
 487        return insn->n;
 488}
 489
 490static int ni_pcidio_ns_to_timer(int *nanosec, unsigned int flags)
 491{
 492        int divider, base;
 493
 494        base = TIMER_BASE;
 495
 496        switch (flags & CMDF_ROUND_MASK) {
 497        case CMDF_ROUND_NEAREST:
 498        default:
 499                divider = DIV_ROUND_CLOSEST(*nanosec, base);
 500                break;
 501        case CMDF_ROUND_DOWN:
 502                divider = (*nanosec) / base;
 503                break;
 504        case CMDF_ROUND_UP:
 505                divider = DIV_ROUND_UP(*nanosec, base);
 506                break;
 507        }
 508
 509        *nanosec = base * divider;
 510        return divider;
 511}
 512
 513static int ni_pcidio_cmdtest(struct comedi_device *dev,
 514                             struct comedi_subdevice *s, struct comedi_cmd *cmd)
 515{
 516        int err = 0;
 517        unsigned int arg;
 518
 519        /* Step 1 : check if triggers are trivially valid */
 520
 521        err |= comedi_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_INT);
 522        err |= comedi_check_trigger_src(&cmd->scan_begin_src,
 523                                        TRIG_TIMER | TRIG_EXT);
 524        err |= comedi_check_trigger_src(&cmd->convert_src, TRIG_NOW);
 525        err |= comedi_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
 526        err |= comedi_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE);
 527
 528        if (err)
 529                return 1;
 530
 531        /* Step 2a : make sure trigger sources are unique */
 532
 533        err |= comedi_check_trigger_is_unique(cmd->start_src);
 534        err |= comedi_check_trigger_is_unique(cmd->scan_begin_src);
 535        err |= comedi_check_trigger_is_unique(cmd->stop_src);
 536
 537        /* Step 2b : and mutually compatible */
 538
 539        if (err)
 540                return 2;
 541
 542        /* Step 3: check if arguments are trivially valid */
 543
 544        err |= comedi_check_trigger_arg_is(&cmd->start_arg, 0);
 545
 546#define MAX_SPEED       (TIMER_BASE)    /* in nanoseconds */
 547
 548        if (cmd->scan_begin_src == TRIG_TIMER) {
 549                err |= comedi_check_trigger_arg_min(&cmd->scan_begin_arg,
 550                                                    MAX_SPEED);
 551                /* no minimum speed */
 552        } else {
 553                /* TRIG_EXT */
 554                /* should be level/edge, hi/lo specification here */
 555                if ((cmd->scan_begin_arg & ~(CR_EDGE | CR_INVERT)) != 0) {
 556                        cmd->scan_begin_arg &= (CR_EDGE | CR_INVERT);
 557                        err |= -EINVAL;
 558                }
 559        }
 560
 561        err |= comedi_check_trigger_arg_is(&cmd->convert_arg, 0);
 562        err |= comedi_check_trigger_arg_is(&cmd->scan_end_arg,
 563                                           cmd->chanlist_len);
 564
 565        if (cmd->stop_src == TRIG_COUNT)
 566                err |= comedi_check_trigger_arg_min(&cmd->stop_arg, 1);
 567        else    /* TRIG_NONE */
 568                err |= comedi_check_trigger_arg_is(&cmd->stop_arg, 0);
 569
 570        if (err)
 571                return 3;
 572
 573        /* step 4: fix up any arguments */
 574
 575        if (cmd->scan_begin_src == TRIG_TIMER) {
 576                arg = cmd->scan_begin_arg;
 577                ni_pcidio_ns_to_timer(&arg, cmd->flags);
 578                err |= comedi_check_trigger_arg_is(&cmd->scan_begin_arg, arg);
 579        }
 580
 581        if (err)
 582                return 4;
 583
 584        return 0;
 585}
 586
 587static int ni_pcidio_inttrig(struct comedi_device *dev,
 588                             struct comedi_subdevice *s,
 589                             unsigned int trig_num)
 590{
 591        struct nidio96_private *devpriv = dev->private;
 592        struct comedi_cmd *cmd = &s->async->cmd;
 593
 594        if (trig_num != cmd->start_arg)
 595                return -EINVAL;
 596
 597        writeb(devpriv->OpModeBits, dev->mmio + OpMode);
 598        s->async->inttrig = NULL;
 599
 600        return 1;
 601}
 602
 603static int ni_pcidio_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 604{
 605        struct nidio96_private *devpriv = dev->private;
 606        struct comedi_cmd *cmd = &s->async->cmd;
 607
 608        /* XXX configure ports for input */
 609        writel(0x0000, dev->mmio + Port_Pin_Directions(0));
 610
 611        if (1) {
 612                /* enable fifos A B C D */
 613                writeb(0x0f, dev->mmio + Data_Path);
 614
 615                /* set transfer width a 32 bits */
 616                writeb(TransferWidth(0) | TransferLength(0),
 617                       dev->mmio + Transfer_Size_Control);
 618        } else {
 619                writeb(0x03, dev->mmio + Data_Path);
 620                writeb(TransferWidth(3) | TransferLength(0),
 621                       dev->mmio + Transfer_Size_Control);
 622        }
 623
 624        /* protocol configuration */
 625        if (cmd->scan_begin_src == TRIG_TIMER) {
 626                /* page 4-5, "input with internal REQs" */
 627                writeb(0, dev->mmio + OpMode);
 628                writeb(0x00, dev->mmio + ClockReg);
 629                writeb(1, dev->mmio + Sequence);
 630                writeb(0x04, dev->mmio + ReqReg);
 631                writeb(4, dev->mmio + BlockMode);
 632                writeb(3, dev->mmio + LinePolarities);
 633                writeb(0xc0, dev->mmio + AckSer);
 634                writel(ni_pcidio_ns_to_timer(&cmd->scan_begin_arg,
 635                                             CMDF_ROUND_NEAREST),
 636                       dev->mmio + StartDelay);
 637                writeb(1, dev->mmio + ReqDelay);
 638                writeb(1, dev->mmio + ReqNotDelay);
 639                writeb(1, dev->mmio + AckDelay);
 640                writeb(0x0b, dev->mmio + AckNotDelay);
 641                writeb(0x01, dev->mmio + Data1Delay);
 642                /*
 643                 * manual, page 4-5:
 644                 * ClockSpeed comment is incorrectly listed on DAQOptions
 645                 */
 646                writew(0, dev->mmio + ClockSpeed);
 647                writeb(0, dev->mmio + DAQOptions);
 648        } else {
 649                /* TRIG_EXT */
 650                /* page 4-5, "input with external REQs" */
 651                writeb(0, dev->mmio + OpMode);
 652                writeb(0x00, dev->mmio + ClockReg);
 653                writeb(0, dev->mmio + Sequence);
 654                writeb(0x00, dev->mmio + ReqReg);
 655                writeb(4, dev->mmio + BlockMode);
 656                if (!(cmd->scan_begin_arg & CR_INVERT)) /* Leading Edge */
 657                        writeb(0, dev->mmio + LinePolarities);
 658                else                                    /* Trailing Edge */
 659                        writeb(2, dev->mmio + LinePolarities);
 660                writeb(0x00, dev->mmio + AckSer);
 661                writel(1, dev->mmio + StartDelay);
 662                writeb(1, dev->mmio + ReqDelay);
 663                writeb(1, dev->mmio + ReqNotDelay);
 664                writeb(1, dev->mmio + AckDelay);
 665                writeb(0x0C, dev->mmio + AckNotDelay);
 666                writeb(0x10, dev->mmio + Data1Delay);
 667                writew(0, dev->mmio + ClockSpeed);
 668                writeb(0x60, dev->mmio + DAQOptions);
 669        }
 670
 671        if (cmd->stop_src == TRIG_COUNT) {
 672                writel(cmd->stop_arg,
 673                       dev->mmio + Transfer_Count);
 674        } else {
 675                /* XXX */
 676        }
 677
 678#ifdef USE_DMA
 679        writeb(ClearPrimaryTC | ClearSecondaryTC,
 680               dev->mmio + Group_1_First_Clear);
 681
 682        {
 683                int retval = setup_mite_dma(dev, s);
 684
 685                if (retval)
 686                        return retval;
 687        }
 688#else
 689        writeb(0x00, dev->mmio + DMA_Line_Control_Group1);
 690#endif
 691        writeb(0x00, dev->mmio + DMA_Line_Control_Group2);
 692
 693        /* clear and enable interrupts */
 694        writeb(0xff, dev->mmio + Group_1_First_Clear);
 695        /* writeb(ClearExpired, dev->mmio+Group_1_Second_Clear); */
 696
 697        writeb(IntEn, dev->mmio + Interrupt_Control);
 698        writeb(0x03, dev->mmio + Master_DMA_And_Interrupt_Control);
 699
 700        if (cmd->stop_src == TRIG_NONE) {
 701                devpriv->OpModeBits = DataLatching(0) | RunMode(7);
 702        } else {                /* TRIG_TIMER */
 703                devpriv->OpModeBits = Numbered | RunMode(7);
 704        }
 705        if (cmd->start_src == TRIG_NOW) {
 706                /* start */
 707                writeb(devpriv->OpModeBits, dev->mmio + OpMode);
 708                s->async->inttrig = NULL;
 709        } else {
 710                /* TRIG_INT */
 711                s->async->inttrig = ni_pcidio_inttrig;
 712        }
 713
 714        return 0;
 715}
 716
 717static int ni_pcidio_cancel(struct comedi_device *dev,
 718                            struct comedi_subdevice *s)
 719{
 720        writeb(0x00, dev->mmio + Master_DMA_And_Interrupt_Control);
 721        ni_pcidio_release_di_mite_channel(dev);
 722
 723        return 0;
 724}
 725
 726static int ni_pcidio_change(struct comedi_device *dev,
 727                            struct comedi_subdevice *s)
 728{
 729        struct nidio96_private *devpriv = dev->private;
 730        int ret;
 731
 732        ret = mite_buf_change(devpriv->di_mite_ring, s);
 733        if (ret < 0)
 734                return ret;
 735
 736        memset(s->async->prealloc_buf, 0xaa, s->async->prealloc_bufsz);
 737
 738        return 0;
 739}
 740
 741static int pci_6534_load_fpga(struct comedi_device *dev,
 742                              const u8 *data, size_t data_len,
 743                              unsigned long context)
 744{
 745        static const int timeout = 1000;
 746        int fpga_index = context;
 747        int i;
 748        size_t j;
 749
 750        writew(0x80 | fpga_index, dev->mmio + Firmware_Control_Register);
 751        writew(0xc0 | fpga_index, dev->mmio + Firmware_Control_Register);
 752        for (i = 0;
 753             (readw(dev->mmio + Firmware_Status_Register) & 0x2) == 0 &&
 754             i < timeout; ++i) {
 755                udelay(1);
 756        }
 757        if (i == timeout) {
 758                dev_warn(dev->class_dev,
 759                         "ni_pcidio: failed to load fpga %i, waiting for status 0x2\n",
 760                         fpga_index);
 761                return -EIO;
 762        }
 763        writew(0x80 | fpga_index, dev->mmio + Firmware_Control_Register);
 764        for (i = 0;
 765             readw(dev->mmio + Firmware_Status_Register) != 0x3 &&
 766             i < timeout; ++i) {
 767                udelay(1);
 768        }
 769        if (i == timeout) {
 770                dev_warn(dev->class_dev,
 771                         "ni_pcidio: failed to load fpga %i, waiting for status 0x3\n",
 772                         fpga_index);
 773                return -EIO;
 774        }
 775        for (j = 0; j + 1 < data_len;) {
 776                unsigned int value = data[j++];
 777
 778                value |= data[j++] << 8;
 779                writew(value, dev->mmio + Firmware_Data_Register);
 780                for (i = 0;
 781                     (readw(dev->mmio + Firmware_Status_Register) & 0x2) == 0
 782                     && i < timeout; ++i) {
 783                        udelay(1);
 784                }
 785                if (i == timeout) {
 786                        dev_warn(dev->class_dev,
 787                                 "ni_pcidio: failed to load word into fpga %i\n",
 788                                 fpga_index);
 789                        return -EIO;
 790                }
 791                if (need_resched())
 792                        schedule();
 793        }
 794        writew(0x0, dev->mmio + Firmware_Control_Register);
 795        return 0;
 796}
 797
 798static int pci_6534_reset_fpga(struct comedi_device *dev, int fpga_index)
 799{
 800        return pci_6534_load_fpga(dev, NULL, 0, fpga_index);
 801}
 802
 803static int pci_6534_reset_fpgas(struct comedi_device *dev)
 804{
 805        int ret;
 806        int i;
 807
 808        writew(0x0, dev->mmio + Firmware_Control_Register);
 809        for (i = 0; i < 3; ++i) {
 810                ret = pci_6534_reset_fpga(dev, i);
 811                if (ret < 0)
 812                        break;
 813        }
 814        writew(0x0, dev->mmio + Firmware_Mask_Register);
 815        return ret;
 816}
 817
 818static void pci_6534_init_main_fpga(struct comedi_device *dev)
 819{
 820        writel(0, dev->mmio + FPGA_Control1_Register);
 821        writel(0, dev->mmio + FPGA_Control2_Register);
 822        writel(0, dev->mmio + FPGA_SCALS_Counter_Register);
 823        writel(0, dev->mmio + FPGA_SCAMS_Counter_Register);
 824        writel(0, dev->mmio + FPGA_SCBLS_Counter_Register);
 825        writel(0, dev->mmio + FPGA_SCBMS_Counter_Register);
 826}
 827
 828static int pci_6534_upload_firmware(struct comedi_device *dev)
 829{
 830        struct nidio96_private *devpriv = dev->private;
 831        static const char *const fw_file[3] = {
 832                FW_PCI_6534_SCARAB_DI,  /* loaded into scarab A for DI */
 833                FW_PCI_6534_SCARAB_DO,  /* loaded into scarab B for DO */
 834                FW_PCI_6534_MAIN,       /* loaded into main FPGA */
 835        };
 836        int ret;
 837        int n;
 838
 839        ret = pci_6534_reset_fpgas(dev);
 840        if (ret < 0)
 841                return ret;
 842        /* load main FPGA first, then the two scarabs */
 843        for (n = 2; n >= 0; n--) {
 844                ret = comedi_load_firmware(dev, &devpriv->mite->pcidev->dev,
 845                                           fw_file[n],
 846                                           pci_6534_load_fpga, n);
 847                if (ret == 0 && n == 2)
 848                        pci_6534_init_main_fpga(dev);
 849                if (ret < 0)
 850                        break;
 851        }
 852        return ret;
 853}
 854
 855static void nidio_reset_board(struct comedi_device *dev)
 856{
 857        writel(0, dev->mmio + Port_IO(0));
 858        writel(0, dev->mmio + Port_Pin_Directions(0));
 859        writel(0, dev->mmio + Port_Pin_Mask(0));
 860
 861        /* disable interrupts on board */
 862        writeb(0, dev->mmio + Master_DMA_And_Interrupt_Control);
 863}
 864
 865static int nidio_auto_attach(struct comedi_device *dev,
 866                             unsigned long context)
 867{
 868        struct pci_dev *pcidev = comedi_to_pci_dev(dev);
 869        const struct nidio_board *board = NULL;
 870        struct nidio96_private *devpriv;
 871        struct comedi_subdevice *s;
 872        int ret;
 873        unsigned int irq;
 874
 875        if (context < ARRAY_SIZE(nidio_boards))
 876                board = &nidio_boards[context];
 877        if (!board)
 878                return -ENODEV;
 879        dev->board_ptr = board;
 880        dev->board_name = board->name;
 881
 882        ret = comedi_pci_enable(dev);
 883        if (ret)
 884                return ret;
 885
 886        devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
 887        if (!devpriv)
 888                return -ENOMEM;
 889
 890        spin_lock_init(&devpriv->mite_channel_lock);
 891
 892        devpriv->mite = mite_attach(dev, false);        /* use win0 */
 893        if (!devpriv->mite)
 894                return -ENOMEM;
 895
 896        devpriv->di_mite_ring = mite_alloc_ring(devpriv->mite);
 897        if (!devpriv->di_mite_ring)
 898                return -ENOMEM;
 899
 900        if (board->uses_firmware) {
 901                ret = pci_6534_upload_firmware(dev);
 902                if (ret < 0)
 903                        return ret;
 904        }
 905
 906        nidio_reset_board(dev);
 907
 908        ret = comedi_alloc_subdevices(dev, 1);
 909        if (ret)
 910                return ret;
 911
 912        dev_info(dev->class_dev, "%s rev=%d\n", dev->board_name,
 913                 readb(dev->mmio + Chip_Version));
 914
 915        s = &dev->subdevices[0];
 916
 917        dev->read_subdev = s;
 918        s->type = COMEDI_SUBD_DIO;
 919        s->subdev_flags =
 920                SDF_READABLE | SDF_WRITABLE | SDF_LSAMPL | SDF_PACKED |
 921                SDF_CMD_READ;
 922        s->n_chan = 32;
 923        s->range_table = &range_digital;
 924        s->maxdata = 1;
 925        s->insn_config = &ni_pcidio_insn_config;
 926        s->insn_bits = &ni_pcidio_insn_bits;
 927        s->do_cmd = &ni_pcidio_cmd;
 928        s->do_cmdtest = &ni_pcidio_cmdtest;
 929        s->cancel = &ni_pcidio_cancel;
 930        s->len_chanlist = 32;   /* XXX */
 931        s->buf_change = &ni_pcidio_change;
 932        s->async_dma_dir = DMA_BIDIRECTIONAL;
 933        s->poll = &ni_pcidio_poll;
 934
 935        irq = pcidev->irq;
 936        if (irq) {
 937                ret = request_irq(irq, nidio_interrupt, IRQF_SHARED,
 938                                  dev->board_name, dev);
 939                if (ret == 0)
 940                        dev->irq = irq;
 941        }
 942
 943        return 0;
 944}
 945
 946static void nidio_detach(struct comedi_device *dev)
 947{
 948        struct nidio96_private *devpriv = dev->private;
 949
 950        if (dev->irq)
 951                free_irq(dev->irq, dev);
 952        if (devpriv) {
 953                if (devpriv->di_mite_ring) {
 954                        mite_free_ring(devpriv->di_mite_ring);
 955                        devpriv->di_mite_ring = NULL;
 956                }
 957                mite_detach(devpriv->mite);
 958        }
 959        if (dev->mmio)
 960                iounmap(dev->mmio);
 961        comedi_pci_disable(dev);
 962}
 963
 964static struct comedi_driver ni_pcidio_driver = {
 965        .driver_name    = "ni_pcidio",
 966        .module         = THIS_MODULE,
 967        .auto_attach    = nidio_auto_attach,
 968        .detach         = nidio_detach,
 969};
 970
 971static int ni_pcidio_pci_probe(struct pci_dev *dev,
 972                               const struct pci_device_id *id)
 973{
 974        return comedi_pci_auto_config(dev, &ni_pcidio_driver, id->driver_data);
 975}
 976
 977static const struct pci_device_id ni_pcidio_pci_table[] = {
 978        { PCI_VDEVICE(NI, 0x1150), BOARD_PCIDIO_32HS },
 979        { PCI_VDEVICE(NI, 0x12b0), BOARD_PCI6534 },
 980        { PCI_VDEVICE(NI, 0x1320), BOARD_PXI6533 },
 981        { 0 }
 982};
 983MODULE_DEVICE_TABLE(pci, ni_pcidio_pci_table);
 984
 985static struct pci_driver ni_pcidio_pci_driver = {
 986        .name           = "ni_pcidio",
 987        .id_table       = ni_pcidio_pci_table,
 988        .probe          = ni_pcidio_pci_probe,
 989        .remove         = comedi_pci_auto_unconfig,
 990};
 991module_comedi_pci_driver(ni_pcidio_driver, ni_pcidio_pci_driver);
 992
 993MODULE_AUTHOR("Comedi http://www.comedi.org");
 994MODULE_DESCRIPTION("Comedi low-level driver");
 995MODULE_LICENSE("GPL");
 996