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 "../comedidev.h"
  57
  58#include "comedi_fc.h"
  59#include "mite.h"
  60
  61/* defines for the PCI-DIO-32HS */
  62
  63#define Window_Address                  4       /* W */
  64#define Interrupt_And_Window_Status     4       /* R */
  65#define IntStatus1                              (1<<0)
  66#define IntStatus2                              (1<<1)
  67#define WindowAddressStatus_mask                0x7c
  68
  69#define Master_DMA_And_Interrupt_Control 5      /* W */
  70#define InterruptLine(x)                        ((x)&3)
  71#define OpenInt                         (1<<2)
  72#define Group_Status                    5       /* R */
  73#define DataLeft                                (1<<0)
  74#define Req                                     (1<<2)
  75#define StopTrig                                (1<<3)
  76
  77#define Group_1_Flags                   6       /* R */
  78#define Group_2_Flags                   7       /* R */
  79#define TransferReady                           (1<<0)
  80#define CountExpired                            (1<<1)
  81#define Waited                          (1<<5)
  82#define PrimaryTC                               (1<<6)
  83#define SecondaryTC                             (1<<7)
  84  /* #define SerialRose */
  85  /* #define ReqRose */
  86  /* #define Paused */
  87
  88#define Group_1_First_Clear             6       /* W */
  89#define Group_2_First_Clear             7       /* W */
  90#define ClearWaited                             (1<<3)
  91#define ClearPrimaryTC                  (1<<4)
  92#define ClearSecondaryTC                        (1<<5)
  93#define DMAReset                                (1<<6)
  94#define FIFOReset                               (1<<7)
  95#define ClearAll                                0xf8
  96
  97#define Group_1_FIFO                    8       /* W */
  98#define Group_2_FIFO                    12      /* W */
  99
 100#define Transfer_Count                  20
 101#define Chip_ID_D                       24
 102#define Chip_ID_I                       25
 103#define Chip_ID_O                       26
 104#define Chip_Version                    27
 105#define Port_IO(x)                      (28+(x))
 106#define Port_Pin_Directions(x)          (32+(x))
 107#define Port_Pin_Mask(x)                (36+(x))
 108#define Port_Pin_Polarities(x)          (40+(x))
 109
 110#define Master_Clock_Routing            45
 111#define RTSIClocking(x)                 (((x)&3)<<4)
 112
 113#define Group_1_Second_Clear            46      /* W */
 114#define Group_2_Second_Clear            47      /* W */
 115#define ClearExpired                            (1<<0)
 116
 117#define Port_Pattern(x)                 (48+(x))
 118
 119#define Data_Path                       64
 120#define FIFOEnableA             (1<<0)
 121#define FIFOEnableB             (1<<1)
 122#define FIFOEnableC             (1<<2)
 123#define FIFOEnableD             (1<<3)
 124#define Funneling(x)            (((x)&3)<<4)
 125#define GroupDirection  (1<<7)
 126
 127#define Protocol_Register_1             65
 128#define OpMode                          Protocol_Register_1
 129#define RunMode(x)              ((x)&7)
 130#define Numbered                (1<<3)
 131
 132#define Protocol_Register_2             66
 133#define ClockReg                        Protocol_Register_2
 134#define ClockLine(x)            (((x)&3)<<5)
 135#define InvertStopTrig  (1<<7)
 136#define DataLatching(x)       (((x)&3)<<5)
 137
 138#define Protocol_Register_3             67
 139#define Sequence                        Protocol_Register_3
 140
 141#define Protocol_Register_14            68      /* 16 bit */
 142#define ClockSpeed                      Protocol_Register_14
 143
 144#define Protocol_Register_4             70
 145#define ReqReg                          Protocol_Register_4
 146#define ReqConditioning(x)      (((x)&7)<<3)
 147
 148#define Protocol_Register_5             71
 149#define BlockMode                       Protocol_Register_5
 150
 151#define FIFO_Control                    72
 152#define ReadyLevel(x)           ((x)&7)
 153
 154#define Protocol_Register_6             73
 155#define LinePolarities                  Protocol_Register_6
 156#define InvertAck               (1<<0)
 157#define InvertReq               (1<<1)
 158#define InvertClock             (1<<2)
 159#define InvertSerial            (1<<3)
 160#define OpenAck         (1<<4)
 161#define OpenClock               (1<<5)
 162
 163#define Protocol_Register_7             74
 164#define AckSer                          Protocol_Register_7
 165#define AckLine(x)              (((x)&3)<<2)
 166#define ExchangePins            (1<<7)
 167
 168#define Interrupt_Control               75
 169  /* bits same as flags */
 170
 171#define DMA_Line_Control_Group1         76
 172#define DMA_Line_Control_Group2         108
 173/* channel zero is none */
 174static inline unsigned primary_DMAChannel_bits(unsigned channel)
 175{
 176        return channel & 0x3;
 177}
 178
 179static inline unsigned secondary_DMAChannel_bits(unsigned channel)
 180{
 181        return (channel << 2) & 0xc;
 182}
 183
 184#define Transfer_Size_Control           77
 185#define TransferWidth(x)        ((x)&3)
 186#define TransferLength(x)       (((x)&3)<<3)
 187#define RequireRLevel           (1<<5)
 188
 189#define Protocol_Register_15            79
 190#define DAQOptions                      Protocol_Register_15
 191#define StartSource(x)                  ((x)&0x3)
 192#define InvertStart                             (1<<2)
 193#define StopSource(x)                           (((x)&0x3)<<3)
 194#define ReqStart                                (1<<6)
 195#define PreStart                                (1<<7)
 196
 197#define Pattern_Detection               81
 198#define DetectionMethod                 (1<<0)
 199#define InvertMatch                             (1<<1)
 200#define IE_Pattern_Detection                    (1<<2)
 201
 202#define Protocol_Register_9             82
 203#define ReqDelay                        Protocol_Register_9
 204
 205#define Protocol_Register_10            83
 206#define ReqNotDelay                     Protocol_Register_10
 207
 208#define Protocol_Register_11            84
 209#define AckDelay                        Protocol_Register_11
 210
 211#define Protocol_Register_12            85
 212#define AckNotDelay                     Protocol_Register_12
 213
 214#define Protocol_Register_13            86
 215#define Data1Delay                      Protocol_Register_13
 216
 217#define Protocol_Register_8             88      /* 32 bit */
 218#define StartDelay                      Protocol_Register_8
 219
 220/* Firmware files for PCI-6524 */
 221#define FW_PCI_6534_MAIN                "ni6534a.bin"
 222#define FW_PCI_6534_SCARAB_DI           "niscrb01.bin"
 223#define FW_PCI_6534_SCARAB_DO           "niscrb02.bin"
 224MODULE_FIRMWARE(FW_PCI_6534_MAIN);
 225MODULE_FIRMWARE(FW_PCI_6534_SCARAB_DI);
 226MODULE_FIRMWARE(FW_PCI_6534_SCARAB_DO);
 227
 228enum pci_6534_firmware_registers {      /* 16 bit */
 229        Firmware_Control_Register = 0x100,
 230        Firmware_Status_Register = 0x104,
 231        Firmware_Data_Register = 0x108,
 232        Firmware_Mask_Register = 0x10c,
 233        Firmware_Debug_Register = 0x110,
 234};
 235/* main fpga registers (32 bit)*/
 236enum pci_6534_fpga_registers {
 237        FPGA_Control1_Register = 0x200,
 238        FPGA_Control2_Register = 0x204,
 239        FPGA_Irq_Mask_Register = 0x208,
 240        FPGA_Status_Register = 0x20c,
 241        FPGA_Signature_Register = 0x210,
 242        FPGA_SCALS_Counter_Register = 0x280,    /*write-clear */
 243        FPGA_SCAMS_Counter_Register = 0x284,    /*write-clear */
 244        FPGA_SCBLS_Counter_Register = 0x288,    /*write-clear */
 245        FPGA_SCBMS_Counter_Register = 0x28c,    /*write-clear */
 246        FPGA_Temp_Control_Register = 0x2a0,
 247        FPGA_DAR_Register = 0x2a8,
 248        FPGA_ELC_Read_Register = 0x2b8,
 249        FPGA_ELC_Write_Register = 0x2bc,
 250};
 251enum FPGA_Control_Bits {
 252        FPGA_Enable_Bit = 0x8000,
 253};
 254
 255#define TIMER_BASE 50           /* nanoseconds */
 256
 257#ifdef USE_DMA
 258#define IntEn (CountExpired|Waited|PrimaryTC|SecondaryTC)
 259#else
 260#define IntEn (TransferReady|CountExpired|Waited|PrimaryTC|SecondaryTC)
 261#endif
 262
 263enum nidio_boardid {
 264        BOARD_PCIDIO_32HS,
 265        BOARD_PXI6533,
 266        BOARD_PCI6534,
 267};
 268
 269struct nidio_board {
 270        const char *name;
 271        unsigned int uses_firmware:1;
 272};
 273
 274static const struct nidio_board nidio_boards[] = {
 275        [BOARD_PCIDIO_32HS] = {
 276                .name           = "pci-dio-32hs",
 277        },
 278        [BOARD_PXI6533] = {
 279                .name           = "pxi-6533",
 280        },
 281        [BOARD_PCI6534] = {
 282                .name           = "pci-6534",
 283                .uses_firmware  = 1,
 284        },
 285};
 286
 287struct nidio96_private {
 288        struct mite_struct *mite;
 289        int boardtype;
 290        int dio;
 291        unsigned short OpModeBits;
 292        struct mite_channel *di_mite_chan;
 293        struct mite_dma_descriptor_ring *di_mite_ring;
 294        spinlock_t mite_channel_lock;
 295};
 296
 297static int ni_pcidio_request_di_mite_channel(struct comedi_device *dev)
 298{
 299        struct nidio96_private *devpriv = dev->private;
 300        unsigned long flags;
 301
 302        spin_lock_irqsave(&devpriv->mite_channel_lock, flags);
 303        BUG_ON(devpriv->di_mite_chan);
 304        devpriv->di_mite_chan =
 305            mite_request_channel_in_range(devpriv->mite,
 306                                          devpriv->di_mite_ring, 1, 2);
 307        if (devpriv->di_mite_chan == NULL) {
 308                spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags);
 309                dev_err(dev->class_dev, "failed to reserve mite dma channel\n");
 310                return -EBUSY;
 311        }
 312        devpriv->di_mite_chan->dir = COMEDI_INPUT;
 313        writeb(primary_DMAChannel_bits(devpriv->di_mite_chan->channel) |
 314               secondary_DMAChannel_bits(devpriv->di_mite_chan->channel),
 315               dev->mmio + DMA_Line_Control_Group1);
 316        mmiowb();
 317        spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags);
 318        return 0;
 319}
 320
 321static void ni_pcidio_release_di_mite_channel(struct comedi_device *dev)
 322{
 323        struct nidio96_private *devpriv = dev->private;
 324        unsigned long flags;
 325
 326        spin_lock_irqsave(&devpriv->mite_channel_lock, flags);
 327        if (devpriv->di_mite_chan) {
 328                mite_dma_disarm(devpriv->di_mite_chan);
 329                mite_dma_reset(devpriv->di_mite_chan);
 330                mite_release_channel(devpriv->di_mite_chan);
 331                devpriv->di_mite_chan = NULL;
 332                writeb(primary_DMAChannel_bits(0) |
 333                       secondary_DMAChannel_bits(0),
 334                       dev->mmio + DMA_Line_Control_Group1);
 335                mmiowb();
 336        }
 337        spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags);
 338}
 339
 340static int setup_mite_dma(struct comedi_device *dev, struct comedi_subdevice *s)
 341{
 342        struct nidio96_private *devpriv = dev->private;
 343        int retval;
 344        unsigned long flags;
 345
 346        retval = ni_pcidio_request_di_mite_channel(dev);
 347        if (retval)
 348                return retval;
 349
 350        /* write alloc the entire buffer */
 351        comedi_buf_write_alloc(s, s->async->prealloc_bufsz);
 352
 353        spin_lock_irqsave(&devpriv->mite_channel_lock, flags);
 354        if (devpriv->di_mite_chan) {
 355                mite_prep_dma(devpriv->di_mite_chan, 32, 32);
 356                mite_dma_arm(devpriv->di_mite_chan);
 357        } else
 358                retval = -EIO;
 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_EOA | 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_EOA | 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 = (*nanosec + base / 2) / base;
 529                break;
 530        case CMDF_ROUND_DOWN:
 531                divider = (*nanosec) / base;
 532                break;
 533        case CMDF_ROUND_UP:
 534                divider = (*nanosec + base - 1) / 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 |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_INT);
 551        err |= cfc_check_trigger_src(&cmd->scan_begin_src,
 552                                        TRIG_TIMER | TRIG_EXT);
 553        err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_NOW);
 554        err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
 555        err |= cfc_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 |= cfc_check_trigger_is_unique(cmd->start_src);
 563        err |= cfc_check_trigger_is_unique(cmd->scan_begin_src);
 564        err |= cfc_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 |= cfc_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 |= cfc_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 |= cfc_check_trigger_arg_is(&cmd->convert_arg, 0);
 591        err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
 592
 593        if (cmd->stop_src == TRIG_COUNT)
 594                err |= cfc_check_trigger_arg_min(&cmd->stop_arg, 1);
 595        else    /* TRIG_NONE */
 596                err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
 597
 598        if (err)
 599                return 3;
 600
 601        /* step 4: fix up any arguments */
 602
 603        if (cmd->scan_begin_src == TRIG_TIMER) {
 604                arg = cmd->scan_begin_arg;
 605                ni_pcidio_ns_to_timer(&arg, cmd->flags);
 606                err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, arg);
 607        }
 608
 609        if (err)
 610                return 4;
 611
 612        return 0;
 613}
 614
 615static int ni_pcidio_inttrig(struct comedi_device *dev,
 616                             struct comedi_subdevice *s,
 617                             unsigned int trig_num)
 618{
 619        struct nidio96_private *devpriv = dev->private;
 620        struct comedi_cmd *cmd = &s->async->cmd;
 621
 622        if (trig_num != cmd->start_arg)
 623                return -EINVAL;
 624
 625        writeb(devpriv->OpModeBits, dev->mmio + OpMode);
 626        s->async->inttrig = NULL;
 627
 628        return 1;
 629}
 630
 631static int ni_pcidio_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 632{
 633        struct nidio96_private *devpriv = dev->private;
 634        struct comedi_cmd *cmd = &s->async->cmd;
 635
 636        /* XXX configure ports for input */
 637        writel(0x0000, dev->mmio + Port_Pin_Directions(0));
 638
 639        if (1) {
 640                /* enable fifos A B C D */
 641                writeb(0x0f, dev->mmio + Data_Path);
 642
 643                /* set transfer width a 32 bits */
 644                writeb(TransferWidth(0) | TransferLength(0),
 645                       dev->mmio + Transfer_Size_Control);
 646        } else {
 647                writeb(0x03, dev->mmio + Data_Path);
 648                writeb(TransferWidth(3) | TransferLength(0),
 649                       dev->mmio + Transfer_Size_Control);
 650        }
 651
 652        /* protocol configuration */
 653        if (cmd->scan_begin_src == TRIG_TIMER) {
 654                /* page 4-5, "input with internal REQs" */
 655                writeb(0, dev->mmio + OpMode);
 656                writeb(0x00, dev->mmio + ClockReg);
 657                writeb(1, dev->mmio + Sequence);
 658                writeb(0x04, dev->mmio + ReqReg);
 659                writeb(4, dev->mmio + BlockMode);
 660                writeb(3, dev->mmio + LinePolarities);
 661                writeb(0xc0, dev->mmio + AckSer);
 662                writel(ni_pcidio_ns_to_timer(&cmd->scan_begin_arg,
 663                                             CMDF_ROUND_NEAREST),
 664                       dev->mmio + StartDelay);
 665                writeb(1, dev->mmio + ReqDelay);
 666                writeb(1, dev->mmio + ReqNotDelay);
 667                writeb(1, dev->mmio + AckDelay);
 668                writeb(0x0b, dev->mmio + AckNotDelay);
 669                writeb(0x01, dev->mmio + Data1Delay);
 670                /* manual, page 4-5: ClockSpeed comment is incorrectly listed
 671                 * on DAQOptions */
 672                writew(0, dev->mmio + ClockSpeed);
 673                writeb(0, dev->mmio + DAQOptions);
 674        } else {
 675                /* TRIG_EXT */
 676                /* page 4-5, "input with external REQs" */
 677                writeb(0, dev->mmio + OpMode);
 678                writeb(0x00, dev->mmio + ClockReg);
 679                writeb(0, dev->mmio + Sequence);
 680                writeb(0x00, dev->mmio + ReqReg);
 681                writeb(4, dev->mmio + BlockMode);
 682                if (!(cmd->scan_begin_arg & CR_INVERT)) /* Leading Edge */
 683                        writeb(0, dev->mmio + LinePolarities);
 684                else                                    /* Trailing Edge */
 685                        writeb(2, dev->mmio + LinePolarities);
 686                writeb(0x00, dev->mmio + AckSer);
 687                writel(1, dev->mmio + StartDelay);
 688                writeb(1, dev->mmio + ReqDelay);
 689                writeb(1, dev->mmio + ReqNotDelay);
 690                writeb(1, dev->mmio + AckDelay);
 691                writeb(0x0C, dev->mmio + AckNotDelay);
 692                writeb(0x10, dev->mmio + Data1Delay);
 693                writew(0, dev->mmio + ClockSpeed);
 694                writeb(0x60, dev->mmio + DAQOptions);
 695        }
 696
 697        if (cmd->stop_src == TRIG_COUNT) {
 698                writel(cmd->stop_arg,
 699                       dev->mmio + Transfer_Count);
 700        } else {
 701                /* XXX */
 702        }
 703
 704#ifdef USE_DMA
 705        writeb(ClearPrimaryTC | ClearSecondaryTC,
 706               dev->mmio + Group_1_First_Clear);
 707
 708        {
 709                int retval = setup_mite_dma(dev, s);
 710
 711                if (retval)
 712                        return retval;
 713        }
 714#else
 715        writeb(0x00, dev->mmio + DMA_Line_Control_Group1);
 716#endif
 717        writeb(0x00, dev->mmio + DMA_Line_Control_Group2);
 718
 719        /* clear and enable interrupts */
 720        writeb(0xff, dev->mmio + Group_1_First_Clear);
 721        /* writeb(ClearExpired, dev->mmio+Group_1_Second_Clear); */
 722
 723        writeb(IntEn, dev->mmio + Interrupt_Control);
 724        writeb(0x03, dev->mmio + Master_DMA_And_Interrupt_Control);
 725
 726        if (cmd->stop_src == TRIG_NONE) {
 727                devpriv->OpModeBits = DataLatching(0) | RunMode(7);
 728        } else {                /* TRIG_TIMER */
 729                devpriv->OpModeBits = Numbered | RunMode(7);
 730        }
 731        if (cmd->start_src == TRIG_NOW) {
 732                /* start */
 733                writeb(devpriv->OpModeBits, dev->mmio + OpMode);
 734                s->async->inttrig = NULL;
 735        } else {
 736                /* TRIG_INT */
 737                s->async->inttrig = ni_pcidio_inttrig;
 738        }
 739
 740        return 0;
 741}
 742
 743static int ni_pcidio_cancel(struct comedi_device *dev,
 744                            struct comedi_subdevice *s)
 745{
 746        writeb(0x00, dev->mmio + Master_DMA_And_Interrupt_Control);
 747        ni_pcidio_release_di_mite_channel(dev);
 748
 749        return 0;
 750}
 751
 752static int ni_pcidio_change(struct comedi_device *dev,
 753                            struct comedi_subdevice *s)
 754{
 755        struct nidio96_private *devpriv = dev->private;
 756        int ret;
 757
 758        ret = mite_buf_change(devpriv->di_mite_ring, s);
 759        if (ret < 0)
 760                return ret;
 761
 762        memset(s->async->prealloc_buf, 0xaa, s->async->prealloc_bufsz);
 763
 764        return 0;
 765}
 766
 767static int pci_6534_load_fpga(struct comedi_device *dev,
 768                              const u8 *data, size_t data_len,
 769                              unsigned long context)
 770{
 771        static const int timeout = 1000;
 772        int fpga_index = context;
 773        int i;
 774        size_t j;
 775
 776        writew(0x80 | fpga_index, dev->mmio + Firmware_Control_Register);
 777        writew(0xc0 | fpga_index, dev->mmio + Firmware_Control_Register);
 778        for (i = 0;
 779             (readw(dev->mmio + Firmware_Status_Register) & 0x2) == 0 &&
 780             i < timeout; ++i) {
 781                udelay(1);
 782        }
 783        if (i == timeout) {
 784                dev_warn(dev->class_dev,
 785                         "ni_pcidio: failed to load fpga %i, waiting for status 0x2\n",
 786                         fpga_index);
 787                return -EIO;
 788        }
 789        writew(0x80 | fpga_index, dev->mmio + Firmware_Control_Register);
 790        for (i = 0;
 791             readw(dev->mmio + Firmware_Status_Register) != 0x3 &&
 792             i < timeout; ++i) {
 793                udelay(1);
 794        }
 795        if (i == timeout) {
 796                dev_warn(dev->class_dev,
 797                         "ni_pcidio: failed to load fpga %i, waiting for status 0x3\n",
 798                         fpga_index);
 799                return -EIO;
 800        }
 801        for (j = 0; j + 1 < data_len;) {
 802                unsigned int value = data[j++];
 803
 804                value |= data[j++] << 8;
 805                writew(value, dev->mmio + Firmware_Data_Register);
 806                for (i = 0;
 807                     (readw(dev->mmio + Firmware_Status_Register) & 0x2) == 0
 808                     && i < timeout; ++i) {
 809                        udelay(1);
 810                }
 811                if (i == timeout) {
 812                        dev_warn(dev->class_dev,
 813                                 "ni_pcidio: failed to load word into fpga %i\n",
 814                                 fpga_index);
 815                        return -EIO;
 816                }
 817                if (need_resched())
 818                        schedule();
 819        }
 820        writew(0x0, dev->mmio + Firmware_Control_Register);
 821        return 0;
 822}
 823
 824static int pci_6534_reset_fpga(struct comedi_device *dev, int fpga_index)
 825{
 826        return pci_6534_load_fpga(dev, NULL, 0, fpga_index);
 827}
 828
 829static int pci_6534_reset_fpgas(struct comedi_device *dev)
 830{
 831        int ret;
 832        int i;
 833
 834        writew(0x0, dev->mmio + Firmware_Control_Register);
 835        for (i = 0; i < 3; ++i) {
 836                ret = pci_6534_reset_fpga(dev, i);
 837                if (ret < 0)
 838                        break;
 839        }
 840        writew(0x0, dev->mmio + Firmware_Mask_Register);
 841        return ret;
 842}
 843
 844static void pci_6534_init_main_fpga(struct comedi_device *dev)
 845{
 846        writel(0, dev->mmio + FPGA_Control1_Register);
 847        writel(0, dev->mmio + FPGA_Control2_Register);
 848        writel(0, dev->mmio + FPGA_SCALS_Counter_Register);
 849        writel(0, dev->mmio + FPGA_SCAMS_Counter_Register);
 850        writel(0, dev->mmio + FPGA_SCBLS_Counter_Register);
 851        writel(0, dev->mmio + FPGA_SCBMS_Counter_Register);
 852}
 853
 854static int pci_6534_upload_firmware(struct comedi_device *dev)
 855{
 856        struct nidio96_private *devpriv = dev->private;
 857        static const char *const fw_file[3] = {
 858                FW_PCI_6534_SCARAB_DI,  /* loaded into scarab A for DI */
 859                FW_PCI_6534_SCARAB_DO,  /* loaded into scarab B for DO */
 860                FW_PCI_6534_MAIN,       /* loaded into main FPGA */
 861        };
 862        int ret;
 863        int n;
 864
 865        ret = pci_6534_reset_fpgas(dev);
 866        if (ret < 0)
 867                return ret;
 868        /* load main FPGA first, then the two scarabs */
 869        for (n = 2; n >= 0; n--) {
 870                ret = comedi_load_firmware(dev, &devpriv->mite->pcidev->dev,
 871                                           fw_file[n],
 872                                           pci_6534_load_fpga, n);
 873                if (ret == 0 && n == 2)
 874                        pci_6534_init_main_fpga(dev);
 875                if (ret < 0)
 876                        break;
 877        }
 878        return ret;
 879}
 880
 881static void nidio_reset_board(struct comedi_device *dev)
 882{
 883        writel(0, dev->mmio + Port_IO(0));
 884        writel(0, dev->mmio + Port_Pin_Directions(0));
 885        writel(0, dev->mmio + Port_Pin_Mask(0));
 886
 887        /* disable interrupts on board */
 888        writeb(0, dev->mmio + Master_DMA_And_Interrupt_Control);
 889}
 890
 891static int nidio_auto_attach(struct comedi_device *dev,
 892                             unsigned long context)
 893{
 894        struct pci_dev *pcidev = comedi_to_pci_dev(dev);
 895        const struct nidio_board *board = NULL;
 896        struct nidio96_private *devpriv;
 897        struct comedi_subdevice *s;
 898        int ret;
 899        unsigned int irq;
 900
 901        if (context < ARRAY_SIZE(nidio_boards))
 902                board = &nidio_boards[context];
 903        if (!board)
 904                return -ENODEV;
 905        dev->board_ptr = board;
 906        dev->board_name = board->name;
 907
 908        ret = comedi_pci_enable(dev);
 909        if (ret)
 910                return ret;
 911
 912        devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
 913        if (!devpriv)
 914                return -ENOMEM;
 915
 916        spin_lock_init(&devpriv->mite_channel_lock);
 917
 918        devpriv->mite = mite_alloc(pcidev);
 919        if (!devpriv->mite)
 920                return -ENOMEM;
 921
 922        ret = mite_setup(dev, devpriv->mite);
 923        if (ret < 0)
 924                return ret;
 925
 926        devpriv->di_mite_ring = mite_alloc_ring(devpriv->mite);
 927        if (devpriv->di_mite_ring == NULL)
 928                return -ENOMEM;
 929
 930        if (board->uses_firmware) {
 931                ret = pci_6534_upload_firmware(dev);
 932                if (ret < 0)
 933                        return ret;
 934        }
 935
 936        nidio_reset_board(dev);
 937
 938        ret = comedi_alloc_subdevices(dev, 1);
 939        if (ret)
 940                return ret;
 941
 942        dev_info(dev->class_dev, "%s rev=%d\n", dev->board_name,
 943                 readb(dev->mmio + Chip_Version));
 944
 945        s = &dev->subdevices[0];
 946
 947        dev->read_subdev = s;
 948        s->type = COMEDI_SUBD_DIO;
 949        s->subdev_flags =
 950                SDF_READABLE | SDF_WRITABLE | SDF_LSAMPL | SDF_PACKED |
 951                SDF_CMD_READ;
 952        s->n_chan = 32;
 953        s->range_table = &range_digital;
 954        s->maxdata = 1;
 955        s->insn_config = &ni_pcidio_insn_config;
 956        s->insn_bits = &ni_pcidio_insn_bits;
 957        s->do_cmd = &ni_pcidio_cmd;
 958        s->do_cmdtest = &ni_pcidio_cmdtest;
 959        s->cancel = &ni_pcidio_cancel;
 960        s->len_chanlist = 32;   /* XXX */
 961        s->buf_change = &ni_pcidio_change;
 962        s->async_dma_dir = DMA_BIDIRECTIONAL;
 963        s->poll = &ni_pcidio_poll;
 964
 965        irq = pcidev->irq;
 966        if (irq) {
 967                ret = request_irq(irq, nidio_interrupt, IRQF_SHARED,
 968                                  dev->board_name, dev);
 969                if (ret == 0)
 970                        dev->irq = irq;
 971        }
 972
 973        return 0;
 974}
 975
 976static void nidio_detach(struct comedi_device *dev)
 977{
 978        struct nidio96_private *devpriv = dev->private;
 979
 980        if (dev->irq)
 981                free_irq(dev->irq, dev);
 982        if (devpriv) {
 983                if (devpriv->di_mite_ring) {
 984                        mite_free_ring(devpriv->di_mite_ring);
 985                        devpriv->di_mite_ring = NULL;
 986                }
 987                mite_detach(devpriv->mite);
 988        }
 989        if (dev->mmio)
 990                iounmap(dev->mmio);
 991        comedi_pci_disable(dev);
 992}
 993
 994static struct comedi_driver ni_pcidio_driver = {
 995        .driver_name    = "ni_pcidio",
 996        .module         = THIS_MODULE,
 997        .auto_attach    = nidio_auto_attach,
 998        .detach         = nidio_detach,
 999};
