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