linux/drivers/staging/comedi/drivers/adl_pci9118.c
<<
>>
Prefs
   1/*
   2 *  comedi/drivers/adl_pci9118.c
   3 *
   4 *  hardware driver for ADLink cards:
   5 *   card:   PCI-9118DG, PCI-9118HG, PCI-9118HR
   6 *   driver: pci9118dg,  pci9118hg,  pci9118hr
   7 *
   8 * Author: Michal Dobes <dobes@tesnet.cz>
   9 *
  10 */
  11
  12/*
  13 * Driver: adl_pci9118
  14 * Description: Adlink PCI-9118DG, PCI-9118HG, PCI-9118HR
  15 * Author: Michal Dobes <dobes@tesnet.cz>
  16 * Devices: [ADLink] PCI-9118DG (pci9118dg), PCI-9118HG (pci9118hg),
  17 * PCI-9118HR (pci9118hr)
  18 * Status: works
  19 *
  20 * This driver supports AI, AO, DI and DO subdevices.
  21 * AI subdevice supports cmd and insn interface,
  22 * other subdevices support only insn interface.
  23 * For AI:
  24 * - If cmd->scan_begin_src=TRIG_EXT then trigger input is TGIN (pin 46).
  25 * - If cmd->convert_src=TRIG_EXT then trigger input is EXTTRG (pin 44).
  26 * - If cmd->start_src/stop_src=TRIG_EXT then trigger input is TGIN (pin 46).
  27 * - It is not necessary to have cmd.scan_end_arg=cmd.chanlist_len but
  28 * cmd.scan_end_arg modulo cmd.chanlist_len must by 0.
  29 * - If return value of cmdtest is 5 then you've bad channel list
  30 * (it isn't possible mixture S.E. and DIFF inputs or bipolar and unipolar
  31 * ranges).
  32 *
  33 * There are some hardware limitations:
  34 * a) You cann't use mixture of unipolar/bipoar ranges or differencial/single
  35 *  ended inputs.
  36 * b) DMA transfers must have the length aligned to two samples (32 bit),
  37 *  so there is some problems if cmd->chanlist_len is odd. This driver tries
  38 *  bypass this with adding one sample to the end of the every scan and discard
  39 *  it on output but this can't be used if cmd->scan_begin_src=TRIG_FOLLOW
  40 *  and is used flag CMDF_WAKE_EOS, then driver switch to interrupt driven mode
  41 *  with interrupt after every sample.
  42 * c) If isn't used DMA then you can use only mode where
  43 *  cmd->scan_begin_src=TRIG_FOLLOW.
  44 *
  45 * Configuration options:
  46 * [0] - PCI bus of device (optional)
  47 * [1] - PCI slot of device (optional)
  48 *       If bus/slot is not specified, then first available PCI
  49 *       card will be used.
  50 * [2] - 0= standard 8 DIFF/16 SE channels configuration
  51 *       n = external multiplexer connected, 1 <= n <= 256
  52 * [3] - ignored
  53 * [4] - sample&hold signal - card can generate signal for external S&H board
  54 *       0 = use SSHO(pin 45) signal is generated in onboard hardware S&H logic
  55 *       0 != use ADCHN7(pin 23) signal is generated from driver, number say how
  56 *              long delay is requested in ns and sign polarity of the hold
  57 *              (in this case external multiplexor can serve only 128 channels)
  58 * [5] - ignored
  59 */
  60
  61/*
  62 * FIXME
  63 *
  64 * All the supported boards have the same PCI vendor and device IDs, so
  65 * auto-attachment of PCI devices will always find the first board type.
  66 *
  67 * Perhaps the boards have different subdevice IDs that we could use to
  68 * distinguish them?
  69 *
  70 * Need some device attributes so the board type can be corrected after
  71 * attachment if necessary, and possibly to set other options supported by
  72 * manual attachment.
  73 */
  74
  75#include <linux/module.h>
  76#include <linux/delay.h>
  77#include <linux/gfp.h>
  78#include <linux/interrupt.h>
  79#include <linux/io.h>
  80
  81#include "../comedi_pci.h"
  82
  83#include "amcc_s5933.h"
  84#include "comedi_8254.h"
  85
  86/*
  87 * PCI BAR2 Register map (dev->iobase)
  88 */
  89#define PCI9118_TIMER_BASE              0x00
  90#define PCI9118_AI_FIFO_REG             0x10
  91#define PCI9118_AO_REG(x)               (0x10 + ((x) * 4))
  92#define PCI9118_AI_STATUS_REG           0x18
  93#define PCI9118_AI_STATUS_NFULL         BIT(8)  /* 0=FIFO full (fatal) */
  94#define PCI9118_AI_STATUS_NHFULL        BIT(7)  /* 0=FIFO half full */
  95#define PCI9118_AI_STATUS_NEPTY         BIT(6)  /* 0=FIFO empty */
  96#define PCI9118_AI_STATUS_ACMP          BIT(5)  /* 1=about trigger complete */
  97#define PCI9118_AI_STATUS_DTH           BIT(4)  /* 1=ext. digital trigger */
  98#define PCI9118_AI_STATUS_BOVER         BIT(3)  /* 1=burst overrun (fatal) */
  99#define PCI9118_AI_STATUS_ADOS          BIT(2)  /* 1=A/D over speed (warn) */
 100#define PCI9118_AI_STATUS_ADOR          BIT(1)  /* 1=A/D overrun (fatal) */
 101#define PCI9118_AI_STATUS_ADRDY         BIT(0)  /* 1=A/D ready */
 102#define PCI9118_AI_CTRL_REG             0x18
 103#define PCI9118_AI_CTRL_UNIP            BIT(7)  /* 1=unipolar */
 104#define PCI9118_AI_CTRL_DIFF            BIT(6)  /* 1=differential inputs */
 105#define PCI9118_AI_CTRL_SOFTG           BIT(5)  /* 1=8254 software gate */
 106#define PCI9118_AI_CTRL_EXTG            BIT(4)  /* 1=8254 TGIN(pin 46) gate */
 107#define PCI9118_AI_CTRL_EXTM            BIT(3)  /* 1=ext. trigger (pin 44) */
 108#define PCI9118_AI_CTRL_TMRTR           BIT(2)  /* 1=8254 is trigger source */
 109#define PCI9118_AI_CTRL_INT             BIT(1)  /* 1=enable interrupt */
 110#define PCI9118_AI_CTRL_DMA             BIT(0)  /* 1=enable DMA */
 111#define PCI9118_DIO_REG                 0x1c
 112#define PCI9118_SOFTTRG_REG             0x20
 113#define PCI9118_AI_CHANLIST_REG         0x24
 114#define PCI9118_AI_CHANLIST_RANGE(x)    (((x) & 0x3) << 8)
 115#define PCI9118_AI_CHANLIST_CHAN(x)     ((x) << 0)
 116#define PCI9118_AI_BURST_NUM_REG        0x28
 117#define PCI9118_AI_AUTOSCAN_MODE_REG    0x2c
 118#define PCI9118_AI_CFG_REG              0x30
 119#define PCI9118_AI_CFG_PDTRG            BIT(7)  /* 1=positive trigger */
 120#define PCI9118_AI_CFG_PETRG            BIT(6)  /* 1=positive ext. trigger */
 121#define PCI9118_AI_CFG_BSSH             BIT(5)  /* 1=with sample & hold */
 122#define PCI9118_AI_CFG_BM               BIT(4)  /* 1=burst mode */
 123#define PCI9118_AI_CFG_BS               BIT(3)  /* 1=burst mode start */
 124#define PCI9118_AI_CFG_PM               BIT(2)  /* 1=post trigger */
 125#define PCI9118_AI_CFG_AM               BIT(1)  /* 1=about trigger */
 126#define PCI9118_AI_CFG_START            BIT(0)  /* 1=trigger start */
 127#define PCI9118_FIFO_RESET_REG          0x34
 128#define PCI9118_INT_CTRL_REG            0x38
 129#define PCI9118_INT_CTRL_TIMER          BIT(3)  /* timer interrupt */
 130#define PCI9118_INT_CTRL_ABOUT          BIT(2)  /* about trigger complete */
 131#define PCI9118_INT_CTRL_HFULL          BIT(1)  /* A/D FIFO half full */
 132#define PCI9118_INT_CTRL_DTRG           BIT(0)  /* ext. digital trigger */
 133
 134#define START_AI_EXT    0x01    /* start measure on external trigger */
 135#define STOP_AI_EXT     0x02    /* stop measure on external trigger */
 136#define STOP_AI_INT     0x08    /* stop measure on internal trigger */
 137
 138static const struct comedi_lrange pci9118_ai_range = {
 139        8, {
 140                BIP_RANGE(5),
 141                BIP_RANGE(2.5),
 142                BIP_RANGE(1.25),
 143                BIP_RANGE(0.625),
 144                UNI_RANGE(10),
 145                UNI_RANGE(5),
 146                UNI_RANGE(2.5),
 147                UNI_RANGE(1.25)
 148        }
 149};
 150
 151static const struct comedi_lrange pci9118hg_ai_range = {
 152        8, {
 153                BIP_RANGE(5),
 154                BIP_RANGE(0.5),
 155                BIP_RANGE(0.05),
 156                BIP_RANGE(0.005),
 157                UNI_RANGE(10),
 158                UNI_RANGE(1),
 159                UNI_RANGE(0.1),
 160                UNI_RANGE(0.01)
 161        }
 162};
 163
 164enum pci9118_boardid {
 165        BOARD_PCI9118DG,
 166        BOARD_PCI9118HG,
 167        BOARD_PCI9118HR,
 168};
 169
 170struct pci9118_boardinfo {
 171        const char *name;
 172        unsigned int ai_is_16bit:1;
 173        unsigned int is_hg:1;
 174};
 175
 176static const struct pci9118_boardinfo pci9118_boards[] = {
 177        [BOARD_PCI9118DG] = {
 178                .name           = "pci9118dg",
 179        },
 180        [BOARD_PCI9118HG] = {
 181                .name           = "pci9118hg",
 182                .is_hg          = 1,
 183        },
 184        [BOARD_PCI9118HR] = {
 185                .name           = "pci9118hr",
 186                .ai_is_16bit    = 1,
 187        },
 188};
 189
 190struct pci9118_dmabuf {
 191        unsigned short *virt;   /* virtual address of buffer */
 192        dma_addr_t hw;          /* hardware (bus) address of buffer */
 193        unsigned int size;      /* size of dma buffer in bytes */
 194        unsigned int use_size;  /* which size we may now use for transfer */
 195};
 196
 197struct pci9118_private {
 198        unsigned long iobase_a; /* base+size for AMCC chip */
 199        unsigned int master:1;
 200        unsigned int dma_doublebuf:1;
 201        unsigned int ai_neverending:1;
 202        unsigned int usedma:1;
 203        unsigned int usemux:1;
 204        unsigned char ai_ctrl;
 205        unsigned char int_ctrl;
 206        unsigned char ai_cfg;
 207        unsigned int ai_do;             /* what do AI? 0=nothing, 1 to 4 mode */
 208        unsigned int ai_n_realscanlen;  /*
 209                                         * what we must transfer for one
 210                                         * outgoing scan include front/back adds
 211                                         */
 212        unsigned int ai_act_dmapos;     /* position in actual real stream */
 213        unsigned int ai_add_front;      /*
 214                                         * how many channels we must add
 215                                         * before scan to satisfy S&H?
 216                                         */
 217        unsigned int ai_add_back;       /*
 218                                         * how many channels we must add
 219                                         * before scan to satisfy DMA?
 220                                         */
 221        unsigned int ai_flags;
 222        char ai12_startstop;            /*
 223                                         * measure can start/stop
 224                                         * on external trigger
 225                                         */
 226        unsigned int dma_actbuf;                /* which buffer is used now */
 227        struct pci9118_dmabuf dmabuf[2];
 228        int softsshdelay;               /*
 229                                         * >0 use software S&H,
 230                                         * numer is requested delay in ns
 231                                         */
 232        unsigned char softsshsample;    /*
 233                                         * polarity of S&H signal
 234                                         * in sample state
 235                                         */
 236        unsigned char softsshhold;      /*
 237                                         * polarity of S&H signal
 238                                         * in hold state
 239                                         */
 240        unsigned int ai_ns_min;
 241};
 242
 243static void pci9118_amcc_setup_dma(struct comedi_device *dev, unsigned int buf)
 244{
 245        struct pci9118_private *devpriv = dev->private;
 246        struct pci9118_dmabuf *dmabuf = &devpriv->dmabuf[buf];
 247
 248        /* set the master write address and transfer count */
 249        outl(dmabuf->hw, devpriv->iobase_a + AMCC_OP_REG_MWAR);
 250        outl(dmabuf->use_size, devpriv->iobase_a + AMCC_OP_REG_MWTC);
 251}
 252
 253static void pci9118_amcc_dma_ena(struct comedi_device *dev, bool enable)
 254{
 255        struct pci9118_private *devpriv = dev->private;
 256        unsigned int mcsr;
 257
 258        mcsr = inl(devpriv->iobase_a + AMCC_OP_REG_MCSR);
 259        if (enable)
 260                mcsr |= RESET_A2P_FLAGS | A2P_HI_PRIORITY | EN_A2P_TRANSFERS;
 261        else
 262                mcsr &= ~EN_A2P_TRANSFERS;
 263        outl(mcsr, devpriv->iobase_a + AMCC_OP_REG_MCSR);
 264}
 265
 266static void pci9118_amcc_int_ena(struct comedi_device *dev, bool enable)
 267{
 268        struct pci9118_private *devpriv = dev->private;
 269        unsigned int intcsr;
 270
 271        /* enable/disable interrupt for AMCC Incoming Mailbox 4 (32-bit) */
 272        intcsr = inl(devpriv->iobase_a + AMCC_OP_REG_INTCSR);
 273        if (enable)
 274                intcsr |= 0x1f00;
 275        else
 276                intcsr &= ~0x1f00;
 277        outl(intcsr, devpriv->iobase_a + AMCC_OP_REG_INTCSR);
 278}
 279
 280static void pci9118_ai_reset_fifo(struct comedi_device *dev)
 281{
 282        /* writing any value resets the A/D FIFO */
 283        outl(0, dev->iobase + PCI9118_FIFO_RESET_REG);
 284}
 285
 286static int pci9118_ai_check_chanlist(struct comedi_device *dev,
 287                                     struct comedi_subdevice *s,
 288                                     struct comedi_cmd *cmd)
 289{
 290        struct pci9118_private *devpriv = dev->private;
 291        unsigned int range0 = CR_RANGE(cmd->chanlist[0]);
 292        unsigned int aref0 = CR_AREF(cmd->chanlist[0]);
 293        int i;
 294
 295        /* single channel scans are always ok */
 296        if (cmd->chanlist_len == 1)
 297                return 0;
 298
 299        for (i = 1; i < cmd->chanlist_len; i++) {
 300                unsigned int chan = CR_CHAN(cmd->chanlist[i]);
 301                unsigned int range = CR_RANGE(cmd->chanlist[i]);
 302                unsigned int aref = CR_AREF(cmd->chanlist[i]);
 303
 304                if (aref != aref0) {
 305                        dev_err(dev->class_dev,
 306                                "Differential and single ended inputs can't be mixed!\n");
 307                        return -EINVAL;
 308                }
 309                if (comedi_range_is_bipolar(s, range) !=
 310                    comedi_range_is_bipolar(s, range0)) {
 311                        dev_err(dev->class_dev,
 312                                "Bipolar and unipolar ranges can't be mixed!\n");
 313                        return -EINVAL;
 314                }
 315                if (!devpriv->usemux && aref == AREF_DIFF &&
 316                    (chan >= (s->n_chan / 2))) {
 317                        dev_err(dev->class_dev,
 318                                "AREF_DIFF is only available for the first 8 channels!\n");
 319                        return -EINVAL;
 320                }
 321        }
 322
 323        return 0;
 324}
 325
 326static void pci9118_set_chanlist(struct comedi_device *dev,
 327                                 struct comedi_subdevice *s,
 328                                 int n_chan, unsigned int *chanlist,
 329                                 int frontadd, int backadd)
 330{
 331        struct pci9118_private *devpriv = dev->private;
 332        unsigned int chan0 = CR_CHAN(chanlist[0]);
 333        unsigned int range0 = CR_RANGE(chanlist[0]);
 334        unsigned int aref0 = CR_AREF(chanlist[0]);
 335        unsigned int ssh = 0x00;
 336        unsigned int val;
 337        int i;
 338
 339        /*
 340         * Configure analog input based on the first chanlist entry.
 341         * All entries are either unipolar or bipolar and single-ended
 342         * or differential.
 343         */
 344        devpriv->ai_ctrl = 0;
 345        if (comedi_range_is_unipolar(s, range0))
 346                devpriv->ai_ctrl |= PCI9118_AI_CTRL_UNIP;
 347        if (aref0 == AREF_DIFF)
 348                devpriv->ai_ctrl |= PCI9118_AI_CTRL_DIFF;
 349        outl(devpriv->ai_ctrl, dev->iobase + PCI9118_AI_CTRL_REG);
 350
 351        /* gods know why this sequence! */
 352        outl(2, dev->iobase + PCI9118_AI_AUTOSCAN_MODE_REG);
 353        outl(0, dev->iobase + PCI9118_AI_AUTOSCAN_MODE_REG);
 354        outl(1, dev->iobase + PCI9118_AI_AUTOSCAN_MODE_REG);
 355
 356        /* insert channels for S&H */
 357        if (frontadd) {
 358                val = PCI9118_AI_CHANLIST_CHAN(chan0) |
 359                      PCI9118_AI_CHANLIST_RANGE(range0);
 360                ssh = devpriv->softsshsample;
 361                for (i = 0; i < frontadd; i++) {
 362                        outl(val | ssh, dev->iobase + PCI9118_AI_CHANLIST_REG);
 363                        ssh = devpriv->softsshhold;
 364                }
 365        }
 366
 367        /* store chanlist */
 368        for (i = 0; i < n_chan; i++) {
 369                unsigned int chan = CR_CHAN(chanlist[i]);
 370                unsigned int range = CR_RANGE(chanlist[i]);
 371
 372                val = PCI9118_AI_CHANLIST_CHAN(chan) |
 373                      PCI9118_AI_CHANLIST_RANGE(range);
 374                outl(val | ssh, dev->iobase + PCI9118_AI_CHANLIST_REG);
 375        }
 376
 377        /* insert channels to fit onto 32bit DMA */
 378        if (backadd) {
 379                val = PCI9118_AI_CHANLIST_CHAN(chan0) |
 380                      PCI9118_AI_CHANLIST_RANGE(range0);
 381                for (i = 0; i < backadd; i++)
 382                        outl(val | ssh, dev->iobase + PCI9118_AI_CHANLIST_REG);
 383        }
 384        /* close scan queue */
 385        outl(0, dev->iobase + PCI9118_AI_AUTOSCAN_MODE_REG);
 386        /* udelay(100); important delay, or first sample will be crippled */
 387}
 388
 389static void pci9118_ai_mode4_switch(struct comedi_device *dev,
 390                                    unsigned int next_buf)
 391{
 392        struct pci9118_private *devpriv = dev->private;
 393        struct pci9118_dmabuf *dmabuf = &devpriv->dmabuf[next_buf];
 394
 395        devpriv->ai_cfg = PCI9118_AI_CFG_PDTRG | PCI9118_AI_CFG_PETRG |
 396                          PCI9118_AI_CFG_AM;
 397        outl(devpriv->ai_cfg, dev->iobase + PCI9118_AI_CFG_REG);
 398        comedi_8254_load(dev->pacer, 0, dmabuf->hw >> 1,
 399                         I8254_MODE0 | I8254_BINARY);
 400        devpriv->ai_cfg |= PCI9118_AI_CFG_START;
 401        outl(devpriv->ai_cfg, dev->iobase + PCI9118_AI_CFG_REG);
 402}
 403
 404static unsigned int pci9118_ai_samples_ready(struct comedi_device *dev,
 405                                             struct comedi_subdevice *s,
 406                                             unsigned int n_raw_samples)
 407{
 408        struct pci9118_private *devpriv = dev->private;
 409        struct comedi_cmd *cmd = &s->async->cmd;
 410        unsigned int start_pos = devpriv->ai_add_front;
 411        unsigned int stop_pos = start_pos + cmd->chanlist_len;
 412        unsigned int span_len = stop_pos + devpriv->ai_add_back;
 413        unsigned int dma_pos = devpriv->ai_act_dmapos;
 414        unsigned int whole_spans, n_samples, x;
 415
 416        if (span_len == cmd->chanlist_len)
 417                return n_raw_samples;   /* use all samples */
 418
 419        /*
 420         * Not all samples are to be used.  Buffer contents consist of a
 421         * possibly non-whole number of spans and a region of each span
 422         * is to be used.
 423         *
 424         * Account for samples in whole number of spans.
 425         */
 426        whole_spans = n_raw_samples / span_len;
 427        n_samples = whole_spans * cmd->chanlist_len;
 428        n_raw_samples -= whole_spans * span_len;
 429
 430        /*
 431         * Deal with remaining samples which could overlap up to two spans.
 432         */
 433        while (n_raw_samples) {
 434                if (dma_pos < start_pos) {
 435                        /* Skip samples before start position. */
 436                        x = start_pos - dma_pos;
 437                        if (x > n_raw_samples)
 438                                x = n_raw_samples;
 439                        dma_pos += x;
 440                        n_raw_samples -= x;
 441                        if (!n_raw_samples)
 442                                break;
 443                }
 444                if (dma_pos < stop_pos) {
 445                        /* Include samples before stop position. */
 446                        x = stop_pos - dma_pos;
 447                        if (x > n_raw_samples)
 448                                x = n_raw_samples;
 449                        n_samples += x;
 450                        dma_pos += x;
 451                        n_raw_samples -= x;
 452                }
 453                /* Advance to next span. */
 454                start_pos += span_len;
 455                stop_pos += span_len;
 456        }
 457        return n_samples;
 458}
 459
 460static void pci9118_ai_dma_xfer(struct comedi_device *dev,
 461                                struct comedi_subdevice *s,
 462                                unsigned short *dma_buffer,
 463                                unsigned int n_raw_samples)
 464{
 465        struct pci9118_private *devpriv = dev->private;
 466        struct comedi_cmd *cmd = &s->async->cmd;
 467        unsigned int start_pos = devpriv->ai_add_front;
 468        unsigned int stop_pos = start_pos + cmd->chanlist_len;
 469        unsigned int span_len = stop_pos + devpriv->ai_add_back;
 470        unsigned int dma_pos = devpriv->ai_act_dmapos;
 471        unsigned int x;
 472
 473        if (span_len == cmd->chanlist_len) {
 474                /* All samples are to be copied. */
 475                comedi_buf_write_samples(s, dma_buffer, n_raw_samples);
 476                dma_pos += n_raw_samples;
 477        } else {
 478                /*
 479                 * Not all samples are to be copied.  Buffer contents consist
 480                 * of a possibly non-whole number of spans and a region of
 481                 * each span is to be copied.
 482                 */
 483                while (n_raw_samples) {
 484                        if (dma_pos < start_pos) {
 485                                /* Skip samples before start position. */
 486                                x = start_pos - dma_pos;
 487                                if (x > n_raw_samples)
 488                                        x = n_raw_samples;
 489                                dma_pos += x;
 490                                n_raw_samples -= x;
 491                                if (!n_raw_samples)
 492                                        break;
 493                        }
 494                        if (dma_pos < stop_pos) {
 495                                /* Copy samples before stop position. */
 496                                x = stop_pos - dma_pos;
 497                                if (x > n_raw_samples)
 498                                        x = n_raw_samples;
 499                                comedi_buf_write_samples(s, dma_buffer, x);
 500                                dma_pos += x;
 501                                n_raw_samples -= x;
 502                        }
 503                        /* Advance to next span. */
 504                        start_pos += span_len;
 505                        stop_pos += span_len;
 506                }
 507        }
 508        /* Update position in span for next time. */
 509        devpriv->ai_act_dmapos = dma_pos % span_len;
 510}
 511
 512static void pci9118_exttrg_enable(struct comedi_device *dev, bool enable)
 513{
 514        struct pci9118_private *devpriv = dev->private;
 515
 516        if (enable)
 517                devpriv->int_ctrl |= PCI9118_INT_CTRL_DTRG;
 518        else
 519                devpriv->int_ctrl &= ~PCI9118_INT_CTRL_DTRG;
 520        outl(devpriv->int_ctrl, dev->iobase + PCI9118_INT_CTRL_REG);
 521
 522        if (devpriv->int_ctrl)
 523                pci9118_amcc_int_ena(dev, true);
 524        else
 525                pci9118_amcc_int_ena(dev, false);
 526}
 527
 528static void pci9118_calc_divisors(struct comedi_device *dev,
 529                                  struct comedi_subdevice *s,
 530                                  unsigned int *tim1, unsigned int *tim2,
 531                                  unsigned int flags, int chans,
 532                                  unsigned int *div1, unsigned int *div2,
 533                                  unsigned int chnsshfront)
 534{
 535        struct comedi_8254 *pacer = dev->pacer;
 536        struct comedi_cmd *cmd = &s->async->cmd;
 537
 538        *div1 = *tim2 / pacer->osc_base;        /* convert timer (burst) */
 539        *div2 = *tim1 / pacer->osc_base;        /* scan timer */
 540        *div2 = *div2 / *div1;                  /* major timer is c1*c2 */
 541        if (*div2 < chans)
 542                *div2 = chans;
 543
 544        *tim2 = *div1 * pacer->osc_base;        /* real convert timer */
 545
 546        if (cmd->convert_src == TRIG_NOW && !chnsshfront) {
 547                /* use BSSH signal */
 548                if (*div2 < (chans + 2))
 549                        *div2 = chans + 2;
 550        }
 551
 552        *tim1 = *div1 * *div2 * pacer->osc_base;
 553}
 554
 555static void pci9118_start_pacer(struct comedi_device *dev, int mode)
 556{
 557        if (mode == 1 || mode == 2 || mode == 4)
 558                comedi_8254_pacer_enable(dev->pacer, 1, 2, true);
 559}
 560
 561static int pci9118_ai_cancel(struct comedi_device *dev,
 562                             struct comedi_subdevice *s)
 563{
 564        struct pci9118_private *devpriv = dev->private;
 565
 566        if (devpriv->usedma)
 567                pci9118_amcc_dma_ena(dev, false);
 568        pci9118_exttrg_enable(dev, false);
 569        comedi_8254_pacer_enable(dev->pacer, 1, 2, false);
 570        /* set default config (disable burst and triggers) */
 571        devpriv->ai_cfg = PCI9118_AI_CFG_PDTRG | PCI9118_AI_CFG_PETRG;
 572        outl(devpriv->ai_cfg, dev->iobase + PCI9118_AI_CFG_REG);
 573        /* reset acqusition control */
 574        devpriv->ai_ctrl = 0;
 575        outl(devpriv->ai_ctrl, dev->iobase + PCI9118_AI_CTRL_REG);
 576        outl(0, dev->iobase + PCI9118_AI_BURST_NUM_REG);
 577        /* reset scan queue */
 578        outl(1, dev->iobase + PCI9118_AI_AUTOSCAN_MODE_REG);
 579        outl(2, dev->iobase + PCI9118_AI_AUTOSCAN_MODE_REG);
 580        pci9118_ai_reset_fifo(dev);
 581
 582        devpriv->int_ctrl = 0;
 583        outl(devpriv->int_ctrl, dev->iobase + PCI9118_INT_CTRL_REG);
 584        pci9118_amcc_int_ena(dev, false);
 585
 586        devpriv->ai_do = 0;
 587        devpriv->usedma = 0;
 588
 589        devpriv->ai_act_dmapos = 0;
 590        s->async->inttrig = NULL;
 591        devpriv->ai_neverending = 0;
 592        devpriv->dma_actbuf = 0;
 593
 594        return 0;
 595}
 596
 597static void pci9118_ai_munge(struct comedi_device *dev,
 598                             struct comedi_subdevice *s, void *data,
 599                             unsigned int num_bytes,
 600                             unsigned int start_chan_index)
 601{
 602        struct pci9118_private *devpriv = dev->private;
 603        unsigned short *array = data;
 604        unsigned int num_samples = comedi_bytes_to_samples(s, num_bytes);
 605        unsigned int i;
 606        __be16 *barray = data;
 607
 608        for (i = 0; i < num_samples; i++) {
 609                if (devpriv->usedma)
 610                        array[i] = be16_to_cpu(barray[i]);
 611                if (s->maxdata == 0xffff)
 612                        array[i] ^= 0x8000;
 613                else
 614                        array[i] = (array[i] >> 4) & 0x0fff;
 615        }
 616}
 617
 618static void pci9118_ai_get_onesample(struct comedi_device *dev,
 619                                     struct comedi_subdevice *s)
 620{
 621        struct pci9118_private *devpriv = dev->private;
 622        struct comedi_cmd *cmd = &s->async->cmd;
 623        unsigned short sampl;
 624
 625        sampl = inl(dev->iobase + PCI9118_AI_FIFO_REG);
 626
 627        comedi_buf_write_samples(s, &sampl, 1);
 628
 629        if (!devpriv->ai_neverending) {
 630                if (s->async->scans_done >= cmd->stop_arg)
 631                        s->async->events |= COMEDI_CB_EOA;
 632        }
 633}
 634
 635static void pci9118_ai_get_dma(struct comedi_device *dev,
 636                               struct comedi_subdevice *s)
 637{
 638        struct pci9118_private *devpriv = dev->private;
 639        struct comedi_cmd *cmd = &s->async->cmd;
 640        struct pci9118_dmabuf *dmabuf = &devpriv->dmabuf[devpriv->dma_actbuf];
 641        unsigned int n_all = comedi_bytes_to_samples(s, dmabuf->use_size);
 642        unsigned int n_valid;
 643        bool more_dma;
 644
 645        /* determine whether more DMA buffers to do after this one */
 646        n_valid = pci9118_ai_samples_ready(dev, s, n_all);
 647        more_dma = n_valid < comedi_nsamples_left(s, n_valid + 1);
 648
 649        /* switch DMA buffers and restart DMA if double buffering */
 650        if (more_dma && devpriv->dma_doublebuf) {
 651                devpriv->dma_actbuf = 1 - devpriv->dma_actbuf;
 652                pci9118_amcc_setup_dma(dev, devpriv->dma_actbuf);
 653                if (devpriv->ai_do == 4)
 654                        pci9118_ai_mode4_switch(dev, devpriv->dma_actbuf);
 655        }
 656
 657        if (n_all)
 658                pci9118_ai_dma_xfer(dev, s, dmabuf->virt, n_all);
 659
 660        if (!devpriv->ai_neverending) {
 661                if (s->async->scans_done >= cmd->stop_arg)
 662                        s->async->events |= COMEDI_CB_EOA;
 663        }
 664
 665        if (s->async->events & COMEDI_CB_CANCEL_MASK)
 666                more_dma = false;
 667
 668        /* restart DMA if not double buffering */
 669        if (more_dma && !devpriv->dma_doublebuf) {
 670                pci9118_amcc_setup_dma(dev, 0);
 671                if (devpriv->ai_do == 4)
 672                        pci9118_ai_mode4_switch(dev, 0);
 673        }
 674}
 675
 676static irqreturn_t pci9118_interrupt(int irq, void *d)
 677{
 678        struct comedi_device *dev = d;
 679        struct comedi_subdevice *s = dev->read_subdev;
 680        struct pci9118_private *devpriv = dev->private;
 681        unsigned int intsrc;    /* IRQ reasons from card */
 682        unsigned int intcsr;    /* INT register from AMCC chip */
 683        unsigned int adstat;    /* STATUS register */
 684
 685        if (!dev->attached)
 686                return IRQ_NONE;
 687
 688        intsrc = inl(dev->iobase + PCI9118_INT_CTRL_REG) & 0xf;
 689        intcsr = inl(devpriv->iobase_a + AMCC_OP_REG_INTCSR);
 690
 691        if (!intsrc && !(intcsr & ANY_S593X_INT))
 692                return IRQ_NONE;
 693
 694        outl(intcsr | 0x00ff0000, devpriv->iobase_a + AMCC_OP_REG_INTCSR);
 695
 696        if (intcsr & MASTER_ABORT_INT) {
 697                dev_err(dev->class_dev, "AMCC IRQ - MASTER DMA ABORT!\n");
 698                s->async->events |= COMEDI_CB_ERROR;
 699                goto interrupt_exit;
 700        }
 701
 702        if (intcsr & TARGET_ABORT_INT) {
 703                dev_err(dev->class_dev, "AMCC IRQ - TARGET DMA ABORT!\n");
 704                s->async->events |= COMEDI_CB_ERROR;
 705                goto interrupt_exit;
 706        }
 707
 708        adstat = inl(dev->iobase + PCI9118_AI_STATUS_REG);
 709        if ((adstat & PCI9118_AI_STATUS_NFULL) == 0) {
 710                dev_err(dev->class_dev,
 711                        "A/D FIFO Full status (Fatal Error!)\n");
 712                s->async->events |= COMEDI_CB_ERROR | COMEDI_CB_OVERFLOW;
 713                goto interrupt_exit;
 714        }
 715        if (adstat & PCI9118_AI_STATUS_BOVER) {
 716                dev_err(dev->class_dev,
 717                        "A/D Burst Mode Overrun Status (Fatal Error!)\n");
 718                s->async->events |= COMEDI_CB_ERROR | COMEDI_CB_OVERFLOW;
 719                goto interrupt_exit;
 720        }
 721        if (adstat & PCI9118_AI_STATUS_ADOS) {
 722                dev_err(dev->class_dev, "A/D Over Speed Status (Warning!)\n");
 723                s->async->events |= COMEDI_CB_ERROR;
 724                goto interrupt_exit;
 725        }
 726        if (adstat & PCI9118_AI_STATUS_ADOR) {
 727                dev_err(dev->class_dev, "A/D Overrun Status (Fatal Error!)\n");
 728                s->async->events |= COMEDI_CB_ERROR | COMEDI_CB_OVERFLOW;
 729                goto interrupt_exit;
 730        }
 731
 732        if (!devpriv->ai_do)
 733                return IRQ_HANDLED;
 734
 735        if (devpriv->ai12_startstop) {
 736                if ((adstat & PCI9118_AI_STATUS_DTH) &&
 737                    (intsrc & PCI9118_INT_CTRL_DTRG)) {
 738                        /* start/stop of measure */
 739                        if (devpriv->ai12_startstop & START_AI_EXT) {
 740                                /* deactivate EXT trigger */
 741                                devpriv->ai12_startstop &= ~START_AI_EXT;
 742                                if (!(devpriv->ai12_startstop & STOP_AI_EXT))
 743                                        pci9118_exttrg_enable(dev, false);
 744
 745                                /* start pacer */
 746                                pci9118_start_pacer(dev, devpriv->ai_do);
 747                                outl(devpriv->ai_ctrl,
 748                                     dev->iobase + PCI9118_AI_CTRL_REG);
 749                        } else if (devpriv->ai12_startstop & STOP_AI_EXT) {
 750                                /* deactivate EXT trigger */
 751                                devpriv->ai12_startstop &= ~STOP_AI_EXT;
 752                                pci9118_exttrg_enable(dev, false);
 753
 754                                /* on next interrupt measure will stop */
 755                                devpriv->ai_neverending = 0;
 756                        }
 757                }
 758        }
 759
 760        if (devpriv->usedma)
 761                pci9118_ai_get_dma(dev, s);
 762        else
 763                pci9118_ai_get_onesample(dev, s);
 764
 765interrupt_exit:
 766        comedi_handle_events(dev, s);
 767        return IRQ_HANDLED;
 768}
 769
 770static void pci9118_ai_cmd_start(struct comedi_device *dev)
 771{
 772        struct pci9118_private *devpriv = dev->private;
 773
 774        outl(devpriv->int_ctrl, dev->iobase + PCI9118_INT_CTRL_REG);
 775        outl(devpriv->ai_cfg, dev->iobase + PCI9118_AI_CFG_REG);
 776        if (devpriv->ai_do != 3) {
 777                pci9118_start_pacer(dev, devpriv->ai_do);
 778                devpriv->ai_ctrl |= PCI9118_AI_CTRL_SOFTG;
 779        }
 780        outl(devpriv->ai_ctrl, dev->iobase + PCI9118_AI_CTRL_REG);
 781}
 782
 783static int pci9118_ai_inttrig(struct comedi_device *dev,
 784                              struct comedi_subdevice *s,
 785                              unsigned int trig_num)
 786{
 787        struct comedi_cmd *cmd = &s->async->cmd;
 788
 789        if (trig_num != cmd->start_arg)
 790                return -EINVAL;
 791
 792        s->async->inttrig = NULL;
 793        pci9118_ai_cmd_start(dev);
 794
 795        return 1;
 796}
 797
 798static int pci9118_ai_setup_dma(struct comedi_device *dev,
 799                                struct comedi_subdevice *s)
 800{
 801        struct pci9118_private *devpriv = dev->private;
 802        struct comedi_cmd *cmd = &s->async->cmd;
 803        struct pci9118_dmabuf *dmabuf0 = &devpriv->dmabuf[0];
 804        struct pci9118_dmabuf *dmabuf1 = &devpriv->dmabuf[1];
 805        unsigned int dmalen0 = dmabuf0->size;
 806        unsigned int dmalen1 = dmabuf1->size;
 807        unsigned int scan_bytes = devpriv->ai_n_realscanlen *
 808                                  comedi_bytes_per_sample(s);
 809
 810        /* isn't output buff smaller that our DMA buff? */
 811        if (dmalen0 > s->async->prealloc_bufsz) {
 812                /* align to 32bit down */
 813                dmalen0 = s->async->prealloc_bufsz & ~3L;
 814        }
 815        if (dmalen1 > s->async->prealloc_bufsz) {
 816                /* align to 32bit down */
 817                dmalen1 = s->async->prealloc_bufsz & ~3L;
 818        }
 819
 820        /* we want wake up every scan? */
 821        if (devpriv->ai_flags & CMDF_WAKE_EOS) {
 822                if (dmalen0 < scan_bytes) {
 823                        /* uff, too short DMA buffer, disable EOS support! */
 824                        devpriv->ai_flags &= (~CMDF_WAKE_EOS);
 825                        dev_info(dev->class_dev,
 826                                 "WAR: DMA0 buf too short, can't support CMDF_WAKE_EOS (%d<%d)\n",
 827                                  dmalen0, scan_bytes);
 828                } else {
 829                        /* short first DMA buffer to one scan */
 830                        dmalen0 = scan_bytes;
 831                        if (dmalen0 < 4) {
 832                                dev_info(dev->class_dev,
 833                                         "ERR: DMA0 buf len bug? (%d<4)\n",
 834                                         dmalen0);
 835                                dmalen0 = 4;
 836                        }
 837                }
 838        }
 839        if (devpriv->ai_flags & CMDF_WAKE_EOS) {
 840                if (dmalen1 < scan_bytes) {
 841                        /* uff, too short DMA buffer, disable EOS support! */
 842                        devpriv->ai_flags &= (~CMDF_WAKE_EOS);
 843                        dev_info(dev->class_dev,
 844                                 "WAR: DMA1 buf too short, can't support CMDF_WAKE_EOS (%d<%d)\n",
 845                                 dmalen1, scan_bytes);
 846                } else {
 847                        /* short second DMA buffer to one scan */
 848                        dmalen1 = scan_bytes;
 849                        if (dmalen1 < 4) {
 850                                dev_info(dev->class_dev,
 851                                         "ERR: DMA1 buf len bug? (%d<4)\n",
 852                                         dmalen1);
 853                                dmalen1 = 4;
 854                        }
 855                }
 856        }
 857
 858        /* transfer without CMDF_WAKE_EOS */
 859        if (!(devpriv->ai_flags & CMDF_WAKE_EOS)) {
 860                unsigned int tmp;
 861
 862                /* if it's possible then align DMA buffers to length of scan */
 863                tmp = dmalen0;
 864                dmalen0 = (dmalen0 / scan_bytes) * scan_bytes;
 865                dmalen0 &= ~3L;
 866                if (!dmalen0)
 867                        dmalen0 = tmp;  /* uff. very long scan? */
 868                tmp = dmalen1;
 869                dmalen1 = (dmalen1 / scan_bytes) * scan_bytes;
 870                dmalen1 &= ~3L;
 871                if (!dmalen1)
 872                        dmalen1 = tmp;  /* uff. very long scan? */
 873                /*
 874                 * if measure isn't neverending then test, if it fits whole
 875                 * into one or two DMA buffers
 876                 */
 877                if (!devpriv->ai_neverending) {
 878                        unsigned long long scanlen;
 879
 880                        scanlen = (unsigned long long)scan_bytes *
 881                                  cmd->stop_arg;
 882
 883                        /* fits whole measure into one DMA buffer? */
 884                        if (dmalen0 > scanlen) {
 885                                dmalen0 = scanlen;
 886                                dmalen0 &= ~3L;
 887                        } else {
 888                                /* fits whole measure into two DMA buffer? */
 889                                if (dmalen1 > (scanlen - dmalen0)) {
 890                                        dmalen1 = scanlen - dmalen0;
 891                                        dmalen1 &= ~3L;
 892                                }
 893                        }
 894                }
 895        }
 896
 897        /* these DMA buffer size will be used */
 898        devpriv->dma_actbuf = 0;
 899        dmabuf0->use_size = dmalen0;
 900        dmabuf1->use_size = dmalen1;
 901
 902        pci9118_amcc_dma_ena(dev, false);
 903        pci9118_amcc_setup_dma(dev, 0);
 904        /* init DMA transfer */
 905        outl(0x00000000 | AINT_WRITE_COMPL,
 906             devpriv->iobase_a + AMCC_OP_REG_INTCSR);
 907/* outl(0x02000000|AINT_WRITE_COMPL, devpriv->iobase_a+AMCC_OP_REG_INTCSR); */
 908        pci9118_amcc_dma_ena(dev, true);
 909        outl(inl(devpriv->iobase_a + AMCC_OP_REG_INTCSR) | EN_A2P_TRANSFERS,
 910             devpriv->iobase_a + AMCC_OP_REG_INTCSR);
 911                                                /* allow bus mastering */
 912
 913        return 0;
 914}
 915
 916static int pci9118_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 917{
 918        struct pci9118_private *devpriv = dev->private;
 919        struct comedi_8254 *pacer = dev->pacer;
 920        struct comedi_cmd *cmd = &s->async->cmd;
 921        unsigned int addchans = 0;
 922        unsigned int scanlen;
 923
 924        devpriv->ai12_startstop = 0;
 925        devpriv->ai_flags = cmd->flags;
 926        devpriv->ai_add_front = 0;
 927        devpriv->ai_add_back = 0;
 928
 929        /* prepare for start/stop conditions */
 930        if (cmd->start_src == TRIG_EXT)
 931                devpriv->ai12_startstop |= START_AI_EXT;
 932        if (cmd->stop_src == TRIG_EXT) {
 933                devpriv->ai_neverending = 1;
 934                devpriv->ai12_startstop |= STOP_AI_EXT;
 935        }
 936        if (cmd->stop_src == TRIG_NONE)
 937                devpriv->ai_neverending = 1;
 938        if (cmd->stop_src == TRIG_COUNT)
 939                devpriv->ai_neverending = 0;
 940
 941        /*
 942         * use additional sample at end of every scan
 943         * to satisty DMA 32 bit transfer?
 944         */
 945        devpriv->ai_add_front = 0;
 946        devpriv->ai_add_back = 0;
 947        if (devpriv->master) {
 948                devpriv->usedma = 1;
 949                if ((cmd->flags & CMDF_WAKE_EOS) &&
 950                    (cmd->scan_end_arg == 1)) {
 951                        if (cmd->convert_src == TRIG_NOW)
 952                                devpriv->ai_add_back = 1;
 953                        if (cmd->convert_src == TRIG_TIMER) {
 954                                devpriv->usedma = 0;
 955                                        /*
 956                                         * use INT transfer if scanlist
 957                                         * have only one channel
 958                                         */
 959                        }
 960                }
 961                if ((cmd->flags & CMDF_WAKE_EOS) &&
 962                    (cmd->scan_end_arg & 1) &&
 963                    (cmd->scan_end_arg > 1)) {
 964                        if (cmd->scan_begin_src == TRIG_FOLLOW) {
 965                                devpriv->usedma = 0;
 966                                /*
 967                                 * XXX maybe can be corrected to use 16 bit DMA
 968                                 */
 969                        } else {        /*
 970                                         * well, we must insert one sample
 971                                         * to end of EOS to meet 32 bit transfer
 972                                         */
 973                                devpriv->ai_add_back = 1;
 974                        }
 975                }
 976        } else {        /* interrupt transfer don't need any correction */
 977                devpriv->usedma = 0;
 978        }
 979
 980        /*
 981         * we need software S&H signal?
 982         * It adds two samples before every scan as minimum
 983         */
 984        if (cmd->convert_src == TRIG_NOW && devpriv->softsshdelay) {
 985                devpriv->ai_add_front = 2;
 986                if ((devpriv->usedma == 1) && (devpriv->ai_add_back == 1)) {
 987                                                        /* move it to front */
 988                        devpriv->ai_add_front++;
 989                        devpriv->ai_add_back = 0;
 990                }
 991                if (cmd->convert_arg < devpriv->ai_ns_min)
 992                        cmd->convert_arg = devpriv->ai_ns_min;
 993                addchans = devpriv->softsshdelay / cmd->convert_arg;
 994                if (devpriv->softsshdelay % cmd->convert_arg)
 995                        addchans++;
 996                if (addchans > (devpriv->ai_add_front - 1)) {
 997                                                        /* uff, still short */
 998                        devpriv->ai_add_front = addchans + 1;
 999                        if (devpriv->usedma == 1)
1000                                if ((devpriv->ai_add_front +
1001                                     cmd->chanlist_len +
1002                                     devpriv->ai_add_back) & 1)
1003                                        devpriv->ai_add_front++;
1004                                                        /* round up to 32 bit */
1005                }
1006        }
1007        /* well, we now know what must be all added */
1008        scanlen = devpriv->ai_add_front + cmd->chanlist_len +
1009                  devpriv->ai_add_back;
1010        /*
1011         * what we must take from card in real to have cmd->scan_end_arg
1012         * on output?
1013         */
1014        devpriv->ai_n_realscanlen = scanlen *
1015                                    (cmd->scan_end_arg / cmd->chanlist_len);
1016
1017        if (scanlen > s->len_chanlist) {
1018                dev_err(dev->class_dev,
1019                        "range/channel list is too long for actual configuration!\n");
1020                return -EINVAL;
1021        }
1022
1023        /*
1024         * Configure analog input and load the chanlist.
1025         * The acqusition control bits are enabled later.
1026         */
1027        pci9118_set_chanlist(dev, s, cmd->chanlist_len, cmd->chanlist,
1028                             devpriv->ai_add_front, devpriv->ai_add_back);
1029
1030        /* Determine acqusition mode and calculate timing */
1031        devpriv->ai_do = 0;
1032        if (cmd->scan_begin_src != TRIG_TIMER &&
1033            cmd->convert_src == TRIG_TIMER) {
1034                /* cascaded timers 1 and 2 are used for convert timing */
1035                if (cmd->scan_begin_src == TRIG_EXT)
1036                        devpriv->ai_do = 4;
1037                else
1038                        devpriv->ai_do = 1;
1039
1040                comedi_8254_cascade_ns_to_timer(pacer, &cmd->convert_arg,
1041                                                devpriv->ai_flags &
1042                                                CMDF_ROUND_NEAREST);
1043                comedi_8254_update_divisors(pacer);
1044
1045                devpriv->ai_ctrl |= PCI9118_AI_CTRL_TMRTR;
1046
1047                if (!devpriv->usedma) {
1048                        devpriv->ai_ctrl |= PCI9118_AI_CTRL_INT;
1049                        devpriv->int_ctrl |= PCI9118_INT_CTRL_TIMER;
1050                }
1051
1052                if (cmd->scan_begin_src == TRIG_EXT) {
1053                        struct pci9118_dmabuf *dmabuf = &devpriv->dmabuf[0];
1054
1055                        devpriv->ai_cfg |= PCI9118_AI_CFG_AM;
1056                        outl(devpriv->ai_cfg, dev->iobase + PCI9118_AI_CFG_REG);
1057                        comedi_8254_load(pacer, 0, dmabuf->hw >> 1,
1058                                         I8254_MODE0 | I8254_BINARY);
1059                        devpriv->ai_cfg |= PCI9118_AI_CFG_START;
1060                }
1061        }
1062
1063        if (cmd->scan_begin_src == TRIG_TIMER &&
1064            cmd->convert_src != TRIG_EXT) {
1065                if (!devpriv->usedma) {
1066                        dev_err(dev->class_dev,
1067                                "cmd->scan_begin_src=TRIG_TIMER works only with bus mastering!\n");
1068                        return -EIO;
1069                }
1070
1071                /* double timed action */
1072                devpriv->ai_do = 2;
1073
1074                pci9118_calc_divisors(dev, s,
1075                                      &cmd->scan_begin_arg, &cmd->convert_arg,
1076                                      devpriv->ai_flags,
1077                                      devpriv->ai_n_realscanlen,
1078                                      &pacer->divisor1,
1079                                      &pacer->divisor2,
1080                                      devpriv->ai_add_front);
1081
1082                devpriv->ai_ctrl |= PCI9118_AI_CTRL_TMRTR;
1083                devpriv->ai_cfg |= PCI9118_AI_CFG_BM | PCI9118_AI_CFG_BS;
1084                if (cmd->convert_src == TRIG_NOW && !devpriv->softsshdelay)
1085                        devpriv->ai_cfg |= PCI9118_AI_CFG_BSSH;
1086                outl(devpriv->ai_n_realscanlen,
1087                     dev->iobase + PCI9118_AI_BURST_NUM_REG);
1088        }
1089
1090        if (cmd->scan_begin_src == TRIG_FOLLOW &&
1091            cmd->convert_src == TRIG_EXT) {
1092                /* external trigger conversion */
1093                devpriv->ai_do = 3;
1094
1095                devpriv->ai_ctrl |= PCI9118_AI_CTRL_EXTM;
1096        }
1097
1098        if (devpriv->ai_do == 0) {
1099                dev_err(dev->class_dev,
1100                        "Unable to determine acqusition mode! BUG in (*do_cmdtest)?\n");
1101                return -EINVAL;
1102        }
1103
1104        if (devpriv->usedma)
1105                devpriv->ai_ctrl |= PCI9118_AI_CTRL_DMA;
1106
1107        /* set default config (disable burst and triggers) */
1108        devpriv->ai_cfg = PCI9118_AI_CFG_PDTRG | PCI9118_AI_CFG_PETRG;
1109        outl(devpriv->ai_cfg, dev->iobase + PCI9118_AI_CFG_REG);
1110        udelay(1);
1111        pci9118_ai_reset_fifo(dev);
1112
1113        /* clear A/D and INT status registers */
1114        inl(dev->iobase + PCI9118_AI_STATUS_REG);
1115        inl(dev->iobase + PCI9118_INT_CTRL_REG);
1116
1117        devpriv->ai_act_dmapos = 0;
1118
1119        if (devpriv->usedma) {
1120                pci9118_ai_setup_dma(dev, s);
1121
1122                outl(0x02000000 | AINT_WRITE_COMPL,
1123                     devpriv->iobase_a + AMCC_OP_REG_INTCSR);
1124        } else {
1125                pci9118_amcc_int_ena(dev, true);
1126        }
1127
1128        /* start async command now or wait for internal trigger */
1129        if (cmd->start_src == TRIG_NOW)
1130                pci9118_ai_cmd_start(dev);
1131        else if (cmd->start_src == TRIG_INT)
1132                s->async->inttrig = pci9118_ai_inttrig;
1133
1134        /* enable external trigger for command start/stop */
1135        if (cmd->start_src == TRIG_EXT || cmd->stop_src == TRIG_EXT)
1136                pci9118_exttrg_enable(dev, true);
1137
1138        return 0;
1139}
1140
1141static int pci9118_ai_cmdtest(struct comedi_device *dev,
1142                              struct comedi_subdevice *s,
1143                              struct comedi_cmd *cmd)
1144{
1145        struct pci9118_private *devpriv = dev->private;
1146        int err = 0;
1147        unsigned int flags;
1148        unsigned int arg;
1149
1150        /* Step 1 : check if triggers are trivially valid */
1151
1152        err |= comedi_check_trigger_src(&cmd->start_src,
1153                                        TRIG_NOW | TRIG_EXT | TRIG_INT);
1154
1155        flags = TRIG_FOLLOW;
1156        if (devpriv->master)
1157                flags |= TRIG_TIMER | TRIG_EXT;
1158        err |= comedi_check_trigger_src(&cmd->scan_begin_src, flags);
1159
1160        flags = TRIG_TIMER | TRIG_EXT;
1161        if (devpriv->master)
1162                flags |= TRIG_NOW;
1163        err |= comedi_check_trigger_src(&cmd->convert_src, flags);
1164
1165        err |= comedi_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
1166        err |= comedi_check_trigger_src(&cmd->stop_src,
1167                                        TRIG_COUNT | TRIG_NONE | TRIG_EXT);
1168
1169        if (err)
1170                return 1;
1171
1172        /* Step 2a : make sure trigger sources are unique */
1173
1174        err |= comedi_check_trigger_is_unique(cmd->start_src);
1175        err |= comedi_check_trigger_is_unique(cmd->scan_begin_src);
1176        err |= comedi_check_trigger_is_unique(cmd->convert_src);
1177        err |= comedi_check_trigger_is_unique(cmd->stop_src);
1178
1179        /* Step 2b : and mutually compatible */
1180
1181        if (cmd->start_src == TRIG_EXT && cmd->scan_begin_src == TRIG_EXT)
1182                err |= -EINVAL;
1183
1184        if ((cmd->scan_begin_src & (TRIG_TIMER | TRIG_EXT)) &&
1185            (!(cmd->convert_src & (TRIG_TIMER | TRIG_NOW))))
1186                err |= -EINVAL;
1187
1188        if ((cmd->scan_begin_src == TRIG_FOLLOW) &&
1189            (!(cmd->convert_src & (TRIG_TIMER | TRIG_EXT))))
1190                err |= -EINVAL;
1191
1192        if (cmd->stop_src == TRIG_EXT && cmd->scan_begin_src == TRIG_EXT)
1193                err |= -EINVAL;
1194
1195        if (err)
1196                return 2;
1197
1198        /* Step 3: check if arguments are trivially valid */
1199
1200        switch (cmd->start_src) {
1201        case TRIG_NOW:
1202        case TRIG_EXT:
1203                err |= comedi_check_trigger_arg_is(&cmd->start_arg, 0);
1204                break;
1205        case TRIG_INT:
1206                /* start_arg is the internal trigger (any value) */
1207                break;
1208        }
1209
1210        if (cmd->scan_begin_src & (TRIG_FOLLOW | TRIG_EXT))
1211                err |= comedi_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
1212
1213        if ((cmd->scan_begin_src == TRIG_TIMER) &&
1214            (cmd->convert_src == TRIG_TIMER) && (cmd->scan_end_arg == 1)) {
1215                cmd->scan_begin_src = TRIG_FOLLOW;
1216                cmd->convert_arg = cmd->scan_begin_arg;
1217                cmd->scan_begin_arg = 0;
1218        }
1219
1220        if (cmd->scan_begin_src == TRIG_TIMER) {
1221                err |= comedi_check_trigger_arg_min(&cmd->scan_begin_arg,
1222                                                    devpriv->ai_ns_min);
1223        }
1224
1225        if (cmd->scan_begin_src == TRIG_EXT) {
1226                if (cmd->scan_begin_arg) {
1227                        cmd->scan_begin_arg = 0;
1228                        err |= -EINVAL;
1229                        err |= comedi_check_trigger_arg_max(&cmd->scan_end_arg,
1230                                                            65535);
1231                }
1232        }
1233
1234        if (cmd->convert_src & (TRIG_TIMER | TRIG_NOW)) {
1235                err |= comedi_check_trigger_arg_min(&cmd->convert_arg,
1236                                                    devpriv->ai_ns_min);
1237        }
1238
1239        if (cmd->convert_src == TRIG_EXT)
1240                err |= comedi_check_trigger_arg_is(&cmd->convert_arg, 0);
1241
1242        if (cmd->stop_src == TRIG_COUNT)
1243                err |= comedi_check_trigger_arg_min(&cmd->stop_arg, 1);
1244        else    /* TRIG_NONE */
1245                err |= comedi_check_trigger_arg_is(&cmd->stop_arg, 0);
1246
1247        err |= comedi_check_trigger_arg_min(&cmd->chanlist_len, 1);
1248
1249        err |= comedi_check_trigger_arg_min(&cmd->scan_end_arg,
1250                                            cmd->chanlist_len);
1251
1252        if ((cmd->scan_end_arg % cmd->chanlist_len)) {
1253                cmd->scan_end_arg =
1254                    cmd->chanlist_len * (cmd->scan_end_arg / cmd->chanlist_len);
1255                err |= -EINVAL;
1256        }
1257
1258        if (err)
1259                return 3;
1260
1261        /* step 4: fix up any arguments */
1262
1263        if (cmd->scan_begin_src == TRIG_TIMER) {
1264                arg = cmd->scan_begin_arg;
1265                comedi_8254_cascade_ns_to_timer(dev->pacer, &arg, cmd->flags);
1266                err |= comedi_check_trigger_arg_is(&cmd->scan_begin_arg, arg);
1267        }
1268
1269        if (cmd->convert_src & (TRIG_TIMER | TRIG_NOW)) {
1270                arg = cmd->convert_arg;
1271                comedi_8254_cascade_ns_to_timer(dev->pacer, &arg, cmd->flags);
1272                err |= comedi_check_trigger_arg_is(&cmd->convert_arg, arg);
1273
1274                if (cmd->scan_begin_src == TRIG_TIMER &&
1275                    cmd->convert_src == TRIG_NOW) {
1276                        if (cmd->convert_arg == 0) {
1277                                arg = devpriv->ai_ns_min *
1278                                      (cmd->scan_end_arg + 2);
1279                        } else {
1280                                arg = cmd->convert_arg * cmd->chanlist_len;
1281                        }
1282                        err |= comedi_check_trigger_arg_min(&cmd->
1283                                                            scan_begin_arg,
1284                                                            arg);
1285                }
1286        }
1287
1288        if (err)
1289                return 4;
1290
1291        /* Step 5: check channel list if it exists */
1292
1293        if (cmd->chanlist)
1294                err |= pci9118_ai_check_chanlist(dev, s, cmd);
1295
1296        if (err)
1297                return 5;
1298
1299        return 0;
1300}
1301
1302static int pci9118_ai_eoc(struct comedi_device *dev,
1303                          struct comedi_subdevice *s,
1304                          struct comedi_insn *insn,
1305                          unsigned long context)
1306{
1307        unsigned int status;
1308
1309        status = inl(dev->iobase + PCI9118_AI_STATUS_REG);
1310        if (status & PCI9118_AI_STATUS_ADRDY)
1311                return 0;
1312        return -EBUSY;
1313}
1314
1315static void pci9118_ai_start_conv(struct comedi_device *dev)
1316{
1317        /* writing any value triggers an A/D conversion */
1318        outl(0, dev->iobase + PCI9118_SOFTTRG_REG);
1319}
1320
1321static int pci9118_ai_insn_read(struct comedi_device *dev,
1322                                struct comedi_subdevice *s,
1323                                struct comedi_insn *insn,
1324                                unsigned int *data)
1325{
1326        struct pci9118_private *devpriv = dev->private;
1327        unsigned int val;
1328        int ret;
1329        int i;
1330
1331       /*
1332        * Configure analog input based on the chanspec.
1333        * Acqusition is software controlled without interrupts.
1334        */
1335        pci9118_set_chanlist(dev, s, 1, &insn->chanspec, 0, 0);
1336
1337        /* set default config (disable burst and triggers) */
1338        devpriv->ai_cfg = PCI9118_AI_CFG_PDTRG | PCI9118_AI_CFG_PETRG;
1339        outl(devpriv->ai_cfg, dev->iobase + PCI9118_AI_CFG_REG);
1340
1341        pci9118_ai_reset_fifo(dev);
1342
1343        for (i = 0; i < insn->n; i++) {
1344                pci9118_ai_start_conv(dev);
1345
1346                ret = comedi_timeout(dev, s, insn, pci9118_ai_eoc, 0);
1347                if (ret)
1348                        return ret;
1349
1350                val = inl(dev->iobase + PCI9118_AI_FIFO_REG);
1351                if (s->maxdata == 0xffff)
1352                        data[i] = (val & 0xffff) ^ 0x8000;
1353                else
1354                        data[i] = (val >> 4) & 0xfff;
1355        }
1356
1357        return insn->n;
1358}
1359
1360static int pci9118_ao_insn_write(struct comedi_device *dev,
1361                                 struct comedi_subdevice *s,
1362                                 struct comedi_insn *insn,
1363                                 unsigned int *data)
1364{
1365        unsigned int chan = CR_CHAN(insn->chanspec);
1366        unsigned int val = s->readback[chan];
1367        int i;
1368
1369        for (i = 0; i < insn->n; i++) {
1370                val = data[i];
1371                outl(val, dev->iobase + PCI9118_AO_REG(chan));
1372        }
1373        s->readback[chan] = val;
1374
1375        return insn->n;
1376}
1377
1378static int pci9118_di_insn_bits(struct comedi_device *dev,
1379                                struct comedi_subdevice *s,
1380                                struct comedi_insn *insn,
1381                                unsigned int *data)
1382{
1383        /*
1384         * The digital inputs and outputs share the read register.
1385         * bits [7:4] are the digital outputs
1386         * bits [3:0] are the digital inputs
1387         */
1388        data[1] = inl(dev->iobase + PCI9118_DIO_REG) & 0xf;
1389
1390        return insn->n;
1391}
1392
1393static int pci9118_do_insn_bits(struct comedi_device *dev,
1394                                struct comedi_subdevice *s,
1395                                struct comedi_insn *insn,
1396                                unsigned int *data)
1397{
1398        /*
1399         * The digital outputs are set with the same register that
1400         * the digital inputs and outputs are read from. But the
1401         * outputs are set with bits [3:0] so we can simply write
1402         * the s->state to set them.
1403         */
1404        if (comedi_dio_update_state(s, data))
1405                outl(s->state, dev->iobase + PCI9118_DIO_REG);
1406
1407        data[1] = s->state;
1408
1409        return insn->n;
1410}
1411
1412static void pci9118_reset(struct comedi_device *dev)
1413{
1414        /* reset analog input subsystem */
1415        outl(0, dev->iobase + PCI9118_INT_CTRL_REG);
1416        outl(0, dev->iobase + PCI9118_AI_CTRL_REG);
1417        outl(0, dev->iobase + PCI9118_AI_CFG_REG);
1418        pci9118_ai_reset_fifo(dev);
1419
1420        /* clear any pending interrupts and status */
1421        inl(dev->iobase + PCI9118_INT_CTRL_REG);
1422        inl(dev->iobase + PCI9118_AI_STATUS_REG);
1423
1424        /* reset DMA and scan queue */
1425        outl(0, dev->iobase + PCI9118_AI_BURST_NUM_REG);
1426        outl(1, dev->iobase + PCI9118_AI_AUTOSCAN_MODE_REG);
1427        outl(2, dev->iobase + PCI9118_AI_AUTOSCAN_MODE_REG);
1428
1429        /* reset analog outputs to 0V */
1430        outl(2047, dev->iobase + PCI9118_AO_REG(0));
1431        outl(2047, dev->iobase + PCI9118_AO_REG(1));
1432}
1433
1434static struct pci_dev *pci9118_find_pci(struct comedi_device *dev,
1435                                        struct comedi_devconfig *it)
1436{
1437        struct pci_dev *pcidev = NULL;
1438        int bus = it->options[0];
1439        int slot = it->options[1];
1440
1441        for_each_pci_dev(pcidev) {
1442                if (pcidev->vendor != PCI_VENDOR_ID_AMCC)
1443                        continue;
1444                if (pcidev->device != 0x80d9)
1445                        continue;
1446                if (bus || slot) {
1447                        /* requested particular bus/slot */
1448                        if (pcidev->bus->number != bus ||
1449                            PCI_SLOT(pcidev->devfn) != slot)
1450                                continue;
1451                }
1452                return pcidev;
1453        }
1454        dev_err(dev->class_dev,
1455                "no supported board found! (req. bus/slot : %d/%d)\n",
1456                bus, slot);
1457        return NULL;
1458}
1459
1460static void pci9118_alloc_dma(struct comedi_device *dev)
1461{
1462        struct pci9118_private *devpriv = dev->private;
1463        struct pci9118_dmabuf *dmabuf;
1464        int order;
1465        int i;
1466
1467        for (i = 0; i < 2; i++) {
1468                dmabuf = &devpriv->dmabuf[i];
1469                for (order = 2; order >= 0; order--) {
1470                        dmabuf->virt =
1471                            dma_alloc_coherent(dev->hw_dev, PAGE_SIZE << order,
1472                                               &dmabuf->hw, GFP_KERNEL);
1473                        if (dmabuf->virt)
1474                                break;
1475                }
1476                if (!dmabuf->virt)
1477                        break;
1478                dmabuf->size = PAGE_SIZE << order;
1479
1480                if (i == 0)
1481                        devpriv->master = 1;
1482                if (i == 1)
1483                        devpriv->dma_doublebuf = 1;
1484        }
1485}
1486
1487static void pci9118_free_dma(struct comedi_device *dev)
1488{
1489        struct pci9118_private *devpriv = dev->private;
1490        struct pci9118_dmabuf *dmabuf;
1491        int i;
1492
1493        if (!devpriv)
1494                return;
1495
1496        for (i = 0; i < 2; i++) {
1497                dmabuf = &devpriv->dmabuf[i];
1498                if (dmabuf->virt) {
1499                        dma_free_coherent(dev->hw_dev, dmabuf->size,
1500                                          dmabuf->virt, dmabuf->hw);
1501                }
1502        }
1503}
1504
1505static int pci9118_common_attach(struct comedi_device *dev,
1506                                 int ext_mux, int softsshdelay)
1507{
1508        const struct pci9118_boardinfo *board = dev->board_ptr;
1509        struct pci_dev *pcidev = comedi_to_pci_dev(dev);
1510        struct pci9118_private *devpriv;
1511        struct comedi_subdevice *s;
1512        int ret;
1513        int i;
1514        u16 u16w;
1515
1516        devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
1517        if (!devpriv)
1518                return -ENOMEM;
1519
1520        ret = comedi_pci_enable(dev);
1521        if (ret)
1522                return ret;
1523        pci_set_master(pcidev);
1524
1525        devpriv->iobase_a = pci_resource_start(pcidev, 0);
1526        dev->iobase = pci_resource_start(pcidev, 2);
1527
1528        dev->pacer = comedi_8254_init(dev->iobase + PCI9118_TIMER_BASE,
1529                                      I8254_OSC_BASE_4MHZ, I8254_IO32, 0);
1530        if (!dev->pacer)
1531                return -ENOMEM;
1532
1533        pci9118_reset(dev);
1534
1535        if (pcidev->irq) {
1536                ret = request_irq(pcidev->irq, pci9118_interrupt, IRQF_SHARED,
1537                                  dev->board_name, dev);
1538                if (ret == 0) {
1539                        dev->irq = pcidev->irq;
1540
1541                        pci9118_alloc_dma(dev);
1542                }
1543        }
1544
1545        if (ext_mux > 0) {
1546                if (ext_mux > 256)
1547                        ext_mux = 256;  /* max 256 channels! */
1548                if (softsshdelay > 0)
1549                        if (ext_mux > 128)
1550                                ext_mux = 128;
1551                devpriv->usemux = 1;
1552        } else {
1553                devpriv->usemux = 0;
1554        }
1555
1556        if (softsshdelay < 0) {
1557                /* select sample&hold signal polarity */
1558                devpriv->softsshdelay = -softsshdelay;
1559                devpriv->softsshsample = 0x80;
1560                devpriv->softsshhold = 0x00;
1561        } else {
1562                devpriv->softsshdelay = softsshdelay;
1563                devpriv->softsshsample = 0x00;
1564                devpriv->softsshhold = 0x80;
1565        }
1566
1567        pci_read_config_word(pcidev, PCI_COMMAND, &u16w);
1568        pci_write_config_word(pcidev, PCI_COMMAND, u16w | 64);
1569                                /* Enable parity check for parity error */
1570
1571        ret = comedi_alloc_subdevices(dev, 4);
1572        if (ret)
1573                return ret;
1574
1575        /* Analog Input subdevice */
1576        s = &dev->subdevices[0];
1577        s->type         = COMEDI_SUBD_AI;
1578        s->subdev_flags = SDF_READABLE | SDF_COMMON | SDF_GROUND | SDF_DIFF;
1579        s->n_chan       = (devpriv->usemux) ? ext_mux : 16;
1580        s->maxdata      = board->ai_is_16bit ? 0xffff : 0x0fff;
1581        s->range_table  = board->is_hg ? &pci9118hg_ai_range
1582                                       : &pci9118_ai_range;
1583        s->insn_read    = pci9118_ai_insn_read;
1584        if (dev->irq) {
1585                dev->read_subdev = s;
1586                s->subdev_flags |= SDF_CMD_READ;
1587                s->len_chanlist = 255;
1588                s->do_cmdtest   = pci9118_ai_cmdtest;
1589                s->do_cmd       = pci9118_ai_cmd;
1590                s->cancel       = pci9118_ai_cancel;
1591                s->munge        = pci9118_ai_munge;
1592        }
1593
1594        if (s->maxdata == 0xffff) {
1595                /*
1596                 * 16-bit samples are from an ADS7805 A/D converter.
1597                 * Minimum sampling rate is 10us.
1598                 */
1599                devpriv->ai_ns_min = 10000;
1600        } else {
1601                /*
1602                 * 12-bit samples are from an ADS7800 A/D converter.
1603                 * Minimum sampling rate is 3us.
1604                 */
1605                devpriv->ai_ns_min = 3000;
1606        }
1607
1608        /* Analog Output subdevice */
1609        s = &dev->subdevices[1];
1610        s->type         = COMEDI_SUBD_AO;
1611        s->subdev_flags = SDF_WRITABLE | SDF_GROUND | SDF_COMMON;
1612        s->n_chan       = 2;
1613        s->maxdata      = 0x0fff;
1614        s->range_table  = &range_bipolar10;
1615        s->insn_write   = pci9118_ao_insn_write;
1616
1617        ret = comedi_alloc_subdev_readback(s);
1618        if (ret)
1619                return ret;
1620
1621        /* the analog outputs were reset to 0V, make the readback match */
1622        for (i = 0; i < s->n_chan; i++)
1623                s->readback[i] = 2047;
1624
1625        /* Digital Input subdevice */
1626        s = &dev->subdevices[2];
1627        s->type         = COMEDI_SUBD_DI;
1628        s->subdev_flags = SDF_READABLE;
1629        s->n_chan       = 4;
1630        s->maxdata      = 1;
1631        s->range_table  = &range_digital;
1632        s->insn_bits    = pci9118_di_insn_bits;
1633
1634        /* Digital Output subdevice */
1635        s = &dev->subdevices[3];
1636        s->type         = COMEDI_SUBD_DO;
1637        s->subdev_flags = SDF_WRITABLE;
1638        s->n_chan       = 4;
1639        s->maxdata      = 1;
1640        s->range_table  = &range_digital;
1641        s->insn_bits    = pci9118_do_insn_bits;
1642
1643        /* get the current state of the digital outputs */
1644        s->state = inl(dev->iobase + PCI9118_DIO_REG) >> 4;
1645
1646        return 0;
1647}
1648
1649static int pci9118_attach(struct comedi_device *dev,
1650                          struct comedi_devconfig *it)
1651{
1652        struct pci_dev *pcidev;
1653        int ext_mux, softsshdelay;
1654
1655        ext_mux = it->options[2];
1656        softsshdelay = it->options[4];
1657
1658        pcidev = pci9118_find_pci(dev, it);
1659        if (!pcidev)
1660                return -EIO;
1661        comedi_set_hw_dev(dev, &pcidev->dev);
1662
1663        return pci9118_common_attach(dev, ext_mux, softsshdelay);
1664}
1665
1666static int pci9118_auto_attach(struct comedi_device *dev,
1667                               unsigned long context)
1668{
1669        struct pci_dev *pcidev = comedi_to_pci_dev(dev);
1670        const struct pci9118_boardinfo *board = NULL;
1671
1672        if (context < ARRAY_SIZE(pci9118_boards))
1673                board = &pci9118_boards[context];
1674        if (!board)
1675                return -ENODEV;
1676        dev->board_ptr = board;
1677        dev->board_name = board->name;
1678
1679        /*
1680         * Need to 'get' the PCI device to match the 'put' in pci9118_detach().
1681         * (The 'put' also matches the implicit 'get' by pci9118_find_pci().)
1682         */
1683        pci_dev_get(pcidev);
1684        /* no external mux, no sample-hold delay */
1685        return pci9118_common_attach(dev, 0, 0);
1686}
1687
1688static void pci9118_detach(struct comedi_device *dev)
1689{
1690        struct pci_dev *pcidev = comedi_to_pci_dev(dev);
1691
1692        if (dev->iobase)
1693                pci9118_reset(dev);
1694        comedi_pci_detach(dev);
1695        pci9118_free_dma(dev);
1696        if (pcidev)
1697                pci_dev_put(pcidev);
1698}
1699
1700static struct comedi_driver adl_pci9118_driver = {
1701        .driver_name    = "adl_pci9118",
1702        .module         = THIS_MODULE,
1703        .attach         = pci9118_attach,
1704        .auto_attach    = pci9118_auto_attach,
1705        .detach         = pci9118_detach,
1706        .num_names      = ARRAY_SIZE(pci9118_boards),
1707        .board_name     = &pci9118_boards[0].name,
1708        .offset         = sizeof(struct pci9118_boardinfo),
1709};
1710
1711static int adl_pci9118_pci_probe(struct pci_dev *dev,
1712                                 const struct pci_device_id *id)
1713{
1714        return comedi_pci_auto_config(dev, &adl_pci9118_driver,
1715                                      id->driver_data);
1716}
1717
1718/* FIXME: All the supported board types have the same device ID! */
1719static const struct pci_device_id adl_pci9118_pci_table[] = {
1720        { PCI_VDEVICE(AMCC, 0x80d9), BOARD_PCI9118DG },
1721/*      { PCI_VDEVICE(AMCC, 0x80d9), BOARD_PCI9118HG }, */
1722/*      { PCI_VDEVICE(AMCC, 0x80d9), BOARD_PCI9118HR }, */
1723        { 0 }
1724};
1725MODULE_DEVICE_TABLE(pci, adl_pci9118_pci_table);
1726
1727static struct pci_driver adl_pci9118_pci_driver = {
1728        .name           = "adl_pci9118",
1729        .id_table       = adl_pci9118_pci_table,
1730        .probe          = adl_pci9118_pci_probe,
1731        .remove         = comedi_pci_auto_unconfig,
1732};
1733module_comedi_pci_driver(adl_pci9118_driver, adl_pci9118_pci_driver);
1734
1735MODULE_AUTHOR("Comedi http://www.comedi.org");
1736MODULE_DESCRIPTION("Comedi low-level driver");
1737MODULE_LICENSE("GPL");
1738
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.