1000
1001static int ni_pcidio_pci_probe(struct pci_dev *dev,
1002                               const struct pci_device_id *id)
1003{
1004        return comedi_pci_auto_config(dev, &ni_pcidio_driver, id->driver_data);
1005}
1006
1007static const struct pci_device_id ni_pcidio_pci_table[] = {
1008        { PCI_VDEVICE(NI, 0x1150), BOARD_PCIDIO_32HS },
1009        { PCI_VDEVICE(NI, 0x12b0), BOARD_PCI6534 },
1010        { PCI_VDEVICE(NI, 0x1320), BOARD_PXI6533 },
1011        { 0 }
1012};
1013MODULE_DEVICE_TABLE(pci, ni_pcidio_pci_table);
1014
1015static struct pci_driver ni_pcidio_pci_driver = {
1016        .name           = "ni_pcidio",
1017        .id_table       = ni_pcidio_pci_table,
1018        .probe          = ni_pcidio_pci_probe,
1019        .remove         = comedi_pci_auto_unconfig,
1020};
1021module_comedi_pci_driver(ni_pcidio_driver, ni_pcidio_pci_driver);
1022
1023MODULE_AUTHOR("Comedi http://www.comedi.org");
1024MODULE_DESCRIPTION("Comedi low-level driver");
1025MODULE_LICENSE("GPL");
1026
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.