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