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 *mite;
 288        int boardtype;
 289        int dio;
 290        unsigned short OpModeBits;
 291        struct mite_channel *di_mite_chan;
 292        struct mite_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_release_channel(devpriv->di_mite_chan);
 328                devpriv->di_mite_chan = NULL;
 329                writeb(primary_DMAChannel_bits(0) |
 330                       secondary_DMAChannel_bits(0),
 331                       dev->mmio + DMA_Line_Control_Group1);
 332                mmiowb();
 333        }
 334        spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags);
 335}
 336
 337static int setup_mite_dma(struct comedi_device *dev, struct comedi_subdevice *s)
 338{
 339        struct nidio96_private *devpriv = dev->private;
 340        int retval;
 341        unsigned long flags;
 342
 343        retval = ni_pcidio_request_di_mite_channel(dev);
 344        if (retval)
 345                return retval;
 346
 347        /* write alloc the entire buffer */
 348        comedi_buf_write_alloc(s, s->async->prealloc_bufsz);
 349
 350        spin_lock_irqsave(&devpriv->mite_channel_lock, flags);
 351        if (devpriv->di_mite_chan) {
 352                mite_prep_dma(devpriv->di_mite_chan, 32, 32);
 353                mite_dma_arm(devpriv->di_mite_chan);
 354        } else {
 355                retval = -EIO;
 356        }
 357        spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags);
 358
 359        return retval;
 360}
 361
 362static int ni_pcidio_poll(struct comedi_device *dev, struct comedi_subdevice *s)
 363{
 364        struct nidio96_private *devpriv = dev->private;
 365        unsigned long irq_flags;
 366        int count;
 367
 368        spin_lock_irqsave(&dev->spinlock, irq_flags);
 369        spin_lock(&devpriv->mite_channel_lock);
 370        if (devpriv->di_mite_chan)
 371                mite_sync_dma(devpriv->di_mite_chan, s);
 372        spin_unlock(&devpriv->mite_channel_lock);
 373        count = comedi_buf_n_bytes_ready(s);
 374        spin_unlock_irqrestore(&dev->spinlock, irq_flags);
 375        return count;
 376}
 377
 378static irqreturn_t nidio_interrupt(int irq, void *d)
 379{
 380        struct comedi_device *dev = d;
 381        struct nidio96_private *devpriv = dev->private;
 382        struct comedi_subdevice *s = dev->read_subdev;
 383        struct comedi_async *async = s->async;
 384        unsigned int auxdata;
 385        int flags;
 386        int status;
 387        int work = 0;
 388
 389        /* interrupcions parasites */
 390        if (!dev->attached) {
 391                /* assume it's from another card */
 392                return IRQ_NONE;
 393        }
 394
 395        /* Lock to avoid race with comedi_poll */
 396        spin_lock(&dev->spinlock);
 397
 398        status = readb(dev->mmio + Interrupt_And_Window_Status);
 399        flags = readb(dev->mmio + Group_1_Flags);
 400
 401        spin_lock(&devpriv->mite_channel_lock);
 402        if (devpriv->di_mite_chan) {
 403                mite_ack_linkc(devpriv->di_mite_chan, s, false);
 404                /* XXX need to byteswap sync'ed dma */
 405        }
 406        spin_unlock(&devpriv->mite_channel_lock);
 407
 408        while (status & DataLeft) {
 409                work++;
 410                if (work > 20) {
 411                        dev_dbg(dev->class_dev, "too much work in interrupt\n");
 412                        writeb(0x00,
 413                               dev->mmio + Master_DMA_And_Interrupt_Control);
 414                        break;
 415                }
 416
 417                flags &= IntEn;
 418
 419                if (flags & TransferReady) {
 420                        while (flags & TransferReady) {
 421                                work++;
 422                                if (work > 100) {
 423                                        dev_dbg(dev->class_dev,
 424                                                "too much work in interrupt\n");
 425                                        writeb(0x00, dev->mmio +
 426                                               Master_DMA_And_Interrupt_Control
 427                                              );
 428                                        goto out;
 429                                }
 430                                auxdata = readl(dev->mmio + Group_1_FIFO);
 431                                comedi_buf_write_samples(s, &auxdata, 1);
 432                                flags = readb(dev->mmio + Group_1_Flags);
 433                        }
 434                }
 435
 436                if (flags & CountExpired) {
 437                        writeb(ClearExpired, dev->mmio + Group_1_Second_Clear);
 438                        async->events |= COMEDI_CB_EOA;
 439
 440                        writeb(0x00, dev->mmio + OpMode);
 441                        break;
 442                } else if (flags & Waited) {
 443                        writeb(ClearWaited, dev->mmio + Group_1_First_Clear);
 444                        async->events |= COMEDI_CB_ERROR;
 445                        break;
 446                } else if (flags & PrimaryTC) {
 447                        writeb(ClearPrimaryTC,
 448                               dev->mmio + Group_1_First_Clear);
 449                        async->events |= COMEDI_CB_EOA;
 450                } else if (flags & SecondaryTC) {
 451                        writeb(ClearSecondaryTC,
 452                               dev->mmio + Group_1_First_Clear);
 453                        async->events |= COMEDI_CB_EOA;
 454                }
 455
 456                flags = readb(dev->mmio + Group_1_Flags);
 457                status = readb(dev->mmio + Interrupt_And_Window_Status);
 458        }
 459
 460out:
 461        comedi_handle_events(dev, s);
 462#if 0
 463        if (!tag)
 464                writeb(0x03, dev->mmio + Master_DMA_And_Interrupt_Control);
 465#endif
 466
 467        spin_unlock(&dev->spinlock);
 468        return IRQ_HANDLED;
 469}
 470
 471static int ni_pcidio_insn_config(struct comedi_device *dev,
 472                                 struct comedi_subdevice *s,
 473                                 struct comedi_insn *insn,
 474                                 unsigned int *data)
 475{
 476        int ret;
 477
 478        ret = comedi_dio_insn_config(dev, s, insn, data, 0);
 479        if (ret)
 480                return ret;
 481
 482        writel(s->io_bits, dev->mmio + Port_Pin_Directions(0));
 483
 484        return insn->n;
 485}
 486
 487static int ni_pcidio_insn_bits(struct comedi_device *dev,
 488                               struct comedi_subdevice *s,
 489                               struct comedi_insn *insn,
 490                               unsigned int *data)
 491{
 492        if (comedi_dio_update_state(s, data))
 493                writel(s->state, dev->mmio + Port_IO(0));
 494
 495        data[1] = readl(dev->mmio + Port_IO(0));
 496
 497        return insn->n;
 498}
 499
 500static int ni_pcidio_ns_to_timer(int *nanosec, unsigned int flags)
 501{
 502        int divider, base;
 503
 504        base = TIMER_BASE;
 505
 506        switch (flags & CMDF_ROUND_MASK) {
 507        case CMDF_ROUND_NEAREST:
 508        default:
 509                divider = DIV_ROUND_CLOSEST(*nanosec, base);
 510                break;
 511        case CMDF_ROUND_DOWN:
 512                divider = (*nanosec) / base;
 513                break;
 514        case CMDF_ROUND_UP:
 515                divider = DIV_ROUND_UP(*nanosec, base);
 516                break;
 517        }
 518
 519        *nanosec = base * divider;
 520        return divider;
 521}
 522
 523static int ni_pcidio_cmdtest(struct comedi_device *dev,
 524                             struct comedi_subdevice *s, struct comedi_cmd *cmd)
 525{
 526        int err = 0;
 527        unsigned int arg;
 528
 529        /* Step 1 : check if triggers are trivially valid */
 530
 531        err |= comedi_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_INT);
 532        err |= comedi_check_trigger_src(&cmd->scan_begin_src,
 533                                        TRIG_TIMER | TRIG_EXT);
 534        err |= comedi_check_trigger_src(&cmd->convert_src, TRIG_NOW);
 535        err |= comedi_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
 536        err |= comedi_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE);
 537
 538        if (err)
 539                return 1;
 540
 541        /* Step 2a : make sure trigger sources are unique */
 542
 543        err |= comedi_check_trigger_is_unique(cmd->start_src);
 544        err |= comedi_check_trigger_is_unique(cmd->scan_begin_src);
 545        err |= comedi_check_trigger_is_unique(cmd->stop_src);
 546
 547        /* Step 2b : and mutually compatible */
 548
 549        if (err)
 550                return 2;
 551
 552        /* Step 3: check if arguments are trivially valid */
 553
 554        err |= comedi_check_trigger_arg_is(&cmd->start_arg, 0);
 555
 556#define MAX_SPEED       (TIMER_BASE)    /* in nanoseconds */
 557
 558        if (cmd->scan_begin_src == TRIG_TIMER) {
 559                err |= comedi_check_trigger_arg_min(&cmd->scan_begin_arg,
 560                                                    MAX_SPEED);
 561                /* no minimum speed */
 562        } else {
 563                /* TRIG_EXT */
 564                /* should be level/edge, hi/lo specification here */
 565                if ((cmd->scan_begin_arg & ~(CR_EDGE | CR_INVERT)) != 0) {
 566                        cmd->scan_begin_arg &= (CR_EDGE | CR_INVERT);
 567                        err |= -EINVAL;
 568                }
 569        }
 570
 571        err |= comedi_check_trigger_arg_is(&cmd->convert_arg, 0);
 572        err |= comedi_check_trigger_arg_is(&cmd->scan_end_arg,
 573                                           cmd->chanlist_len);
 574
 575        if (cmd->stop_src == TRIG_COUNT)
 576                err |= comedi_check_trigger_arg_min(&cmd->stop_arg, 1);
 577        else    /* TRIG_NONE */
 578                err |= comedi_check_trigger_arg_is(&cmd->stop_arg, 0);
 579
 580        if (err)
 581                return 3;
 582
 583        /* step 4: fix up any arguments */
 584
 585        if (cmd->scan_begin_src == TRIG_TIMER) {
 586                arg = cmd->scan_begin_arg;
 587                ni_pcidio_ns_to_timer(&arg, cmd->flags);
 588                err |= comedi_check_trigger_arg_is(&cmd->scan_begin_arg, arg);
 589        }
 590
 591        if (err)
 592                return 4;
 593
 594        return 0;
 595}
 596
 597static int ni_pcidio_inttrig(struct comedi_device *dev,
 598                             struct comedi_subdevice *s,
 599                             unsigned int trig_num)
 600{
 601        struct nidio96_private *devpriv = dev->private;
 602        struct comedi_cmd *cmd = &s->async->cmd;
 603
 604        if (trig_num != cmd->start_arg)
 605                return -EINVAL;
 606
 607        writeb(devpriv->OpModeBits, dev->mmio + OpMode);
 608        s->async->inttrig = NULL;
 609
 610        return 1;
 611}
 612
 613static int ni_pcidio_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 614{
 615        struct nidio96_private *devpriv = dev->private;
 616        struct comedi_cmd *cmd = &s->async->cmd;
 617
 618        /* XXX configure ports for input */
 619        writel(0x0000, dev->mmio + Port_Pin_Directions(0));
 620
 621        if (1) {
 622                /* enable fifos A B C D */
 623                writeb(0x0f, dev->mmio + Data_Path);
 624
 625                /* set transfer width a 32 bits */
 626                writeb(TransferWidth(0) | TransferLength(0),
 627                       dev->mmio + Transfer_Size_Control);
 628        } else {
 629                writeb(0x03, dev->mmio + Data_Path);
 630                writeb(TransferWidth(3) | TransferLength(0),
 631                       dev->mmio + Transfer_Size_Control);
 632        }
 633
 634        /* protocol configuration */
 635        if (cmd->scan_begin_src == TRIG_TIMER) {
 636                /* page 4-5, "input with internal REQs" */
 637                writeb(0, dev->mmio + OpMode);
 638                writeb(0x00, dev->mmio + ClockReg);
 639                writeb(1, dev->mmio + Sequence);
 640                writeb(0x04, dev->mmio + ReqReg);
 641                writeb(4, dev->mmio + BlockMode);
 642                writeb(3, dev->mmio + LinePolarities);
 643                writeb(0xc0, dev->mmio + AckSer);
 644                writel(ni_pcidio_ns_to_timer(&cmd->scan_begin_arg,
 645                                             CMDF_ROUND_NEAREST),
 646                       dev->mmio + StartDelay);
 647                writeb(1, dev->mmio + ReqDelay);
 648                writeb(1, dev->mmio + ReqNotDelay);
 649                writeb(1, dev->mmio + AckDelay);
 650                writeb(0x0b, dev->mmio + AckNotDelay);
 651                writeb(0x01, dev->mmio + Data1Delay);
 652                /* manual, page 4-5: ClockSpeed comment is incorrectly listed
 653                 * on DAQOptions */
 654                writew(0, dev->mmio + ClockSpeed);
 655                writeb(0, dev->mmio + DAQOptions);
 656        } else {
 657                /* TRIG_EXT */
 658                /* page 4-5, "input with external REQs" */
 659                writeb(0, dev->mmio + OpMode);
 660                writeb(0x00, dev->mmio + ClockReg);
 661                writeb(0, dev->mmio + Sequence);
 662                writeb(0x00, dev->mmio + ReqReg);
 663                writeb(4, dev->mmio + BlockMode);
 664                if (!(cmd->scan_begin_arg & CR_INVERT)) /* Leading Edge */
 665                        writeb(0, dev->mmio + LinePolarities);
 666                else                                    /* Trailing Edge */
 667                        writeb(2, dev->mmio + LinePolarities);
 668                writeb(0x00, dev->mmio + AckSer);
 669                writel(1, dev->mmio + StartDelay);
 670                writeb(1, dev->mmio + ReqDelay);
 671                writeb(1, dev->mmio + ReqNotDelay);
 672                writeb(1, dev->mmio + AckDelay);
 673                writeb(0x0C, dev->mmio + AckNotDelay);
 674                writeb(0x10, dev->mmio + Data1Delay);
 675                writew(0, dev->mmio + ClockSpeed);
 676                writeb(0x60, dev->mmio + DAQOptions);
 677        }
 678
 679        if (cmd->stop_src == TRIG_COUNT) {
 680                writel(cmd->stop_arg,
 681                       dev->mmio + Transfer_Count);
 682        } else {
 683                /* XXX */
 684        }
 685
 686#ifdef USE_DMA
 687        writeb(ClearPrimaryTC | ClearSecondaryTC,
 688               dev->mmio + Group_1_First_Clear);
 689
 690        {
 691                int retval = setup_mite_dma(dev, s);
 692
 693                if (retval)
 694                        return retval;
 695        }
 696#else
 697        writeb(0x00, dev->mmio + DMA_Line_Control_Group1);
 698#endif
 699        writeb(0x00, dev->mmio + DMA_Line_Control_Group2);
 700
 701        /* clear and enable interrupts */
 702        writeb(0xff, dev->mmio + Group_1_First_Clear);
 703        /* writeb(ClearExpired, dev->mmio+Group_1_Second_Clear); */
 704
 705        writeb(IntEn, dev->mmio + Interrupt_Control);
 706        writeb(0x03, dev->mmio + Master_DMA_And_Interrupt_Control);
 707
 708        if (cmd->stop_src == TRIG_NONE) {
 709                devpriv->OpModeBits = DataLatching(0) | RunMode(7);
 710        } else {                /* TRIG_TIMER */
 711                devpriv->OpModeBits = Numbered | RunMode(7);
 712        }
 713        if (cmd->start_src == TRIG_NOW) {
 714                /* start */
 715                writeb(devpriv->OpModeBits, dev->mmio + OpMode);
 716                s->async->inttrig = NULL;
 717        } else {
 718                /* TRIG_INT */
 719                s->async->inttrig = ni_pcidio_inttrig;
 720        }
 721
 722        return 0;
 723}
 724
 725static int ni_pcidio_cancel(struct comedi_device *dev,
 726                            struct comedi_subdevice *s)
 727{
 728        writeb(0x00, dev->mmio + Master_DMA_And_Interrupt_Control);
 729        ni_pcidio_release_di_mite_channel(dev);
 730
 731        return 0;
 732}
 733
 734static int ni_pcidio_change(struct comedi_device *dev,
 735                            struct comedi_subdevice *s)
 736{
 737        struct nidio96_private *devpriv = dev->private;
 738        int ret;
 739
 740        ret = mite_buf_change(devpriv->di_mite_ring, s);
 741        if (ret < 0)
 742                return ret;
 743
 744        memset(s->async->prealloc_buf, 0xaa, s->async->prealloc_bufsz);
 745
 746        return 0;
 747}
 748
 749static int pci_6534_load_fpga(struct comedi_device *dev,
 750                              const u8 *data, size_t data_len,
 751                              unsigned long context)
 752{
 753        static const int timeout = 1000;
 754        int fpga_index = context;
 755        int i;
 756        size_t j;
 757
 758        writew(0x80 | fpga_index, dev->mmio + Firmware_Control_Register);
 759        writew(0xc0 | fpga_index, dev->mmio + Firmware_Control_Register);
 760        for (i = 0;
 761             (readw(dev->mmio + Firmware_Status_Register) & 0x2) == 0 &&
 762             i < timeout; ++i) {
 763                udelay(1);
 764        }
 765        if (i == timeout) {
 766                dev_warn(dev->class_dev,
 767                         "ni_pcidio: failed to load fpga %i, waiting for status 0x2\n",
 768                         fpga_index);
 769                return -EIO;
 770        }
 771        writew(0x80 | fpga_index, dev->mmio + Firmware_Control_Register);
 772        for (i = 0;
 773             readw(dev->mmio + Firmware_Status_Register) != 0x3 &&
 774             i < timeout; ++i) {
 775                udelay(1);
 776        }
 777        if (i == timeout) {
 778                dev_warn(dev->class_dev,
 779                         "ni_pcidio: failed to load fpga %i, waiting for status 0x3\n",
 780                         fpga_index);
 781                return -EIO;
 782        }
 783        for (j = 0; j + 1 < data_len;) {
 784                unsigned int value = data[j++];
 785
 786                value |= data[j++] << 8;
 787                writew(value, dev->mmio + Firmware_Data_Register);
 788                for (i = 0;
 789                     (readw(dev->mmio + Firmware_Status_Register) & 0x2) == 0
 790                     && i < timeout; ++i) {
 791                        udelay(1);
 792                }
 793                if (i == timeout) {
 794                        dev_warn(dev->class_dev,
 795                                 "ni_pcidio: failed to load word into fpga %i\n",
 796                                 fpga_index);
 797                        return -EIO;
 798                }
 799                if (need_resched())
 800                        schedule();
 801        }
 802        writew(0x0, dev->mmio + Firmware_Control_Register);
 803        return 0;
 804}
 805
 806static int pci_6534_reset_fpga(struct comedi_device *dev, int fpga_index)
 807{
 808        return pci_6534_load_fpga(dev, NULL, 0, fpga_index);
 809}
 810
 811static int pci_6534_reset_fpgas(struct comedi_device *dev)
 812{
 813        int ret;
 814        int i;
 815
 816        writew(0x0, dev->mmio + Firmware_Control_Register);
 817        for (i = 0; i < 3; ++i) {
 818                ret = pci_6534_reset_fpga(dev, i);
 819                if (ret < 0)
 820                        break;
 821        }
 822        writew(0x0, dev->mmio + Firmware_Mask_Register);
 823        return ret;
 824}
 825
 826static void pci_6534_init_main_fpga(struct comedi_device *dev)
 827{
 828        writel(0, dev->mmio + FPGA_Control1_Register);
 829        writel(0, dev->mmio + FPGA_Control2_Register);
 830        writel(0, dev->mmio + FPGA_SCALS_Counter_Register);
 831        writel(0, dev->mmio + FPGA_SCAMS_Counter_Register);
 832        writel(0, dev->mmio + FPGA_SCBLS_Counter_Register);
 833        writel(0, dev->mmio + FPGA_SCBMS_Counter_Register);
 834}
 835
 836static int pci_6534_upload_firmware(struct comedi_device *dev)
 837{
 838        struct nidio96_private *devpriv = dev->private;
 839        static const char *const fw_file[3] = {
 840                FW_PCI_6534_SCARAB_DI,  /* loaded into scarab A for DI */
 841                FW_PCI_6534_SCARAB_DO,  /* loaded into scarab B for DO */
 842                FW_PCI_6534_MAIN,       /* loaded into main FPGA */
 843        };
 844        int ret;
 845        int n;
 846
 847        ret = pci_6534_reset_fpgas(dev);
 848        if (ret < 0)
 849                return ret;
 850        /* load main FPGA first, then the two scarabs */
 851        for (n = 2; n >= 0; n--) {
 852                ret = comedi_load_firmware(dev, &devpriv->mite->pcidev->dev,
 853                                           fw_file[n],
 854                                           pci_6534_load_fpga, n);
 855                if (ret == 0 && n == 2)
 856                        pci_6534_init_main_fpga(dev);
 857                if (ret < 0)
 858                        break;
 859        }
 860        return ret;
 861}
 862
 863static void nidio_reset_board(struct comedi_device *dev)
 864{
 865        writel(0, dev->mmio + Port_IO(0));
 866        writel(0, dev->mmio + Port_Pin_Directions(0));
 867        writel(0, dev->mmio + Port_Pin_Mask(0));
 868
 869        /* disable interrupts on board */
 870        writeb(0, dev->mmio + Master_DMA_And_Interrupt_Control);
 871}
 872
 873static int nidio_auto_attach(struct comedi_device *dev,
 874                             unsigned long context)
 875{
 876        struct pci_dev *pcidev = comedi_to_pci_dev(dev);
 877        const struct nidio_board *board = NULL;
 878        struct nidio96_private *devpriv;
 879        struct comedi_subdevice *s;
 880        int ret;
 881        unsigned int irq;
 882
 883        if (context < ARRAY_SIZE(nidio_boards))
 884                board = &nidio_boards[context];
 885        if (!board)
 886                return -ENODEV;
 887        dev->board_ptr = board;
 888        dev->board_name = board->name;
 889
 890        ret = comedi_pci_enable(dev);
 891        if (ret)
 892                return ret;
 893
 894        devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
 895        if (!devpriv)
 896                return -ENOMEM;
 897
 898        spin_lock_init(&devpriv->mite_channel_lock);
 899
 900        devpriv->mite = mite_attach(dev, false);        /* use win0 */
 901        if (!devpriv->mite)
 902                return -ENOMEM;
 903
 904        devpriv->di_mite_ring = mite_alloc_ring(devpriv->mite);
 905        if (!devpriv->di_mite_ring)
 906                return -ENOMEM;
 907
 908        if (board->uses_firmware) {
 909                ret = pci_6534_upload_firmware(dev);
 910                if (ret < 0)
 911                        return ret;
 912        }
 913
 914        nidio_reset_board(dev);
 915
 916        ret = comedi_alloc_subdevices(dev, 1);
 917        if (ret)
 918                return ret;
 919
 920        dev_info(dev->class_dev, "%s rev=%d\n", dev->board_name,
 921                 readb(dev->mmio + Chip_Version));
 922
 923        s = &dev->subdevices[0];
 924
 925        dev->read_subdev = s;
 926        s->type = COMEDI_SUBD_DIO;
 927        s->subdev_flags =
 928                SDF_READABLE | SDF_WRITABLE | SDF_LSAMPL | SDF_PACKED |
 929                SDF_CMD_READ;
 930        s->n_chan = 32;
 931        s->range_table = &range_digital;
 932        s->maxdata = 1;
 933        s->insn_config = &ni_pcidio_insn_config;
 934        s->insn_bits = &ni_pcidio_insn_bits;
 935        s->do_cmd = &ni_pcidio_cmd;
 936        s->do_cmdtest = &ni_pcidio_cmdtest;
 937        s->cancel = &ni_pcidio_cancel;
 938        s->len_chanlist = 32;   /* XXX */
 939        s->buf_change = &ni_pcidio_change;
 940        s->async_dma_dir = DMA_BIDIRECTIONAL;
 941        s->poll = &ni_pcidio_poll;
 942
 943        irq = pcidev->irq;
 944        if (irq) {
 945                ret = request_irq(irq, nidio_interrupt, IRQF_SHARED,
 946                                  dev->board_name, dev);
 947                if (ret == 0)
 948                        dev->irq = irq;
 949        }
 950
 951        return 0;
 952}
 953
 954static void nidio_detach(struct comedi_device *dev)
 955{
 956        struct nidio96_private *devpriv = dev->private;
 957
 958        if (dev->irq)
 959                free_irq(dev->irq, dev);
 960        if (devpriv) {
 961                if (devpriv->di_mite_ring) {
 962                        mite_free_ring(devpriv->di_mite_ring);
 963                        devpriv->di_mite_ring = NULL;
 964                }
 965                mite_detach(devpriv->mite);
 966        }
 967        if (dev->mmio)
 968                iounmap(dev->mmio);
 969        comedi_pci_disable(dev);
 970}
 971
 972static struct comedi_driver ni_pcidio_driver = {
 973        .driver_name    = "ni_pcidio",
 974        .module         = THIS_MODULE,
 975        .auto_attach    = nidio_auto_attach,
 976        .detach         = nidio_detach,
 977};
 978
 979static int ni_pcidio_pci_probe(struct pci_dev *dev,
 980                               const struct pci_device_id *id)
 981{
 982        return comedi_pci_auto_config(dev, &ni_pcidio_driver, id->driver_data);
 983}
 984
 985static const struct pci_device_id ni_pcidio_pci_table[] = {
 986        { PCI_VDEVICE(NI, 0x1150), BOARD_PCIDIO_32HS },
 987        { PCI_VDEVICE(NI, 0x12b0), BOARD_PCI6534 },
 988        { PCI_VDEVICE(NI, 0x1320), BOARD_PXI6533 },
 989        { 0 }
 990};
 991MODULE_DEVICE_TABLE(pci, ni_pcidio_pci_table);
 992
 993static struct pci_driver ni_pcidio_pci_driver = {
 994        .name           = "ni_pcidio",
 995        .id_table       = ni_pcidio_pci_table,
 996        .probe          = ni_pcidio_pci_probe,
 997        .remove         = comedi_pci_auto_unconfig,
 998};
 999module_comedi_pci_driver(ni_pcidio_driver, ni_pcidio_pci_driver);
1000
1001MODULE_AUTHOR("Comedi http://www.comedi.org");
1002MODULE_DESCRIPTION("Comedi low-level driver");
1003MODULE_LICENSE("GPL");
1004
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.