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