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