linux/drivers/staging/comedi/drivers/pcl812.c
<<
>>
Prefs
   1/*
   2 * comedi/drivers/pcl812.c
   3 *
   4 * Author: Michal Dobes <dobes@tesnet.cz>
   5 *
   6 * hardware driver for Advantech cards
   7 *  card:   PCL-812, PCL-812PG, PCL-813, PCL-813B
   8 *  driver: pcl812,  pcl812pg,  pcl813,  pcl813b
   9 * and for ADlink cards
  10 *  card:   ACL-8112DG, ACL-8112HG, ACL-8112PG, ACL-8113, ACL-8216
  11 *  driver: acl8112dg,  acl8112hg,  acl8112pg,  acl8113,  acl8216
  12 * and for ICP DAS cards
  13 *  card:   ISO-813, A-821PGH, A-821PGL, A-821PGL-NDA, A-822PGH, A-822PGL,
  14 *  driver: iso813,  a821pgh,  a-821pgl, a-821pglnda,  a822pgh,  a822pgl,
  15 *  card:   A-823PGH, A-823PGL, A-826PG
  16 * driver:  a823pgh,  a823pgl,  a826pg
  17 */
  18
  19/*
  20 * Driver: pcl812
  21 * Description: Advantech PCL-812/PG, PCL-813/B,
  22 *           ADLink ACL-8112DG/HG/PG, ACL-8113, ACL-8216,
  23 *           ICP DAS A-821PGH/PGL/PGL-NDA, A-822PGH/PGL, A-823PGH/PGL, A-826PG,
  24 *           ICP DAS ISO-813
  25 * Author: Michal Dobes <dobes@tesnet.cz>
  26 * Devices: [Advantech] PCL-812 (pcl812), PCL-812PG (pcl812pg),
  27 *      PCL-813 (pcl813), PCL-813B (pcl813b), [ADLink] ACL-8112DG (acl8112dg),
  28 *      ACL-8112HG (acl8112hg), ACL-8113 (acl-8113), ACL-8216 (acl8216),
  29 *      [ICP] ISO-813 (iso813), A-821PGH (a821pgh), A-821PGL (a821pgl),
  30 *      A-821PGL-NDA (a821pclnda), A-822PGH (a822pgh), A-822PGL (a822pgl),
  31 *      A-823PGH (a823pgh), A-823PGL (a823pgl), A-826PG (a826pg)
  32 * Updated: Mon, 06 Aug 2007 12:03:15 +0100
  33 * Status: works (I hope. My board fire up under my hands
  34 *             and I cann't test all features.)
  35 *
  36 * This driver supports insn and cmd interfaces. Some boards support only insn
  37 * because their hardware don't allow more (PCL-813/B, ACL-8113, ISO-813).
  38 * Data transfer over DMA is supported only when you measure only one
  39 * channel, this is too hardware limitation of these boards.
  40 *
  41 * Options for PCL-812:
  42 *   [0] - IO Base
  43 *   [1] - IRQ  (0=disable, 2, 3, 4, 5, 6, 7; 10, 11, 12, 14, 15)
  44 *   [2] - DMA  (0=disable, 1, 3)
  45 *   [3] - 0=trigger source is internal 8253 with 2MHz clock
  46 *         1=trigger source is external
  47 *   [4] - 0=A/D input range is +/-10V
  48 *         1=A/D input range is +/-5V
  49 *         2=A/D input range is +/-2.5V
  50 *         3=A/D input range is +/-1.25V
  51 *         4=A/D input range is +/-0.625V
  52 *         5=A/D input range is +/-0.3125V
  53 *   [5] - 0=D/A outputs 0-5V  (internal reference -5V)
  54 *         1=D/A outputs 0-10V (internal reference -10V)
  55 *         2=D/A outputs unknown (external reference)
  56 *
  57 * Options for PCL-812PG, ACL-8112PG:
  58 *   [0] - IO Base
  59 *   [1] - IRQ  (0=disable, 2, 3, 4, 5, 6, 7; 10, 11, 12, 14, 15)
  60 *   [2] - DMA  (0=disable, 1, 3)
  61 *   [3] - 0=trigger source is internal 8253 with 2MHz clock
  62 *         1=trigger source is external
  63 *   [4] - 0=A/D have max +/-5V input
  64 *         1=A/D have max +/-10V input
  65 *   [5] - 0=D/A outputs 0-5V  (internal reference -5V)
  66 *         1=D/A outputs 0-10V (internal reference -10V)
  67 *         2=D/A outputs unknown (external reference)
  68 *
  69 * Options for ACL-8112DG/HG, A-822PGL/PGH, A-823PGL/PGH, ACL-8216, A-826PG:
  70 *   [0] - IO Base
  71 *   [1] - IRQ  (0=disable, 2, 3, 4, 5, 6, 7; 10, 11, 12, 14, 15)
  72 *   [2] - DMA  (0=disable, 1, 3)
  73 *   [3] - 0=trigger source is internal 8253 with 2MHz clock
  74 *         1=trigger source is external
  75 *   [4] - 0=A/D channels are S.E.
  76 *         1=A/D channels are DIFF
  77 *   [5] - 0=D/A outputs 0-5V  (internal reference -5V)
  78 *         1=D/A outputs 0-10V (internal reference -10V)
  79 *         2=D/A outputs unknown (external reference)
  80 *
  81 * Options for A-821PGL/PGH:
  82 *   [0] - IO Base
  83 *   [1] - IRQ  (0=disable, 2, 3, 4, 5, 6, 7)
  84 *   [2] - 0=A/D channels are S.E.
  85 *         1=A/D channels are DIFF
  86 *   [3] - 0=D/A output 0-5V  (internal reference -5V)
  87 *         1=D/A output 0-10V (internal reference -10V)
  88 *
  89 * Options for A-821PGL-NDA:
  90 *   [0] - IO Base
  91 *   [1] - IRQ  (0=disable, 2, 3, 4, 5, 6, 7)
  92 *   [2] - 0=A/D channels are S.E.
  93 *         1=A/D channels are DIFF
  94 *
  95 * Options for PCL-813:
  96 *   [0] - IO Base
  97 *
  98 * Options for PCL-813B:
  99 *   [0] - IO Base
 100 *   [1] - 0= bipolar inputs
 101 *         1= unipolar inputs
 102 *
 103 * Options for ACL-8113, ISO-813:
 104 *   [0] - IO Base
 105 *   [1] - 0= 10V bipolar inputs
 106 *         1= 10V unipolar inputs
 107 *         2= 20V bipolar inputs
 108 *         3= 20V unipolar inputs
 109 */
 110
 111#include <linux/module.h>
 112#include <linux/interrupt.h>
 113#include <linux/gfp.h>
 114#include "../comedidev.h"
 115
 116#include <linux/delay.h>
 117#include <linux/io.h>
 118#include <asm/dma.h>
 119
 120#include "comedi_fc.h"
 121#include "8253.h"
 122
 123/* hardware types of the cards */
 124#define boardPCL812PG         0 /* and ACL-8112PG */
 125#define boardPCL813B          1
 126#define boardPCL812           2
 127#define boardPCL813           3
 128#define boardISO813           5
 129#define boardACL8113          6
 130#define boardACL8112          7 /* ACL-8112DG/HG, A-822PGL/PGH, A-823PGL/PGH */
 131#define boardACL8216          8 /* and ICP DAS A-826PG */
 132#define boardA821             9 /* PGH, PGL, PGL/NDA versions */
 133
 134#define PCLx1x_IORANGE       16
 135
 136#define PCL812_CTR0           0
 137#define PCL812_CTR1           1
 138#define PCL812_CTR2           2
 139#define PCL812_CTRCTL         3
 140#define PCL812_AD_LO          4
 141#define PCL812_DA1_LO         4
 142#define PCL812_AD_HI          5
 143#define PCL812_DA1_HI         5
 144#define PCL812_DA2_LO         6
 145#define PCL812_DI_LO          6
 146#define PCL812_DA2_HI         7
 147#define PCL812_DI_HI          7
 148#define PCL812_CLRINT         8
 149#define PCL812_GAIN           9
 150#define PCL812_MUX           10
 151#define PCL812_MODE          11
 152#define PCL812_CNTENABLE     10
 153#define PCL812_SOFTTRIG      12
 154#define PCL812_DO_LO         13
 155#define PCL812_DO_HI         14
 156
 157#define PCL812_DRDY        0x10 /* =0 data ready */
 158
 159#define ACL8216_STATUS        8 /* 5. bit signalize data ready */
 160
 161#define ACL8216_DRDY       0x20 /* =0 data ready */
 162
 163#define MAX_CHANLIST_LEN    256 /* length of scan list */
 164
 165static const struct comedi_lrange range_pcl812pg_ai = {
 166        5, {
 167                BIP_RANGE(5),
 168                BIP_RANGE(2.5),
 169                BIP_RANGE(1.25),
 170                BIP_RANGE(0.625),
 171                BIP_RANGE(0.3125)
 172        }
 173};
 174
 175static const struct comedi_lrange range_pcl812pg2_ai = {
 176        5, {
 177                BIP_RANGE(10),
 178                BIP_RANGE(5),
 179                BIP_RANGE(2.5),
 180                BIP_RANGE(1.25),
 181                BIP_RANGE(0.625)
 182        }
 183};
 184
 185static const struct comedi_lrange range812_bipolar1_25 = {
 186        1, {
 187                BIP_RANGE(1.25)
 188        }
 189};
 190
 191static const struct comedi_lrange range812_bipolar0_625 = {
 192        1, {
 193                BIP_RANGE(0.625)
 194        }
 195};
 196
 197static const struct comedi_lrange range812_bipolar0_3125 = {
 198        1, {
 199                BIP_RANGE(0.3125)
 200        }
 201};
 202
 203static const struct comedi_lrange range_pcl813b_ai = {
 204        4, {
 205                BIP_RANGE(5),
 206                BIP_RANGE(2.5),
 207                BIP_RANGE(1.25),
 208                BIP_RANGE(0.625)
 209        }
 210};
 211
 212static const struct comedi_lrange range_pcl813b2_ai = {
 213        4, {
 214                UNI_RANGE(10),
 215                UNI_RANGE(5),
 216                UNI_RANGE(2.5),
 217                UNI_RANGE(1.25)
 218        }
 219};
 220
 221static const struct comedi_lrange range_iso813_1_ai = {
 222        5, {
 223                BIP_RANGE(5),
 224                BIP_RANGE(2.5),
 225                BIP_RANGE(1.25),
 226                BIP_RANGE(0.625),
 227                BIP_RANGE(0.3125)
 228        }
 229};
 230
 231static const struct comedi_lrange range_iso813_1_2_ai = {
 232        5, {
 233                UNI_RANGE(10),
 234                UNI_RANGE(5),
 235                UNI_RANGE(2.5),
 236                UNI_RANGE(1.25),
 237                UNI_RANGE(0.625)
 238        }
 239};
 240
 241static const struct comedi_lrange range_iso813_2_ai = {
 242        4, {
 243                BIP_RANGE(5),
 244                BIP_RANGE(2.5),
 245                BIP_RANGE(1.25),
 246                BIP_RANGE(0.625)
 247        }
 248};
 249
 250static const struct comedi_lrange range_iso813_2_2_ai = {
 251        4, {
 252                UNI_RANGE(10),
 253                UNI_RANGE(5),
 254                UNI_RANGE(2.5),
 255                UNI_RANGE(1.25)
 256        }
 257};
 258
 259static const struct comedi_lrange range_acl8113_1_ai = {
 260        4, {
 261                BIP_RANGE(5),
 262                BIP_RANGE(2.5),
 263                BIP_RANGE(1.25),
 264                BIP_RANGE(0.625)
 265        }
 266};
 267
 268static const struct comedi_lrange range_acl8113_1_2_ai = {
 269        4, {
 270                UNI_RANGE(10),
 271                UNI_RANGE(5),
 272                UNI_RANGE(2.5),
 273                UNI_RANGE(1.25)
 274        }
 275};
 276
 277static const struct comedi_lrange range_acl8113_2_ai = {
 278        3, {
 279                BIP_RANGE(5),
 280                BIP_RANGE(2.5),
 281                BIP_RANGE(1.25)
 282        }
 283};
 284
 285static const struct comedi_lrange range_acl8113_2_2_ai = {
 286        3, {
 287                UNI_RANGE(10),
 288                UNI_RANGE(5),
 289                UNI_RANGE(2.5)
 290        }
 291};
 292
 293static const struct comedi_lrange range_acl8112dg_ai = {
 294        9, {
 295                BIP_RANGE(5),
 296                BIP_RANGE(2.5),
 297                BIP_RANGE(1.25),
 298                BIP_RANGE(0.625),
 299                UNI_RANGE(10),
 300                UNI_RANGE(5),
 301                UNI_RANGE(2.5),
 302                UNI_RANGE(1.25),
 303                BIP_RANGE(10)
 304        }
 305};
 306
 307static const struct comedi_lrange range_acl8112hg_ai = {
 308        12, {
 309                BIP_RANGE(5),
 310                BIP_RANGE(0.5),
 311                BIP_RANGE(0.05),
 312                BIP_RANGE(0.005),
 313                UNI_RANGE(10),
 314                UNI_RANGE(1),
 315                UNI_RANGE(0.1),
 316                UNI_RANGE(0.01),
 317                BIP_RANGE(10),
 318                BIP_RANGE(1),
 319                BIP_RANGE(0.1),
 320                BIP_RANGE(0.01)
 321        }
 322};
 323
 324static const struct comedi_lrange range_a821pgh_ai = {
 325        4, {
 326                BIP_RANGE(5),
 327                BIP_RANGE(0.5),
 328                BIP_RANGE(0.05),
 329                BIP_RANGE(0.005)
 330        }
 331};
 332
 333struct pcl812_board {
 334
 335        const char *name;       /*  board name */
 336        int board_type;         /*  type of this board */
 337        int n_aichan;           /*  num of AI chans in S.E. */
 338        int n_aichan_diff;      /*  DIFF num of chans */
 339        int n_aochan;           /*  num of DA chans */
 340        int n_dichan;           /*  DI and DO chans */
 341        int n_dochan;
 342        int ai_maxdata;         /*  AI resolution */
 343        unsigned int ai_ns_min; /*  max sample speed of card v ns */
 344        unsigned int i8254_osc_base;    /*  clock base */
 345        const struct comedi_lrange *rangelist_ai;       /*  rangelist for A/D */
 346        const struct comedi_lrange *rangelist_ao;       /*  rangelist for D/A */
 347        unsigned int IRQbits;   /*  allowed IRQ */
 348        unsigned char DMAbits;  /*  allowed DMA chans */
 349        unsigned char io_range; /*  iorange for this board */
 350        unsigned char haveMPC508;       /*  1=board use MPC508A multiplexor */
 351};
 352
 353struct pcl812_private {
 354
 355        unsigned char valid;    /*  =1 device is OK */
 356        unsigned char dma;      /*  >0 use dma ( usedDMA channel) */
 357        unsigned char use_diff; /*  =1 diff inputs */
 358        unsigned char use_MPC;  /*  1=board uses MPC508A multiplexor */
 359        unsigned char use_ext_trg;      /*  1=board uses external trigger */
 360        unsigned char range_correction; /*  =1 we must add 1 to range number */
 361        unsigned char old_chan_reg;     /*  lastly used chan/gain pair */
 362        unsigned char old_gain_reg;
 363        unsigned char mode_reg_int;     /*  there is stored INT number for some card */
 364        unsigned char ai_neverending;   /*  =1 we do unlimited AI */
 365        unsigned char ai_eos;   /*  1=EOS wake up */
 366        unsigned char ai_dma;   /*  =1 we use DMA */
 367        unsigned int ai_poll_ptr;       /*  how many sampes transfer poll */
 368        unsigned int ai_scans;  /*  len of scanlist */
 369        unsigned int ai_act_scan;       /*  how many scans we finished */
 370        unsigned int ai_chanlist[MAX_CHANLIST_LEN];     /*  our copy of channel/range list */
 371        unsigned int ai_n_chan; /*  how many channels is measured */
 372        unsigned int ai_flags;  /*  flaglist */
 373        unsigned int ai_data_len;       /*  len of data buffer */
 374        unsigned int ai_is16b;  /*  =1 we have 16 bit card */
 375        unsigned long dmabuf[2];        /*  PTR to DMA buf */
 376        unsigned int dmapages[2];       /*  how many pages we have allocated */
 377        unsigned int hwdmaptr[2];       /*  HW PTR to DMA buf */
 378        unsigned int hwdmasize[2];      /*  DMA buf size in bytes */
 379        unsigned int dmabytestomove[2]; /*  how many bytes DMA transfer */
 380        int next_dma_buf;       /*  which buffer is next to use */
 381        unsigned int dma_runs_to_end;   /*  how many times we must switch DMA buffers */
 382        unsigned int last_dma_run;      /*  how many bytes to transfer on last DMA buffer */
 383        unsigned int max_812_ai_mode0_rangewait;        /*  setling time for gain */
 384        unsigned int ao_readback[2];    /*  data for AO readback */
 385};
 386
 387/*
 388==============================================================================
 389*/
 390static void start_pacer(struct comedi_device *dev, int mode,
 391                        unsigned int divisor1, unsigned int divisor2);
 392static void setup_range_channel(struct comedi_device *dev,
 393                                struct comedi_subdevice *s,
 394                                unsigned int rangechan, char wait);
 395static int pcl812_ai_cancel(struct comedi_device *dev,
 396                            struct comedi_subdevice *s);
 397/*
 398==============================================================================
 399*/
 400static int pcl812_ai_insn_read(struct comedi_device *dev,
 401                               struct comedi_subdevice *s,
 402                               struct comedi_insn *insn, unsigned int *data)
 403{
 404        struct pcl812_private *devpriv = dev->private;
 405        int n;
 406        int timeout, hi;
 407
 408        /* select software trigger */
 409        outb(devpriv->mode_reg_int | 1, dev->iobase + PCL812_MODE);
 410        /*  select channel and renge */
 411        setup_range_channel(dev, s, insn->chanspec, 1);
 412        for (n = 0; n < insn->n; n++) {
 413                /* start conversion */
 414                outb(255, dev->iobase + PCL812_SOFTTRIG);
 415                udelay(5);
 416                timeout = 50;   /* wait max 50us, it must finish under 33us */
 417                while (timeout--) {
 418                        hi = inb(dev->iobase + PCL812_AD_HI);
 419                        if (!(hi & PCL812_DRDY))
 420                                goto conv_finish;
 421                        udelay(1);
 422                }
 423                dev_dbg(dev->class_dev, "A/D insn read timeout\n");
 424                outb(devpriv->mode_reg_int | 0, dev->iobase + PCL812_MODE);
 425                return -ETIME;
 426
 427conv_finish:
 428                data[n] = ((hi & 0xf) << 8) | inb(dev->iobase + PCL812_AD_LO);
 429        }
 430        outb(devpriv->mode_reg_int | 0, dev->iobase + PCL812_MODE);
 431        return n;
 432}
 433
 434/*
 435==============================================================================
 436*/
 437static int acl8216_ai_insn_read(struct comedi_device *dev,
 438                                struct comedi_subdevice *s,
 439                                struct comedi_insn *insn, unsigned int *data)
 440{
 441        int n;
 442        int timeout;
 443
 444        /* select software trigger */
 445        outb(1, dev->iobase + PCL812_MODE);
 446        /*  select channel and renge */
 447        setup_range_channel(dev, s, insn->chanspec, 1);
 448        for (n = 0; n < insn->n; n++) {
 449                /* start conversion */
 450                outb(255, dev->iobase + PCL812_SOFTTRIG);
 451                udelay(5);
 452                timeout = 50;   /* wait max 50us, it must finish under 33us */
 453                while (timeout--) {
 454                        if (!(inb(dev->iobase + ACL8216_STATUS) & ACL8216_DRDY))
 455                                goto conv_finish;
 456                        udelay(1);
 457                }
 458                dev_dbg(dev->class_dev, "A/D insn read timeout\n");
 459                outb(0, dev->iobase + PCL812_MODE);
 460                return -ETIME;
 461
 462conv_finish:
 463                data[n] =
 464                    (inb(dev->iobase +
 465                         PCL812_AD_HI) << 8) | inb(dev->iobase + PCL812_AD_LO);
 466        }
 467        outb(0, dev->iobase + PCL812_MODE);
 468        return n;
 469}
 470
 471/*
 472==============================================================================
 473*/
 474static int pcl812_ao_insn_write(struct comedi_device *dev,
 475                                struct comedi_subdevice *s,
 476                                struct comedi_insn *insn, unsigned int *data)
 477{
 478        struct pcl812_private *devpriv = dev->private;
 479        int chan = CR_CHAN(insn->chanspec);
 480        int i;
 481
 482        for (i = 0; i < insn->n; i++) {
 483                outb((data[i] & 0xff),
 484                     dev->iobase + (chan ? PCL812_DA2_LO : PCL812_DA1_LO));
 485                outb((data[i] >> 8) & 0x0f,
 486                     dev->iobase + (chan ? PCL812_DA2_HI : PCL812_DA1_HI));
 487                devpriv->ao_readback[chan] = data[i];
 488        }
 489
 490        return i;
 491}
 492
 493/*
 494==============================================================================
 495*/
 496static int pcl812_ao_insn_read(struct comedi_device *dev,
 497                               struct comedi_subdevice *s,
 498                               struct comedi_insn *insn, unsigned int *data)
 499{
 500        struct pcl812_private *devpriv = dev->private;
 501        int chan = CR_CHAN(insn->chanspec);
 502        int i;
 503
 504        for (i = 0; i < insn->n; i++)
 505                data[i] = devpriv->ao_readback[chan];
 506
 507        return i;
 508}
 509
 510/*
 511==============================================================================
 512*/
 513static int pcl812_di_insn_bits(struct comedi_device *dev,
 514                               struct comedi_subdevice *s,
 515                               struct comedi_insn *insn, unsigned int *data)
 516{
 517        data[1] = inb(dev->iobase + PCL812_DI_LO);
 518        data[1] |= inb(dev->iobase + PCL812_DI_HI) << 8;
 519
 520        return insn->n;
 521}
 522
 523static int pcl812_do_insn_bits(struct comedi_device *dev,
 524                               struct comedi_subdevice *s,
 525                               struct comedi_insn *insn,
 526                               unsigned int *data)
 527{
 528        if (comedi_dio_update_state(s, data)) {
 529                outb(s->state & 0xff, dev->iobase + PCL812_DO_LO);
 530                outb((s->state >> 8), dev->iobase + PCL812_DO_HI);
 531        }
 532
 533        data[1] = s->state;
 534
 535        return insn->n;
 536}
 537
 538/*
 539==============================================================================
 540*/
 541static int pcl812_ai_cmdtest(struct comedi_device *dev,
 542                             struct comedi_subdevice *s, struct comedi_cmd *cmd)
 543{
 544        const struct pcl812_board *board = comedi_board(dev);
 545        struct pcl812_private *devpriv = dev->private;
 546        int err = 0;
 547        unsigned int flags;
 548        int tmp, divisor1, divisor2;
 549
 550        /* Step 1 : check if triggers are trivially valid */
 551
 552        err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW);
 553        err |= cfc_check_trigger_src(&cmd->scan_begin_src, TRIG_FOLLOW);
 554
 555        if (devpriv->use_ext_trg)
 556                flags = TRIG_EXT;
 557        else
 558                flags = TRIG_TIMER;
 559        err |= cfc_check_trigger_src(&cmd->convert_src, flags);
 560
 561        err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
 562        err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE);
 563
 564        if (err)
 565                return 1;
 566
 567        /* Step 2a : make sure trigger sources are unique */
 568
 569        err |= cfc_check_trigger_is_unique(cmd->stop_src);
 570
 571        /* Step 2b : and mutually compatible */
 572
 573        if (err)
 574                return 2;
 575
 576        /* Step 3: check if arguments are trivially valid */
 577
 578        err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
 579        err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
 580
 581        if (cmd->convert_src == TRIG_TIMER)
 582                err |= cfc_check_trigger_arg_min(&cmd->convert_arg,
 583                                                 board->ai_ns_min);
 584        else    /* TRIG_EXT */
 585                err |= cfc_check_trigger_arg_is(&cmd->convert_arg, 0);
 586
 587        err |= cfc_check_trigger_arg_min(&cmd->chanlist_len, 1);
 588        err |= cfc_check_trigger_arg_max(&cmd->chanlist_len, MAX_CHANLIST_LEN);
 589        err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
 590
 591        if (cmd->stop_src == TRIG_COUNT)
 592                err |= cfc_check_trigger_arg_min(&cmd->stop_arg, 1);
 593        else    /* TRIG_NONE */
 594                err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
 595
 596        if (err)
 597                return 3;
 598
 599        /* step 4: fix up any arguments */
 600
 601        if (cmd->convert_src == TRIG_TIMER) {
 602                tmp = cmd->convert_arg;
 603                i8253_cascade_ns_to_timer(board->i8254_osc_base,
 604                                          &divisor1, &divisor2,
 605                                          &cmd->convert_arg, cmd->flags);
 606                if (cmd->convert_arg < board->ai_ns_min)
 607                        cmd->convert_arg = board->ai_ns_min;
 608                if (tmp != cmd->convert_arg)
 609                        err++;
 610        }
 611
 612        if (err)
 613                return 4;
 614
 615        return 0;
 616}
 617
 618/*
 619==============================================================================
 620*/
 621static int pcl812_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 622{
 623        const struct pcl812_board *board = comedi_board(dev);
 624        struct pcl812_private *devpriv = dev->private;
 625        unsigned int divisor1 = 0, divisor2 = 0, i, dma_flags, bytes;
 626        struct comedi_cmd *cmd = &s->async->cmd;
 627
 628        if (cmd->start_src != TRIG_NOW)
 629                return -EINVAL;
 630        if (cmd->scan_begin_src != TRIG_FOLLOW)
 631                return -EINVAL;
 632        if (devpriv->use_ext_trg) {
 633                if (cmd->convert_src != TRIG_EXT)
 634                        return -EINVAL;
 635        } else {
 636                if (cmd->convert_src != TRIG_TIMER)
 637                        return -EINVAL;
 638        }
 639        if (cmd->scan_end_src != TRIG_COUNT)
 640                return -EINVAL;
 641        if (cmd->scan_end_arg != cmd->chanlist_len)
 642                return -EINVAL;
 643        if (cmd->chanlist_len > MAX_CHANLIST_LEN)
 644                return -EINVAL;
 645
 646        if (cmd->convert_src == TRIG_TIMER) {
 647                if (cmd->convert_arg < board->ai_ns_min)
 648                        cmd->convert_arg = board->ai_ns_min;
 649                i8253_cascade_ns_to_timer(board->i8254_osc_base,
 650                                          &divisor1, &divisor2,
 651                                          &cmd->convert_arg, cmd->flags);
 652        }
 653
 654        start_pacer(dev, -1, 0, 0);     /*  stop pacer */
 655
 656        devpriv->ai_n_chan = cmd->chanlist_len;
 657        memcpy(devpriv->ai_chanlist, cmd->chanlist,
 658               sizeof(unsigned int) * cmd->scan_end_arg);
 659        /*  select first channel and range */
 660        setup_range_channel(dev, s, devpriv->ai_chanlist[0], 1);
 661
 662        if (devpriv->dma) {     /*  check if we can use DMA transfer */
 663                devpriv->ai_dma = 1;
 664                for (i = 1; i < devpriv->ai_n_chan; i++)
 665                        if (devpriv->ai_chanlist[0] != devpriv->ai_chanlist[i]) {
 666                                /*  we cann't use DMA :-( */
 667                                devpriv->ai_dma = 0;
 668                                break;
 669                        }
 670        } else
 671                devpriv->ai_dma = 0;
 672
 673        devpriv->ai_flags = cmd->flags;
 674        devpriv->ai_data_len = s->async->prealloc_bufsz;
 675        if (cmd->stop_src == TRIG_COUNT) {
 676                devpriv->ai_scans = cmd->stop_arg;
 677                devpriv->ai_neverending = 0;
 678        } else {
 679                devpriv->ai_scans = 0;
 680                devpriv->ai_neverending = 1;
 681        }
 682
 683        devpriv->ai_act_scan = 0;
 684        devpriv->ai_poll_ptr = 0;
 685        s->async->cur_chan = 0;
 686
 687        /*  don't we want wake up every scan? */
 688        if ((devpriv->ai_flags & TRIG_WAKE_EOS)) {
 689                devpriv->ai_eos = 1;
 690
 691                /*  DMA is useless for this situation */
 692                if (devpriv->ai_n_chan == 1)
 693                        devpriv->ai_dma = 0;
 694        }
 695
 696        if (devpriv->ai_dma) {
 697                /*  we use EOS, so adapt DMA buffer to one scan */
 698                if (devpriv->ai_eos) {
 699                        devpriv->dmabytestomove[0] =
 700                            devpriv->ai_n_chan * sizeof(short);
 701                        devpriv->dmabytestomove[1] =
 702                            devpriv->ai_n_chan * sizeof(short);
 703                        devpriv->dma_runs_to_end = 1;
 704                } else {
 705                        devpriv->dmabytestomove[0] = devpriv->hwdmasize[0];
 706                        devpriv->dmabytestomove[1] = devpriv->hwdmasize[1];
 707                        if (devpriv->ai_data_len < devpriv->hwdmasize[0])
 708                                devpriv->dmabytestomove[0] =
 709                                    devpriv->ai_data_len;
 710                        if (devpriv->ai_data_len < devpriv->hwdmasize[1])
 711                                devpriv->dmabytestomove[1] =
 712                                    devpriv->ai_data_len;
 713                        if (devpriv->ai_neverending) {
 714                                devpriv->dma_runs_to_end = 1;
 715                        } else {
 716                                /*  how many samples we must transfer? */
 717                                bytes = devpriv->ai_n_chan *
 718                                        devpriv->ai_scans * sizeof(short);
 719
 720                                /*  how many DMA pages we must fill */
 721                                devpriv->dma_runs_to_end =
 722                                        bytes / devpriv->dmabytestomove[0];
 723
 724                                /* on last dma transfer must be moved */
 725                                devpriv->last_dma_run =
 726                                        bytes % devpriv->dmabytestomove[0];
 727                                if (devpriv->dma_runs_to_end == 0)
 728                                        devpriv->dmabytestomove[0] =
 729                                            devpriv->last_dma_run;
 730                                devpriv->dma_runs_to_end--;
 731                        }
 732                }
 733                if (devpriv->dmabytestomove[0] > devpriv->hwdmasize[0]) {
 734                        devpriv->dmabytestomove[0] = devpriv->hwdmasize[0];
 735                        devpriv->ai_eos = 0;
 736                }
 737                if (devpriv->dmabytestomove[1] > devpriv->hwdmasize[1]) {
 738                        devpriv->dmabytestomove[1] = devpriv->hwdmasize[1];
 739                        devpriv->ai_eos = 0;
 740                }
 741                devpriv->next_dma_buf = 0;
 742                set_dma_mode(devpriv->dma, DMA_MODE_READ);
 743                dma_flags = claim_dma_lock();
 744                clear_dma_ff(devpriv->dma);
 745                set_dma_addr(devpriv->dma, devpriv->hwdmaptr[0]);
 746                set_dma_count(devpriv->dma, devpriv->dmabytestomove[0]);
 747                release_dma_lock(dma_flags);
 748                enable_dma(devpriv->dma);
 749        }
 750
 751        switch (cmd->convert_src) {
 752        case TRIG_TIMER:
 753                start_pacer(dev, 1, divisor1, divisor2);
 754                break;
 755        }
 756
 757        if (devpriv->ai_dma)                                    /*  let's go! */
 758                outb(devpriv->mode_reg_int | 2, dev->iobase + PCL812_MODE);
 759        else                                                    /*  let's go! */
 760                outb(devpriv->mode_reg_int | 6, dev->iobase + PCL812_MODE);
 761
 762        return 0;
 763}
 764
 765/*
 766==============================================================================
 767*/
 768static irqreturn_t interrupt_pcl812_ai_int(int irq, void *d)
 769{
 770        char err = 1;
 771        unsigned int mask, timeout;
 772        struct comedi_device *dev = d;
 773        struct pcl812_private *devpriv = dev->private;
 774        struct comedi_subdevice *s = dev->read_subdev;
 775        unsigned int next_chan;
 776
 777        s->async->events = 0;
 778
 779        timeout = 50;           /* wait max 50us, it must finish under 33us */
 780        if (devpriv->ai_is16b) {
 781                mask = 0xffff;
 782                while (timeout--) {
 783                        if (!(inb(dev->iobase + ACL8216_STATUS) & ACL8216_DRDY)) {
 784                                err = 0;
 785                                break;
 786                        }
 787                        udelay(1);
 788                }
 789        } else {
 790                mask = 0x0fff;
 791                while (timeout--) {
 792                        if (!(inb(dev->iobase + PCL812_AD_HI) & PCL812_DRDY)) {
 793                                err = 0;
 794                                break;
 795                        }
 796                        udelay(1);
 797                }
 798        }
 799
 800        if (err) {
 801                dev_dbg(dev->class_dev, "A/D cmd IRQ without DRDY!\n");
 802                pcl812_ai_cancel(dev, s);
 803                s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR;
 804                comedi_event(dev, s);
 805                return IRQ_HANDLED;
 806        }
 807
 808        comedi_buf_put(s->async,
 809                       ((inb(dev->iobase + PCL812_AD_HI) << 8) |
 810                        inb(dev->iobase + PCL812_AD_LO)) & mask);
 811
 812        /* Set up next channel. Added by abbotti 2010-01-20, but untested. */
 813        next_chan = s->async->cur_chan + 1;
 814        if (next_chan >= devpriv->ai_n_chan)
 815                next_chan = 0;
 816        if (devpriv->ai_chanlist[s->async->cur_chan] !=
 817                        devpriv->ai_chanlist[next_chan])
 818                setup_range_channel(dev, s, devpriv->ai_chanlist[next_chan], 0);
 819
 820        outb(0, dev->iobase + PCL812_CLRINT);   /* clear INT request */
 821
 822        s->async->cur_chan = next_chan;
 823        if (next_chan == 0) {   /* one scan done */
 824                devpriv->ai_act_scan++;
 825                if (!(devpriv->ai_neverending))
 826                                                        /* all data sampled */
 827                        if (devpriv->ai_act_scan >= devpriv->ai_scans) {
 828                                pcl812_ai_cancel(dev, s);
 829                                s->async->events |= COMEDI_CB_EOA;
 830                        }
 831        }
 832
 833        comedi_event(dev, s);
 834        return IRQ_HANDLED;
 835}
 836
 837/*
 838==============================================================================
 839*/
 840static void transfer_from_dma_buf(struct comedi_device *dev,
 841                                  struct comedi_subdevice *s,
 842                                  unsigned short *ptr,
 843                                  unsigned int bufptr, unsigned int len)
 844{
 845        struct pcl812_private *devpriv = dev->private;
 846        unsigned int i;
 847
 848        s->async->events = 0;
 849        for (i = len; i; i--) {
 850                                                        /*  get one sample */
 851                comedi_buf_put(s->async, ptr[bufptr++]);
 852
 853                s->async->cur_chan++;
 854                if (s->async->cur_chan >= devpriv->ai_n_chan) {
 855                        s->async->cur_chan = 0;
 856                        devpriv->ai_act_scan++;
 857                        if (!devpriv->ai_neverending)
 858                                                        /* all data sampled */
 859                                if (devpriv->ai_act_scan >= devpriv->ai_scans) {
 860                                        pcl812_ai_cancel(dev, s);
 861                                        s->async->events |= COMEDI_CB_EOA;
 862                                        break;
 863                                }
 864                }
 865        }
 866
 867        comedi_event(dev, s);
 868}
 869
 870/*
 871==============================================================================
 872*/
 873static irqreturn_t interrupt_pcl812_ai_dma(int irq, void *d)
 874{
 875        struct comedi_device *dev = d;
 876        struct pcl812_private *devpriv = dev->private;
 877        struct comedi_subdevice *s = dev->read_subdev;
 878        unsigned long dma_flags;
 879        int len, bufptr;
 880        unsigned short *ptr;
 881
 882        ptr = (unsigned short *)devpriv->dmabuf[devpriv->next_dma_buf];
 883        len = (devpriv->dmabytestomove[devpriv->next_dma_buf] >> 1) -
 884            devpriv->ai_poll_ptr;
 885
 886        devpriv->next_dma_buf = 1 - devpriv->next_dma_buf;
 887        disable_dma(devpriv->dma);
 888        set_dma_mode(devpriv->dma, DMA_MODE_READ);
 889        dma_flags = claim_dma_lock();
 890        set_dma_addr(devpriv->dma, devpriv->hwdmaptr[devpriv->next_dma_buf]);
 891        if (devpriv->ai_eos) {
 892                set_dma_count(devpriv->dma,
 893                              devpriv->dmabytestomove[devpriv->next_dma_buf]);
 894        } else {
 895                if (devpriv->dma_runs_to_end) {
 896                        set_dma_count(devpriv->dma,
 897                                      devpriv->dmabytestomove[devpriv->
 898                                                              next_dma_buf]);
 899                } else {
 900                        set_dma_count(devpriv->dma, devpriv->last_dma_run);
 901                }
 902                devpriv->dma_runs_to_end--;
 903        }
 904        release_dma_lock(dma_flags);
 905        enable_dma(devpriv->dma);
 906
 907        outb(0, dev->iobase + PCL812_CLRINT);   /* clear INT request */
 908
 909        bufptr = devpriv->ai_poll_ptr;
 910        devpriv->ai_poll_ptr = 0;
 911
 912        transfer_from_dma_buf(dev, s, ptr, bufptr, len);
 913
 914        return IRQ_HANDLED;
 915}
 916
 917/*
 918==============================================================================
 919*/
 920static irqreturn_t interrupt_pcl812(int irq, void *d)
 921{
 922        struct comedi_device *dev = d;
 923        struct pcl812_private *devpriv = dev->private;
 924
 925        if (!dev->attached) {
 926                comedi_error(dev, "spurious interrupt");
 927                return IRQ_HANDLED;
 928        }
 929        if (devpriv->ai_dma)
 930                return interrupt_pcl812_ai_dma(irq, d);
 931        else
 932                return interrupt_pcl812_ai_int(irq, d);
 933}
 934
 935/*
 936==============================================================================
 937*/
 938static int pcl812_ai_poll(struct comedi_device *dev, struct comedi_subdevice *s)
 939{
 940        struct pcl812_private *devpriv = dev->private;
 941        unsigned long flags;
 942        unsigned int top1, top2, i;
 943
 944        if (!devpriv->ai_dma)
 945                return 0;       /*  poll is valid only for DMA transfer */
 946
 947        spin_lock_irqsave(&dev->spinlock, flags);
 948
 949        for (i = 0; i < 10; i++) {
 950                /*  where is now DMA */
 951                top1 = get_dma_residue(devpriv->ai_dma);
 952                top2 = get_dma_residue(devpriv->ai_dma);
 953                if (top1 == top2)
 954                        break;
 955        }
 956
 957        if (top1 != top2) {
 958                spin_unlock_irqrestore(&dev->spinlock, flags);
 959                return 0;
 960        }
 961        /*  where is now DMA in buffer */
 962        top1 = devpriv->dmabytestomove[1 - devpriv->next_dma_buf] - top1;
 963        top1 >>= 1;             /*  sample position */
 964        top2 = top1 - devpriv->ai_poll_ptr;
 965        if (top2 < 1) {         /*  no new samples */
 966                spin_unlock_irqrestore(&dev->spinlock, flags);
 967                return 0;
 968        }
 969
 970        transfer_from_dma_buf(dev, s,
 971                              (void *)devpriv->dmabuf[1 -
 972                                                      devpriv->next_dma_buf],
 973                              devpriv->ai_poll_ptr, top2);
 974
 975        devpriv->ai_poll_ptr = top1;    /*  new buffer position */
 976
 977        spin_unlock_irqrestore(&dev->spinlock, flags);
 978
 979        return s->async->buf_write_count - s->async->buf_read_count;
 980}
 981
 982/*
 983==============================================================================
 984*/
 985static void setup_range_channel(struct comedi_device *dev,
 986                                struct comedi_subdevice *s,
 987                                unsigned int rangechan, char wait)
 988{
 989        struct pcl812_private *devpriv = dev->private;
 990        unsigned char chan_reg = CR_CHAN(rangechan);    /*  normal board */
 991                                                        /*  gain index */
 992        unsigned char gain_reg = CR_RANGE(rangechan) +
 993                                 devpriv->range_correction;
 994
 995        if ((chan_reg == devpriv->old_chan_reg)
 996            && (gain_reg == devpriv->old_gain_reg))
 997                return;         /*  we can return, no change */
 998
 999        devpriv->old_chan_reg = chan_reg;
1000        devpriv->old_gain_reg = gain_reg;
1001
1002        if (devpriv->use_MPC) {
1003                if (devpriv->use_diff) {
1004                        chan_reg = chan_reg | 0x30;     /*  DIFF inputs */
1005                } else {
1006                        if (chan_reg & 0x80)
1007                                                        /*  SE inputs 8-15 */
1008                                chan_reg = chan_reg | 0x20;
1009                        else
1010                                                        /*  SE inputs 0-7 */
1011                                chan_reg = chan_reg | 0x10;
1012                }
1013        }
1014
1015        outb(chan_reg, dev->iobase + PCL812_MUX);       /* select channel */
1016        outb(gain_reg, dev->iobase + PCL812_GAIN);      /* select gain */
1017
1018
1019        if (wait)
1020                /*
1021                 * XXX this depends on selected range and can be very long for
1022                 * some high gain ranges!
1023                 */
1024                udelay(devpriv->max_812_ai_mode0_rangewait);
1025}
1026
1027/*
1028==============================================================================
1029*/
1030static void start_pacer(struct comedi_device *dev, int mode,
1031                        unsigned int divisor1, unsigned int divisor2)
1032{
1033        outb(0xb4, dev->iobase + PCL812_CTRCTL);
1034        outb(0x74, dev->iobase + PCL812_CTRCTL);
1035        udelay(1);
1036
1037        if (mode == 1) {
1038                outb(divisor2 & 0xff, dev->iobase + PCL812_CTR2);
1039                outb((divisor2 >> 8) & 0xff, dev->iobase + PCL812_CTR2);
1040                outb(divisor1 & 0xff, dev->iobase + PCL812_CTR1);
1041                outb((divisor1 >> 8) & 0xff, dev->iobase + PCL812_CTR1);
1042        }
1043}
1044
1045/*
1046==============================================================================
1047*/
1048static int pcl812_ai_cancel(struct comedi_device *dev,
1049                            struct comedi_subdevice *s)
1050{
1051        struct pcl812_private *devpriv = dev->private;
1052
1053        if (devpriv->ai_dma)
1054                disable_dma(devpriv->dma);
1055        outb(0, dev->iobase + PCL812_CLRINT);   /* clear INT request */
1056                                                        /* Stop A/D */
1057        outb(devpriv->mode_reg_int | 0, dev->iobase + PCL812_MODE);
1058        start_pacer(dev, -1, 0, 0);     /*  stop 8254 */
1059        outb(0, dev->iobase + PCL812_CLRINT);   /* clear INT request */
1060        return 0;
1061}
1062
1063/*
1064==============================================================================
1065*/
1066static void pcl812_reset(struct comedi_device *dev)
1067{
1068        const struct pcl812_board *board = comedi_board(dev);
1069        struct pcl812_private *devpriv = dev->private;
1070
1071        outb(0, dev->iobase + PCL812_MUX);
1072        outb(0 + devpriv->range_correction, dev->iobase + PCL812_GAIN);
1073        devpriv->old_chan_reg = -1;     /*  invalidate chain/gain memory */
1074        devpriv->old_gain_reg = -1;
1075
1076        switch (board->board_type) {
1077        case boardPCL812PG:
1078        case boardPCL812:
1079        case boardACL8112:
1080        case boardACL8216:
1081                outb(0, dev->iobase + PCL812_DA2_LO);
1082                outb(0, dev->iobase + PCL812_DA2_HI);
1083        case boardA821:
1084                outb(0, dev->iobase + PCL812_DA1_LO);
1085                outb(0, dev->iobase + PCL812_DA1_HI);
1086                start_pacer(dev, -1, 0, 0);     /*  stop 8254 */
1087                outb(0, dev->iobase + PCL812_DO_HI);
1088                outb(0, dev->iobase + PCL812_DO_LO);
1089                outb(devpriv->mode_reg_int | 0, dev->iobase + PCL812_MODE);
1090                outb(0, dev->iobase + PCL812_CLRINT);
1091                break;
1092        case boardPCL813B:
1093        case boardPCL813:
1094        case boardISO813:
1095        case boardACL8113:
1096                udelay(5);
1097                break;
1098        }
1099        udelay(5);
1100}
1101
1102static int pcl812_attach(struct comedi_device *dev, struct comedi_devconfig *it)
1103{
1104        const struct pcl812_board *board = comedi_board(dev);
1105        struct pcl812_private *devpriv;
1106        int ret, subdev;
1107        unsigned int dma;
1108        unsigned long pages;
1109        struct comedi_subdevice *s;
1110        int n_subdevices;
1111
1112        ret = comedi_request_region(dev, it->options[0], board->io_range);
1113        if (ret)
1114                return ret;
1115
1116        devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
1117        if (!devpriv)
1118                return -ENOMEM;
1119
1120        if ((1 << it->options[1]) & board->IRQbits) {
1121                ret = request_irq(it->options[1], interrupt_pcl812, 0,
1122                                  dev->board_name, dev);
1123                if (ret == 0)
1124                        dev->irq = it->options[1];
1125        }
1126
1127        dma = 0;
1128        devpriv->dma = dma;
1129        if (!dev->irq)
1130                goto no_dma;    /* if we haven't IRQ, we can't use DMA */
1131        if (board->DMAbits != 0) {      /* board support DMA */
1132                dma = it->options[2];
1133                if (((1 << dma) & board->DMAbits) == 0) {
1134                        dev_err(dev->class_dev,
1135                                "DMA is out of allowed range, FAIL!\n");
1136                        return -EINVAL; /* Bad DMA */
1137                }
1138                ret = request_dma(dma, dev->board_name);
1139                if (ret) {
1140                        dev_err(dev->class_dev,
1141                                "unable to allocate DMA %u, FAIL!\n", dma);
1142                        return -EBUSY;  /* DMA isn't free */
1143                }
1144                devpriv->dma = dma;
1145                pages = 1;      /* we want 8KB */
1146                devpriv->dmabuf[0] = __get_dma_pages(GFP_KERNEL, pages);
1147                if (!devpriv->dmabuf[0]) {
1148                        dev_err(dev->class_dev,
1149                                "unable to allocate DMA buffer, FAIL!\n");
1150                        /*
1151                         * maybe experiment with try_to_free_pages()
1152                         * will help ....
1153                         */
1154                        return -EBUSY;  /* no buffer :-( */
1155                }
1156                devpriv->dmapages[0] = pages;
1157                devpriv->hwdmaptr[0] = virt_to_bus((void *)devpriv->dmabuf[0]);
1158                devpriv->hwdmasize[0] = PAGE_SIZE * (1 << pages);
1159                devpriv->dmabuf[1] = __get_dma_pages(GFP_KERNEL, pages);
1160                if (!devpriv->dmabuf[1]) {
1161                        dev_err(dev->class_dev,
1162                                "unable to allocate DMA buffer, FAIL!\n");
1163                        return -EBUSY;
1164                }
1165                devpriv->dmapages[1] = pages;
1166                devpriv->hwdmaptr[1] = virt_to_bus((void *)devpriv->dmabuf[1]);
1167                devpriv->hwdmasize[1] = PAGE_SIZE * (1 << pages);
1168        }
1169no_dma:
1170
1171        n_subdevices = 0;
1172        if (board->n_aichan > 0)
1173                n_subdevices++;
1174        if (board->n_aochan > 0)
1175                n_subdevices++;
1176        if (board->n_dichan > 0)
1177                n_subdevices++;
1178        if (board->n_dochan > 0)
1179                n_subdevices++;
1180
1181        ret = comedi_alloc_subdevices(dev, n_subdevices);
1182        if (ret)
1183                return ret;
1184
1185        subdev = 0;
1186
1187        /* analog input */
1188        if (board->n_aichan > 0) {
1189                s = &dev->subdevices[subdev];
1190                s->type = COMEDI_SUBD_AI;
1191                s->subdev_flags = SDF_READABLE;
1192                switch (board->board_type) {
1193                case boardA821:
1194                        if (it->options[2] == 1) {
1195                                s->n_chan = board->n_aichan_diff;
1196                                s->subdev_flags |= SDF_DIFF;
1197                                devpriv->use_diff = 1;
1198                        } else {
1199                                s->n_chan = board->n_aichan;
1200                                s->subdev_flags |= SDF_GROUND;
1201                        }
1202                        break;
1203                case boardACL8112:
1204                case boardACL8216:
1205                        if (it->options[4] == 1) {
1206                                s->n_chan = board->n_aichan_diff;
1207                                s->subdev_flags |= SDF_DIFF;
1208                                devpriv->use_diff = 1;
1209                        } else {
1210                                s->n_chan = board->n_aichan;
1211                                s->subdev_flags |= SDF_GROUND;
1212                        }
1213                        break;
1214                default:
1215                        s->n_chan = board->n_aichan;
1216                        s->subdev_flags |= SDF_GROUND;
1217                        break;
1218                }
1219                s->maxdata = board->ai_maxdata;
1220                s->range_table = board->rangelist_ai;
1221                if (board->board_type == boardACL8216)
1222                        s->insn_read = acl8216_ai_insn_read;
1223                else
1224                        s->insn_read = pcl812_ai_insn_read;
1225
1226                devpriv->use_MPC = board->haveMPC508;
1227                if (dev->irq) {
1228                        dev->read_subdev = s;
1229                        s->subdev_flags |= SDF_CMD_READ;
1230                        s->len_chanlist = MAX_CHANLIST_LEN;
1231                        s->do_cmdtest = pcl812_ai_cmdtest;
1232                        s->do_cmd = pcl812_ai_cmd;
1233                        s->poll = pcl812_ai_poll;
1234                        s->cancel = pcl812_ai_cancel;
1235                }
1236                switch (board->board_type) {
1237                case boardPCL812PG:
1238                        if (it->options[4] == 1)
1239                                s->range_table = &range_pcl812pg2_ai;
1240                        break;
1241                case boardPCL812:
1242                        switch (it->options[4]) {
1243                        case 0:
1244                                s->range_table = &range_bipolar10;
1245                                break;
1246                        case 1:
1247                                s->range_table = &range_bipolar5;
1248                                break;
1249                        case 2:
1250                                s->range_table = &range_bipolar2_5;
1251                                break;
1252                        case 3:
1253                                s->range_table = &range812_bipolar1_25;
1254                                break;
1255                        case 4:
1256                                s->range_table = &range812_bipolar0_625;
1257                                break;
1258                        case 5:
1259                                s->range_table = &range812_bipolar0_3125;
1260                                break;
1261                        default:
1262                                s->range_table = &range_bipolar10;
1263                                break;
1264                        }
1265                        break;
1266                        break;
1267                case boardPCL813B:
1268                        if (it->options[1] == 1)
1269                                s->range_table = &range_pcl813b2_ai;
1270                        break;
1271                case boardISO813:
1272                        switch (it->options[1]) {
1273                        case 0:
1274                                s->range_table = &range_iso813_1_ai;
1275                                break;
1276                        case 1:
1277                                s->range_table = &range_iso813_1_2_ai;
1278                                break;
1279                        case 2:
1280                                s->range_table = &range_iso813_2_ai;
1281                                devpriv->range_correction = 1;
1282                                break;
1283                        case 3:
1284                                s->range_table = &range_iso813_2_2_ai;
1285                                devpriv->range_correction = 1;
1286                                break;
1287                        default:
1288                                s->range_table = &range_iso813_1_ai;
1289                                break;
1290                        }
1291                        break;
1292                case boardACL8113:
1293                        switch (it->options[1]) {
1294                        case 0:
1295                                s->range_table = &range_acl8113_1_ai;
1296                                break;
1297                        case 1:
1298                                s->range_table = &range_acl8113_1_2_ai;
1299                                break;
1300                        case 2:
1301                                s->range_table = &range_acl8113_2_ai;
1302                                devpriv->range_correction = 1;
1303                                break;
1304                        case 3:
1305                                s->range_table = &range_acl8113_2_2_ai;
1306                                devpriv->range_correction = 1;
1307                                break;
1308                        default:
1309                                s->range_table = &range_acl8113_1_ai;
1310                                break;
1311                        }
1312                        break;
1313                }
1314                subdev++;
1315        }
1316
1317        /* analog output */
1318        if (board->n_aochan > 0) {
1319                s = &dev->subdevices[subdev];
1320                s->type = COMEDI_SUBD_AO;
1321                s->subdev_flags = SDF_WRITABLE | SDF_GROUND;
1322                s->n_chan = board->n_aochan;
1323                s->maxdata = 0xfff;
1324                s->range_table = board->rangelist_ao;
1325                s->insn_read = pcl812_ao_insn_read;
1326                s->insn_write = pcl812_ao_insn_write;
1327                switch (board->board_type) {
1328                case boardA821:
1329                        if (it->options[3] == 1)
1330                                s->range_table = &range_unipolar10;
1331                        break;
1332                case boardPCL812:
1333                case boardACL8112:
1334                case boardPCL812PG:
1335                case boardACL8216:
1336                        if (it->options[5] == 1)
1337                                s->range_table = &range_unipolar10;
1338                        if (it->options[5] == 2)
1339                                s->range_table = &range_unknown;
1340                        break;
1341                }
1342                subdev++;
1343        }
1344
1345        /* digital input */
1346        if (board->n_dichan > 0) {
1347                s = &dev->subdevices[subdev];
1348                s->type = COMEDI_SUBD_DI;
1349                s->subdev_flags = SDF_READABLE;
1350                s->n_chan = board->n_dichan;
1351                s->maxdata = 1;
1352                s->range_table = &range_digital;
1353                s->insn_bits = pcl812_di_insn_bits;
1354                subdev++;
1355        }
1356
1357        /* digital output */
1358        if (board->n_dochan > 0) {
1359                s = &dev->subdevices[subdev];
1360                s->type = COMEDI_SUBD_DO;
1361                s->subdev_flags = SDF_WRITABLE;
1362                s->n_chan = board->n_dochan;
1363                s->maxdata = 1;
1364                s->range_table = &range_digital;
1365                s->insn_bits = pcl812_do_insn_bits;
1366                subdev++;
1367        }
1368
1369        switch (board->board_type) {
1370        case boardACL8216:
1371                devpriv->ai_is16b = 1;
1372        case boardPCL812PG:
1373        case boardPCL812:
1374        case boardACL8112:
1375                devpriv->max_812_ai_mode0_rangewait = 1;
1376                if (it->options[3] > 0)
1377                                                /*  we use external trigger */
1378                        devpriv->use_ext_trg = 1;
1379                break;
1380        case boardA821:
1381                devpriv->max_812_ai_mode0_rangewait = 1;
1382                devpriv->mode_reg_int = (dev->irq << 4) & 0xf0;
1383                break;
1384        case boardPCL813B:
1385        case boardPCL813:
1386        case boardISO813:
1387        case boardACL8113:
1388                /* maybe there must by greatest timeout */
1389                devpriv->max_812_ai_mode0_rangewait = 5;
1390                break;
1391        }
1392
1393        devpriv->valid = 1;
1394
1395        pcl812_reset(dev);
1396
1397        return 0;
1398}
1399
1400static void pcl812_detach(struct comedi_device *dev)
1401{
1402        struct pcl812_private *devpriv = dev->private;
1403
1404        if (devpriv) {
1405                if (devpriv->dmabuf[0])
1406                        free_pages(devpriv->dmabuf[0], devpriv->dmapages[0]);
1407                if (devpriv->dmabuf[1])
1408                        free_pages(devpriv->dmabuf[1], devpriv->dmapages[1]);
1409                if (devpriv->dma)
1410                        free_dma(devpriv->dma);
1411        }
1412        comedi_legacy_detach(dev);
1413}
1414
1415static const struct pcl812_board boardtypes[] = {
1416        {"pcl812", boardPCL812, 16, 0, 2, 16, 16, 0x0fff,
1417         33000, I8254_OSC_BASE_2MHZ, &range_bipolar10, &range_unipolar5,
1418         0xdcfc, 0x0a, PCLx1x_IORANGE, 0},
1419        {"pcl812pg", boardPCL812PG, 16, 0, 2, 16, 16, 0x0fff,
1420         33000, I8254_OSC_BASE_2MHZ, &range_pcl812pg_ai, &range_unipolar5,
1421         0xdcfc, 0x0a, PCLx1x_IORANGE, 0},
1422        {"acl8112pg", boardPCL812PG, 16, 0, 2, 16, 16, 0x0fff,
1423         10000, I8254_OSC_BASE_2MHZ, &range_pcl812pg_ai, &range_unipolar5,
1424         0xdcfc, 0x0a, PCLx1x_IORANGE, 0},
1425        {"acl8112dg", boardACL8112, 16, 8, 2, 16, 16, 0x0fff,
1426         10000, I8254_OSC_BASE_2MHZ, &range_acl8112dg_ai, &range_unipolar5,
1427         0xdcfc, 0x0a, PCLx1x_IORANGE, 1},
1428        {"acl8112hg", boardACL8112, 16, 8, 2, 16, 16, 0x0fff,
1429         10000, I8254_OSC_BASE_2MHZ, &range_acl8112hg_ai, &range_unipolar5,
1430         0xdcfc, 0x0a, PCLx1x_IORANGE, 1},
1431        {"a821pgl", boardA821, 16, 8, 1, 16, 16, 0x0fff,
1432         10000, I8254_OSC_BASE_2MHZ, &range_pcl813b_ai, &range_unipolar5,
1433         0x000c, 0x00, PCLx1x_IORANGE, 0},
1434        {"a821pglnda", boardA821, 16, 8, 0, 0, 0, 0x0fff,
1435         10000, I8254_OSC_BASE_2MHZ, &range_pcl813b_ai, NULL,
1436         0x000c, 0x00, PCLx1x_IORANGE, 0},
1437        {"a821pgh", boardA821, 16, 8, 1, 16, 16, 0x0fff,
1438         10000, I8254_OSC_BASE_2MHZ, &range_a821pgh_ai, &range_unipolar5,
1439         0x000c, 0x00, PCLx1x_IORANGE, 0},
1440        {"a822pgl", boardACL8112, 16, 8, 2, 16, 16, 0x0fff,
1441         10000, I8254_OSC_BASE_2MHZ, &range_acl8112dg_ai, &range_unipolar5,
1442         0xdcfc, 0x0a, PCLx1x_IORANGE, 0},
1443        {"a822pgh", boardACL8112, 16, 8, 2, 16, 16, 0x0fff,
1444         10000, I8254_OSC_BASE_2MHZ, &range_acl8112hg_ai, &range_unipolar5,
1445         0xdcfc, 0x0a, PCLx1x_IORANGE, 0},
1446        {"a823pgl", boardACL8112, 16, 8, 2, 16, 16, 0x0fff,
1447         8000, I8254_OSC_BASE_2MHZ, &range_acl8112dg_ai, &range_unipolar5,
1448         0xdcfc, 0x0a, PCLx1x_IORANGE, 0},
1449        {"a823pgh", boardACL8112, 16, 8, 2, 16, 16, 0x0fff,
1450         8000, I8254_OSC_BASE_2MHZ, &range_acl8112hg_ai, &range_unipolar5,
1451         0xdcfc, 0x0a, PCLx1x_IORANGE, 0},
1452        {"pcl813", boardPCL813, 32, 0, 0, 0, 0, 0x0fff,
1453         0, 0, &range_pcl813b_ai, NULL,
1454         0x0000, 0x00, PCLx1x_IORANGE, 0},
1455        {"pcl813b", boardPCL813B, 32, 0, 0, 0, 0, 0x0fff,
1456         0, 0, &range_pcl813b_ai, NULL,
1457         0x0000, 0x00, PCLx1x_IORANGE, 0},
1458        {"acl8113", boardACL8113, 32, 0, 0, 0, 0, 0x0fff,
1459         0, 0, &range_acl8113_1_ai, NULL,
1460         0x0000, 0x00, PCLx1x_IORANGE, 0},
1461        {"iso813", boardISO813, 32, 0, 0, 0, 0, 0x0fff,
1462         0, 0, &range_iso813_1_ai, NULL,
1463         0x0000, 0x00, PCLx1x_IORANGE, 0},
1464        {"acl8216", boardACL8216, 16, 8, 2, 16, 16, 0xffff,
1465         10000, I8254_OSC_BASE_2MHZ, &range_pcl813b2_ai, &range_unipolar5,
1466         0xdcfc, 0x0a, PCLx1x_IORANGE, 1},
1467        {"a826pg", boardACL8216, 16, 8, 2, 16, 16, 0xffff,
1468         10000, I8254_OSC_BASE_2MHZ, &range_pcl813b2_ai, &range_unipolar5,
1469         0xdcfc, 0x0a, PCLx1x_IORANGE, 0},
1470};
1471
1472static struct comedi_driver pcl812_driver = {
1473        .driver_name    = "pcl812",
1474        .module         = THIS_MODULE,
1475        .attach         = pcl812_attach,
1476        .detach         = pcl812_detach,
1477        .board_name     = &boardtypes[0].name,
1478        .num_names      = ARRAY_SIZE(boardtypes),
1479        .offset         = sizeof(struct pcl812_board),
1480};
1481module_comedi_driver(pcl812_driver);
1482
1483MODULE_AUTHOR("Comedi http://www.comedi.org");
1484MODULE_DESCRIPTION("Comedi low-level driver");
1485MODULE_LICENSE("GPL");
1486