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/*
 135 * Register I/O map
 136 */
 137#define PCL812_TIMER_BASE                       0x00
 138#define PCL812_AI_LSB_REG                       0x04
 139#define PCL812_AI_MSB_REG                       0x05
 140#define PCL812_AI_MSB_DRDY                      (1 << 4)
 141#define PCL812_AO_LSB_REG(x)                    (0x04 + ((x) * 2))
 142#define PCL812_AO_MSB_REG(x)                    (0x05 + ((x) * 2))
 143#define PCL812_DI_LSB_REG                       0x06
 144#define PCL812_DI_MSB_REG                       0x07
 145#define PCL812_STATUS_REG                       0x08
 146#define PCL812_STATUS_DRDY                      (1 << 5)
 147#define PCL812_RANGE_REG                        0x09
 148#define PCL812_MUX_REG                          0x0a
 149#define PCL812_MUX_CHAN(x)                      ((x) << 0)
 150#define PCL812_MUX_CS0                          (1 << 4)
 151#define PCL812_MUX_CS1                          (1 << 5)
 152#define PCL812_CTRL_REG                         0x0b
 153#define PCL812_CTRL_DISABLE_TRIG                (0 << 0)
 154#define PCL812_CTRL_SOFT_TRIG                   (1 << 0)
 155#define PCL812_CTRL_PACER_DMA_TRIG              (2 << 0)
 156#define PCL812_CTRL_PACER_EOC_TRIG              (6 << 0)
 157#define PCL812_SOFTTRIG_REG                     0x0c
 158#define PCL812_DO_LSB_REG                       0x0d
 159#define PCL812_DO_MSB_REG                       0x0e
 160
 161#define MAX_CHANLIST_LEN    256 /* length of scan list */
 162
 163static const struct comedi_lrange range_pcl812pg_ai = {
 164        5, {
 165                BIP_RANGE(5),
 166                BIP_RANGE(2.5),
 167                BIP_RANGE(1.25),
 168                BIP_RANGE(0.625),
 169                BIP_RANGE(0.3125)
 170        }
 171};
 172
 173static const struct comedi_lrange range_pcl812pg2_ai = {
 174        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 = {
 184        1, {
 185                BIP_RANGE(1.25)
 186        }
 187};
 188
 189static const struct comedi_lrange range812_bipolar0_625 = {
 190        1, {
 191                BIP_RANGE(0.625)
 192        }
 193};
 194
 195static const struct comedi_lrange range812_bipolar0_3125 = {
 196        1, {
 197                BIP_RANGE(0.3125)
 198        }
 199};
 200
 201static const struct comedi_lrange range_pcl813b_ai = {
 202        4, {
 203                BIP_RANGE(5),
 204                BIP_RANGE(2.5),
 205                BIP_RANGE(1.25),
 206                BIP_RANGE(0.625)
 207        }
 208};
 209
 210static const struct comedi_lrange range_pcl813b2_ai = {
 211        4, {
 212                UNI_RANGE(10),
 213                UNI_RANGE(5),
 214                UNI_RANGE(2.5),
 215                UNI_RANGE(1.25)
 216        }
 217};
 218
 219static const struct comedi_lrange range_iso813_1_ai = {
 220        5, {
 221                BIP_RANGE(5),
 222                BIP_RANGE(2.5),
 223                BIP_RANGE(1.25),
 224                BIP_RANGE(0.625),
 225                BIP_RANGE(0.3125)
 226        }
 227};
 228
 229static const struct comedi_lrange range_iso813_1_2_ai = {
 230        5, {
 231                UNI_RANGE(10),
 232                UNI_RANGE(5),
 233                UNI_RANGE(2.5),
 234                UNI_RANGE(1.25),
 235                UNI_RANGE(0.625)
 236        }
 237};
 238
 239static const struct comedi_lrange range_iso813_2_ai = {
 240        4, {
 241                BIP_RANGE(5),
 242                BIP_RANGE(2.5),
 243                BIP_RANGE(1.25),
 244                BIP_RANGE(0.625)
 245        }
 246};
 247
 248static const struct comedi_lrange range_iso813_2_2_ai = {
 249        4, {
 250                UNI_RANGE(10),
 251                UNI_RANGE(5),
 252                UNI_RANGE(2.5),
 253                UNI_RANGE(1.25)
 254        }
 255};
 256
 257static const struct comedi_lrange range_acl8113_1_ai = {
 258        4, {
 259                BIP_RANGE(5),
 260                BIP_RANGE(2.5),
 261                BIP_RANGE(1.25),
 262                BIP_RANGE(0.625)
 263        }
 264};
 265
 266static const struct comedi_lrange range_acl8113_1_2_ai = {
 267        4, {
 268                UNI_RANGE(10),
 269                UNI_RANGE(5),
 270                UNI_RANGE(2.5),
 271                UNI_RANGE(1.25)
 272        }
 273};
 274
 275static const struct comedi_lrange range_acl8113_2_ai = {
 276        3, {
 277                BIP_RANGE(5),
 278                BIP_RANGE(2.5),
 279                BIP_RANGE(1.25)
 280        }
 281};
 282
 283static const struct comedi_lrange range_acl8113_2_2_ai = {
 284        3, {
 285                UNI_RANGE(10),
 286                UNI_RANGE(5),
 287                UNI_RANGE(2.5)
 288        }
 289};
 290
 291static const struct comedi_lrange range_acl8112dg_ai = {
 292        9, {
 293                BIP_RANGE(5),
 294                BIP_RANGE(2.5),
 295                BIP_RANGE(1.25),
 296                BIP_RANGE(0.625),
 297                UNI_RANGE(10),
 298                UNI_RANGE(5),
 299                UNI_RANGE(2.5),
 300                UNI_RANGE(1.25),
 301                BIP_RANGE(10)
 302        }
 303};
 304
 305static const struct comedi_lrange range_acl8112hg_ai = {
 306        12, {
 307                BIP_RANGE(5),
 308                BIP_RANGE(0.5),
 309                BIP_RANGE(0.05),
 310                BIP_RANGE(0.005),
 311                UNI_RANGE(10),
 312                UNI_RANGE(1),
 313                UNI_RANGE(0.1),
 314                UNI_RANGE(0.01),
 315                BIP_RANGE(10),
 316                BIP_RANGE(1),
 317                BIP_RANGE(0.1),
 318                BIP_RANGE(0.01)
 319        }
 320};
 321
 322static const struct comedi_lrange range_a821pgh_ai = {
 323        4, {
 324                BIP_RANGE(5),
 325                BIP_RANGE(0.5),
 326                BIP_RANGE(0.05),
 327                BIP_RANGE(0.005)
 328        }
 329};
 330
 331struct pcl812_board {
 332        const char *name;
 333        int board_type;
 334        int n_aichan;
 335        int n_aochan;
 336        unsigned int ai_ns_min;
 337        const struct comedi_lrange *rangelist_ai;
 338        unsigned int IRQbits;
 339        unsigned int has_dma:1;
 340        unsigned int has_16bit_ai:1;
 341        unsigned int has_mpc508_mux:1;
 342        unsigned int has_dio:1;
 343};
 344
 345static const struct pcl812_board boardtypes[] = {
 346        {
 347                .name           = "pcl812",
 348                .board_type     = boardPCL812,
 349                .n_aichan       = 16,
 350                .n_aochan       = 2,
 351                .ai_ns_min      = 33000,
 352                .rangelist_ai   = &range_bipolar10,
 353                .IRQbits        = 0xdcfc,
 354                .has_dma        = 1,
 355                .has_dio        = 1,
 356        }, {
 357                .name           = "pcl812pg",
 358                .board_type     = boardPCL812PG,
 359                .n_aichan       = 16,
 360                .n_aochan       = 2,
 361                .ai_ns_min      = 33000,
 362                .rangelist_ai   = &range_pcl812pg_ai,
 363                .IRQbits        = 0xdcfc,
 364                .has_dma        = 1,
 365                .has_dio        = 1,
 366        }, {
 367                .name           = "acl8112pg",
 368                .board_type     = boardPCL812PG,
 369                .n_aichan       = 16,
 370                .n_aochan       = 2,
 371                .ai_ns_min      = 10000,
 372                .rangelist_ai   = &range_pcl812pg_ai,
 373                .IRQbits        = 0xdcfc,
 374                .has_dma        = 1,
 375                .has_dio        = 1,
 376        }, {
 377                .name           = "acl8112dg",
 378                .board_type     = boardACL8112,
 379                .n_aichan       = 16,   /* 8 differential */
 380                .n_aochan       = 2,
 381                .ai_ns_min      = 10000,
 382                .rangelist_ai   = &range_acl8112dg_ai,
 383                .IRQbits        = 0xdcfc,
 384                .has_dma        = 1,
 385                .has_mpc508_mux = 1,
 386                .has_dio        = 1,
 387        }, {
 388                .name           = "acl8112hg",
 389                .board_type     = boardACL8112,
 390                .n_aichan       = 16,   /* 8 differential */
 391                .n_aochan       = 2,
 392                .ai_ns_min      = 10000,
 393                .rangelist_ai   = &range_acl8112hg_ai,
 394                .IRQbits        = 0xdcfc,
 395                .has_dma        = 1,
 396                .has_mpc508_mux = 1,
 397                .has_dio        = 1,
 398        }, {
 399                .name           = "a821pgl",
 400                .board_type     = boardA821,
 401                .n_aichan       = 16,   /* 8 differential */
 402                .n_aochan       = 1,
 403                .ai_ns_min      = 10000,
 404                .rangelist_ai   = &range_pcl813b_ai,
 405                .IRQbits        = 0x000c,
 406                .has_dio        = 1,
 407        }, {
 408                .name           = "a821pglnda",
 409                .board_type     = boardA821,
 410                .n_aichan       = 16,   /* 8 differential */
 411                .ai_ns_min      = 10000,
 412                .rangelist_ai   = &range_pcl813b_ai,
 413                .IRQbits        = 0x000c,
 414        }, {
 415                .name           = "a821pgh",
 416                .board_type     = boardA821,
 417                .n_aichan       = 16,   /* 8 differential */
 418                .n_aochan       = 1,
 419                .ai_ns_min      = 10000,
 420                .rangelist_ai   = &range_a821pgh_ai,
 421                .IRQbits        = 0x000c,
 422                .has_dio        = 1,
 423        }, {
 424                .name           = "a822pgl",
 425                .board_type     = boardACL8112,
 426                .n_aichan       = 16,   /* 8 differential */
 427                .n_aochan       = 2,
 428                .ai_ns_min      = 10000,
 429                .rangelist_ai   = &range_acl8112dg_ai,
 430                .IRQbits        = 0xdcfc,
 431                .has_dma        = 1,
 432                .has_dio        = 1,
 433        }, {
 434                .name           = "a822pgh",
 435                .board_type     = boardACL8112,
 436                .n_aichan       = 16,   /* 8 differential */
 437                .n_aochan       = 2,
 438                .ai_ns_min      = 10000,
 439                .rangelist_ai   = &range_acl8112hg_ai,
 440                .IRQbits        = 0xdcfc,
 441                .has_dma        = 1,
 442                .has_dio        = 1,
 443        }, {
 444                .name           = "a823pgl",
 445                .board_type     = boardACL8112,
 446                .n_aichan       = 16,   /* 8 differential */
 447                .n_aochan       = 2,
 448                .ai_ns_min      = 8000,
 449                .rangelist_ai   = &range_acl8112dg_ai,
 450                .IRQbits        = 0xdcfc,
 451                .has_dma        = 1,
 452                .has_dio        = 1,
 453        }, {
 454                .name           = "a823pgh",
 455                .board_type     = boardACL8112,
 456                .n_aichan       = 16,   /* 8 differential */
 457                .n_aochan       = 2,
 458                .ai_ns_min      = 8000,
 459                .rangelist_ai   = &range_acl8112hg_ai,
 460                .IRQbits        = 0xdcfc,
 461                .has_dma        = 1,
 462                .has_dio        = 1,
 463        }, {
 464                .name           = "pcl813",
 465                .board_type     = boardPCL813,
 466                .n_aichan       = 32,
 467                .rangelist_ai   = &range_pcl813b_ai,
 468        }, {
 469                .name           = "pcl813b",
 470                .board_type     = boardPCL813B,
 471                .n_aichan       = 32,
 472                .rangelist_ai   = &range_pcl813b_ai,
 473        }, {
 474                .name           = "acl8113",
 475                .board_type     = boardACL8113,
 476                .n_aichan       = 32,
 477                .rangelist_ai   = &range_acl8113_1_ai,
 478        }, {
 479                .name           = "iso813",
 480                .board_type     = boardISO813,
 481                .n_aichan       = 32,
 482                .rangelist_ai   = &range_iso813_1_ai,
 483        }, {
 484                .name           = "acl8216",
 485                .board_type     = boardACL8216,
 486                .n_aichan       = 16,   /* 8 differential */
 487                .n_aochan       = 2,
 488                .ai_ns_min      = 10000,
 489                .rangelist_ai   = &range_pcl813b2_ai,
 490                .IRQbits        = 0xdcfc,
 491                .has_dma        = 1,
 492                .has_16bit_ai   = 1,
 493                .has_mpc508_mux = 1,
 494                .has_dio        = 1,
 495        }, {
 496                .name           = "a826pg",
 497                .board_type     = boardACL8216,
 498                .n_aichan       = 16,   /* 8 differential */
 499                .n_aochan       = 2,
 500                .ai_ns_min      = 10000,
 501                .rangelist_ai   = &range_pcl813b2_ai,
 502                .IRQbits        = 0xdcfc,
 503                .has_dma        = 1,
 504                .has_16bit_ai   = 1,
 505                .has_dio        = 1,
 506        },
 507};
 508
 509struct pcl812_private {
 510        unsigned char dma;      /*  >0 use dma ( usedDMA channel) */
 511        unsigned char range_correction; /*  =1 we must add 1 to range number */
 512        unsigned int last_ai_chanspec;
 513        unsigned char mode_reg_int;     /*  there is stored INT number for some card */
 514        unsigned int ai_poll_ptr;       /*  how many sampes transfer poll */
 515        unsigned int ai_act_scan;       /*  how many scans we finished */
 516        unsigned int dmapages;
 517        unsigned int hwdmasize;
 518        unsigned long dmabuf[2];        /*  PTR to DMA buf */
 519        unsigned int hwdmaptr[2];       /*  HW PTR to DMA buf */
 520        unsigned int dmabytestomove[2]; /*  how many bytes DMA transfer */
 521        int next_dma_buf;       /*  which buffer is next to use */
 522        unsigned int dma_runs_to_end;   /*  how many times we must switch DMA buffers */
 523        unsigned int last_dma_run;      /*  how many bytes to transfer on last DMA buffer */
 524        unsigned int max_812_ai_mode0_rangewait;        /*  setling time for gain */
 525        unsigned int divisor1;
 526        unsigned int divisor2;
 527        unsigned int use_diff:1;
 528        unsigned int use_mpc508:1;
 529        unsigned int use_ext_trg:1;
 530        unsigned int ai_dma:1;
 531        unsigned int ai_eos:1;
 532};
 533
 534static void pcl812_start_pacer(struct comedi_device *dev, bool load_timers)
 535{
 536        struct pcl812_private *devpriv = dev->private;
 537        unsigned long timer_base = dev->iobase + PCL812_TIMER_BASE;
 538
 539        i8254_set_mode(timer_base, 0, 2, I8254_MODE2 | I8254_BINARY);
 540        i8254_set_mode(timer_base, 0, 1, I8254_MODE2 | I8254_BINARY);
 541        udelay(1);
 542
 543        if (load_timers) {
 544                i8254_write(timer_base, 0, 2, devpriv->divisor2);
 545                i8254_write(timer_base, 0, 1, devpriv->divisor1);
 546        }
 547}
 548
 549static void pcl812_ai_setup_dma(struct comedi_device *dev,
 550                                struct comedi_subdevice *s)
 551{
 552        struct pcl812_private *devpriv = dev->private;
 553        struct comedi_cmd *cmd = &s->async->cmd;
 554        unsigned int dma_flags;
 555        unsigned int bytes;
 556
 557        /*  we use EOS, so adapt DMA buffer to one scan */
 558        if (devpriv->ai_eos) {
 559                devpriv->dmabytestomove[0] = cfc_bytes_per_scan(s);
 560                devpriv->dmabytestomove[1] = cfc_bytes_per_scan(s);
 561                devpriv->dma_runs_to_end = 1;
 562        } else {
 563                devpriv->dmabytestomove[0] = devpriv->hwdmasize;
 564                devpriv->dmabytestomove[1] = devpriv->hwdmasize;
 565                if (s->async->prealloc_bufsz < devpriv->hwdmasize) {
 566                        devpriv->dmabytestomove[0] =
 567                                s->async->prealloc_bufsz;
 568                        devpriv->dmabytestomove[1] =
 569                                s->async->prealloc_bufsz;
 570                }
 571                if (cmd->stop_src == TRIG_NONE) {
 572                        devpriv->dma_runs_to_end = 1;
 573                } else {
 574                        /*  how many samples we must transfer? */
 575                        bytes = cmd->stop_arg * cfc_bytes_per_scan(s);
 576
 577                        /*  how many DMA pages we must fill */
 578                        devpriv->dma_runs_to_end =
 579                                bytes / devpriv->dmabytestomove[0];
 580
 581                        /* on last dma transfer must be moved */
 582                        devpriv->last_dma_run =
 583                                bytes % devpriv->dmabytestomove[0];
 584                        if (devpriv->dma_runs_to_end == 0)
 585                                devpriv->dmabytestomove[0] =
 586                                        devpriv->last_dma_run;
 587                        devpriv->dma_runs_to_end--;
 588                }
 589        }
 590        if (devpriv->dmabytestomove[0] > devpriv->hwdmasize) {
 591                devpriv->dmabytestomove[0] = devpriv->hwdmasize;
 592                devpriv->ai_eos = 0;
 593        }
 594        if (devpriv->dmabytestomove[1] > devpriv->hwdmasize) {
 595                devpriv->dmabytestomove[1] = devpriv->hwdmasize;
 596                devpriv->ai_eos = 0;
 597        }
 598        devpriv->next_dma_buf = 0;
 599        set_dma_mode(devpriv->dma, DMA_MODE_READ);
 600        dma_flags = claim_dma_lock();
 601        clear_dma_ff(devpriv->dma);
 602        set_dma_addr(devpriv->dma, devpriv->hwdmaptr[0]);
 603        set_dma_count(devpriv->dma, devpriv->dmabytestomove[0]);
 604        release_dma_lock(dma_flags);
 605        enable_dma(devpriv->dma);
 606}
 607
 608static void pcl812_ai_setup_next_dma(struct comedi_device *dev,
 609                                     struct comedi_subdevice *s)
 610{
 611        struct pcl812_private *devpriv = dev->private;
 612        unsigned long dma_flags;
 613
 614        devpriv->next_dma_buf = 1 - devpriv->next_dma_buf;
 615        disable_dma(devpriv->dma);
 616        set_dma_mode(devpriv->dma, DMA_MODE_READ);
 617        dma_flags = claim_dma_lock();
 618        set_dma_addr(devpriv->dma, devpriv->hwdmaptr[devpriv->next_dma_buf]);
 619        if (devpriv->ai_eos) {
 620                set_dma_count(devpriv->dma,
 621                              devpriv->dmabytestomove[devpriv->next_dma_buf]);
 622        } else {
 623                if (devpriv->dma_runs_to_end) {
 624                        set_dma_count(devpriv->dma,
 625                                      devpriv->dmabytestomove[devpriv->
 626                                                              next_dma_buf]);
 627                } else {
 628                        set_dma_count(devpriv->dma, devpriv->last_dma_run);
 629                }
 630                devpriv->dma_runs_to_end--;
 631        }
 632        release_dma_lock(dma_flags);
 633        enable_dma(devpriv->dma);
 634}
 635
 636static void pcl812_ai_set_chan_range(struct comedi_device *dev,
 637                                     unsigned int chanspec, char wait)
 638{
 639        struct pcl812_private *devpriv = dev->private;
 640        unsigned int chan = CR_CHAN(chanspec);
 641        unsigned int range = CR_RANGE(chanspec);
 642        unsigned int mux = 0;
 643
 644        if (chanspec == devpriv->last_ai_chanspec)
 645                return;
 646
 647        devpriv->last_ai_chanspec = chanspec;
 648
 649        if (devpriv->use_mpc508) {
 650                if (devpriv->use_diff) {
 651                        mux |= PCL812_MUX_CS0 | PCL812_MUX_CS1;
 652                } else {
 653                        if (chan < 8)
 654                                mux |= PCL812_MUX_CS0;
 655                        else
 656                                mux |= PCL812_MUX_CS1;
 657                }
 658        }
 659
 660        outb(mux | PCL812_MUX_CHAN(chan), dev->iobase + PCL812_MUX_REG);
 661        outb(range + devpriv->range_correction, dev->iobase + PCL812_RANGE_REG);
 662
 663        if (wait)
 664                /*
 665                 * XXX this depends on selected range and can be very long for
 666                 * some high gain ranges!
 667                 */
 668                udelay(devpriv->max_812_ai_mode0_rangewait);
 669}
 670
 671static void pcl812_ai_clear_eoc(struct comedi_device *dev)
 672{
 673        /* writing any value clears the interrupt request */
 674        outb(0, dev->iobase + PCL812_STATUS_REG);
 675}
 676
 677static void pcl812_ai_soft_trig(struct comedi_device *dev)
 678{
 679        /* writing any value triggers a software conversion */
 680        outb(255, dev->iobase + PCL812_SOFTTRIG_REG);
 681}
 682
 683static unsigned int pcl812_ai_get_sample(struct comedi_device *dev,
 684                                         struct comedi_subdevice *s)
 685{
 686        unsigned int val;
 687
 688        val = inb(dev->iobase + PCL812_AI_MSB_REG) << 8;
 689        val |= inb(dev->iobase + PCL812_AI_LSB_REG);
 690
 691        return val & s->maxdata;
 692}
 693
 694static int pcl812_ai_eoc(struct comedi_device *dev,
 695                         struct comedi_subdevice *s,
 696                         struct comedi_insn *insn,
 697                         unsigned long context)
 698{
 699        unsigned int status;
 700
 701        if (s->maxdata > 0x0fff) {
 702                status = inb(dev->iobase + PCL812_STATUS_REG);
 703                if ((status & PCL812_STATUS_DRDY) == 0)
 704                        return 0;
 705        } else {
 706                status = inb(dev->iobase + PCL812_AI_MSB_REG);
 707                if ((status & PCL812_AI_MSB_DRDY) == 0)
 708                        return 0;
 709        }
 710        return -EBUSY;
 711}
 712
 713static int pcl812_ai_cmdtest(struct comedi_device *dev,
 714                             struct comedi_subdevice *s, struct comedi_cmd *cmd)
 715{
 716        const struct pcl812_board *board = dev->board_ptr;
 717        struct pcl812_private *devpriv = dev->private;
 718        int err = 0;
 719        unsigned int flags;
 720        unsigned int arg;
 721
 722        /* Step 1 : check if triggers are trivially valid */
 723
 724        err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW);
 725        err |= cfc_check_trigger_src(&cmd->scan_begin_src, TRIG_FOLLOW);
 726
 727        if (devpriv->use_ext_trg)
 728                flags = TRIG_EXT;
 729        else
 730                flags = TRIG_TIMER;
 731        err |= cfc_check_trigger_src(&cmd->convert_src, flags);
 732
 733        err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
 734        err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE);
 735
 736        if (err)
 737                return 1;
 738
 739        /* Step 2a : make sure trigger sources are unique */
 740
 741        err |= cfc_check_trigger_is_unique(cmd->stop_src);
 742
 743        /* Step 2b : and mutually compatible */
 744
 745        if (err)
 746                return 2;
 747
 748        /* Step 3: check if arguments are trivially valid */
 749
 750        err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
 751        err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
 752
 753        if (cmd->convert_src == TRIG_TIMER)
 754                err |= cfc_check_trigger_arg_min(&cmd->convert_arg,
 755                                                 board->ai_ns_min);
 756        else    /* TRIG_EXT */
 757                err |= cfc_check_trigger_arg_is(&cmd->convert_arg, 0);
 758
 759        err |= cfc_check_trigger_arg_min(&cmd->chanlist_len, 1);
 760        err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
 761
 762        if (cmd->stop_src == TRIG_COUNT)
 763                err |= cfc_check_trigger_arg_min(&cmd->stop_arg, 1);
 764        else    /* TRIG_NONE */
 765                err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
 766
 767        if (err)
 768                return 3;
 769
 770        /* step 4: fix up any arguments */
 771
 772        if (cmd->convert_src == TRIG_TIMER) {
 773                arg = cmd->convert_arg;
 774                i8253_cascade_ns_to_timer(I8254_OSC_BASE_2MHZ,
 775                                          &devpriv->divisor1,
 776                                          &devpriv->divisor2,
 777                                          &arg, cmd->flags);
 778                err |= cfc_check_trigger_arg_is(&cmd->convert_arg, arg);
 779        }
 780
 781        if (err)
 782                return 4;
 783
 784        return 0;
 785}
 786
 787static int pcl812_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 788{
 789        struct pcl812_private *devpriv = dev->private;
 790        struct comedi_cmd *cmd = &s->async->cmd;
 791        unsigned int ctrl = 0;
 792        unsigned int i;
 793
 794        pcl812_start_pacer(dev, false);
 795
 796        pcl812_ai_set_chan_range(dev, cmd->chanlist[0], 1);
 797
 798        if (devpriv->dma) {     /*  check if we can use DMA transfer */
 799                devpriv->ai_dma = 1;
 800                for (i = 1; i < cmd->chanlist_len; i++)
 801                        if (cmd->chanlist[0] != cmd->chanlist[i]) {
 802                                /*  we cann't use DMA :-( */
 803                                devpriv->ai_dma = 0;
 804                                break;
 805                        }
 806        } else {
 807                devpriv->ai_dma = 0;
 808        }
 809
 810        devpriv->ai_act_scan = 0;
 811        devpriv->ai_poll_ptr = 0;
 812        s->async->cur_chan = 0;
 813
 814        /*  don't we want wake up every scan? */
 815        if (cmd->flags & CMDF_WAKE_EOS) {
 816                devpriv->ai_eos = 1;
 817
 818                /*  DMA is useless for this situation */
 819                if (cmd->chanlist_len == 1)
 820                        devpriv->ai_dma = 0;
 821        }
 822
 823        if (devpriv->ai_dma)
 824                pcl812_ai_setup_dma(dev, s);
 825
 826        switch (cmd->convert_src) {
 827        case TRIG_TIMER:
 828                pcl812_start_pacer(dev, true);
 829                break;
 830        }
 831
 832        if (devpriv->ai_dma)
 833                ctrl |= PCL812_CTRL_PACER_DMA_TRIG;
 834        else
 835                ctrl |= PCL812_CTRL_PACER_EOC_TRIG;
 836        outb(devpriv->mode_reg_int | ctrl, dev->iobase + PCL812_CTRL_REG);
 837
 838        return 0;
 839}
 840
 841static bool pcl812_ai_next_chan(struct comedi_device *dev,
 842                                struct comedi_subdevice *s)
 843{
 844        struct pcl812_private *devpriv = dev->private;
 845        struct comedi_cmd *cmd = &s->async->cmd;
 846
 847        s->async->events |= COMEDI_CB_BLOCK;
 848
 849        s->async->cur_chan++;
 850        if (s->async->cur_chan >= cmd->chanlist_len) {
 851                s->async->cur_chan = 0;
 852                devpriv->ai_act_scan++;
 853                s->async->events |= COMEDI_CB_EOS;
 854        }
 855
 856        if (cmd->stop_src == TRIG_COUNT &&
 857            devpriv->ai_act_scan >= cmd->stop_arg) {
 858                /* all data sampled */
 859                s->async->events |= COMEDI_CB_EOA;
 860                return false;
 861        }
 862
 863        return true;
 864}
 865
 866static void pcl812_handle_eoc(struct comedi_device *dev,
 867                              struct comedi_subdevice *s)
 868{
 869        struct comedi_cmd *cmd = &s->async->cmd;
 870        unsigned int next_chan;
 871
 872        if (pcl812_ai_eoc(dev, s, NULL, 0)) {
 873                dev_dbg(dev->class_dev, "A/D cmd IRQ without DRDY!\n");
 874                s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR;
 875                return;
 876        }
 877
 878        comedi_buf_put(s, pcl812_ai_get_sample(dev, s));
 879
 880        /* Set up next channel. Added by abbotti 2010-01-20, but untested. */
 881        next_chan = s->async->cur_chan + 1;
 882        if (next_chan >= cmd->chanlist_len)
 883                next_chan = 0;
 884        if (cmd->chanlist[s->async->cur_chan] != cmd->chanlist[next_chan])
 885                pcl812_ai_set_chan_range(dev, cmd->chanlist[next_chan], 0);
 886
 887        pcl812_ai_next_chan(dev, s);
 888}
 889
 890static void transfer_from_dma_buf(struct comedi_device *dev,
 891                                  struct comedi_subdevice *s,
 892                                  unsigned short *ptr,
 893                                  unsigned int bufptr, unsigned int len)
 894{
 895        unsigned int i;
 896
 897        for (i = len; i; i--) {
 898                comedi_buf_put(s, ptr[bufptr++]);
 899
 900                if (!pcl812_ai_next_chan(dev, s))
 901                        break;
 902        }
 903}
 904
 905static void pcl812_handle_dma(struct comedi_device *dev,
 906                              struct comedi_subdevice *s)
 907{
 908        struct pcl812_private *devpriv = dev->private;
 909        int len, bufptr;
 910        unsigned short *ptr;
 911
 912        ptr = (unsigned short *)devpriv->dmabuf[devpriv->next_dma_buf];
 913        len = (devpriv->dmabytestomove[devpriv->next_dma_buf] >> 1) -
 914            devpriv->ai_poll_ptr;
 915
 916        pcl812_ai_setup_next_dma(dev, s);
 917
 918        bufptr = devpriv->ai_poll_ptr;
 919        devpriv->ai_poll_ptr = 0;
 920
 921        transfer_from_dma_buf(dev, s, ptr, bufptr, len);
 922}
 923
 924static irqreturn_t pcl812_interrupt(int irq, void *d)
 925{
 926        struct comedi_device *dev = d;
 927        struct comedi_subdevice *s = dev->read_subdev;
 928        struct pcl812_private *devpriv = dev->private;
 929
 930        if (!dev->attached) {
 931                pcl812_ai_clear_eoc(dev);
 932                return IRQ_HANDLED;
 933        }
 934
 935        if (devpriv->ai_dma)
 936                pcl812_handle_dma(dev, s);
 937        else
 938                pcl812_handle_eoc(dev, s);
 939
 940        pcl812_ai_clear_eoc(dev);
 941
 942        cfc_handle_events(dev, s);
 943        return IRQ_HANDLED;
 944}
 945
 946static int pcl812_ai_poll(struct comedi_device *dev, struct comedi_subdevice *s)
 947{
 948        struct pcl812_private *devpriv = dev->private;
 949        unsigned long flags;
 950        unsigned int top1, top2, i;
 951
 952        if (!devpriv->ai_dma)
 953                return 0;       /*  poll is valid only for DMA transfer */
 954
 955        spin_lock_irqsave(&dev->spinlock, flags);
 956
 957        for (i = 0; i < 10; i++) {
 958                /*  where is now DMA */
 959                top1 = get_dma_residue(devpriv->ai_dma);
 960                top2 = get_dma_residue(devpriv->ai_dma);
 961                if (top1 == top2)
 962                        break;
 963        }
 964
 965        if (top1 != top2) {
 966                spin_unlock_irqrestore(&dev->spinlock, flags);
 967                return 0;
 968        }
 969        /*  where is now DMA in buffer */
 970        top1 = devpriv->dmabytestomove[1 - devpriv->next_dma_buf] - top1;
 971        top1 >>= 1;             /*  sample position */
 972        top2 = top1 - devpriv->ai_poll_ptr;
 973        if (top2 < 1) {         /*  no new samples */
 974                spin_unlock_irqrestore(&dev->spinlock, flags);
 975                return 0;
 976        }
 977
 978        transfer_from_dma_buf(dev, s,
 979                              (void *)devpriv->dmabuf[1 -
 980                                                      devpriv->next_dma_buf],
 981                              devpriv->ai_poll_ptr, top2);
 982
 983        devpriv->ai_poll_ptr = top1;    /*  new buffer position */
 984
 985        spin_unlock_irqrestore(&dev->spinlock, flags);
 986
 987        return comedi_buf_n_bytes_ready(s);
 988}
 989
 990static int pcl812_ai_cancel(struct comedi_device *dev,
 991                            struct comedi_subdevice *s)
 992{
 993        struct pcl812_private *devpriv = dev->private;
 994
 995        if (devpriv->ai_dma)
 996                disable_dma(devpriv->dma);
 997
 998        outb(devpriv->mode_reg_int | PCL812_CTRL_DISABLE_TRIG,
 999             dev->iobase + PCL812_CTRL_REG);
1000        pcl812_start_pacer(dev, false);
1001        pcl812_ai_clear_eoc(dev);
1002        return 0;
1003}
1004
1005static int pcl812_ai_insn_read(struct comedi_device *dev,
1006                               struct comedi_subdevice *s,
1007                               struct comedi_insn *insn,
1008                               unsigned int *data)
1009{
1010        struct pcl812_private *devpriv = dev->private;
1011        int ret = 0;
1012        int i;
1013
1014        outb(devpriv->mode_reg_int | PCL812_CTRL_SOFT_TRIG,
1015             dev->iobase + PCL812_CTRL_REG);
1016
1017        pcl812_ai_set_chan_range(dev, insn->chanspec, 1);
1018
1019        for (i = 0; i < insn->n; i++) {
1020                pcl812_ai_clear_eoc(dev);
1021                pcl812_ai_soft_trig(dev);
1022
1023                ret = comedi_timeout(dev, s, insn, pcl812_ai_eoc, 0);
1024                if (ret)
1025                        break;
1026
1027                data[i] = pcl812_ai_get_sample(dev, s);
1028        }
1029        outb(devpriv->mode_reg_int | PCL812_CTRL_DISABLE_TRIG,
1030             dev->iobase + PCL812_CTRL_REG);
1031        pcl812_ai_clear_eoc(dev);
1032
1033        return ret ? ret : insn->n;
1034}
1035
1036static int pcl812_ao_insn_write(struct comedi_device *dev,
1037                                struct comedi_subdevice *s,
1038                                struct comedi_insn *insn,
1039                                unsigned int *data)
1040{
1041        unsigned int chan = CR_CHAN(insn->chanspec);
1042        unsigned int val = s->readback[chan];
1043        int i;
1044
1045        for (i = 0; i < insn->n; i++) {
1046                val = data[i];
1047                outb(val & 0xff, dev->iobase + PCL812_AO_LSB_REG(chan));
1048                outb((val >> 8) & 0x0f, dev->iobase + PCL812_AO_MSB_REG(chan));
1049        }
1050        s->readback[chan] = val;
1051
1052        return insn->n;
1053}
1054
1055static int pcl812_di_insn_bits(struct comedi_device *dev,
1056                               struct comedi_subdevice *s,
1057                               struct comedi_insn *insn,
1058                               unsigned int *data)
1059{
1060        data[1] = inb(dev->iobase + PCL812_DI_LSB_REG) |
1061                  (inb(dev->iobase + PCL812_DI_MSB_REG) << 8);
1062
1063        return insn->n;
1064}
1065
1066static int pcl812_do_insn_bits(struct comedi_device *dev,
1067                               struct comedi_subdevice *s,
1068                               struct comedi_insn *insn,
1069                               unsigned int *data)
1070{
1071        if (comedi_dio_update_state(s, data)) {
1072                outb(s->state & 0xff, dev->iobase + PCL812_DO_LSB_REG);
1073                outb((s->state >> 8), dev->iobase + PCL812_DO_MSB_REG);
1074        }
1075
1076        data[1] = s->state;
1077
1078        return insn->n;
1079}
1080
1081static void pcl812_reset(struct comedi_device *dev)
1082{
1083        const struct pcl812_board *board = dev->board_ptr;
1084        struct pcl812_private *devpriv = dev->private;
1085        unsigned int chan;
1086
1087        /* disable analog input trigger */
1088        outb(devpriv->mode_reg_int | PCL812_CTRL_DISABLE_TRIG,
1089             dev->iobase + PCL812_CTRL_REG);
1090        pcl812_ai_clear_eoc(dev);
1091
1092        /* stop pacer */
1093        if (board->IRQbits)
1094                pcl812_start_pacer(dev, false);
1095
1096        /*
1097         * Invalidate last_ai_chanspec then set analog input to
1098         * known channel/range.
1099         */
1100        devpriv->last_ai_chanspec = CR_PACK(16, 0, 0);
1101        pcl812_ai_set_chan_range(dev, CR_PACK(0, 0, 0), 0);
1102
1103        /* set analog output channels to 0V */
1104        for (chan = 0; chan < board->n_aochan; chan++) {
1105                outb(0, dev->iobase + PCL812_AO_LSB_REG(chan));
1106                outb(0, dev->iobase + PCL812_AO_MSB_REG(chan));
1107        }
1108
1109        /* set all digital outputs low */
1110        if (board->has_dio) {
1111                outb(0, dev->iobase + PCL812_DO_MSB_REG);
1112                outb(0, dev->iobase + PCL812_DO_LSB_REG);
1113        }
1114}
1115
1116static void pcl812_set_ai_range_table(struct comedi_device *dev,
1117                                      struct comedi_subdevice *s,
1118                                      struct comedi_devconfig *it)
1119{
1120        const struct pcl812_board *board = dev->board_ptr;
1121        struct pcl812_private *devpriv = dev->private;
1122
1123        /* default to the range table from the boardinfo */
1124        s->range_table = board->rangelist_ai;
1125
1126        /* now check the user config option based on the boardtype */
1127        switch (board->board_type) {
1128        case boardPCL812PG:
1129                if (it->options[4] == 1)
1130                        s->range_table = &range_pcl812pg2_ai;
1131                break;
1132        case boardPCL812:
1133                switch (it->options[4]) {
1134                case 0:
1135                        s->range_table = &range_bipolar10;
1136                        break;
1137                case 1:
1138                        s->range_table = &range_bipolar5;
1139                        break;
1140                case 2:
1141                        s->range_table = &range_bipolar2_5;
1142                        break;
1143                case 3:
1144                        s->range_table = &range812_bipolar1_25;
1145                        break;
1146                case 4:
1147                        s->range_table = &range812_bipolar0_625;
1148                        break;
1149                case 5:
1150                        s->range_table = &range812_bipolar0_3125;
1151                        break;
1152                default:
1153                        s->range_table = &range_bipolar10;
1154                        break;
1155                }
1156                break;
1157        case boardPCL813B:
1158                if (it->options[1] == 1)
1159                        s->range_table = &range_pcl813b2_ai;
1160                break;
1161        case boardISO813:
1162                switch (it->options[1]) {
1163                case 0:
1164                        s->range_table = &range_iso813_1_ai;
1165                        break;
1166                case 1:
1167                        s->range_table = &range_iso813_1_2_ai;
1168                        break;
1169                case 2:
1170                        s->range_table = &range_iso813_2_ai;
1171                        devpriv->range_correction = 1;
1172                        break;
1173                case 3:
1174                        s->range_table = &range_iso813_2_2_ai;
1175                        devpriv->range_correction = 1;
1176                        break;
1177                default:
1178                        s->range_table = &range_iso813_1_ai;
1179                        break;
1180                }
1181                break;
1182        case boardACL8113:
1183                switch (it->options[1]) {
1184                case 0:
1185                        s->range_table = &range_acl8113_1_ai;
1186                        break;
1187                case 1:
1188                        s->range_table = &range_acl8113_1_2_ai;
1189                        break;
1190                case 2:
1191                        s->range_table = &range_acl8113_2_ai;
1192                        devpriv->range_correction = 1;
1193                        break;
1194                case 3:
1195                        s->range_table = &range_acl8113_2_2_ai;
1196                        devpriv->range_correction = 1;
1197                        break;
1198                default:
1199                        s->range_table = &range_acl8113_1_ai;
1200                        break;
1201                }
1202                break;
1203        }
1204}
1205
1206static int pcl812_attach(struct comedi_device *dev, struct comedi_devconfig *it)
1207{
1208        const struct pcl812_board *board = dev->board_ptr;
1209        struct pcl812_private *devpriv;
1210        struct comedi_subdevice *s;
1211        int n_subdevices;
1212        int subdev;
1213        int ret;
1214        int i;
1215
1216        devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
1217        if (!devpriv)
1218                return -ENOMEM;
1219
1220        ret = comedi_request_region(dev, it->options[0], 0x10);
1221        if (ret)
1222                return ret;
1223
1224        if ((1 << it->options[1]) & board->IRQbits) {
1225                ret = request_irq(it->options[1], pcl812_interrupt, 0,
1226                                  dev->board_name, dev);
1227                if (ret == 0)
1228                        dev->irq = it->options[1];
1229        }
1230
1231        /* we need an IRQ to do DMA on channel 3 or 1 */
1232        if (dev->irq && board->has_dma &&
1233            (it->options[2] == 3 || it->options[2] == 1)) {
1234                ret = request_dma(it->options[2], dev->board_name);
1235                if (ret) {
1236                        dev_err(dev->class_dev,
1237                                "unable to request DMA channel %d\n",
1238                                it->options[2]);
1239                        return -EBUSY;
1240                }
1241                devpriv->dma = it->options[2];
1242
1243                devpriv->dmapages = 1;  /* we want 8KB */
1244                devpriv->hwdmasize = (1 << devpriv->dmapages) * PAGE_SIZE;
1245
1246                for (i = 0; i < 2; i++) {
1247                        unsigned long dmabuf;
1248
1249                        dmabuf =  __get_dma_pages(GFP_KERNEL, devpriv->dmapages);
1250                        if (!dmabuf)
1251                                return -ENOMEM;
1252
1253                        devpriv->dmabuf[i] = dmabuf;
1254                        devpriv->hwdmaptr[i] = virt_to_bus((void *)dmabuf);
1255                }
1256        }
1257
1258        /* differential analog inputs? */
1259        switch (board->board_type) {
1260        case boardA821:
1261                if (it->options[2] == 1)
1262                        devpriv->use_diff = 1;
1263                break;
1264        case boardACL8112:
1265        case boardACL8216:
1266                if (it->options[4] == 1)
1267                        devpriv->use_diff = 1;
1268                break;
1269        }
1270
1271        n_subdevices = 1;               /* all boardtypes have analog inputs */
1272        if (board->n_aochan > 0)
1273                n_subdevices++;
1274        if (board->has_dio)
1275                n_subdevices += 2;
1276
1277        ret = comedi_alloc_subdevices(dev, n_subdevices);
1278        if (ret)
1279                return ret;
1280
1281        subdev = 0;
1282
1283        /* Analog Input subdevice */
1284        s = &dev->subdevices[subdev];
1285        s->type         = COMEDI_SUBD_AI;
1286        s->subdev_flags = SDF_READABLE;
1287        if (devpriv->use_diff) {
1288                s->subdev_flags |= SDF_DIFF;
1289                s->n_chan       = board->n_aichan / 2;
1290        } else {
1291                s->subdev_flags |= SDF_GROUND;
1292                s->n_chan       = board->n_aichan;
1293        }
1294        s->maxdata      = board->has_16bit_ai ? 0xffff : 0x0fff;
1295
1296        pcl812_set_ai_range_table(dev, s, it);
1297
1298        s->insn_read    = pcl812_ai_insn_read;
1299
1300        if (dev->irq) {
1301                dev->read_subdev = s;
1302                s->subdev_flags |= SDF_CMD_READ;
1303                s->len_chanlist = MAX_CHANLIST_LEN;
1304                s->do_cmdtest   = pcl812_ai_cmdtest;
1305                s->do_cmd       = pcl812_ai_cmd;
1306                s->poll         = pcl812_ai_poll;
1307                s->cancel       = pcl812_ai_cancel;
1308        }
1309
1310        devpriv->use_mpc508 = board->has_mpc508_mux;
1311
1312        subdev++;
1313
1314        /* analog output */
1315        if (board->n_aochan > 0) {
1316                s = &dev->subdevices[subdev];
1317                s->type         = COMEDI_SUBD_AO;
1318                s->subdev_flags = SDF_WRITABLE | SDF_GROUND;
1319                s->n_chan       = board->n_aochan;
1320                s->maxdata      = 0xfff;
1321                s->range_table  = &range_unipolar5;
1322                switch (board->board_type) {
1323                case boardA821:
1324                        if (it->options[3] == 1)
1325                                s->range_table = &range_unipolar10;
1326                        break;
1327                case boardPCL812:
1328                case boardACL8112:
1329                case boardPCL812PG:
1330                case boardACL8216:
1331                        if (it->options[5] == 1)
1332                                s->range_table = &range_unipolar10;
1333                        if (it->options[5] == 2)
1334                                s->range_table = &range_unknown;
1335                        break;
1336                }
1337                s->insn_write   = pcl812_ao_insn_write;
1338                s->insn_read    = comedi_readback_insn_read;
1339
1340                ret = comedi_alloc_subdev_readback(s);
1341                if (ret)
1342                        return ret;
1343
1344                subdev++;
1345        }
1346
1347        if (board->has_dio) {
1348                /* Digital Input subdevice */
1349                s = &dev->subdevices[subdev];
1350                s->type         = COMEDI_SUBD_DI;
1351                s->subdev_flags = SDF_READABLE;
1352                s->n_chan       = 16;
1353                s->maxdata      = 1;
1354                s->range_table  = &range_digital;
1355                s->insn_bits    = pcl812_di_insn_bits;
1356                subdev++;
1357
1358                /* Digital Output subdevice */
1359                s = &dev->subdevices[subdev];
1360                s->type         = COMEDI_SUBD_DO;
1361                s->subdev_flags = SDF_WRITABLE;
1362                s->n_chan       = 16;
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        case boardPCL812PG:
1372        case boardPCL812:
1373        case boardACL8112:
1374                devpriv->max_812_ai_mode0_rangewait = 1;
1375                if (it->options[3] > 0)
1376                                                /*  we use external trigger */
1377                        devpriv->use_ext_trg = 1;
1378                break;
1379        case boardA821:
1380                devpriv->max_812_ai_mode0_rangewait = 1;
1381                devpriv->mode_reg_int = (dev->irq << 4) & 0xf0;
1382                break;
1383        case boardPCL813B:
1384        case boardPCL813:
1385        case boardISO813:
1386        case boardACL8113:
1387                /* maybe there must by greatest timeout */
1388                devpriv->max_812_ai_mode0_rangewait = 5;
1389                break;
1390        }
1391
1392        pcl812_reset(dev);
1393
1394        return 0;
1395}
1396
1397static void pcl812_detach(struct comedi_device *dev)
1398{
1399        struct pcl812_private *devpriv = dev->private;
1400
1401        if (devpriv) {
1402                if (devpriv->dmabuf[0])
1403                        free_pages(devpriv->dmabuf[0], devpriv->dmapages);
1404                if (devpriv->dmabuf[1])
1405                        free_pages(devpriv->dmabuf[1], devpriv->dmapages);
1406                if (devpriv->dma)
1407                        free_dma(devpriv->dma);
1408        }
1409        comedi_legacy_detach(dev);
1410}
1411
1412static struct comedi_driver pcl812_driver = {
1413        .driver_name    = "pcl812",
1414        .module         = THIS_MODULE,
1415        .attach         = pcl812_attach,
1416        .detach         = pcl812_detach,
1417        .board_name     = &boardtypes[0].name,
1418        .num_names      = ARRAY_SIZE(boardtypes),
1419        .offset         = sizeof(struct pcl812_board),
1420};
1421module_comedi_driver(pcl812_driver);
1422
1423MODULE_AUTHOR("Comedi http://www.comedi.org");
1424MODULE_DESCRIPTION("Comedi low-level driver");
1425MODULE_LICENSE("GPL");
1426